From d805f2ba86561e401d57644d71b5ed86b1c154e4 Mon Sep 17 00:00:00 2001 From: lucas doremus Date: Mon, 22 Jun 2026 11:49:35 +0200 Subject: [PATCH] first commit --- CMakeLists.txt | 56 + README.md | 0 description.txt | 20 + .../automation/automated_property_provider.h | 35 + include/engine/automation/automation_player.h | 112 + include/engine/automation/automation_source.h | 86 + .../automation/automation_source_group.h | 62 + include/engine/core/ace.h | 125 + .../core/cached_graphic_resource_factory.h | 48 + .../core/cached_mixer_resource_factory.h | 36 + .../core/cached_renderer_resource_factory.h | 46 + include/engine/core/camera.h | 152 + include/engine/core/clock.h | 70 + include/engine/core/core_profiler.h | 70 + .../engine/core/embedded_resource_extractor.h | 38 + .../embedded_resource_handler_interface.h | 36 + include/engine/core/emitter.h | 224 + include/engine/core/engine.h | 20 + include/engine/core/geometry.h | 257 + include/engine/core/geometry_bih.h | 99 + include/engine/core/geometry_kdtree.h | 126 + include/engine/core/geometry_reducer.h | 120 + include/engine/core/geometry_template.h | 91 + .../engine/core/geometry_to_triangle_list.h | 60 + include/engine/core/geometry_tree.h | 100 + .../engine/core/graphic_resource_factory.h | 57 + include/engine/core/iso_surface.h | 123 + include/engine/core/item.h | 177 + include/engine/core/light.h | 191 + include/engine/core/material.h | 184 + include/engine/core/material_channel.h | 38 + include/engine/core/material_to_shader_tree.h | 31 + include/engine/core/mixer.h | 93 + include/engine/core/mixer_data.h | 36 + include/engine/core/mixer_resource_factory.h | 42 + include/engine/core/mixer_thread_controller.h | 248 + include/engine/core/null_mixer.h | 68 + include/engine/core/null_renderer.h | 119 + include/engine/core/object.h | 100 + include/engine/core/octree_renderable.h | 74 + include/engine/core/path_kdtree.h | 155 + include/engine/core/physic_material.h | 66 + include/engine/core/raster_font.h | 94 + include/engine/core/render_data.h | 205 + include/engine/core/render_primitive.h | 53 + include/engine/core/render_resource_factory.h | 45 + include/engine/core/renderable.h | 50 + include/engine/core/renderer.h | 402 ++ .../core/renderer_environment_interface.h | 72 + .../engine/core/renderer_resource_factory.h | 40 + include/engine/core/renderer_toolbox.h | 66 + include/engine/core/resource_factories.h | 32 + .../core/resource_factory_event_interface.h | 29 + .../engine/core/resource_geometry_generator.h | 27 + include/engine/core/shader.h | 79 + include/engine/core/shader_block.h | 859 ++++ include/engine/core/shader_input.h | 225 + include/engine/core/shader_isl_to_glsl.h | 36 + include/engine/core/shader_isl_to_hlsl.h | 31 + include/engine/core/shader_tree.h | 74 + include/engine/core/shader_tree_compiler.h | 158 + .../engine/core/shader_tree_compiler_isl.h | 83 + .../engine/core/shader_tree_compiler_tinyc.h | 109 + ..._convert_static_texture_block_to_dynamic.h | 23 + include/engine/core/shader_tree_to_shader.h | 23 + include/engine/core/simple_list_renderable.h | 45 + include/engine/core/skin.h | 36 + include/engine/core/sound.h | 42 + include/engine/core/tangent_frame.h | 24 + include/engine/core/terrain.h | 208 + .../engine/core/terrain_shader_generator.h | 26 + include/engine/core/texture_parm.h | 120 + include/engine/core/tool_mode.h | 25 + include/engine/core/triangle_list.h | 69 + include/engine/core/trigger.h | 48 + include/engine/gpu/gpu_caps.h | 40 + include/engine/gpu/gpu_config.h | 64 + include/engine/gpu/gpu_display_list.h | 113 + include/engine/gpu/gpu_draw_context.h | 65 + include/engine/gpu/gpu_fbo.h | 75 + include/engine/gpu/gpu_geometry.h | 46 + include/engine/gpu/gpu_material.h | 71 + include/engine/gpu/gpu_material_shader.h | 105 + include/engine/gpu/gpu_perf_tools.h | 61 + include/engine/gpu/gpu_render_list.h | 36 + include/engine/gpu/gpu_renderer.h | 647 +++ include/engine/gpu/gpu_shader.h | 165 + include/engine/gpu/gpu_shader_compiler.h | 47 + include/engine/gpu/gpu_shader_object.h | 39 + include/engine/gpu/gpu_terrain.h | 40 + include/engine/gpu/gpu_texture.h | 29 + include/engine/gpu/gpu_triangle_batch.h | 52 + include/engine/gpu/gpu_types.h | 57 + include/engine/gpu/gpu_vbo.h | 78 + include/engine/import/import_interface.h | 64 + include/engine/motion/motion.h | 114 + .../engine/motion/motion_automation_source.h | 63 + include/engine/motion/motion_channel.h | 76 + include/engine/motion/quaternion_channel.h | 76 + include/engine/motion/scene_motion.h | 46 + .../engine/motion/scene_motion_container.h | 30 + include/engine/physic/physic_constraint.h | 47 + .../engine/physic/physic_constraint_desc.h | 43 + include/engine/physic/physic_item.h | 122 + include/engine/physic/physic_item_desc.h | 89 + include/engine/physic/physic_message.h | 57 + include/engine/physic/physic_shape.h | 89 + include/engine/physic/physic_wheel.h | 61 + include/engine/physic/physic_world.h | 137 + .../engine/physic/physic_world_interface.h | 30 + include/engine/project/project.h | 145 + .../project/project_factory_interface.h | 28 + include/engine/project/project_layer.h | 29 + .../engine/project/project_scene_instance.h | 75 + include/engine/project/project_script_unit.h | 38 + include/engine/scene3d/group.h | 95 + include/engine/scene3d/instance.h | 60 + .../item_automated_property_provider.h | 41 + include/engine/scene3d/mcamera.h | 39 + include/engine/scene3d/mconstraint.h | 41 + include/engine/scene3d/memitter.h | 42 + include/engine/scene3d/mitem.h | 138 + .../engine/scene3d/mitem_event_interface.h | 57 + .../scene3d/mitem_event_script_interface.h | 51 + include/engine/scene3d/mitem_script_unit.h | 46 + .../engine/scene3d/mitem_scripted_object.h | 37 + include/engine/scene3d/mitem_type.h | 31 + include/engine/scene3d/mlight.h | 41 + include/engine/scene3d/mobject.h | 41 + include/engine/scene3d/mterrain.h | 39 + include/engine/scene3d/mtrigger.h | 53 + include/engine/scene3d/scene.h | 336 ++ include/engine/scene3d/scene_ace_manager.h | 34 + include/engine/scene3d/scene_debug.h | 62 + .../engine/scene3d/scene_event_interface.h | 41 + .../scene3d/scene_event_script_interface.h | 41 + include/engine/scene3d/scene_info.h | 20 + include/engine/scene3d/scene_io_flag.h | 35 + include/engine/scene3d/scene_message.h | 65 + .../scene3d/scene_physic_world_interface.h | 36 + include/engine/scene3d/scene_profiler.h | 62 + .../scene_renderer_environment_interface.h | 53 + include/engine/scene3d/scene_script_unit.h | 56 + .../engine/scene3d/scene_scripted_object.h | 37 + .../engine/script/script_binding_interface.h | 42 + include/engine/script/script_debugger.h | 169 + include/engine/script/script_engine_types.h | 99 + include/engine/script/script_object.h | 65 + include/engine/script/script_profiler.h | 100 + include/engine/script/script_unit.h | 88 + include/engine/script/script_variant.h | 69 + include/engine/script/script_vm.h | 145 + .../script/script_vm_debug_profile_base.h | 58 + include/engine/script/scripted_object.h | 62 + include/engine/ui/ui.h | 169 + include/engine/ui/ui_ace_manager.h | 36 + include/engine/ui/ui_camera.h | 33 + include/engine/ui/ui_cursor.h | 49 + include/engine/ui/ui_event_handler.h | 84 + include/engine/ui/ui_group.h | 35 + include/engine/ui/ui_item.h | 142 + .../ui/ui_item_automated_property_provider.h | 40 + include/engine/ui/ui_item_event_interface.h | 45 + include/engine/ui/ui_item_script_event.h | 44 + include/engine/ui/ui_item_script_unit.h | 46 + include/engine/ui/ui_item_scripted_object.h | 37 + include/engine/ui/ui_message.h | 63 + include/engine/ui/ui_scene_event_interface.h | 36 + include/engine/ui/ui_scene_script_event.h | 36 + include/engine/ui/ui_scene_scripted_object.h | 37 + include/engine/ui/ui_script_unit.h | 38 + include/engine/ui/ui_sprite.h | 80 + include/engine/ui/ui_window.h | 87 + include/engine/ui/ui_window_skin.h | 38 + include/engine/ui/widget.h | 128 + include/engine/ui/widget_bitmap.h | 29 + include/engine/ui/widget_canvas.h | 36 + include/engine/ui/widget_check.h | 66 + include/engine/ui/widget_drawable.h | 45 + include/engine/ui/widget_sizer.h | 53 + include/engine/ui/widget_spacer.h | 43 + include/engine/ui/widget_staticcontainer.h | 54 + include/engine/ui/widget_text.h | 95 + include/framework/ascii/ascii_encoder.h | 82 + include/framework/ascii/parser.h | 50 + include/framework/audio/audio_io.h | 47 + include/framework/audio/sample_factory.h | 32 + include/framework/audio/sample_format.h | 46 + include/framework/audio/sample_interface.h | 37 + .../framework/audio/sample_stream_factory.h | 34 + include/framework/audio/sample_wav.h | 60 + include/framework/audio/sample_wav_factory.h | 29 + include/framework/audio/stream_factory.h | 31 + include/framework/audio/stream_interface.h | 42 + include/framework/bih/bih.h | 140 + include/framework/color/color.h | 106 + include/framework/data/nvariant.h | 136 + include/framework/data/registry.h | 65 + include/framework/font/font_cache.h | 56 + include/framework/font/font_extended.h | 70 + include/framework/font/font_factory.h | 26 + include/framework/font/font_interface.h | 60 + include/framework/font/font_renderer.h | 122 + include/framework/geometry/bounding_box.h | 184 + include/framework/geometry/curve.h | 171 + include/framework/geometry/frustum.h | 76 + include/framework/geometry/geometric_tools.h | 103 + include/framework/geometry/plane.h | 55 + include/framework/geometry/rect.h | 112 + include/framework/geometry/sat.h | 59 + include/framework/math/matrix3.h | 225 + include/framework/math/matrix4.h | 239 + include/framework/math/quaternion.h | 107 + include/framework/math/vector.h | 301 ++ include/framework/math/vector_nml.h | 50 + include/framework/metafile/nml.h | 224 + include/framework/metafile/nml_object.h | 60 + include/framework/metafile/nml_string.h | 28 + include/framework/picture/pict.h | 341 ++ include/framework/picture/pict_color_format.h | 147 + include/framework/picture/pict_gradient.h | 51 + include/framework/picture/pict_io.h | 67 + include/framework/picture/pict_io_codec.h | 51 + include/framework/picture/pict_tools.h | 22 + include/framework/plugin/plugin_manager.h | 114 + include/framework/plugin/shared_systems.h | 37 + include/framework/shape/shape.h | 31 + include/framework/shape/shape_box.h | 47 + include/framework/shape/shape_convex.h | 59 + include/framework/shape/shape_sphere.h | 47 + include/framework/sort/sort.h | 111 + include/framework/timing/benchmark.h | 51 + include/framework/timing/loop_benchmark.h | 42 + include/framework/timing/profiler.h | 77 + include/modules/archive/archive.h | 163 + .../audio_stream_ogg/audio_stream_ogg.h | 63 + .../audio_stream_ogg_factory.h | 31 + include/modules/debug_enet/network_debugger.h | 68 + .../debug_enet/network_debugger_thread.h | 76 + include/modules/font_freetype/ft2_font.h | 64 + .../modules/font_freetype/ft2_font_factory.h | 36 + include/modules/http_curl/http_curl.h | 48 + include/modules/import_fbx/import_fbx.h | 118 + include/modules/import_obj/import_obj.h | 46 + include/modules/io_archive/io_archive.h | 62 + include/modules/io_net/io_net_client.h | 73 + .../io_net/io_net_client_worker_thread.h | 131 + include/modules/io_net/io_net_server.h | 118 + include/modules/io_net/io_net_server_thread.h | 51 + include/modules/io_zip/io_zip.h | 74 + include/modules/nav_detour/navmesh.h | 40 + include/modules/nav_detour/navpath.h | 13 + include/modules/network_enet/enet_network.h | 63 + .../bullet_character_controller.h | 189 + .../modules/physic_bullet/bullet_constraint.h | 51 + include/modules/physic_bullet/bullet_debug.h | 75 + include/modules/physic_bullet/bullet_item.h | 175 + include/modules/physic_bullet/bullet_world.h | 127 + .../pict_io_jpeglib/pict_jpeglib_codec.h | 34 + include/modules/pict_io_stb/pict_stb_codec.h | 34 + include/modules/raytracer/raytracer_core.h | 296 ++ include/modules/raytracer/raytracer_job.h | 58 + include/modules/raytracer/raytracer_scene.h | 124 + include/modules/raytracer/raytracer_spread.h | 31 + .../modules/script_squirrel/cobject/cobject.h | 58 + .../script_squirrel/cobject/cobject_decl.h | 20 + .../cobject/geometry_template_decl.h | 20 + .../script_squirrel/cobject/matrix_decl.h | 25 + .../script_squirrel/cobject/quaternion_decl.h | 24 + .../cobject/squirrel_bindings_utils.h | 239 + .../script_squirrel/cobject/squirrel_object.h | 187 + .../script_squirrel/cobject/uc_binding.h | 18 + .../modules/script_squirrel/cobject/uv_decl.h | 19 + .../script_squirrel/cobject/vector_decl.h | 20 + include/modules/script_squirrel/engine_vm.h | 41 + .../script_squirrel/engine_vm_debugger.h | 31 + .../script_squirrel/engine_vm_profiler.h | 35 + .../script_squirrel/legacy/binding_helpers.h | 201 + .../script_squirrel/legacy/squirrel_binding.h | 63 + .../script_squirrel/legacy/ws_manager.h | 118 + include/modules/script_squirrel/mmf.h | 44 + .../script_squirrel/squirrel_analyzer.h | 104 + .../script_squirrel/squirrel_debugger.h | 63 + include/modules/script_squirrel/squirrel_vm.h | 116 + include/modules/tools/geometry_merge.h | 24 + include/modules/tools/resource_explorer.h | 93 + .../modules/tools/scene_merge_object_list.h | 30 + include/modules/viewer_base/viewer_base.h | 222 + .../viewer_base/viewer_base_debugger.h | 42 + .../modules/viewer_base/viewer_base_vmhook.h | 42 + include/opencv2/calib3d.hpp | 1873 ++++++++ include/opencv2/calib3d/calib3d.hpp | 48 + include/opencv2/calib3d/calib3d_c.h | 422 ++ include/opencv2/core.hpp | 3111 ++++++++++++ include/opencv2/core/affine.hpp | 522 ++ include/opencv2/core/base.hpp | 745 +++ include/opencv2/core/bufferpool.hpp | 31 + include/opencv2/core/core.hpp | 48 + include/opencv2/core/core_c.h | 3152 ++++++++++++ include/opencv2/core/cuda.hpp | 845 ++++ include/opencv2/core/cuda.inl.hpp | 621 +++ include/opencv2/core/cuda/block.hpp | 211 + .../opencv2/core/cuda/border_interpolate.hpp | 722 +++ include/opencv2/core/cuda/color.hpp | 309 ++ include/opencv2/core/cuda/common.hpp | 109 + include/opencv2/core/cuda/datamov_utils.hpp | 113 + .../opencv2/core/cuda/detail/color_detail.hpp | 1980 ++++++++ include/opencv2/core/cuda/detail/reduce.hpp | 365 ++ .../core/cuda/detail/reduce_key_val.hpp | 502 ++ .../core/cuda/detail/transform_detail.hpp | 399 ++ .../core/cuda/detail/type_traits_detail.hpp | 191 + .../core/cuda/detail/vec_distance_detail.hpp | 121 + include/opencv2/core/cuda/dynamic_smem.hpp | 88 + include/opencv2/core/cuda/emulation.hpp | 269 ++ include/opencv2/core/cuda/filters.hpp | 286 ++ include/opencv2/core/cuda/funcattrib.hpp | 79 + include/opencv2/core/cuda/functional.hpp | 797 ++++ include/opencv2/core/cuda/limits.hpp | 128 + include/opencv2/core/cuda/reduce.hpp | 205 + include/opencv2/core/cuda/saturate_cast.hpp | 292 ++ include/opencv2/core/cuda/scan.hpp | 258 + include/opencv2/core/cuda/simd_functions.hpp | 869 ++++ include/opencv2/core/cuda/transform.hpp | 75 + include/opencv2/core/cuda/type_traits.hpp | 90 + include/opencv2/core/cuda/utility.hpp | 221 + include/opencv2/core/cuda/vec_distance.hpp | 232 + include/opencv2/core/cuda/vec_math.hpp | 930 ++++ include/opencv2/core/cuda/vec_traits.hpp | 288 ++ include/opencv2/core/cuda/warp.hpp | 139 + include/opencv2/core/cuda/warp_reduce.hpp | 76 + include/opencv2/core/cuda/warp_shuffle.hpp | 153 + include/opencv2/core/cuda_stream_accessor.hpp | 87 + include/opencv2/core/cuda_types.hpp | 135 + include/opencv2/core/cvdef.h | 231 + include/opencv2/core/cvstd.hpp | 1059 ++++ include/opencv2/core/cvstd.inl.hpp | 267 ++ include/opencv2/core/directx.hpp | 105 + include/opencv2/core/eigen.hpp | 280 ++ include/opencv2/core/ippasync.hpp | 195 + include/opencv2/core/mat.hpp | 3398 +++++++++++++ include/opencv2/core/mat.inl.hpp | 3436 +++++++++++++ include/opencv2/core/matx.hpp | 1376 ++++++ include/opencv2/core/ocl.hpp | 691 +++ include/opencv2/core/ocl_genbase.hpp | 64 + include/opencv2/core/opengl.hpp | 684 +++ include/opencv2/core/operations.hpp | 530 ++ include/opencv2/core/optim.hpp | 302 ++ include/opencv2/core/persistence.hpp | 1195 +++++ include/opencv2/core/private.cuda.hpp | 172 + include/opencv2/core/private.hpp | 296 ++ include/opencv2/core/ptr.inl.hpp | 342 ++ include/opencv2/core/sse_utils.hpp | 645 +++ include/opencv2/core/traits.hpp | 326 ++ include/opencv2/core/types.hpp | 2228 +++++++++ include/opencv2/core/types_c.h | 1834 +++++++ include/opencv2/core/utility.hpp | 889 ++++ include/opencv2/core/version.hpp | 71 + include/opencv2/core/wimage.hpp | 603 +++ include/opencv2/cvconfig.h | 183 + include/opencv2/features2d.hpp | 1299 +++++ include/opencv2/features2d/features2d.hpp | 48 + include/opencv2/flann.hpp | 561 +++ include/opencv2/flann/all_indices.h | 155 + include/opencv2/flann/allocator.h | 188 + include/opencv2/flann/any.h | 323 ++ include/opencv2/flann/autotuned_index.h | 587 +++ include/opencv2/flann/composite_index.h | 194 + include/opencv2/flann/config.h | 38 + include/opencv2/flann/defines.h | 177 + include/opencv2/flann/dist.h | 905 ++++ include/opencv2/flann/dummy.h | 16 + include/opencv2/flann/dynamic_bitset.h | 159 + include/opencv2/flann/flann.hpp | 48 + include/opencv2/flann/flann_base.hpp | 290 ++ include/opencv2/flann/general.h | 50 + include/opencv2/flann/ground_truth.h | 94 + include/opencv2/flann/hdf5.h | 231 + include/opencv2/flann/heap.h | 165 + .../flann/hierarchical_clustering_index.h | 848 ++++ include/opencv2/flann/index_testing.h | 318 ++ include/opencv2/flann/kdtree_index.h | 621 +++ include/opencv2/flann/kdtree_single_index.h | 634 +++ include/opencv2/flann/kmeans_index.h | 1167 +++++ include/opencv2/flann/linear_index.h | 132 + include/opencv2/flann/logger.h | 130 + include/opencv2/flann/lsh_index.h | 392 ++ include/opencv2/flann/lsh_table.h | 492 ++ include/opencv2/flann/matrix.h | 116 + include/opencv2/flann/miniflann.hpp | 158 + include/opencv2/flann/nn_index.h | 177 + include/opencv2/flann/object_factory.h | 91 + include/opencv2/flann/params.h | 99 + include/opencv2/flann/random.h | 133 + include/opencv2/flann/result_set.h | 543 +++ include/opencv2/flann/sampling.h | 81 + include/opencv2/flann/saving.h | 187 + include/opencv2/flann/simplex_downhill.h | 186 + include/opencv2/flann/timer.h | 94 + include/opencv2/hal.hpp | 98 + include/opencv2/hal/defs.h | 675 +++ include/opencv2/hal/intrin.hpp | 292 ++ include/opencv2/hal/intrin_cpp.hpp | 811 ++++ include/opencv2/hal/intrin_neon.hpp | 826 ++++ include/opencv2/hal/intrin_sse.hpp | 1554 ++++++ include/opencv2/highgui.hpp | 704 +++ include/opencv2/highgui/highgui.hpp | 48 + include/opencv2/highgui/highgui_c.h | 251 + include/opencv2/imgcodecs.hpp | 250 + include/opencv2/imgcodecs/imgcodecs.hpp | 48 + include/opencv2/imgcodecs/imgcodecs_c.h | 137 + include/opencv2/imgcodecs/ios.h | 57 + include/opencv2/imgproc.hpp | 4244 +++++++++++++++++ include/opencv2/imgproc/imgproc.hpp | 48 + include/opencv2/imgproc/imgproc_c.h | 1210 +++++ include/opencv2/imgproc/types_c.h | 626 +++ include/opencv2/ml.hpp | 1499 ++++++ include/opencv2/ml/ml.hpp | 48 + include/opencv2/objdetect.hpp | 466 ++ .../objdetect/detection_based_tracker.hpp | 224 + include/opencv2/objdetect/objdetect.hpp | 48 + include/opencv2/objdetect/objdetect_c.h | 165 + include/opencv2/opencv.hpp | 58 + include/opencv2/opencv_modules.hpp | 27 + include/opencv2/photo.hpp | 870 ++++ include/opencv2/photo/cuda.hpp | 132 + include/opencv2/photo/photo.hpp | 48 + include/opencv2/photo/photo_c.h | 74 + include/opencv2/shape.hpp | 57 + include/opencv2/shape/emdL1.hpp | 72 + include/opencv2/shape/hist_cost.hpp | 111 + include/opencv2/shape/shape.hpp | 48 + include/opencv2/shape/shape_distance.hpp | 224 + include/opencv2/shape/shape_transformer.hpp | 132 + include/opencv2/stitching.hpp | 257 + .../opencv2/stitching/detail/autocalib.hpp | 86 + include/opencv2/stitching/detail/blenders.hpp | 163 + include/opencv2/stitching/detail/camera.hpp | 78 + .../stitching/detail/exposure_compensate.hpp | 132 + include/opencv2/stitching/detail/matchers.hpp | 275 ++ .../stitching/detail/motion_estimators.hpp | 274 ++ .../opencv2/stitching/detail/seam_finders.hpp | 285 ++ .../opencv2/stitching/detail/timelapsers.hpp | 91 + include/opencv2/stitching/detail/util.hpp | 171 + include/opencv2/stitching/detail/util_inl.hpp | 131 + include/opencv2/stitching/detail/warpers.hpp | 586 +++ .../opencv2/stitching/detail/warpers_inl.hpp | 774 +++ include/opencv2/stitching/warpers.hpp | 183 + include/opencv2/superres.hpp | 207 + include/opencv2/superres/optical_flow.hpp | 203 + include/opencv2/video.hpp | 63 + include/opencv2/video/background_segm.hpp | 306 ++ include/opencv2/video/tracking.hpp | 515 ++ include/opencv2/video/tracking_c.h | 232 + include/opencv2/video/video.hpp | 48 + include/opencv2/videoio.hpp | 648 +++ include/opencv2/videoio/cap_ios.h | 174 + include/opencv2/videoio/videoio.hpp | 48 + include/opencv2/videoio/videoio_c.h | 405 ++ include/opencv2/videostab.hpp | 81 + include/opencv2/videostab/deblurring.hpp | 116 + include/opencv2/videostab/fast_marching.hpp | 121 + .../opencv2/videostab/fast_marching_inl.hpp | 165 + include/opencv2/videostab/frame_source.hpp | 94 + include/opencv2/videostab/global_motion.hpp | 299 ++ include/opencv2/videostab/inpainting.hpp | 212 + include/opencv2/videostab/log.hpp | 80 + include/opencv2/videostab/motion_core.hpp | 129 + .../opencv2/videostab/motion_stabilizing.hpp | 174 + include/opencv2/videostab/optical_flow.hpp | 150 + .../opencv2/videostab/outlier_rejection.hpp | 101 + include/opencv2/videostab/ring_buffer.hpp | 72 + include/opencv2/videostab/stabilizer.hpp | 200 + .../opencv2/videostab/wobble_suppression.hpp | 140 + include/opencv2/world.hpp | 58 + include/platform/alloc/ialloc.h | 218 + include/platform/analytics/analytics.h | 30 + include/platform/assert/nassert.h | 35 + include/platform/async/async_call_queue.h | 201 + .../platform/async/async_call_queue_thread.h | 84 + include/platform/async/future.h | 67 + include/platform/async/job.h | 131 + include/platform/async/job_perf.h | 55 + include/platform/async/task_loop.h | 40 + include/platform/billing/billing.h | 37 + include/platform/container/container_sort.h | 57 + .../platform/container/mpmc_bounded_queue.h | 136 + include/platform/container/narray.h | 215 + include/platform/container/narray_list.h | 268 ++ include/platform/container/nlist.h | 604 +++ include/platform/container/nmap.h | 68 + include/platform/container/nstack.h | 150 + include/platform/container/pair.h | 161 + .../platform/container/smart_median_average.h | 62 + include/platform/filesystem/data_store.h | 85 + include/platform/filesystem/filesystem.h | 73 + include/platform/filesystem/ftp_lib.h | 173 + include/platform/filesystem/io_alias.h | 66 + include/platform/filesystem/io_base.h | 80 + include/platform/filesystem/io_buffer.h | 87 + include/platform/filesystem/io_cache.h | 109 + include/platform/filesystem/io_cfile.h | 70 + include/platform/filesystem/io_crypto.h | 73 + include/platform/filesystem/io_dispatcher.h | 77 + include/platform/filesystem/io_handle.h | 71 + .../platform/filesystem/io_handle_endian.h | 50 + .../platform/filesystem/io_handle_segment.h | 42 + include/platform/filesystem/io_memory.h | 86 + include/platform/filesystem/io_mode.h | 25 + include/platform/hash/md5.h | 114 + include/platform/hash/nsha1.h | 27 + include/platform/hash/sha1.h | 49 + include/platform/http/http_interface.h | 47 + include/platform/input/input_device.h | 136 + include/platform/input/input_keyboard.h | 45 + include/platform/input/input_mouse.h | 56 + include/platform/input/input_null.h | 45 + include/platform/input/input_system.h | 51 + include/platform/input/input_touch.h | 59 + include/platform/licensing/licensing.h | 30 + include/platform/locale/country.h | 37 + include/platform/log/file_log.h | 38 + include/platform/log/log.h | 137 + include/platform/log/log_scope.h | 26 + include/platform/math/nmath.h | 78 + include/platform/math/nrange.h | 49 + include/platform/memory/bit_field.h | 60 + include/platform/memory/endian.h | 52 + include/platform/memory/memory.h | 36 + include/platform/memory/nauto_ptr.h | 78 + include/platform/memory/nshared_ptr.h | 150 + include/platform/memory/nweak_ptr.h | 101 + include/platform/memory/ring_buffer.h | 80 + include/platform/memory/singleton.h | 28 + include/platform/messaging/messaging.h | 48 + include/platform/nconfig.h | 73 + include/platform/network/network_interface.h | 74 + include/platform/nstring/nstring.h | 310 ++ include/platform/ntypes.h | 113 + include/platform/platform.h | 128 + include/platform/platform_config.h | 40 + include/platform/rand/rand.h | 55 + include/platform/reflection/c_refl.h | 44 + include/platform/reflection/nenum_string.h | 30 + include/platform/shared/shared_library.h | 32 + include/platform/signal/signal.h | 175 + include/platform/social/social.h | 38 + include/platform/thread/atomic_value.h | 49 + include/platform/thread/mutex.h | 90 + include/platform/thread/thread.h | 55 + include/platform/thread/thread_controller.h | 135 + include/platform/thread/thread_event.h | 38 + include/platform/time/ntime.h | 81 + include/platform/time/ntime_range.h | 22 + include/platform/unit/nunit.h | 49 + include/platform/video/video_mode.h | 79 + include/squirrel/!!!BEFORE_YOU_UPGRADE!!!.txt | 4 + include/squirrel/COMPILE | 41 + include/squirrel/COPYRIGHT | 21 + include/squirrel/HISTORY | 406 ++ include/squirrel/README | 23 + include/squirrel/include/sqstdaux.h | 16 + include/squirrel/include/sqstdblob.h | 20 + include/squirrel/include/sqstdio.h | 53 + include/squirrel/include/sqstdmath.h | 15 + include/squirrel/include/sqstdstring.h | 33 + include/squirrel/include/sqstdsystem.h | 15 + include/squirrel/include/squirrel.h | 507 ++ include/squirrel/sqstdlib/sqstdaux.cpp | 129 + include/squirrel/sqstdlib/sqstdblob.cpp | 277 ++ include/squirrel/sqstdlib/sqstdblobimpl.h | 108 + include/squirrel/sqstdlib/sqstdio.cpp | 431 ++ include/squirrel/sqstdlib/sqstdmath.cpp | 107 + include/squirrel/sqstdlib/sqstdrex.cpp | 636 +++ include/squirrel/sqstdlib/sqstdstream.cpp | 336 ++ include/squirrel/sqstdlib/sqstdstream.h | 18 + include/squirrel/sqstdlib/sqstdstring.cpp | 378 ++ include/squirrel/sqstdlib/sqstdsystem.cpp | 147 + include/squirrel/squirrel/sqapi.cpp | 1524 ++++++ include/squirrel/squirrel/sqarray.h | 94 + include/squirrel/squirrel/sqbaselib.cpp | 1186 +++++ include/squirrel/squirrel/sqclass.cpp | 213 + include/squirrel/squirrel/sqclass.h | 158 + include/squirrel/squirrel/sqclosure.h | 193 + include/squirrel/squirrel/sqcompiler.cpp | 1505 ++++++ include/squirrel/squirrel/sqcompiler.h | 77 + include/squirrel/squirrel/sqdebug.cpp | 116 + include/squirrel/squirrel/sqfuncproto.h | 154 + include/squirrel/squirrel/sqfuncstate.cpp | 653 +++ include/squirrel/squirrel/sqfuncstate.h | 91 + include/squirrel/squirrel/sqlexer.cpp | 489 ++ include/squirrel/squirrel/sqlexer.h | 47 + include/squirrel/squirrel/sqmem.cpp | 9 + include/squirrel/squirrel/sqobject.cpp | 655 +++ include/squirrel/squirrel/sqobject.h | 354 ++ include/squirrel/squirrel/sqopcodes.h | 132 + include/squirrel/squirrel/sqpcheader.h | 19 + include/squirrel/squirrel/sqstate.cpp | 655 +++ include/squirrel/squirrel/sqstate.h | 142 + include/squirrel/squirrel/sqstring.h | 31 + include/squirrel/squirrel/sqtable.cpp | 221 + include/squirrel/squirrel/sqtable.h | 92 + include/squirrel/squirrel/squserdata.h | 40 + include/squirrel/squirrel/squtils.h | 116 + include/squirrel/squirrel/sqvm.cpp | 1732 +++++++ include/squirrel/squirrel/sqvm.h | 210 + include/squirrel/this_is_squirrel_3.0.4Stable | 0 lib/engine.lib | Bin 0 -> 5798526 bytes lib/extern.lib | Bin 0 -> 5688084 bytes lib/framework.lib | Bin 0 -> 697846 bytes lib/modules.lib | Bin 0 -> 3907946 bytes lib/opencv_ts300.lib | Bin 0 -> 8470742 bytes lib/opencv_world300.lib | Bin 0 -> 1643694 bytes lib/platform.lib | Bin 0 -> 1183618 bytes source/webcam.cpp | 421 ++ source/webcam.h | 84 + source/webcam_binding.cpp | 74 + source/webcam_binding.h | 37 + source/webcam_decl.h | 18 + source/webcam_impl.cpp | 102 + 619 files changed, 126873 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 description.txt create mode 100644 include/engine/automation/automated_property_provider.h create mode 100644 include/engine/automation/automation_player.h create mode 100644 include/engine/automation/automation_source.h create mode 100644 include/engine/automation/automation_source_group.h create mode 100644 include/engine/core/ace.h create mode 100644 include/engine/core/cached_graphic_resource_factory.h create mode 100644 include/engine/core/cached_mixer_resource_factory.h create mode 100644 include/engine/core/cached_renderer_resource_factory.h create mode 100644 include/engine/core/camera.h create mode 100644 include/engine/core/clock.h create mode 100644 include/engine/core/core_profiler.h create mode 100644 include/engine/core/embedded_resource_extractor.h create mode 100644 include/engine/core/embedded_resource_handler_interface.h create mode 100644 include/engine/core/emitter.h create mode 100644 include/engine/core/engine.h create mode 100644 include/engine/core/geometry.h create mode 100644 include/engine/core/geometry_bih.h create mode 100644 include/engine/core/geometry_kdtree.h create mode 100644 include/engine/core/geometry_reducer.h create mode 100644 include/engine/core/geometry_template.h create mode 100644 include/engine/core/geometry_to_triangle_list.h create mode 100644 include/engine/core/geometry_tree.h create mode 100644 include/engine/core/graphic_resource_factory.h create mode 100644 include/engine/core/iso_surface.h create mode 100644 include/engine/core/item.h create mode 100644 include/engine/core/light.h create mode 100644 include/engine/core/material.h create mode 100644 include/engine/core/material_channel.h create mode 100644 include/engine/core/material_to_shader_tree.h create mode 100644 include/engine/core/mixer.h create mode 100644 include/engine/core/mixer_data.h create mode 100644 include/engine/core/mixer_resource_factory.h create mode 100644 include/engine/core/mixer_thread_controller.h create mode 100644 include/engine/core/null_mixer.h create mode 100644 include/engine/core/null_renderer.h create mode 100644 include/engine/core/object.h create mode 100644 include/engine/core/octree_renderable.h create mode 100644 include/engine/core/path_kdtree.h create mode 100644 include/engine/core/physic_material.h create mode 100644 include/engine/core/raster_font.h create mode 100644 include/engine/core/render_data.h create mode 100644 include/engine/core/render_primitive.h create mode 100644 include/engine/core/render_resource_factory.h create mode 100644 include/engine/core/renderable.h create mode 100644 include/engine/core/renderer.h create mode 100644 include/engine/core/renderer_environment_interface.h create mode 100644 include/engine/core/renderer_resource_factory.h create mode 100644 include/engine/core/renderer_toolbox.h create mode 100644 include/engine/core/resource_factories.h create mode 100644 include/engine/core/resource_factory_event_interface.h create mode 100644 include/engine/core/resource_geometry_generator.h create mode 100644 include/engine/core/shader.h create mode 100644 include/engine/core/shader_block.h create mode 100644 include/engine/core/shader_input.h create mode 100644 include/engine/core/shader_isl_to_glsl.h create mode 100644 include/engine/core/shader_isl_to_hlsl.h create mode 100644 include/engine/core/shader_tree.h create mode 100644 include/engine/core/shader_tree_compiler.h create mode 100644 include/engine/core/shader_tree_compiler_isl.h create mode 100644 include/engine/core/shader_tree_compiler_tinyc.h create mode 100644 include/engine/core/shader_tree_convert_static_texture_block_to_dynamic.h create mode 100644 include/engine/core/shader_tree_to_shader.h create mode 100644 include/engine/core/simple_list_renderable.h create mode 100644 include/engine/core/skin.h create mode 100644 include/engine/core/sound.h create mode 100644 include/engine/core/tangent_frame.h create mode 100644 include/engine/core/terrain.h create mode 100644 include/engine/core/terrain_shader_generator.h create mode 100644 include/engine/core/texture_parm.h create mode 100644 include/engine/core/tool_mode.h create mode 100644 include/engine/core/triangle_list.h create mode 100644 include/engine/core/trigger.h create mode 100644 include/engine/gpu/gpu_caps.h create mode 100644 include/engine/gpu/gpu_config.h create mode 100644 include/engine/gpu/gpu_display_list.h create mode 100644 include/engine/gpu/gpu_draw_context.h create mode 100644 include/engine/gpu/gpu_fbo.h create mode 100644 include/engine/gpu/gpu_geometry.h create mode 100644 include/engine/gpu/gpu_material.h create mode 100644 include/engine/gpu/gpu_material_shader.h create mode 100644 include/engine/gpu/gpu_perf_tools.h create mode 100644 include/engine/gpu/gpu_render_list.h create mode 100644 include/engine/gpu/gpu_renderer.h create mode 100644 include/engine/gpu/gpu_shader.h create mode 100644 include/engine/gpu/gpu_shader_compiler.h create mode 100644 include/engine/gpu/gpu_shader_object.h create mode 100644 include/engine/gpu/gpu_terrain.h create mode 100644 include/engine/gpu/gpu_texture.h create mode 100644 include/engine/gpu/gpu_triangle_batch.h create mode 100644 include/engine/gpu/gpu_types.h create mode 100644 include/engine/gpu/gpu_vbo.h create mode 100644 include/engine/import/import_interface.h create mode 100644 include/engine/motion/motion.h create mode 100644 include/engine/motion/motion_automation_source.h create mode 100644 include/engine/motion/motion_channel.h create mode 100644 include/engine/motion/quaternion_channel.h create mode 100644 include/engine/motion/scene_motion.h create mode 100644 include/engine/motion/scene_motion_container.h create mode 100644 include/engine/physic/physic_constraint.h create mode 100644 include/engine/physic/physic_constraint_desc.h create mode 100644 include/engine/physic/physic_item.h create mode 100644 include/engine/physic/physic_item_desc.h create mode 100644 include/engine/physic/physic_message.h create mode 100644 include/engine/physic/physic_shape.h create mode 100644 include/engine/physic/physic_wheel.h create mode 100644 include/engine/physic/physic_world.h create mode 100644 include/engine/physic/physic_world_interface.h create mode 100644 include/engine/project/project.h create mode 100644 include/engine/project/project_factory_interface.h create mode 100644 include/engine/project/project_layer.h create mode 100644 include/engine/project/project_scene_instance.h create mode 100644 include/engine/project/project_script_unit.h create mode 100644 include/engine/scene3d/group.h create mode 100644 include/engine/scene3d/instance.h create mode 100644 include/engine/scene3d/item_automated_property_provider.h create mode 100644 include/engine/scene3d/mcamera.h create mode 100644 include/engine/scene3d/mconstraint.h create mode 100644 include/engine/scene3d/memitter.h create mode 100644 include/engine/scene3d/mitem.h create mode 100644 include/engine/scene3d/mitem_event_interface.h create mode 100644 include/engine/scene3d/mitem_event_script_interface.h create mode 100644 include/engine/scene3d/mitem_script_unit.h create mode 100644 include/engine/scene3d/mitem_scripted_object.h create mode 100644 include/engine/scene3d/mitem_type.h create mode 100644 include/engine/scene3d/mlight.h create mode 100644 include/engine/scene3d/mobject.h create mode 100644 include/engine/scene3d/mterrain.h create mode 100644 include/engine/scene3d/mtrigger.h create mode 100644 include/engine/scene3d/scene.h create mode 100644 include/engine/scene3d/scene_ace_manager.h create mode 100644 include/engine/scene3d/scene_debug.h create mode 100644 include/engine/scene3d/scene_event_interface.h create mode 100644 include/engine/scene3d/scene_event_script_interface.h create mode 100644 include/engine/scene3d/scene_info.h create mode 100644 include/engine/scene3d/scene_io_flag.h create mode 100644 include/engine/scene3d/scene_message.h create mode 100644 include/engine/scene3d/scene_physic_world_interface.h create mode 100644 include/engine/scene3d/scene_profiler.h create mode 100644 include/engine/scene3d/scene_renderer_environment_interface.h create mode 100644 include/engine/scene3d/scene_script_unit.h create mode 100644 include/engine/scene3d/scene_scripted_object.h create mode 100644 include/engine/script/script_binding_interface.h create mode 100644 include/engine/script/script_debugger.h create mode 100644 include/engine/script/script_engine_types.h create mode 100644 include/engine/script/script_object.h create mode 100644 include/engine/script/script_profiler.h create mode 100644 include/engine/script/script_unit.h create mode 100644 include/engine/script/script_variant.h create mode 100644 include/engine/script/script_vm.h create mode 100644 include/engine/script/script_vm_debug_profile_base.h create mode 100644 include/engine/script/scripted_object.h create mode 100644 include/engine/ui/ui.h create mode 100644 include/engine/ui/ui_ace_manager.h create mode 100644 include/engine/ui/ui_camera.h create mode 100644 include/engine/ui/ui_cursor.h create mode 100644 include/engine/ui/ui_event_handler.h create mode 100644 include/engine/ui/ui_group.h create mode 100644 include/engine/ui/ui_item.h create mode 100644 include/engine/ui/ui_item_automated_property_provider.h create mode 100644 include/engine/ui/ui_item_event_interface.h create mode 100644 include/engine/ui/ui_item_script_event.h create mode 100644 include/engine/ui/ui_item_script_unit.h create mode 100644 include/engine/ui/ui_item_scripted_object.h create mode 100644 include/engine/ui/ui_message.h create mode 100644 include/engine/ui/ui_scene_event_interface.h create mode 100644 include/engine/ui/ui_scene_script_event.h create mode 100644 include/engine/ui/ui_scene_scripted_object.h create mode 100644 include/engine/ui/ui_script_unit.h create mode 100644 include/engine/ui/ui_sprite.h create mode 100644 include/engine/ui/ui_window.h create mode 100644 include/engine/ui/ui_window_skin.h create mode 100644 include/engine/ui/widget.h create mode 100644 include/engine/ui/widget_bitmap.h create mode 100644 include/engine/ui/widget_canvas.h create mode 100644 include/engine/ui/widget_check.h create mode 100644 include/engine/ui/widget_drawable.h create mode 100644 include/engine/ui/widget_sizer.h create mode 100644 include/engine/ui/widget_spacer.h create mode 100644 include/engine/ui/widget_staticcontainer.h create mode 100644 include/engine/ui/widget_text.h create mode 100644 include/framework/ascii/ascii_encoder.h create mode 100644 include/framework/ascii/parser.h create mode 100644 include/framework/audio/audio_io.h create mode 100644 include/framework/audio/sample_factory.h create mode 100644 include/framework/audio/sample_format.h create mode 100644 include/framework/audio/sample_interface.h create mode 100644 include/framework/audio/sample_stream_factory.h create mode 100644 include/framework/audio/sample_wav.h create mode 100644 include/framework/audio/sample_wav_factory.h create mode 100644 include/framework/audio/stream_factory.h create mode 100644 include/framework/audio/stream_interface.h create mode 100644 include/framework/bih/bih.h create mode 100644 include/framework/color/color.h create mode 100644 include/framework/data/nvariant.h create mode 100644 include/framework/data/registry.h create mode 100644 include/framework/font/font_cache.h create mode 100644 include/framework/font/font_extended.h create mode 100644 include/framework/font/font_factory.h create mode 100644 include/framework/font/font_interface.h create mode 100644 include/framework/font/font_renderer.h create mode 100644 include/framework/geometry/bounding_box.h create mode 100644 include/framework/geometry/curve.h create mode 100644 include/framework/geometry/frustum.h create mode 100644 include/framework/geometry/geometric_tools.h create mode 100644 include/framework/geometry/plane.h create mode 100644 include/framework/geometry/rect.h create mode 100644 include/framework/geometry/sat.h create mode 100644 include/framework/math/matrix3.h create mode 100644 include/framework/math/matrix4.h create mode 100644 include/framework/math/quaternion.h create mode 100644 include/framework/math/vector.h create mode 100644 include/framework/math/vector_nml.h create mode 100644 include/framework/metafile/nml.h create mode 100644 include/framework/metafile/nml_object.h create mode 100644 include/framework/metafile/nml_string.h create mode 100644 include/framework/picture/pict.h create mode 100644 include/framework/picture/pict_color_format.h create mode 100644 include/framework/picture/pict_gradient.h create mode 100644 include/framework/picture/pict_io.h create mode 100644 include/framework/picture/pict_io_codec.h create mode 100644 include/framework/picture/pict_tools.h create mode 100644 include/framework/plugin/plugin_manager.h create mode 100644 include/framework/plugin/shared_systems.h create mode 100644 include/framework/shape/shape.h create mode 100644 include/framework/shape/shape_box.h create mode 100644 include/framework/shape/shape_convex.h create mode 100644 include/framework/shape/shape_sphere.h create mode 100644 include/framework/sort/sort.h create mode 100644 include/framework/timing/benchmark.h create mode 100644 include/framework/timing/loop_benchmark.h create mode 100644 include/framework/timing/profiler.h create mode 100644 include/modules/archive/archive.h create mode 100644 include/modules/audio_stream_ogg/audio_stream_ogg.h create mode 100644 include/modules/audio_stream_ogg/audio_stream_ogg_factory.h create mode 100644 include/modules/debug_enet/network_debugger.h create mode 100644 include/modules/debug_enet/network_debugger_thread.h create mode 100644 include/modules/font_freetype/ft2_font.h create mode 100644 include/modules/font_freetype/ft2_font_factory.h create mode 100644 include/modules/http_curl/http_curl.h create mode 100644 include/modules/import_fbx/import_fbx.h create mode 100644 include/modules/import_obj/import_obj.h create mode 100644 include/modules/io_archive/io_archive.h create mode 100644 include/modules/io_net/io_net_client.h create mode 100644 include/modules/io_net/io_net_client_worker_thread.h create mode 100644 include/modules/io_net/io_net_server.h create mode 100644 include/modules/io_net/io_net_server_thread.h create mode 100644 include/modules/io_zip/io_zip.h create mode 100644 include/modules/nav_detour/navmesh.h create mode 100644 include/modules/nav_detour/navpath.h create mode 100644 include/modules/network_enet/enet_network.h create mode 100644 include/modules/physic_bullet/bullet_character_controller.h create mode 100644 include/modules/physic_bullet/bullet_constraint.h create mode 100644 include/modules/physic_bullet/bullet_debug.h create mode 100644 include/modules/physic_bullet/bullet_item.h create mode 100644 include/modules/physic_bullet/bullet_world.h create mode 100644 include/modules/pict_io_jpeglib/pict_jpeglib_codec.h create mode 100644 include/modules/pict_io_stb/pict_stb_codec.h create mode 100644 include/modules/raytracer/raytracer_core.h create mode 100644 include/modules/raytracer/raytracer_job.h create mode 100644 include/modules/raytracer/raytracer_scene.h create mode 100644 include/modules/raytracer/raytracer_spread.h create mode 100644 include/modules/script_squirrel/cobject/cobject.h create mode 100644 include/modules/script_squirrel/cobject/cobject_decl.h create mode 100644 include/modules/script_squirrel/cobject/geometry_template_decl.h create mode 100644 include/modules/script_squirrel/cobject/matrix_decl.h create mode 100644 include/modules/script_squirrel/cobject/quaternion_decl.h create mode 100644 include/modules/script_squirrel/cobject/squirrel_bindings_utils.h create mode 100644 include/modules/script_squirrel/cobject/squirrel_object.h create mode 100644 include/modules/script_squirrel/cobject/uc_binding.h create mode 100644 include/modules/script_squirrel/cobject/uv_decl.h create mode 100644 include/modules/script_squirrel/cobject/vector_decl.h create mode 100644 include/modules/script_squirrel/engine_vm.h create mode 100644 include/modules/script_squirrel/engine_vm_debugger.h create mode 100644 include/modules/script_squirrel/engine_vm_profiler.h create mode 100644 include/modules/script_squirrel/legacy/binding_helpers.h create mode 100644 include/modules/script_squirrel/legacy/squirrel_binding.h create mode 100644 include/modules/script_squirrel/legacy/ws_manager.h create mode 100644 include/modules/script_squirrel/mmf.h create mode 100644 include/modules/script_squirrel/squirrel_analyzer.h create mode 100644 include/modules/script_squirrel/squirrel_debugger.h create mode 100644 include/modules/script_squirrel/squirrel_vm.h create mode 100644 include/modules/tools/geometry_merge.h create mode 100644 include/modules/tools/resource_explorer.h create mode 100644 include/modules/tools/scene_merge_object_list.h create mode 100644 include/modules/viewer_base/viewer_base.h create mode 100644 include/modules/viewer_base/viewer_base_debugger.h create mode 100644 include/modules/viewer_base/viewer_base_vmhook.h create mode 100644 include/opencv2/calib3d.hpp create mode 100644 include/opencv2/calib3d/calib3d.hpp create mode 100644 include/opencv2/calib3d/calib3d_c.h create mode 100644 include/opencv2/core.hpp create mode 100644 include/opencv2/core/affine.hpp create mode 100644 include/opencv2/core/base.hpp create mode 100644 include/opencv2/core/bufferpool.hpp create mode 100644 include/opencv2/core/core.hpp create mode 100644 include/opencv2/core/core_c.h create mode 100644 include/opencv2/core/cuda.hpp create mode 100644 include/opencv2/core/cuda.inl.hpp create mode 100644 include/opencv2/core/cuda/block.hpp create mode 100644 include/opencv2/core/cuda/border_interpolate.hpp create mode 100644 include/opencv2/core/cuda/color.hpp create mode 100644 include/opencv2/core/cuda/common.hpp create mode 100644 include/opencv2/core/cuda/datamov_utils.hpp create mode 100644 include/opencv2/core/cuda/detail/color_detail.hpp create mode 100644 include/opencv2/core/cuda/detail/reduce.hpp create mode 100644 include/opencv2/core/cuda/detail/reduce_key_val.hpp create mode 100644 include/opencv2/core/cuda/detail/transform_detail.hpp create mode 100644 include/opencv2/core/cuda/detail/type_traits_detail.hpp create mode 100644 include/opencv2/core/cuda/detail/vec_distance_detail.hpp create mode 100644 include/opencv2/core/cuda/dynamic_smem.hpp create mode 100644 include/opencv2/core/cuda/emulation.hpp create mode 100644 include/opencv2/core/cuda/filters.hpp create mode 100644 include/opencv2/core/cuda/funcattrib.hpp create mode 100644 include/opencv2/core/cuda/functional.hpp create mode 100644 include/opencv2/core/cuda/limits.hpp create mode 100644 include/opencv2/core/cuda/reduce.hpp create mode 100644 include/opencv2/core/cuda/saturate_cast.hpp create mode 100644 include/opencv2/core/cuda/scan.hpp create mode 100644 include/opencv2/core/cuda/simd_functions.hpp create mode 100644 include/opencv2/core/cuda/transform.hpp create mode 100644 include/opencv2/core/cuda/type_traits.hpp create mode 100644 include/opencv2/core/cuda/utility.hpp create mode 100644 include/opencv2/core/cuda/vec_distance.hpp create mode 100644 include/opencv2/core/cuda/vec_math.hpp create mode 100644 include/opencv2/core/cuda/vec_traits.hpp create mode 100644 include/opencv2/core/cuda/warp.hpp create mode 100644 include/opencv2/core/cuda/warp_reduce.hpp create mode 100644 include/opencv2/core/cuda/warp_shuffle.hpp create mode 100644 include/opencv2/core/cuda_stream_accessor.hpp create mode 100644 include/opencv2/core/cuda_types.hpp create mode 100644 include/opencv2/core/cvdef.h create mode 100644 include/opencv2/core/cvstd.hpp create mode 100644 include/opencv2/core/cvstd.inl.hpp create mode 100644 include/opencv2/core/directx.hpp create mode 100644 include/opencv2/core/eigen.hpp create mode 100644 include/opencv2/core/ippasync.hpp create mode 100644 include/opencv2/core/mat.hpp create mode 100644 include/opencv2/core/mat.inl.hpp create mode 100644 include/opencv2/core/matx.hpp create mode 100644 include/opencv2/core/ocl.hpp create mode 100644 include/opencv2/core/ocl_genbase.hpp create mode 100644 include/opencv2/core/opengl.hpp create mode 100644 include/opencv2/core/operations.hpp create mode 100644 include/opencv2/core/optim.hpp create mode 100644 include/opencv2/core/persistence.hpp create mode 100644 include/opencv2/core/private.cuda.hpp create mode 100644 include/opencv2/core/private.hpp create mode 100644 include/opencv2/core/ptr.inl.hpp create mode 100644 include/opencv2/core/sse_utils.hpp create mode 100644 include/opencv2/core/traits.hpp create mode 100644 include/opencv2/core/types.hpp create mode 100644 include/opencv2/core/types_c.h create mode 100644 include/opencv2/core/utility.hpp create mode 100644 include/opencv2/core/version.hpp create mode 100644 include/opencv2/core/wimage.hpp create mode 100644 include/opencv2/cvconfig.h create mode 100644 include/opencv2/features2d.hpp create mode 100644 include/opencv2/features2d/features2d.hpp create mode 100644 include/opencv2/flann.hpp create mode 100644 include/opencv2/flann/all_indices.h create mode 100644 include/opencv2/flann/allocator.h create mode 100644 include/opencv2/flann/any.h create mode 100644 include/opencv2/flann/autotuned_index.h create mode 100644 include/opencv2/flann/composite_index.h create mode 100644 include/opencv2/flann/config.h create mode 100644 include/opencv2/flann/defines.h create mode 100644 include/opencv2/flann/dist.h create mode 100644 include/opencv2/flann/dummy.h create mode 100644 include/opencv2/flann/dynamic_bitset.h create mode 100644 include/opencv2/flann/flann.hpp create mode 100644 include/opencv2/flann/flann_base.hpp create mode 100644 include/opencv2/flann/general.h create mode 100644 include/opencv2/flann/ground_truth.h create mode 100644 include/opencv2/flann/hdf5.h create mode 100644 include/opencv2/flann/heap.h create mode 100644 include/opencv2/flann/hierarchical_clustering_index.h create mode 100644 include/opencv2/flann/index_testing.h create mode 100644 include/opencv2/flann/kdtree_index.h create mode 100644 include/opencv2/flann/kdtree_single_index.h create mode 100644 include/opencv2/flann/kmeans_index.h create mode 100644 include/opencv2/flann/linear_index.h create mode 100644 include/opencv2/flann/logger.h create mode 100644 include/opencv2/flann/lsh_index.h create mode 100644 include/opencv2/flann/lsh_table.h create mode 100644 include/opencv2/flann/matrix.h create mode 100644 include/opencv2/flann/miniflann.hpp create mode 100644 include/opencv2/flann/nn_index.h create mode 100644 include/opencv2/flann/object_factory.h create mode 100644 include/opencv2/flann/params.h create mode 100644 include/opencv2/flann/random.h create mode 100644 include/opencv2/flann/result_set.h create mode 100644 include/opencv2/flann/sampling.h create mode 100644 include/opencv2/flann/saving.h create mode 100644 include/opencv2/flann/simplex_downhill.h create mode 100644 include/opencv2/flann/timer.h create mode 100644 include/opencv2/hal.hpp create mode 100644 include/opencv2/hal/defs.h create mode 100644 include/opencv2/hal/intrin.hpp create mode 100644 include/opencv2/hal/intrin_cpp.hpp create mode 100644 include/opencv2/hal/intrin_neon.hpp create mode 100644 include/opencv2/hal/intrin_sse.hpp create mode 100644 include/opencv2/highgui.hpp create mode 100644 include/opencv2/highgui/highgui.hpp create mode 100644 include/opencv2/highgui/highgui_c.h create mode 100644 include/opencv2/imgcodecs.hpp create mode 100644 include/opencv2/imgcodecs/imgcodecs.hpp create mode 100644 include/opencv2/imgcodecs/imgcodecs_c.h create mode 100644 include/opencv2/imgcodecs/ios.h create mode 100644 include/opencv2/imgproc.hpp create mode 100644 include/opencv2/imgproc/imgproc.hpp create mode 100644 include/opencv2/imgproc/imgproc_c.h create mode 100644 include/opencv2/imgproc/types_c.h create mode 100644 include/opencv2/ml.hpp create mode 100644 include/opencv2/ml/ml.hpp create mode 100644 include/opencv2/objdetect.hpp create mode 100644 include/opencv2/objdetect/detection_based_tracker.hpp create mode 100644 include/opencv2/objdetect/objdetect.hpp create mode 100644 include/opencv2/objdetect/objdetect_c.h create mode 100644 include/opencv2/opencv.hpp create mode 100644 include/opencv2/opencv_modules.hpp create mode 100644 include/opencv2/photo.hpp create mode 100644 include/opencv2/photo/cuda.hpp create mode 100644 include/opencv2/photo/photo.hpp create mode 100644 include/opencv2/photo/photo_c.h create mode 100644 include/opencv2/shape.hpp create mode 100644 include/opencv2/shape/emdL1.hpp create mode 100644 include/opencv2/shape/hist_cost.hpp create mode 100644 include/opencv2/shape/shape.hpp create mode 100644 include/opencv2/shape/shape_distance.hpp create mode 100644 include/opencv2/shape/shape_transformer.hpp create mode 100644 include/opencv2/stitching.hpp create mode 100644 include/opencv2/stitching/detail/autocalib.hpp create mode 100644 include/opencv2/stitching/detail/blenders.hpp create mode 100644 include/opencv2/stitching/detail/camera.hpp create mode 100644 include/opencv2/stitching/detail/exposure_compensate.hpp create mode 100644 include/opencv2/stitching/detail/matchers.hpp create mode 100644 include/opencv2/stitching/detail/motion_estimators.hpp create mode 100644 include/opencv2/stitching/detail/seam_finders.hpp create mode 100644 include/opencv2/stitching/detail/timelapsers.hpp create mode 100644 include/opencv2/stitching/detail/util.hpp create mode 100644 include/opencv2/stitching/detail/util_inl.hpp create mode 100644 include/opencv2/stitching/detail/warpers.hpp create mode 100644 include/opencv2/stitching/detail/warpers_inl.hpp create mode 100644 include/opencv2/stitching/warpers.hpp create mode 100644 include/opencv2/superres.hpp create mode 100644 include/opencv2/superres/optical_flow.hpp create mode 100644 include/opencv2/video.hpp create mode 100644 include/opencv2/video/background_segm.hpp create mode 100644 include/opencv2/video/tracking.hpp create mode 100644 include/opencv2/video/tracking_c.h create mode 100644 include/opencv2/video/video.hpp create mode 100644 include/opencv2/videoio.hpp create mode 100644 include/opencv2/videoio/cap_ios.h create mode 100644 include/opencv2/videoio/videoio.hpp create mode 100644 include/opencv2/videoio/videoio_c.h create mode 100644 include/opencv2/videostab.hpp create mode 100644 include/opencv2/videostab/deblurring.hpp create mode 100644 include/opencv2/videostab/fast_marching.hpp create mode 100644 include/opencv2/videostab/fast_marching_inl.hpp create mode 100644 include/opencv2/videostab/frame_source.hpp create mode 100644 include/opencv2/videostab/global_motion.hpp create mode 100644 include/opencv2/videostab/inpainting.hpp create mode 100644 include/opencv2/videostab/log.hpp create mode 100644 include/opencv2/videostab/motion_core.hpp create mode 100644 include/opencv2/videostab/motion_stabilizing.hpp create mode 100644 include/opencv2/videostab/optical_flow.hpp create mode 100644 include/opencv2/videostab/outlier_rejection.hpp create mode 100644 include/opencv2/videostab/ring_buffer.hpp create mode 100644 include/opencv2/videostab/stabilizer.hpp create mode 100644 include/opencv2/videostab/wobble_suppression.hpp create mode 100644 include/opencv2/world.hpp create mode 100644 include/platform/alloc/ialloc.h create mode 100644 include/platform/analytics/analytics.h create mode 100644 include/platform/assert/nassert.h create mode 100644 include/platform/async/async_call_queue.h create mode 100644 include/platform/async/async_call_queue_thread.h create mode 100644 include/platform/async/future.h create mode 100644 include/platform/async/job.h create mode 100644 include/platform/async/job_perf.h create mode 100644 include/platform/async/task_loop.h create mode 100644 include/platform/billing/billing.h create mode 100644 include/platform/container/container_sort.h create mode 100644 include/platform/container/mpmc_bounded_queue.h create mode 100644 include/platform/container/narray.h create mode 100644 include/platform/container/narray_list.h create mode 100644 include/platform/container/nlist.h create mode 100644 include/platform/container/nmap.h create mode 100644 include/platform/container/nstack.h create mode 100644 include/platform/container/pair.h create mode 100644 include/platform/container/smart_median_average.h create mode 100644 include/platform/filesystem/data_store.h create mode 100644 include/platform/filesystem/filesystem.h create mode 100644 include/platform/filesystem/ftp_lib.h create mode 100644 include/platform/filesystem/io_alias.h create mode 100644 include/platform/filesystem/io_base.h create mode 100644 include/platform/filesystem/io_buffer.h create mode 100644 include/platform/filesystem/io_cache.h create mode 100644 include/platform/filesystem/io_cfile.h create mode 100644 include/platform/filesystem/io_crypto.h create mode 100644 include/platform/filesystem/io_dispatcher.h create mode 100644 include/platform/filesystem/io_handle.h create mode 100644 include/platform/filesystem/io_handle_endian.h create mode 100644 include/platform/filesystem/io_handle_segment.h create mode 100644 include/platform/filesystem/io_memory.h create mode 100644 include/platform/filesystem/io_mode.h create mode 100644 include/platform/hash/md5.h create mode 100644 include/platform/hash/nsha1.h create mode 100644 include/platform/hash/sha1.h create mode 100644 include/platform/http/http_interface.h create mode 100644 include/platform/input/input_device.h create mode 100644 include/platform/input/input_keyboard.h create mode 100644 include/platform/input/input_mouse.h create mode 100644 include/platform/input/input_null.h create mode 100644 include/platform/input/input_system.h create mode 100644 include/platform/input/input_touch.h create mode 100644 include/platform/licensing/licensing.h create mode 100644 include/platform/locale/country.h create mode 100644 include/platform/log/file_log.h create mode 100644 include/platform/log/log.h create mode 100644 include/platform/log/log_scope.h create mode 100644 include/platform/math/nmath.h create mode 100644 include/platform/math/nrange.h create mode 100644 include/platform/memory/bit_field.h create mode 100644 include/platform/memory/endian.h create mode 100644 include/platform/memory/memory.h create mode 100644 include/platform/memory/nauto_ptr.h create mode 100644 include/platform/memory/nshared_ptr.h create mode 100644 include/platform/memory/nweak_ptr.h create mode 100644 include/platform/memory/ring_buffer.h create mode 100644 include/platform/memory/singleton.h create mode 100644 include/platform/messaging/messaging.h create mode 100644 include/platform/nconfig.h create mode 100644 include/platform/network/network_interface.h create mode 100644 include/platform/nstring/nstring.h create mode 100644 include/platform/ntypes.h create mode 100644 include/platform/platform.h create mode 100644 include/platform/platform_config.h create mode 100644 include/platform/rand/rand.h create mode 100644 include/platform/reflection/c_refl.h create mode 100644 include/platform/reflection/nenum_string.h create mode 100644 include/platform/shared/shared_library.h create mode 100644 include/platform/signal/signal.h create mode 100644 include/platform/social/social.h create mode 100644 include/platform/thread/atomic_value.h create mode 100644 include/platform/thread/mutex.h create mode 100644 include/platform/thread/thread.h create mode 100644 include/platform/thread/thread_controller.h create mode 100644 include/platform/thread/thread_event.h create mode 100644 include/platform/time/ntime.h create mode 100644 include/platform/time/ntime_range.h create mode 100644 include/platform/unit/nunit.h create mode 100644 include/platform/video/video_mode.h create mode 100644 include/squirrel/!!!BEFORE_YOU_UPGRADE!!!.txt create mode 100644 include/squirrel/COMPILE create mode 100644 include/squirrel/COPYRIGHT create mode 100644 include/squirrel/HISTORY create mode 100644 include/squirrel/README create mode 100644 include/squirrel/include/sqstdaux.h create mode 100644 include/squirrel/include/sqstdblob.h create mode 100644 include/squirrel/include/sqstdio.h create mode 100644 include/squirrel/include/sqstdmath.h create mode 100644 include/squirrel/include/sqstdstring.h create mode 100644 include/squirrel/include/sqstdsystem.h create mode 100644 include/squirrel/include/squirrel.h create mode 100644 include/squirrel/sqstdlib/sqstdaux.cpp create mode 100644 include/squirrel/sqstdlib/sqstdblob.cpp create mode 100644 include/squirrel/sqstdlib/sqstdblobimpl.h create mode 100644 include/squirrel/sqstdlib/sqstdio.cpp create mode 100644 include/squirrel/sqstdlib/sqstdmath.cpp create mode 100644 include/squirrel/sqstdlib/sqstdrex.cpp create mode 100644 include/squirrel/sqstdlib/sqstdstream.cpp create mode 100644 include/squirrel/sqstdlib/sqstdstream.h create mode 100644 include/squirrel/sqstdlib/sqstdstring.cpp create mode 100644 include/squirrel/sqstdlib/sqstdsystem.cpp create mode 100644 include/squirrel/squirrel/sqapi.cpp create mode 100644 include/squirrel/squirrel/sqarray.h create mode 100644 include/squirrel/squirrel/sqbaselib.cpp create mode 100644 include/squirrel/squirrel/sqclass.cpp create mode 100644 include/squirrel/squirrel/sqclass.h create mode 100644 include/squirrel/squirrel/sqclosure.h create mode 100644 include/squirrel/squirrel/sqcompiler.cpp create mode 100644 include/squirrel/squirrel/sqcompiler.h create mode 100644 include/squirrel/squirrel/sqdebug.cpp create mode 100644 include/squirrel/squirrel/sqfuncproto.h create mode 100644 include/squirrel/squirrel/sqfuncstate.cpp create mode 100644 include/squirrel/squirrel/sqfuncstate.h create mode 100644 include/squirrel/squirrel/sqlexer.cpp create mode 100644 include/squirrel/squirrel/sqlexer.h create mode 100644 include/squirrel/squirrel/sqmem.cpp create mode 100644 include/squirrel/squirrel/sqobject.cpp create mode 100644 include/squirrel/squirrel/sqobject.h create mode 100644 include/squirrel/squirrel/sqopcodes.h create mode 100644 include/squirrel/squirrel/sqpcheader.h create mode 100644 include/squirrel/squirrel/sqstate.cpp create mode 100644 include/squirrel/squirrel/sqstate.h create mode 100644 include/squirrel/squirrel/sqstring.h create mode 100644 include/squirrel/squirrel/sqtable.cpp create mode 100644 include/squirrel/squirrel/sqtable.h create mode 100644 include/squirrel/squirrel/squserdata.h create mode 100644 include/squirrel/squirrel/squtils.h create mode 100644 include/squirrel/squirrel/sqvm.cpp create mode 100644 include/squirrel/squirrel/sqvm.h create mode 100644 include/squirrel/this_is_squirrel_3.0.4Stable create mode 100644 lib/engine.lib create mode 100644 lib/extern.lib create mode 100644 lib/framework.lib create mode 100644 lib/modules.lib create mode 100644 lib/opencv_ts300.lib create mode 100644 lib/opencv_world300.lib create mode 100644 lib/platform.lib create mode 100644 source/webcam.cpp create mode 100644 source/webcam.h create mode 100644 source/webcam_binding.cpp create mode 100644 source/webcam_binding.h create mode 100644 source/webcam_decl.h create mode 100644 source/webcam_impl.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6e152ea --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.20) + +project(webcam LANGUAGES CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE) +endif() + +add_library(webcam SHARED + ./source/webcam.cpp + ./source/webcam_binding.cpp + ./source/webcam_impl.cpp +) + +# Nom de sortie +set_target_properties(webcam PROPERTIES + OUTPUT_NAME "webcam_binding" +) + +target_include_directories(webcam PRIVATE + ./include/modules + ./include/platform + ./include/engine + ./include/framework + ./include + ./include/squirrel + ./include/squirrel/include + ./source +) + +target_compile_definitions(webcam PRIVATE + __PLATFORM_WINDOWS__ + WIN32 + _USRDLL + _GS_DLL_EXPORT +) + +target_link_directories(webcam PRIVATE ./lib) + +target_link_libraries(webcam PRIVATE + modules + platform + engine + framework + opencv_world300 + opencv_ts300 + extern + + Ws2_32 + Winmm + dxguid + dinput8 + wininet + + wldap32 +) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/description.txt b/description.txt new file mode 100644 index 0000000..56db4ff --- /dev/null +++ b/description.txt @@ -0,0 +1,20 @@ +socket binding. +Thomas Simonnet + +string ip_adress +int socket port +_MEMBER_FUNCTION(SocketScriptBinding, constructor, 1, _SC(".si")) + +/*# + Func: PushMessage + Proto: void:string + Desc: send messs + #*/ +_MEMBER_FUNCTION(SocketScriptBinding, PushMessage, -1, _SC(".s")) + +/*# + Func: UpdateProcess + Proto: string:void + Desc: get messs + #*/ +_MEMBER_FUNCTION(SocketScriptBinding, UpdateProcess, -1, _SC(".")) \ No newline at end of file diff --git a/include/engine/automation/automated_property_provider.h b/include/engine/automation/automated_property_provider.h new file mode 100644 index 0000000..fec2fbc --- /dev/null +++ b/include/engine/automation/automated_property_provider.h @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __IAUTOMATEDPROPERTYPROVIDER__ +#define __IAUTOMATEDPROPERTYPROVIDER__ + + + #include "motion/motion_channel.h" + + +namespace GS { + struct Quaternion; + + namespace Automation { + +/// Automated property provider interface. +struct IPropertyProvider +{ +virtual bool GetProperty(Core::MotionChannel::Type, float &); +virtual bool SetProperty(Core::MotionChannel::Type, float); + +virtual Quaternion GetRotation() const; +virtual bool SetRotation(const Quaternion &); + +virtual ~IPropertyProvider() {} +}; + + } // Automation +} // GS + + +#endif // __IAUTOMATEDPROPERTYPROVIDER__ diff --git a/include/engine/automation/automation_player.h b/include/engine/automation/automation_player.h new file mode 100644 index 0000000..c4b8ad9 --- /dev/null +++ b/include/engine/automation/automation_player.h @@ -0,0 +1,112 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NAUTOMATIONPLAYER__ +#define __NAUTOMATIONPLAYER__ + + + #include "automation/automation_source.h" + #include "automation/automated_property_provider.h" + #include "motion/motion.h" // FIXME move to motion_group + #include "math/vector.h" + #include "memory/bit_field.h" + #include "memory/nauto_ptr.h" + #include "memory/nshared_ptr.h" + + +namespace GS { + namespace Automation { + struct SourceGroup; + + using Core::Motion; + using Core::MotionChannel; + +/*! + @short Automation player. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Player +{ +public: + +enum AddSourceMode +{ + SourceSet = 0, ///< Stop all current animation sources. + SourceAdd ///< Add a new animation source. +}; + +enum +{ + FlagRelativeMotion = 1 ///< Motion sources should be evaluated in relative mode (not absolute) +}; + +protected: + + bool active; + + SharedList motions; + SharedList sources; + + /// Only valid during evaluation. + float *weight_table; + +public: + + AutoPtr property_provider; + +/*! + @name Automation player. + @{ +*/ + BitField flags; + + /// Start an automation source. + Source *StartAutomation(Source *, float blend = Units::Sec(0.1), AddSourceMode = SourceSet, float weight = 1); + + /// Dispose of all sources. + void DisposeAutomationSources(); + + bool IsAutomated() const; + bool IsAutomationDone() const; + bool GetAutomationActive() const; + void SetAutomationActive(bool active); + + void Evaluate(const Time &dt_time); + + void BlendAutomatedProperty(MotionChannel::Type, float, float); + + /// Get animation sources. + const SharedList &GetSourceList() const { return sources; } +/// @} + +/*! + @name Motion container. + @{ +*/ + + // FIXME move to motion_group + + const SharedList &GetMotionList() const { return motions; } + + Motion *GetMotion(const char *id) const; + Motion *GetMotionFromIndex(uint index) const; + + bool AddMotion(Motion *motion); + void RemoveMotion(Motion *motion); +/// @} + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); + + Player(); + ~Player(); +}; + + } // Automation +} // GS + + +#endif // __NAUTOMATIONPLAYER__ diff --git a/include/engine/automation/automation_source.h b/include/engine/automation/automation_source.h new file mode 100644 index 0000000..0ac3efb --- /dev/null +++ b/include/engine/automation/automation_source.h @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NAUTOMATIONSOURCE__ +#define __NAUTOMATIONSOURCE__ + + + #include "geometry/curve.h" + #include "math/quaternion.h" + #include "math/vector.h" + #include "memory/nshared_ptr.h" + + +namespace GS { + namespace Automation { + class Player; + +/*! + @short Base automation source. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Source : public SharedObject +{ +public: + +enum Type +{ + TypeMotion = 0 +}; + +protected: + + Type type; + + Vector4 p_pos, + p_euler; + Quaternion p_quat; + + float weight, + weight_target, + weight_step; + + bool dispose; + +public: + + NPLACEMENT_NEW(AnimationSource) + + Time time; + float time_scale; + + bool relative; + + Type GetType() const { return type; } + +virtual void Update(const Time &dt_time); + +virtual void Evaluate(Player &target) = 0; +virtual bool EvaluateRotation(Quaternion &q) = 0; + +virtual void SetLoopMode(Curve::LoopMode = Curve::Reset) {} +virtual void SetLoop(const Time &start = Time::Inf, const Time &end = Time::Inf) {} + + /// Is animation source done. +virtual bool IsDone() const = 0; + + /// Mark the source as disposable. + void Dispose(float blend = Units::Sec(0.1)); + /// Can the source be disposed of. + bool CanDispose() const; + + void SetWeight(float _weight = 1, float _blend = Units::Sec(1)); + float GetWeight() const { return weight; } + + explicit Source(); + ~Source(); +}; + + } // Automation +} // GS + + +#endif // __NAUTOMATIONSOURCE__ diff --git a/include/engine/automation/automation_source_group.h b/include/engine/automation/automation_source_group.h new file mode 100644 index 0000000..5cfd677 --- /dev/null +++ b/include/engine/automation/automation_source_group.h @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NAUTOMATIONSOURCEGROUP__ +#define __NAUTOMATIONSOURCEGROUP__ + + + #include "automation/automation_source.h" + + +namespace GS { + namespace Automation { + +/*! + @short Automation source group. + + This is the structure holding automation sources created when starting + automations on a group of items like a hierarchy, a scene or a group of + items. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct SourceGroup +{ + NPLACEMENT_NEW(AnimationSource) + + SharedList source_list; + + /*! + @short Blend group sources weight to 0 then dispose of them. + @note The group can be deleted before the sources are disposed of. + */ + void Dispose(float blend = Units::Sec(1)); + + void SetLoopMode(Curve::LoopMode = Curve::Reset); + void SetLoop(const Time &loop_start = Time::Inf, const Time &loop_end = Time::Inf); + + void SetTime(const Time &t); + void SetTimeScale(float scale = 1); + + void SetWeight(float weight, float blend = Units::Sec(0.1)); + void SetRelative(bool relative); + + bool IsDone() const; + + /*! + @short Get time. + + Get group time using the root source. + Returns 0 if there is no source in the group. + */ + Time GetTime() const; +}; + + } // Automation +} // GS + + +#endif // __NAUTOMATIONSOURCEGROUP__ diff --git a/include/engine/core/ace.h b/include/engine/core/ace.h new file mode 100644 index 0000000..28dd061 --- /dev/null +++ b/include/engine/core/ace.h @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NACE__ +#define __NACE__ + + + #include "nstring/nstring.h" + #include "container/narray_list.h" + #include "container/nlist.h" + + +namespace GS { + namespace ACE { + class Manager; + +static const int max_command_param = 3; /// Maximum number of parameters to a command. + +#define AceCommandNop -1 ///< No operator (can be used to pause execution (ie: "Nop 1000;" will pause 1 sec)). +#define AceCommandExec -2 ///< Internal use. +#define AceCommandLoop -3 ///< Loop position. +#define AceCommandNext -4 ///< Reset PC back to the loop position (default: 0, reset script). + +/*! + @short ACE base command. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Command +{ + int code; ///< Command code. + float duration, ///< Command duration in ms. + duration_left, ///< Command duration still left to execute in ms. + parm[max_command_param]; ///< Command parameter. + + bool operator == (const Command &other) + { + if ((code != other.code) || (duration != other.duration)) + return false; + for (int n = 0; n < max_command_param; ++n) + if (parm[n] != other.parm[n]) + return false; + return true; + } + + /// Mark a command as executed in the pipeline. + void SetDone() + { duration_left = 0; } +}; + +/*! + @short ACE (Asynchronous Command Execution) unit. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Unit +{ + friend class Manager; + +protected: + + bool is_done; // this flag is raised on the next update following the last command execution + + List list; + List ::Item *pc, *loop_pc; + + /// Execute a command. +virtual bool ExecCommand(Command *cmd, float dt); + +public: + + bool IsCommandListDone() const + { return is_done; } + + void DumpCommandList(); + void ResetCommandList(); + + Unit(); +virtual ~Unit() {} +}; + +/*! + @short ACE command definition. +*/ +struct Define +{ + String id; + int code; + int nparm; +}; + +/*! + @short ACE manager. + + ACE is a mini script system that provides a way to automate + the execution of a series of actions on an object. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Manager +{ + ArrayList define_list; ///< List of defined command. + +public: + + /*! + @short Load a string command list in a unit. + @return Number of generated commands, -1 on error. + */ + int LoadACECommandList(const char *str, Unit *) const; + /// Define a new command in the manager. + bool DefineACECommand(const char *command, int code, int nparm, bool user_code = true); + /// Update a unit. + void UpdateACEUnit(Unit *, float dt); + + Manager(); +virtual ~Manager(); +}; + + } // ACE +} // GS + + +#endif // __NACE__ diff --git a/include/engine/core/cached_graphic_resource_factory.h b/include/engine/core/cached_graphic_resource_factory.h new file mode 100644 index 0000000..af072df --- /dev/null +++ b/include/engine/core/cached_graphic_resource_factory.h @@ -0,0 +1,48 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCACHEDGRAPHICRESOURCEFACTORY__ +#define __NCACHEDGRAPHICRESOURCEFACTORY__ + + + #include "core/graphic_resource_factory.h" + #include "core/geometry.h" + #include "core/emitter.h" + #include "core/shader.h" + #include "picture/pict.h" + #include "metafile/nml_object.h" + + +namespace GS { + namespace Core { + +/* + @short Cached graphic resource factory. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct CachedResourceFactory : public ResourceFactory +{ + SharedList geometries; + SharedList materials; + SharedList shaders; + SharedList particle_models; + SharedList pictures; + +virtual Picture *LoadPicture(const char *); +virtual Geometry *LoadGeometry(const char *); +virtual Material *LoadMaterial(const char *); +virtual Shader *LoadShader(const char *); +virtual ParticleModel *LoadParticleModel(const char *); + +virtual uint GetCachedResourceCount(); +virtual uint PurgeCache(); +}; + + } // Graphic +} // GS + + +#endif // __NCACHEDGRAPHICRESOURCEFACTORY__ diff --git a/include/engine/core/cached_mixer_resource_factory.h b/include/engine/core/cached_mixer_resource_factory.h new file mode 100644 index 0000000..55a1d66 --- /dev/null +++ b/include/engine/core/cached_mixer_resource_factory.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCACHEDAUDIORESOURCEFACTORY__ +#define __NCACHEDAUDIORESOURCEFACTORY__ + + + #include "core/mixer_resource_factory.h" + #include "core/sound.h" + #include "container/nlist.h" + + +namespace GS { + namespace Audio { + +/* + @short Cached audio resource factory. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct CachedResourceFactory : public ResourceFactory +{ + SharedList sounds; + +virtual Sound *LoadSound(const char *); + + CachedResourceFactory(IMixer &m) : ResourceFactory(m) {} +}; + + } // Audio +} // GS + + +#endif // __NCACHEDAUDIORESOURCEFACTORY__ diff --git a/include/engine/core/cached_renderer_resource_factory.h b/include/engine/core/cached_renderer_resource_factory.h new file mode 100644 index 0000000..ce55e0b --- /dev/null +++ b/include/engine/core/cached_renderer_resource_factory.h @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCACHEDRENDERERRESOURCEFACTORY__ +#define __NCACHEDRENDERERRESOURCEFACTORY__ + + + #include "core/renderer_resource_factory.h" + #include "container/nlist.h" + + +namespace GS { + namespace Render { + +/* + @short Cached renderer resource factory. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct CachedRendererResourceFactory : public RendererResourceFactory +{ + SharedList geometries; + SharedList materials; + SharedList textures; + SharedList shaders; + +virtual Geometry *LoadGeometry(const char *, bool bypass_cache = false, Geometry * = 0); +virtual Material *LoadMaterial(const char *, bool bypass_cache = false, Material * = 0); +virtual Texture *LoadTexture(const char *, bool bypass_cache = false, Texture * = 0); +virtual Shader *LoadShader(const char *, bool bypass_cache = false, Shader * = 0); + +virtual void ListCachedResources(); + +virtual uint GetCachedResourceCount(); +virtual uint PurgeCache(); + + CachedRendererResourceFactory(Renderer &r) : RendererResourceFactory(r) {} +}; + + } // Render +} // GS + + +#endif // __NCACHEDRENDERERRESOURCEFACTORY__ diff --git a/include/engine/core/camera.h b/include/engine/core/camera.h new file mode 100644 index 0000000..a4224fe --- /dev/null +++ b/include/engine/core/camera.h @@ -0,0 +1,152 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCAMERA__ +#define __NCAMERA__ + + + #include "core/item.h" + #include "geometry/frustum.h" + #include "geometry/rect.h" + + +namespace GS { + namespace Core { + class Light; + +/*! + @short Camera. + + - World space: + Described by the world_matrix, + transform from object space to world space.
+ - Camera space: + Described by the camera_matrix, + transform from world space to camera space.
+ - Projection matrix: + Transform from a given space (usually camera space) + to a 2D orthonormal space.
+ - View matrix: + Transform from the 2D orthonormal space + to the view (screen) space.
+ + This class is not managed, the user is responsible for freeing it. + For a managed implementation please see S3D::Scene::nMCamera. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Camera : public Item +{ +public: +/*! + @name Aspect ratio system. + + @note On a 16/9 display using a PC resolution the display is stretched + horizontally to fill the whole display area, in such case calling + using ASPECTRATIO_16_9 as the aspect ratio correction will shrink + the render to compensate for the distortion. + @{ +*/ + /// Compute the aspect ration based on the output dimensions. +#define AR_Auto (-1.f) +#define AR_Square (1.f) + +#define AR_Television (1.33f) +#define AR_Pc AR_Television +#define AR_35mm (1.37f) +#define AR_Widescreen (1.78f) +#define AR_EuropeanTheatricalStandard (1.66f) +#define AR_AmericanTheatricalStandard (1.85f) +#define AR_AnamorphicWidescreen (2.35f) + + float aspect_ratio; ///< Aspect ratio horizontal correction. + bool aspect_ratio_ref_yaxis; ///< Reference (fixed) axis for aspect ratio correction. + + /// Compute the current aspect ratio correction coefficients. + Vector4 ComputeAspectRatioCorrection(const fRect &viewport, float global_ar = 1.f) const; +/// @} + + /// Setup render object. +virtual void RenderSetup(ResourceFactories * = 0) {} + + /// Convert from world coordinate to normalized screen coordinate. + bool WorldToScreen(const fRect &viewport, const Vector4 &in, Vector4 &out, bool normalize = true); + /// Convert from normalized screen coordinate to world. + Vector4 ScreenToWorld(const fRect &viewport, float x, float y, float z = 1, float ar = -1); + + /// Compute camera projection matrix. + void ComputeProjectionMatrix(const fRect &viewport, Matrix4 &m) const; + /// Compute camera view frustum. + void ComputeFrustum(Frustum &, const fRect &viewport, float z_near = -1, float z_far = -1) const; + + /// Adjust this camera so that its viewport matches the viewport of a given light. + void AlignTo(const Light &); + + /// Compute world hierarchy matrix. +virtual void ComputeMatrix(); + + /// Get near clipping plane. + float GetNearClippingPlane() const { return z_near; } + /// Get far clipping plane. + float GetFarClippingPlane() const { return z_far; } + /// Set near clipping plane. + void SetNearClippingPlane(float z) { z_near = z; } + /// Set far clipping plane. + void SetFarClippingPlane(float z) { z_far = z; } + + /// Set the camera zoom factor, relative to z = 1 meter. + void SetZoomFactor(float zf = Units::Mtr(1.9f)); + /*! + @short Set the camera field of view. + @note FOV must be in the [Deg(0),Deg(180)[ range. + @see GetFov(). + */ + void SetFov(float fov = Units::Deg(60)); + /*! + @short Get camera fov. + + @note This value is converted on the fly from the current zoom factor. + If you need it frequently and as this class only store fov as the + zoom factor you may want to cache the fov value in your application + to avoid possible numerical drift. + */ + float GetFov() const; + + /// Set viewport (all values in range [0,1]). + void SetViewport(float origin_x, float origin_y, float width, float height); + + Frustum frustum; ///< View frustum. + float z_near; ///< Z near clipping plane. + float z_far; ///< Z far clipping plane. + + bool is_orthographic; ///< Is the camera using an orthographic projection. + float ortho_w; ///< Orthographic view width. + float ortho_h; ///< Orthographic view height. + + float zoom_factor; + + Matrix4 custom_projection; + + bool is_occulus_camera; + float tan_up, tan_down, tan_left, tan_right; + +/*! + @name Serialization. + @{ +*/ + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); +/// @} + + Camera(); +}; + + } // Core +} // GS + + +#endif //__NCAMERA__ + diff --git a/include/engine/core/clock.h b/include/engine/core/clock.h new file mode 100644 index 0000000..dfe848f --- /dev/null +++ b/include/engine/core/clock.h @@ -0,0 +1,70 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCLOCK__ +#define __NCLOCK__ + + + #include "memory/nshared_ptr.h" + #include "container/smart_median_average.h" + + +namespace GS { + namespace Core { + +/*! + @short Clock + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Clock : public SharedObject +{ + bool pause; + int fixed_delta; ///< Fixed dt (ms). + + int _gtick, gtick; ///< System's global tick counter. + int clock_scale; ///< System clock scale factor (x1000). + + int dt_clock; ///< Delta frame. + int dt_error; + + SmartMedianAverage dt_clock_filter; + +public: + + void Reset(); + void Update(); + + void Pause(bool = true); + + /// Sync to current hardware clock (skipping unaccounted dt_clock). + void EatDeltaClock(); + + float Getf() const; + float GetDeltaf() const; + + void SetScalef(float = 1.f); + float GetScalef() const; + + /// Set fixed delta clock in seconds. + void SetFixedDeltaFramef(float = -1.0); + + int GetDelta() const { return dt_clock; } + + void SetScale(int k = 1000) { clock_scale = k; } + int GetScale() const { return clock_scale; } + + int Get() const { return gtick; } + + Clock(); +}; + +typedef SharedPtr sClock; + + } // Core +} // GS + + +#endif // __NCLOCK__ diff --git a/include/engine/core/core_profiler.h b/include/engine/core/core_profiler.h new file mode 100644 index 0000000..0446465 --- /dev/null +++ b/include/engine/core/core_profiler.h @@ -0,0 +1,70 @@ +/* ----------------------------------------------------------------------------- + nEngine - GSFramework + Copyright 2001-2011 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NPROFILER_TOOLS__ +#define __NPROFILER_TOOLS__ + + + #include "color/color.h" + #include "nstring/nstring.h" + + +/*! + @short Core profiler tools. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +namespace GS { + namespace Render { + class Renderer; + class RasterFont; + } + namespace Core { + +enum NumberFormat +{ + Count, + MemorySize +}; + +template const Color &GetColorCode(const T &v, const T &warning, const T &alert) +{ + if (v > alert) + return Color::Red; + if (v > warning) + return Color::Green; + return Color::White; +} + +/// Format a value to string. +template String FormatNumber(const T &v, NumberFormat format = Count) +{ + switch (format) + { + case Count: + if (v < 1000) + return String::Format("%d", (int)v); + else if (v < 1000000) + return String::Format("%.01fK", (float)v / 1000); + return String::Format("%.01fM", (float)v / 1000000); + + case MemorySize: + if (v < 1000) + return String::Format("%dB", (int)v); + else if (v < 1000000) + return String::Format("%.01fKB", (float)v / 1000.f); + return String::Format("%.01fMB", (float)v / 1000000.f); + } + return String() << v; +} + +/// Draw allocator profiler text. +void DrawAllocProfilerText(Render::Renderer &, Render::RasterFont *[2], float &x, float &y, float width = 0, float height = 0); + + } // Core +} // GS + + +#endif // __NPROFILER_TOOLS__ diff --git a/include/engine/core/embedded_resource_extractor.h b/include/engine/core/embedded_resource_extractor.h new file mode 100644 index 0000000..4382bd8 --- /dev/null +++ b/include/engine/core/embedded_resource_extractor.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __EMBEDDEDRESOURCEEXTRACTOR__ +#define __EMBEDDEDRESOURCEEXTRACTOR__ + + + #include "core/embedded_resource_handler_interface.h" + + +namespace GS { + namespace Core { + +// +struct EmbeddedResourceExtractor : public IEmbeddedResourceHandler +{ + bool extract_to_ram; + +/* + @name Provide support for legacy embedded resources. + @{ +*/ +virtual bool ExtractEmbeddedMaterial(String &out, NML::Tag &, const char *context, int slot); +virtual bool ExtractEmbeddedShaderTree(String &out, NML::Tag &, const char *context); +/// @} + + /// Warning: Do not use ram-based extraction in production code! + EmbeddedResourceExtractor(bool extract_to_ramdisk = false); +}; + + } // Core +} // GS + + +#endif // __EMBEDDEDRESOURCEEXTRACTOR__ diff --git a/include/engine/core/embedded_resource_handler_interface.h b/include/engine/core/embedded_resource_handler_interface.h new file mode 100644 index 0000000..4e5d84e --- /dev/null +++ b/include/engine/core/embedded_resource_handler_interface.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __IEMBEDDEDRESOURCEHANDLER__ +#define __IEMBEDDEDRESOURCEHANDLER__ + + + #include "ntypes.h" + + +namespace GS { + class String; + + namespace NML { class Tag; } + namespace Core { + +// +struct IEmbeddedResourceHandler +{ +virtual bool ExtractEmbeddedMaterial(String &nUnused(out), NML::Tag &, const char *nUnused(context), int nUnused(slot)) { return false; } +virtual bool ExtractEmbeddedShaderTree(String &nUnused(out), NML::Tag &, const char *nUnused(context)) { return false; } + +virtual ~IEmbeddedResourceHandler() {} + +static IEmbeddedResourceHandler *Get(); +static void Set(IEmbeddedResourceHandler *); +}; + + } // Core +} // GS + + +#endif // __IEMBEDDEDRESOURCEHANDLER__ \ No newline at end of file diff --git a/include/engine/core/emitter.h b/include/engine/core/emitter.h new file mode 100644 index 0000000..e481b31 --- /dev/null +++ b/include/engine/core/emitter.h @@ -0,0 +1,224 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NEMITTER__ +#define __NEMITTER__ + + + #include "core/item.h" + #include "core/renderable.h" + #include "geometry/curve.h" + #include "sort/sort.h" + + +namespace GS { + namespace Core { + +/*! + @short Particle class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Particle +{ + Time time; + + Vector4 position, + velocity; + + float size; + float angle; + Color color; + +/*! + @name Parameter scaler. + @{ +*/ + float opacity_scale, + size_scale; +/// @} + + /// Is the particle alive. + bool IsAlive() const { return time.toSec() < 0 ? false : true; } + + Particle() + { opacity_scale = 1; } +}; + +/* + @short Particle model. + Models the particle attributes over its lifetime. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ParticleModel : public SharedObject +{ + struct RenderData + { + Render::sMaterial material; + }; + + String name; + String material; + + Time time_to_live; ///< Time to live. + float damping; ///< Particle velocity damping. + Vector4 gravity; ///< Particle gravity. + + Curve angle_curve, + size_curve; + + Curve red_curve, + green_curve, + blue_curve, + opacity_curve; + + AutoPtr render_data; + + /// Setup render data. + void RenderSetup(ResourceFactories * = 0); + + /*! + @short Set template color. + This function does not clear the color and opacity curves. + It only set their default value member, curves with keys will animate + as usual. + */ + void SetColor(const Color &); + /// Add color curve point. + void AddColorPoint(const Time &t, const Color &); + +/*! + @name Serialization. + @{ +*/ + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; +/// @} + + ParticleModel(); +}; + +typedef SharedPtr sParticleModel; + +/*! + @short Emitter class. + Note: Emitters emit particle along the Z axis. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Emitter : public Item, public Renderable +{ +public: + +struct RenderData +{ + sParticleModel particle_model; +}; + +enum Model +{ + Model_Spray = 0 +}; + +/*! + @name Emitter model. + @{ +*/ +protected: + + Model model; + +public: + +/*! + @name Renderable interface. + @{ +*/ + /// Compute the renderable minmax. +virtual void ComputeRenderableMinMax(MinMax &mm) { ComputeMinMax(mm); } + /// Get the renderable primitive list for this renderable. +virtual uint GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack &list, Renderable::Context context = Renderable::Context_Default, bool cull = true); +/// @} + + uint pool_size; ///< Particle pool size. + float birth_rate; ///< Rate in particle/second. + float birth_speed_min, + birth_speed_max; ///< Speed in m.s. + float spray_angle; + +/*! + @name Model scale. + @{ +*/ + float birth_rate_scale, + birth_opacity_scale, + birth_speed_scale, + birth_size_scale; +/// @} + + String particle_model; + + /// Model particle. + void ModelParticle(Particle &, const Item &, const Time &emitter_time); + + /// Get emitter model. + Model GetModel() const { return model; } + /// Set as spray emitter. + void SetSprayModel(float angle = Units::Deg(45.f)); +/// @} + + AutoPtr render_data; + +protected: + + Array particle_pool; + + uint alive_count; + bool is_seen; + + Time time; + Time birth_time; + + Array ::Entry> sort_array; + +public: + + void RenderSetup(ResourceFactories * = 0); + + bool Setup(); + void Update(const Time &dt); + void Free(); + + void ComputeMinMax(MinMax &) const; + + /// Sort emitter particles against a given view matrix. + void Sort(const Matrix4 &view_matrix); + /*! + @short Get alive particle count. + @note The emitter must have been sorted beforehand. + @see Sort(). + */ + uint GetParticleCount() const { return alive_count; } + /* + @short Get alive particle. + @note Particles are returned back to front. + */ + Particle *GetParticle(uint n) const { return n < particle_pool.GetCount() ? &particle_pool[sort_array[alive_count - 1 - n].o] : 0; } + +/*! + @name Serialization. + @{ +*/ + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; +/// @} + + Emitter(); +}; + + } // Core +} // GS + + +#endif // __NEMITTER__ diff --git a/include/engine/core/engine.h b/include/engine/core/engine.h new file mode 100644 index 0000000..79b73eb --- /dev/null +++ b/include/engine/core/engine.h @@ -0,0 +1,20 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NENGINECORE__ +#define __NENGINECORE__ + + +namespace GS { + namespace Core { + +static const char *Version = "1.5.0"; + + } // Core +} // GS + + +#endif // __NENGINECORE__ diff --git a/include/engine/core/geometry.h b/include/engine/core/geometry.h new file mode 100644 index 0000000..1305be4 --- /dev/null +++ b/include/engine/core/geometry.h @@ -0,0 +1,257 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOMETRY__ +#define __NGEOMETRY__ + + + #include "core/tangent_frame.h" + #include "geometry/bounding_box.h" + #include "color/color.h" + #include "memory/nshared_ptr.h" + #include "memory/nauto_ptr.h" + #include "memory/bit_field.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace Core { + using namespace NML; + +//------------------------------------------------------------------------------ +struct GeometrySkin +{ + float w[__PV_BONE_LIMIT__]; + ushort bone_index[__PV_BONE_LIMIT__]; +}; +struct Polygon +{ + ushort vtx_count; + ushort material; + uint *binding; +}; +struct VertexToPolygon +{ + ushort pol_count; + Array pol_index; +}; +struct PolygonVertex +{ + uint pol_index; + uint vtx_index; +}; +struct VertexToVertex +{ + ushort vtx_count; + Array vtx; +}; + +typedef Polygon * pPolygon; +//------------------------------------------------------------------------------ + +/*! + @short Geometry class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Geometry : public SharedObject +{ +public: + + NPLACEMENT_NEW(Geometry) + +/// Item flag. +enum +{ + FlagHidden = (1 << 0), + FlagNullLodProxy = (1 << 1), + FlagNullShadowProxy = (1 << 2), + + // Non-serialized. + FlagNoMaterialCache = (1 << 3) +}; + +private: + + /// Low-level vertex properties comparison. + char VertexPropertiesCompare(uint, uint, uint, uint, uint); + +/*! + @name Serialization + @{ +*/ + void ParseVertex(const Tag *); + void ParseAsciiVertex(const Tag *); + void ParseSkin(const Tag *); + void ParsePolygon(const Tag *); + void ParseAsciiPolygon(const Tag *); + void ParsePolygonNormal(const Tag *); + void ParseVertexNormal(const Tag *); + void ParseVertexTangent(const Tag *); + void ParseRGB(const Tag *); + void ParseAsciiRGB(const Tag *); + void ParseUV(const Tag *); + void ParseAsciiUV(const Tag *); + void ParseMaterials(const Tag *); + + void ParseMisc(const Tag &); +/// @} + +public: + + String name; + BitField flag; + + String copy_lock; ///< Used to prevent publishing. + +/*! + @name Proxies. + @{ +*/ + String lod_proxy; ///< LOD proxy geometry. + float lod_distance; ///< LOD distance. + + String shadow_proxy; ///< Shadow proxy geometry. +/// @} + + /// Return the number of triangles in the mesh. Note: this does not perform any conversion. + uint GetTriangleCount() const + { + uint n, c = 0; + for (n = 0; n < pol.GetCount(); ++n) + if (pol[n].vtx_count >= 3) + c += pol[n].vtx_count - 2; + return c; + } + + /*! + @short Flag vertices sharing the same properties as homogeneous. + + All vertices attributes are checked and compared. If they all lie + under a given threshold then the vertex is reported as homogeneous. + This function is heavily used by the geometry stripper and triangle + list builder. + + @param material_index Optionally restrict attribute comparison + to one material only. + (default: -1 to include all materials in + the geometry.) + */ + void FlagHomogeneousVertex(Array &flag, const Array &polygon_index, const Array &, int material_index = -1) const; + +/*! + @name Topology section. + @{ +*/ + /// Compute the geometry min-max from current vertex set (AABB). + MinMax ComputeMinMax(const Matrix4 * = 0) const; + /// Compute geometry bones bounding volumes. + bool ComputeBoneBoundingVolumes(Array &) const; + + Array vtx, vtx_normal; + Array vtx_tangent; + Array rgb; + Array uv[__UV_PER_GEOMETRY__]; + + /// Return the number of UV channels used by the geometry. + uint GetUVCount() const; + + Array pol; + Array binding; + + bool AllocateVertex(uint); + bool AllocatePolygon(uint); + + /// Allocate polygon binding array. + bool AllocatePolygonBinding(); + /// Compute polygon binding count. + uint ComputePolygonBindingCount() const; +/// @} + +/*! + @name Skinning section. + @{ +*/ + /// Allocate bones array (not the skin weights array). + bool AllocateBone(uint); + /// Return the number of bones referenced by the geometry. + uint GetBoneCount() const; + + Array bone_name; + Array bone_bind_matrix; + + Array skin; ///< Skin weights. +/// @} + + Array pol_normal; + Array pol_tangent; + + bool ComputePolygonNormal(bool force = false); + bool ComputePolygonTangent(uint uv_index = 0, bool force = false); + + bool ComputeVertexNormal(float msa = -1.f, bool force = false); + bool ComputeVertexNormal(Array &, float msa = -1.f); + bool ComputeVertexTangent(bool reverse_t = false, bool reverse_b = false, bool force = false); + +/*! + @name Geometry tools. + @{ +*/ + /// Compute polygon start index. + void ComputePolygonIndex(Array &) const; + /// Compute vertex to polygon table. + void ComputeVertexToPolygon(Array &) const; + /// Compute vertex to vertex table. + void ComputeVertexToVertex(Array &, const Array * = 0) const; +/// @} + + void SmoothRGB(uint pass_count, float max_smooth_angle); + void FreeRGB(); + + void FreeUV(); + +/*! + @name Material section. + @{ +*/ + struct MaterialSlot + { + String name; + bool use_cache; + + MaterialSlot() : use_cache(true) {} + }; + + Array material_table; + + /// Merge duplicate materials in table. + uint MergeDuplicateMaterials(); +/// @} + + void Free(); + +/*! + @name Serialization. + @{ +*/ + bool FromMetaTag(const Tag &); + Tag *AsMetaTag() const; +/// @} + + Geometry(); +virtual ~Geometry(); +}; + + /// Compute the minmax of a vertex array. +extern bool ComputeVertexArrayMinMax(const Array &, MinMax &, const Matrix4 * = 0); + +typedef SharedPtr sGeometry; +typedef Geometry * pGeometry; + + } // Core +} // GS + + +#endif // __NGEOMETRY__ diff --git a/include/engine/core/geometry_bih.h b/include/engine/core/geometry_bih.h new file mode 100644 index 0000000..57077e4 --- /dev/null +++ b/include/engine/core/geometry_bih.h @@ -0,0 +1,99 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOMETRYBIH__ +#define __NGEOMETRYBIH__ + + + #include "bih/bih.h" + #include "core/shader_tree.h" + #include "core/material.h" + #include "core/geometry.h" + #include "core/geometry_tree.h" + + +namespace GS { + namespace Core { + struct ResourceFactory; + +/// BIH ray/triangle intersection acceleration structure. +struct GeometryBIHAccel +{ + char cu, cv; + Array k; + float d; +}; + +struct GeometryBIHMaterial +{ + sMaterial material; + sShaderTree shader_tree; +}; + +/* + @short Geometry polygon bounding interval hierarchy. + + Raytracing/intersection acceleration structure theoretically + performing within 70% of the SAH/KD-Tree performances. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class GeometryBIH : public IGeometryTree, public BIH::Tree +{ + Array material_table; ///< Material table. + Array pol_index; + + Array acc; ///< Raytracing lookup tables. + + /// Trace leaf content. + void TraceLeaf(BIH::Node *leaf, float tmin, float tmax, BIH::Trace &trace, void *parm = 0); + /// Build raytracing lookup tables. + bool BuildLUT(); + +public: + + /// Return the raytracing LUT structure. + const GeometryBIHAccel *GetRaytracingAccelerationStructure() const { return acc; } + + /// Fast polygon test. + bool FastPolyTest(uint ip, Vector4 &s, Vector4 &d, float l = -1.f); + + void RaytraceGeometry(GeometryTrace &trace, const Vector4 &s, const Vector4 &d, float l = -1.f); + bool BuildFromGeometry(ResourceFactory &, Geometry *); + void Free(); +}; + +/*! + @short Geometry BIH tree. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class GeometryBIHTree : public IGeometryTree +{ + GeometryBIH bih; + +public: + +/*! + @name Interface core functions. + @{ +*/ + /// Raytrace the geometry tree. + void RaytraceGeometry(GeometryTrace &trace, const Vector4 &s, const Vector4 &d, float l = -1.f) { bih.RaytraceGeometry(trace, s, d, l); } + /// Build tree from a geometry. + bool BuildFromGeometry(ResourceFactory &gf, Geometry *g) { return bih.BuildFromGeometry(gf, g); } + /// Free all internal structures. + void Free() { bih.Free(); } +/// @} + + ~GeometryBIHTree() + { Free(); } +}; + + } // Core +} // GS + + +#endif // __NGEOMETRYBIH__ diff --git a/include/engine/core/geometry_kdtree.h b/include/engine/core/geometry_kdtree.h new file mode 100644 index 0000000..f9defb2 --- /dev/null +++ b/include/engine/core/geometry_kdtree.h @@ -0,0 +1,126 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOMETRYKDTREE__ +#define __NGEOMETRYKDTREE__ + + + #include "core/geometry_tree.h" + #include "container/narray.h" + #include "container/nlist.h" + + +namespace GS { + namespace Core { + class Geometry; + +/*! + @short Geometry polygon KD-tree. + @author Thomas Simonnet (thomas@movida-mail.com) +*/ +class GeometryKDTree : public IGeometryTree +{ +private: + + Array material_table; + Array pol_index; + + struct KDTreeNode + { + char m_KDTREE_NODE_TYPE_SPLIT; + int m_KDTREE_NODE_ID_ROPE[6]; + float m_KDTREE_NODE_AABB[6]; + float m_KDTREE_NODE_VALUE_SPLIT; + int m_KDTREE_NODE_ID; + int m_KDTREE_NODE_ID_CHILD_LEFT; + int m_KDTREE_NODE_ID_CHILD_RIGHT; + bool m_KDTREE_NODE_IS_LEAF; + int m_KDTREE_NODE_COUNT_POLY; + int* m_KDTREE_NODE_ID_VTX; + int* m_KDTREE_NODE_ID_POLY; + + KDTreeNode(); + ~KDTreeNode(){delete []m_KDTREE_NODE_ID_POLY; delete []m_KDTREE_NODE_ID_VTX;}; + }; + /*#define KDTREE_NODE_TYPE_SPLIT 0 + #define KDTREE_NODE_ID_ROPE 1 + #define KDTREE_NODE_AABB 25 + #define KDTREE_NODE_VALUE_SPLIT 49 + #define KDTREE_NODE_ID 53 + #define KDTREE_NODE_ID_CHILD_LEFT 57 + #define KDTREE_NODE_ID_CHILD_RIGHT 61 + #define KDTREE_NODE_IS_LEAF 65 + #define KDTREE_NODE_COUNT_POLY 66 + #define KDTREE_NODE_ID_POLY 70 +*/ + #define KDTREE_X_AXIS 0 + #define KDTREE_Y_AXIS 1 + #define KDTREE_Z_AXIS 2 + + #define KDTREE_SIDE_LEFT 0 + #define KDTREE_SIDE_RIGHT 1 + #define KDTREE_SIDE_BOTTOM 2 + #define KDTREE_SIDE_TOP 3 + #define KDTREE_SIDE_BACK 4 + #define KDTREE_SIDE_FRONT 5 + + int m_count_bih; + float * m_TempFloatBih; + + List m_ArrayCountPoly; + List m_PointerGeo; + + KDTreeNode* m_NodeTree; + int m_SizeTree; + + int* m_RealIdPoly; + + float* m_Vtx; + Vector4* m_OptimizeEdgePoly; + +protected: + + int planeBoxOverlap(float normal[3], float vert[3], float maxbox[3]); + int triBoxOverlap(float boxcenter[3],float boxhalfsize[3],float Verts1[3],float Verts2[3],float Verts3[3]); + int GetKDtreeSideAABB(float* _AABB, Vector4 &_EntryPoint, int &_LastEntrySide); + bool IntersectTriangle(const Vector4 &s, const Vector4 &d, float* Vtx1, float* Vtx2, float* Vtx3, Vector4* _Edge1, Vector4* _Edge2, float &l_Dist, float &u, float &v, bool& _Backface); + bool AABBIntersectRay(float* _AABB, const Vector4 &o, const Vector4 &d, float &tmin, float &tmax); + void CreateRope(int &_CurrentNode, int *_RopeArray); + void IncreaseSizeNodeKdtreeBuffer(int _IncreaseSize); + void CreateNodeKdtree(int &_CurrentNode, int *_IdPoly, int *_IdVtx, int _CountPoly, float *_Vtx, int _CountVtx, int _CurrentDepth); + +public: + +/*! + @name KD-Tree specific functions. + @{ +*/ + /// Retrieve the index of the closest KD-tree node to a given location in world space. + int InsideKdTreeNode(const Vector4 &p, bool CheckInside=false); +/// @} + +/*! + @name Interface core functions. + @{ +*/ + /// Raytrace the geometry tree. +virtual void RaytraceGeometry(GeometryTrace &trace, const Vector4 &s, const Vector4 &d, float l = -1.f); + /// Build tree from a geometry. +virtual bool BuildFromGeometry(ResourceFactory &gf, Geometry *geo); + /// Free all internal structures. +virtual void Free(); +/// @} + + GeometryKDTree(); + ~GeometryKDTree() + { Free(); } +}; + + } // Core +} // GS + + +#endif // __NGEOMETRYKDTREE__ diff --git a/include/engine/core/geometry_reducer.h b/include/engine/core/geometry_reducer.h new file mode 100644 index 0000000..1d0b217 --- /dev/null +++ b/include/engine/core/geometry_reducer.h @@ -0,0 +1,120 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOREDUCER__ +#define __NGEOREDUCER__ + + + #include "math/vector.h" + + +namespace GS { + namespace Core { + class Geometry; + +struct nLLEDGE +{ + uint a, b; + nLLEDGE *p, *n; +}; + +struct nEENTRY +{ + nLLEDGE *edge; + nEENTRY *n; +}; + +typedef nEENTRY * pnEENTRY; + +class nEDGELIST +{ +public: + + pnEENTRY *lut; + nLLEDGE *root; + uint vtx_count, nedg; + + void SetVertexCount(uint); + void Add(uint, uint); + void Remove(nLLEDGE *); + void RemapEdges(uint, uint); + nLLEDGE *GetEdge(uint, uint); + + nEDGELIST (); + ~nEDGELIST (); +}; + +class nLLTRI +{ +public: + + uint a, b, c; + ushort m; + Vector4 normal; + nLLTRI *p, *n; + + char UseVertex(uint); + void ReplaceVertex(uint, uint); +}; + +struct nTENTRY +{ + nLLTRI *tri; + nTENTRY *n; +}; + +typedef nTENTRY * pnTENTRY; + +class nLTRILIST +{ +public: + + pnTENTRY *lut; + nLLTRI *root; + Geometry *sg; + + void SetGeo(Geometry *); + nLLTRI *Add(uint, uint, uint); + void ReplaceVertex(uint, uint); + void AddTriToVertex(nLLTRI *, uint); + void RemoveTriFromVertex(nLLTRI *t, uint v); + void Remove(nLLTRI *); + void ComputeNormal(nLLTRI *); + + uint ntri; + + nLTRILIST (); + ~nLTRILIST (); +}; + +struct nLVERTEX +{ + char active, locked; + float cost; + uint tgtcollapse; +}; + +class GeometryReducer +{ +public: + + nEDGELIST elist; + nLTRILIST tlist; + nLVERTEX *vlist; + + nLVERTEX *AddVertex(uint v); + void RemoveVertex(uint v); + void ComputeVertexCost(Geometry *, uint); + float ComputeEdgeCost(Geometry *, nLLEDGE *); + Geometry *Reduce(Geometry *, float k); + char IsBorder(uint v); +}; + + } // Core +} // GS + + +#endif // __NGEOREDUCER__ \ No newline at end of file diff --git a/include/engine/core/geometry_template.h b/include/engine/core/geometry_template.h new file mode 100644 index 0000000..c2529b5 --- /dev/null +++ b/include/engine/core/geometry_template.h @@ -0,0 +1,91 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOMETRYTEMPLATE__ +#define __NGEOMETRYTEMPLATE__ + + + #include "core/geometry.h" + #include "container/nlist.h" + + +namespace GS { + namespace Core { + +/*! + @short Geometry template class. + @author Thomas Simonnet (scorpheus) + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class GeometryTemplate +{ + /// Polygon template. +struct Polygon +{ + List vertex; + List normal; + List color; + List uv[__UV_PER_GEOMETRY__]; + ushort material; +}; + + /// Polygon vertex. +struct PolygonVertex +{ + uint ipoly; + uint ivertex; +}; + + Vector4 GetVertex(const PolygonVertex &); + Vector4 GetNormal(const PolygonVertex &); + Vector2 GetUV(uint channel, const PolygonVertex &); + Color GetColor(const Color &); + + float merge_threshold; + + AutoPtr polygon; + AutoList polygons; + List materials; + +public: + +/*! + @name Polygon declaration. + @{ +*/ + void Clear(); + void BeginPolygon(); + + void PushVertex(const Vector4 &); + void PushNormal(const Vector4 &); + void PushUV(uint channel, const Vector2 &); + void PushColor(const Color &); + + void EndPolygon(ushort material_index); +/*! + @} + @name Material table declaration. + @{ +*/ + void ClearMaterials(); + void PushMaterial(const char *uri); +/// @} + + /// Set the vertex merge threshold. + void SetVertexMergeThreshold(float threshold) + { merge_threshold = threshold; } + + /// Instantiate the current template description. + Geometry *Instantiate(const char *name); + + GeometryTemplate(); +}; + + } // Core +} // GS + + +#endif // __NGEOMETRYTEMPLATE__ diff --git a/include/engine/core/geometry_to_triangle_list.h b/include/engine/core/geometry_to_triangle_list.h new file mode 100644 index 0000000..afdc54c --- /dev/null +++ b/include/engine/core/geometry_to_triangle_list.h @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GEOMETRYTOTRIANGLELIST__ +#define __GEOMETRYTOTRIANGLELIST__ + + + #include "ntypes.h" + #include "container/nlist.h" + + +namespace GS { + namespace Core { + class Geometry; + struct Trilist; + +/*! + @short Geometry to triangle list conversion object. + + Takes and convert the original polygonal representation of a geometry into a + list of triangle list. + Each triangle list contains the same buffers as a polygonal geometry + (vertex, normal, UV, etc...) in the same organization and an index buffer. + + Care is taken not to duplicate homogeneous vertices (sharing the same + properties). Triangle lists are always split by material so there is never + more than one material per list. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ + namespace GeometryToTriangleList { + +/*! + @short Convert a polygonal geometry to a triangle list representation. + + @note You can specify the maximum of triangles per triangle list to + this function, the function guarantees that this number is + not exceeded (this is used by some renderer when there is + a limit on the index data type size). + + @note The limit is expressed in number of triangles. + So to limit a triangle list to 65536 index you should limit + the number of triangles to 21845 or 65536/3! + + @note You can optionally call the triangle list optimization function + by passing a non zero positive value to the optimize_cache + parameter. + @see Optimize(). +*/ +bool Convert(const Geometry &, AutoList &, uint max_tri_per_list = 16384, uint vtx_cache_size = 16); + + } // GeometryToTriangleList + } // Core +} // GS + + +#endif // __GEOMETRYTOTRIANGLELIST__ diff --git a/include/engine/core/geometry_tree.h b/include/engine/core/geometry_tree.h new file mode 100644 index 0000000..1a54191 --- /dev/null +++ b/include/engine/core/geometry_tree.h @@ -0,0 +1,100 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOTREE__ +#define __NGEOTREE__ + + + #include "core/graphic_resource_factory.h" + #include "core/geometry.h" + #include "math/vector.h" + + +namespace GS { + namespace Core { + +struct GeometryTraceBase +{ + Geometry *g; + + float i_t; ///< Distance to intersection from ray's origin. + bool backface; ///< Hit is on the back face of the polygon. + + int ip; ///< Polygon index. + uint it; ///< Triangle index in polygon. + uint bi; ///< Polygon binding start index. + float u, v, w; ///< Barycentric coordinates. + + Material *m; + ShaderTree *st; +}; + +// Raytrace result. +struct GeometryTrace : public GeometryTraceBase +{ + Vector4 s; ///< Ray origin. + Vector4 d; ///< Ray direction. + + bool want_closest; + bool has_i; ///< Do we have an intersection. + + uint node_visited; ///< Number of nodes visited. + uint tri_test; ///< Number of triangle tested. + + GeometryTrace(bool closest = true) + { + want_closest = closest; + has_i = false; + + node_visited = 0; + tri_test = 0; + } +}; + +/*! + @short Geometry abstract tree. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class IGeometryTree +{ +protected: + + sGeometry geometry; + +public: + + Geometry *GetGeometry() const { return geometry; } + + /*! + @short Specify a fixed ray origin. + + This function provides the tree implementation with an optimization + opportunity by specifying a fixed ray origin. + + @note Pass NULL to remove hint. + */ +virtual void SetRayOriginHint(const Vector4 *) {} + +/*! + @name Interface core functions. + @{ +*/ + /// Raytrace the geometry tree. +virtual void RaytraceGeometry(GeometryTrace &, const Vector4 &s, const Vector4 &d, float length = -1.f) = 0; + /// Build tree from a geometry. +virtual bool BuildFromGeometry(ResourceFactory &, Geometry *) = 0; + /// Free all internal structures. +virtual void Free() = 0; +/// @} + +virtual ~IGeometryTree() {} +}; + + } // Core +} // GS + + +#endif // __NGEOTREE__ diff --git a/include/engine/core/graphic_resource_factory.h b/include/engine/core/graphic_resource_factory.h new file mode 100644 index 0000000..3a6db03 --- /dev/null +++ b/include/engine/core/graphic_resource_factory.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCORERESOURCEFACTORY__ +#define __NCORERESOURCEFACTORY__ + + + #include "ntypes.h" + #include "core/resource_factory_event_interface.h" + + +namespace GS { + class Picture; + + typedef SharedPtr sPicture; + + namespace Core { + class Geometry; + class ShaderTree; + struct ParticleModel; + struct Material; + struct Shader; + +/* + @short Core resource factory. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ResourceFactory +{ + sIResourceFactoryEvent event_handler; + +virtual Picture *LoadPicture(const char *) = 0; +virtual Geometry *LoadGeometry(const char *) = 0; +virtual Material *LoadMaterial(const char *) = 0; +virtual Shader *LoadShader(const char *) = 0; +virtual ParticleModel *LoadParticleModel(const char *) = 0; + +virtual uint GetCachedResourceCount() { return 0; } +virtual uint PurgeCache() { return 0; } + + ResourceFactory() : event_handler(new IResourceFactoryEvent) {} +virtual ~ResourceFactory() {} +}; + +typedef SharedPtr sGeometry; +typedef SharedPtr sMaterial; +typedef SharedPtr sShader; +typedef SharedPtr sParticleModel; + + } // Core +} // GS + + +#endif // __NCORERESOURCEFACTORY__ diff --git a/include/engine/core/iso_surface.h b/include/engine/core/iso_surface.h new file mode 100644 index 0000000..8bac859 --- /dev/null +++ b/include/engine/core/iso_surface.h @@ -0,0 +1,123 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NISOSURFACE__ +#define __NISOSURFACE__ + + + #include "math/vector.h" + #include "thread/mutex.h" + + +namespace GS { + namespace Core { + class Geometry; + +/*! + @short Isosurface. + @author Thomas Simonnet (scorpheus@hotmail.com) +*/ +class Isosurface +{ +private: + + static const int EdgeArray[256]; + static const int TriTable[256][16]; + + Vector4 m_Pos; + + // grid definition + Vector4 m_NbGridCase; + float *m_Grid; + Vector4 m_GridSize; + + float m_IsoValue; + + // to know on which point of the grid we have to create a triangle + Vector4 * m_TabIndexValid; + int m_NbIndexValid; + + // to precalculate + Vector4 m_CaseSizeDivNbCase; + + + struct STriangle + { + Vector4 m_Vertex[3]; // the 3 vertex of the triangle + int m_Num[3]; // number of the side who have each vertex + }; + + struct TVertex + { + float x, y, z; // Position + float nx, ny, nz; // Normal + float u, v; // UV coordinate + unsigned long Color; // Color + + TVertex(){x=y=z=nx=ny=u=0; nz=v=1; Color =0xFF19E395;}; + }; + + inline void CalcNormalX(float &_x, float &_y, float &_z, Vector4 &_Normal); + inline void CalcNormalY(float &_x, float &_y, float &_z, Vector4 &_Normal); + inline void CalcNormalZ(float &_x, float &_y, float &_z, Vector4 &_Normal); + + // function permit to linear interpolate between vector + void interpolateVect(Vector4 &_Vect1, Vector4 &_Vect2, float &_Val1, float &_Val2, Vector4&_Vect); + + // function permit to linear interpolate between val + float interpolateVal(float &_Val1, float &_Val2, float _Val_cible1, float _Val_cible2); + + // Set the value of the vertex + void EvalPos(float &_x, float &_y, float &_z, Vector4 &_CasePosition); + + // return the good float with the 3d parameter in the grid + int GridIndex(float &_x, float &_y, float &_z)const; + + /// calcul the polygon for one case, and return the number of triangle for the polygon + int CalculPolygon(float &_x, float &_y, float &_z, STriangle* _TriangleList); + + // draw the triangle in the cellule x,y, z + void RenderCell(uint &vtx_count, float &_x, float &_y, float &_z); + + // compute the metaball array to fill the grid with ball + void ComputeMetaball(int nb_metaball, Vector4* pos_metaball, float* value_metaball); + + Threading::Mutex m_Mutex; + +public: + + //max vertex to build the mesh + static uint m_MaxNbVertex; + + // temp for build the mesh + static int m_MaxIdx; + int m_CountIdxBuffer; + static int* m_TempIdxBuffer ; // index buffer containing the geometry + + // temp for build the mesh + static TVertex* m_TempVertexBuffer ; // Vertex buffer containing the geometry + + /// Initialize the iso-surface field + bool Init(const Vector4 &_pos, const Vector4 &size, const Vector4 &step); + + /// Get the iso-surface field size + void GetFieldSize(int &x, int &y, int &z); + + /// Get the iso-surface field + void GetField(float *_Grid); + + /// Triangularize the iso-surface + void Triangularize(Geometry* geometry, int nb_metaball, Vector4* pos_metaball, float* value_metaball); + + Isosurface(); +virtual ~Isosurface(); +}; + + } // Core +} // GS + + +#endif // __NISOSURFACE__ diff --git a/include/engine/core/item.h b/include/engine/core/item.h new file mode 100644 index 0000000..aa22ea0 --- /dev/null +++ b/include/engine/core/item.h @@ -0,0 +1,177 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NITEM__ +#define __NITEM__ + + + #include "math/matrix3.h" + #include "math/matrix4.h" + #include "math/quaternion.h" + #include "data/registry.h" + #include "memory/bit_field.h" + + +namespace GS { + class MinMax; + class Frustum; + + namespace Core { + struct ResourceFactories; + class Item; + + typedef List ItemList; + +/*! + @short Common properties to light/object and camera. + + This class describe a location and orientation in space. + The position is described as a vector. + @see nVector. + + Items can be parented to form a hierarchy where each child inherits its + parent transformation. + @see SetParent(). + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Item +{ +public: + +#define ItemFlagNone 0 + +#define ItemFlagHasTarget (1 << 0) +#define ItemFlagInvisible (1 << 1) +#define ItemFlagInheritPositionOnly (1 << 2) + +#define ItemFlagLocalMatrixDirty (1 << 3) +#define ItemFlagWorldMatrixDirty (1 << 4) +#define ItemFlagInverseWorldMatrixDirty (1 << 5) +#define ItemFlagRotationMatrixDirty (1 << 6) + +#define ItemFlagBoneHint (1 << 16) + +private: + + Math::rOrder rorder; ///< Euler rotation order. + Vector4 position, ///< Position. + rotation, ///< Orientation as 3 Euler angles. + scale; ///< Scale. + + Matrix3 rotation_matrix; + +protected: + + Item *parent; ///< Parent item. The item will inherit all of its parent motion. + ItemList children; + + Matrix4 local_matrix, ///< Local matrix. + prv_matrix, ///< Previous world matrix. + matrix, ///< World matrix. + imatrix; ///< Inverse world matrix. + Matrix4 pivot_matrix; ///< Offset matrix. + + /// Compute world local matrix. + void ComputeLocalMatrix(); + /// Compute world hierarchy matrix. +virtual void ComputeMatrix(); + /// Compute world inverse matrix. + void ComputeInverseMatrix(); + +public: + + NPLACEMENT_NEW(Item3d) + + Registry registry; + +virtual void SetParent(Item * = 0); + const ItemList &GetChildren() const { return children; } + Item *GetParent() const { return parent; } + + void MarkTransformationDirty(bool children_only = false); + void MarkWorldTransformationDirty(); + + const Vector4 &GetPosition() const; + void SetPosition(const Vector4 &); + + void SetRotation(const Vector4 &); + void SetRotation(const Quaternion &); + void SetRotation(const Matrix3 &); + const Vector4 &GetRotation() const; + + void SetScale(const Vector4 &); + const Vector4 &GetScale() const; + + void SetPivot(const Matrix4 &); + const Matrix4 &GetPivot() const; + + Matrix4 GetMatrixNoPivot(); + void SetMatrix(const Matrix4 &); + + const Matrix4 &GetPreviousMatrix() const; + void SetPreviousMatrix(const Matrix4 &); + const Matrix4 &GetLocalMatrix(); + + const Matrix4 &GetMatrix(); + const Matrix4 &GetMatrix() const { return matrix; } + + const Matrix4 &GetInverseMatrix(); + const Matrix4 &GetInverseMatrix() const { return imatrix; } + + const Matrix3 &GetRotationMatrix(); + const Matrix3 &GetRotationMatrix() const { return rotation_matrix; } + + BitField item_flags; + Vector4 target; ///< Target position. + + /// Is this item linked to a given item? + bool IsLinkedTo(Item *); + + /// Set item position in world space (taking account of parent transformations). + void OffsetWorldPosition(const Vector4 &); + + /// Transfer a 4x4 matrix to item position/scale and rotation components. + void SnapshotTransformation(const Matrix4 &, bool parent_space = false, bool only_matrix = false); + + /*! + @short Set item target location. + + @note When a target location exists the item align its local Z + axis (0,0,1} so that it always point towards the target + location. + */ + void SetTarget(const Vector4 * = 0); + void SetTarget(const Vector4 &v) { SetTarget(&v); } + Vector4 GetTarget() { return target; } + + float opacity; ///< Item opacity. + + void SetRotationOrder(Math::rOrder); + Math::rOrder GetRotationOrder() const { return rorder; } + + /// Compute the item axis-aligned bounding box. +virtual void ComputeLocalMinMax(MinMax &) const; + + void *mitem; ///< Managed item. + + /// Setup item render data. +virtual void RenderSetup(ResourceFactories * = 0) = 0; + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + Item(); +virtual ~Item(); +}; + +typedef Item * pItem; + + } // Core +} // GS + + +#endif // __NITEM__ diff --git a/include/engine/core/light.h b/include/engine/core/light.h new file mode 100644 index 0000000..487f67e --- /dev/null +++ b/include/engine/core/light.h @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NLIGHT__ +#define __NLIGHT__ + + + #include "core/item.h" + #include "core/render_data.h" + #include "color/color.h" + #include "geometry/frustum.h" + #include "reflection/nenum_string.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace Core { + +/*! + @short Light. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Light : public Item +{ +public: + +/// +struct RenderData +{ + Render::sTexture projection_texture; + + struct ShadowRenderData + { + virtual ~ShadowRenderData() {} + }; + + /// Shadow data. + struct ShadowData + { + AutoPtr render_data; + + float slice_distance; + Vector4 crop_region; + + Matrix4 imatrix, pmatrix; + }; + + Array shadow_data; +}; + +static Reflection::Property serializable[]; + + /// Light model. +enum Model +{ + Model_None = 0, + + Model_Point, + Model_Linear, + Model_Spot, + + Model_Last +}; +static Reflection::Enum::Dict model_dict[]; + + /// Light falloff. +enum Falloff +{ + Falloff_Linear = 0, ///< Linear. + Falloff_InvDist, ///< Inverse distance. + Falloff_InvDist2 ///< Inverse squared distance. +}; +static Reflection::Enum::Dict falloff_dict[]; + + /// Light shadow method. +enum Shadow +{ + Shadow_None = 0, + Shadow_ProjectionMap, + Shadow_Map +}; +static Reflection::Enum::Dict shadow_dict[]; + + Model model; + Frustum frustum; + +/*! + @name Shadow section. + @{ +*/ + Shadow shadow; + bool shadow_cast_all; + float shadow_range, + shadow_bias, + shadow_distribution, + z_near; +/// @} + +/*! + @name Volumetric section. + @{ +*/ + bool volumetric; + float volumetric_sample_step, + volumetric_range, + volumetric_thickness; +/// @} + +/*! + @name Light section. + @{ +*/ + Falloff falloff; + + float range, + volume_range, ///< Volume range (mainly used as an optimization hint). + clip_distance; + + Color diffuse_color, + specular_color, + shadow_color; + + float diffuse_intensity, + specular_intensity, + cone_angle, + edge_angle; + + String projection_texture; ///< Projection texture. +/// @} + + /// Set the spot cone and edge angles. + void SetSpotAngle(float cone = Units::Deg(40), float edge = Units::Deg(10)) + { + cone_angle = cone; + edge_angle = edge; + } + + /// Sample lighting contributed by this light to a location in space. + bool SampleColor(const Vector4 &p, const Vector4 &n, Color &diff, Color &spec, Vector4 *view = 0, float gloss = 0.8); + /*! + @short Sample energy this light contribute to a location in space. + + This function can sample both the diffuse and specular lightning + contribution from a given light to a given position in space. + You can specify whether the specular should be computed using + accurate Phong model or using the halfway vector (faster/less + accurate). + You can ask that specular reflection be evaluated using the + Cook-Torrance model by calling the function with the parameter + 'cooktorrance' set to true. The default specular reflection uses + the Phong model. + + @note The default specular model used is the halfway vector one. + @note Sampling the specular contribution requires a view vector + and a glossiness value. + + @return True if the light contribute to the surface. + */ + bool SampleEnergy(const Vector4 &p,const Vector4 &n, float *diff = 0, float *spec = 0, Vector4 *view = 0, float gloss = 0.8, bool halfway = false, bool cooktorrance = false); + +virtual void ComputeMatrix(); + void ComputeProjectionMatrix(Matrix4 &m_) const; + void ComputeFrustrum(Frustum &f, float z_near = -1, float z_far = -1) const; + + float GetNearClippingPlane() const { return z_near; } + float GetFarClippingPlane() const { return volume_range; } + void SetNearClippingPlane(float z) { z_near = z; } + void SetFarClippingPlane(float z) { volume_range = z; } + + void RenderSetup(ResourceFactories * = 0); + + AutoPtr render_data; + + void SetDefaults(); + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); + + Light(); +}; + +typedef Light * pLight; + + } // Core +} // GS + + +#endif // __NLIGHT__ diff --git a/include/engine/core/material.h b/include/engine/core/material.h new file mode 100644 index 0000000..075ed90 --- /dev/null +++ b/include/engine/core/material.h @@ -0,0 +1,184 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMATERIAL__ +#define __NMATERIAL__ + + +#include "core/material_channel.h" +#include "core/physic_material.h" +#include "math/matrix4.h" +#include "color/color.h" +#include "memory/nshared_ptr.h" +#include "memory/nauto_ptr.h" +#include "nstring/nstring.h" + + +namespace GS { + namespace Core { + /// Basic material definition. + struct BasicMaterial { + Color diffuse; ///< Diffuse color. + Color specular; ///< Specular color. + Color self; ///< Self color. + Color ambient; ///< Ambient color. + + float glossiness; ///< Glossiness. + float opacity; ///< Opacity (eg. 1 - transparency or alpha). + float reflection; ///< Reflection [0;1] + float irefraction; ///< Index of refraction. + float athreshold; ///< Alpha threshold [0;1]. + + float depth_bias; ///< Depth bias. + + uint renderword; ///< Render word. + uint blendop; ///< Blending operator. + }; + + /*! + @short Material. + + A material describe the rendering properties of a surface. + It usually embeds several textures which can have a very different use + depending on whether they are used by a fixed function hardware renderer or + a programmable renderer or even the raytracer. + + @note A material can have up to nTextureStageLimit texture levels. + @author Emmanuel Julien (ejulien@gsworks.fr) + */ + struct Material : public BasicMaterial, public PhysicMaterial, public SharedObject { + NPLACEMENT_NEW(Material) + + /*! + @short Maximum texture stage count. + @note 1 is the lowest acceptable value as C++ does not allow 0 sized + array declaration. (Default: 6) + */ + static const int max_texture_stage = 6; + + /// Material render word (bit mask). + enum RenderWord { + Render_None = 0, + + Render_Unlit = (1 << 0), + Render_Smooth = (1 << 1), + Render_NormalTangent = (1 << 2), + Render_NoFog = (1 << 3), + + Render_DoubleSided = (1 << 4), + Render_Wire = (1 << 5), + Render_VertexColor = (1 << 6), + Render_ParralaxDisp = (1 << 7), + Render_Toon = (1 << 8), + + Render_NoZWrite = (1 << 9), + Render_NoZTest = (1 << 10), + Render_AlphaTest = (1 << 11), + + Render_AlphaSoftZ = (1 << 12), ///< Soft particle. + Render_AlphaInShadow = (1 << 13), ///< Render alpha/opacity in shadow maps. + + Render_UseFramebuffer = (1 << 14), + Render_Skinned = (1 << 15) + }; + + /// Blending operator. + enum BlendOperator { + Blend_None = 0, + Blend_Alpha, + Blend_Add + }; + + /// Filtering type (exclusive). + enum FilterType { + Filter_None = 0, + Filter_Point = 1, + Filter_Linear = 2, + + Filter_Default = Filter_Point + }; + + enum UVMode { + UV_UV = 0, ///< Geometry standard UV buffer. + UV_LSN, ///< Geometry local space transformed normal component. + UV_FrontMap, ///< Front mapping. + UV_SphericalEnvironment ///< Spherical Environment mapping. + }; + + enum Operator { + Operator_Default = 0, ///< Default operator for a given renderer (usually a function of channel member). + Operator_Multiply, ///< Multiply stage. + Operator_Add ///< Add stage. + }; + + /*! + @short Texture stage. + + A texture stage describes a texture layer in a material. + It links a texture object together with the material layer specific + attributes such as UV wrapping, texture sampling method (point, linear, + etc...). A texture stage is also associated with the channel it modify + (diffuse, color, specular, etc... see StageChannel). It is the + renderer's responsibility to render a given material as accurately as + possible and to provide acceptable fall back in the case a material is + too complex to be rendered. + + @author Emmanuel Julien (ejulien@gsworks.fr) + */ + struct TextureStage { + MaterialChannel channel; ///< Texture channel. + String t; ///< Shared texture object. + + uchar uv_index; ///< UV map index in geometry UV list. + UVMode uv_mode; ///< UV mode. + Matrix4 uv_matrix; ///< UV matrix. + + Operator op; ///< Stage combine operator. + + /// Reset the texture stage. + void Reset(); + + TextureStage() { Reset(); } + }; + + String name; + String shader; + + uint texstage_count; + Array texstage; + + /// Return the texture stage for a given channel (if any). + TextureStage *GetChannelStage(MaterialChannel) const; + + /*! + @short Create a new texture stage. + @note If a stage is already assigned to the material channel + it will be returned and no new stage will be allocated. + */ + TextureStage *NewStage(MaterialChannel, const char *uri = 0, UVMode = UV_UV, uchar uv_index = 0); + + void Reset(); + + /*! + @name Serialization. + @{ + */ + bool FromMetaTag(NML::Tag &); + + NML::Tag *AsMetaTag() const; + + /// @} + + Material(); + }; + + typedef SharedPtr sMaterial; + typedef List MaterialList; + } // Core +} // GS + + +#endif // __NMATERIAL__ diff --git a/include/engine/core/material_channel.h b/include/engine/core/material_channel.h new file mode 100644 index 0000000..a59446f --- /dev/null +++ b/include/engine/core/material_channel.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NChannel__ +#define __NChannel__ + + +namespace GS { + namespace Core { + +enum MaterialChannel +{ + Channel_None = 0, ///< No channel. + Channel_Diffuse, ///< Diffuse channel. + Channel_Decal, ///< Decal channel. + Channel_Opacity, ///< Opacity channel. + Channel_Specular, ///< Specular channel. + Channel_Glossiness, ///< Glossiness channel. + Channel_Normal, ///< Normal channel (tangent/world). + Channel_Reflection, ///< Reflection channel. + Channel_SelfIllum, ///< Self-illumination channel. + Channel_Light, ///< Lighting channel. + Channel_BlendRGB, ///< Red blend channel. + + Channel_Last +}; + +const char *MaterialChannelName(MaterialChannel); +MaterialChannel MaterialChannelFromName(const char *); + + } // Core +} // GS + + +#endif // __NChannel__ diff --git a/include/engine/core/material_to_shader_tree.h b/include/engine/core/material_to_shader_tree.h new file mode 100644 index 0000000..284a113 --- /dev/null +++ b/include/engine/core/material_to_shader_tree.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMATERIALTOSHADERTREE__ +#define __NMATERIALTOSHADERTREE__ + + + #include "core/material.h" + + +namespace GS { + namespace Core { + class ShaderTree; + struct ShaderBlock; + + namespace MaterialToShaderTree { + +/// Convert a material texture stage to a shader tree block. +ShaderBlock *MaterialTextureStageToShaderBlock(const Material &m, const Material::TextureStage *ts, ShaderBlock *nb = 0); +/// Convert a material fixed-function definition to a shader tree. +bool Convert(const Material &, ShaderTree &); + + } // MaterialToShaderTree + } // Core +} // GS + + +#endif // __NMATERIALTOSHADERTREE__ diff --git a/include/engine/core/mixer.h b/include/engine/core/mixer.h new file mode 100644 index 0000000..a2acc44 --- /dev/null +++ b/include/engine/core/mixer.h @@ -0,0 +1,93 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMIXER__ +#define __NMIXER__ + + + #include "core/mixer_data.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace Audio { + +/*! + @short Mixer interface. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct IMixer +{ +enum State +{ + Invalid = 0, + Stopped, + Playing, + Paused +}; + +enum Loop +{ + None = 0, + Repeat +}; + +/*! + @name Interface. + The API any concrete mixer must implement. + @{ +*/ +virtual bool Open() = 0; +virtual void Close() = 0; + +virtual void SuspendWorkerThread() = 0; +virtual void ResumeWorkerThread() = 0; + +virtual void SetMasterVolume(float = 1.0) = 0; +virtual float GetMasterVolume() = 0; + + /// Play a sound, does not wait for the worker thread return code. +virtual bool StartFast(int, FutureData *) = 0; + /// Play a sound, returns the channel on which the stream was started. +virtual int Start(int, FutureData *) = 0; + /// Start a stream, does not wait for the worker thread return code. +virtual bool StreamFast(int, const char *) = 0; + /// Start a stream, returns the channel on which the stream was started. +virtual int Stream(int, const char *) = 0; +virtual void Stop(int) = 0; +virtual void Pause(int) = 0; +virtual void Resume(int) = 0; + +virtual int LockChannel() = 0; +virtual void UnlockChannel(int) = 0; +virtual void UnlockAllChannels() = 0; + +virtual float GetChannelPitch(int) = 0; +virtual float GetChannelVolume(int) = 0; +virtual float GetChannelPanning(int) = 0; +virtual Loop GetChannelLoopMode(int) = 0; +virtual int GetChannelLoopPosition(int) = 0; + +virtual void SetChannelPitch(int, float) = 0; +virtual void SetChannelVolume(int, float) = 0; +virtual void SetChannelPanning(int, float) = 0; +virtual void SetChannelLoopMode(int, Loop = None) = 0; +virtual void SetChannelLoopPosition(int, int ms) = 0; + +virtual State GetState(int) = 0; + +virtual FutureData *LoadSound(const char *) = 0; +virtual void UnloadSound(FutureData *) = 0; +/// @} + +virtual ~IMixer() {} +}; + + } // Audio +} // GS + + +#endif // __NMIXER__ diff --git a/include/engine/core/mixer_data.h b/include/engine/core/mixer_data.h new file mode 100644 index 0000000..57569a5 --- /dev/null +++ b/include/engine/core/mixer_data.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NAUDIODATA__ +#define __NAUDIODATA__ + + + #include "async/future.h" + #include "alloc/ialloc.h" + #include "time/ntime.h" + + +namespace GS { + namespace Audio { + +// +struct Data : public SharedObject +{ + NPLACEMENT_NEW(Mixer) + + Time duration; + +virtual ~Data() {} +}; + +typedef SharedPtr sData; +typedef ASync::Future FutureData; + + } // Audio +} // GS + + +#endif // __NAUDIODATA__ diff --git a/include/engine/core/mixer_resource_factory.h b/include/engine/core/mixer_resource_factory.h new file mode 100644 index 0000000..33592cd --- /dev/null +++ b/include/engine/core/mixer_resource_factory.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NAUDIORESOURCEFACTORY__ +#define __NAUDIORESOURCEFACTORY__ + + + #include "core/resource_factory_event_interface.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace Audio { + struct IMixer; + struct Sound; + +/* + @short Mixer resource factory. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ResourceFactory +{ + AutoPtr event_handler; + + IMixer &mixer; + +virtual Sound *LoadSound(const char *) = 0; + + ResourceFactory(IMixer &m) : event_handler(new IResourceFactoryEvent), mixer(m) {} +virtual ~ResourceFactory() {} +}; + + typedef SharedPtr sSound; + + } // Audio +} // GS + + +#endif // __NAUDIORESOURCEFACTORY__ diff --git a/include/engine/core/mixer_thread_controller.h b/include/engine/core/mixer_thread_controller.h new file mode 100644 index 0000000..dc0f9a0 --- /dev/null +++ b/include/engine/core/mixer_thread_controller.h @@ -0,0 +1,248 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMIXER_THREAD_CONTROLLER__ +#define __NMIXER_THREAD_CONTROLLER__ + + + #include "core/mixer.h" + #include "audio/sample_interface.h" + #include "nstring/nstring.h" + #include "thread/mutex.h" + + +namespace GS { + namespace Audio { + +// +struct MixerVariant : public SharedObject +{ + union + { + int i_value; + float f_value; + }; + + AutoPtr future_data; + + MixerVariant() : i_value(0) {} + MixerVariant(int v) : i_value(v) {} + MixerVariant(float v) : f_value(v) {} + MixerVariant(FutureData *f) : future_data(f) {} +}; + +typedef SharedPtr sMixerVariant; + +// +struct MixerCommand +{ + enum Code + { Nop = 0, LoadSound, UnloadSound, Start, Stream, GetState, Pause, Stop, Resume, Lock, Unlock, Close, + SetMaster, SetVolume, SetPitch, SetPanning, SetLoopMode, SetLoopPosition, + GetMaster, GetVolume, GetPitch, GetPanning, GetLoopMode, GetLoopPosition }; + + Code code; + int channel; + + String uri; + + union + { + bool b_value; + float f_value; + int i_value; + + }; + + sData data; + ASync::Future *result; + + MixerCommand() {} + MixerCommand(Code c) : code(c) {} + MixerCommand(Code c, float v) : code(c), f_value(v) {} + MixerCommand(Code c, const char *name) : code(c), uri(name) {} + MixerCommand(Code c, Data *_data) : code(c), data(_data) {} + MixerCommand(Code c, int n) : code(c), channel(n) {} + MixerCommand(Code c, int n, Data *d) : code(c), channel(n), data(d) {} + MixerCommand(Code c, int n, bool v) : code(c), channel(n), b_value(v) {} + MixerCommand(Code c, int n, float v) : code(c), channel(n), f_value(v) {} + MixerCommand(Code c, int n, int v) : code(c), channel(n), i_value(v) {} + MixerCommand(Code c, int n, const char *name) : code(c), channel(n), uri(name) {} +}; + +/*! + @short Threaded mixer controller. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class ThreadedMixer : public IMixer +{ + AutoPtr <_Thread> thread; + + bool PutCommand(MixerCommand *cmd, MixerVariant **result = 0) + { + if (thread.IsNull() || !thread->device) + return false; + + ASync::Future future_result; + + forever + { + Threading::MutexLock lock(&thread->cmdbuffer_mutex); + + if (thread->cmdbuffer.GetFree() > 0) + if (MixerCommand **put = &thread->cmdbuffer.CurrentPut()) + { + *put = cmd; + cmd->result = result ? &future_result : NULL; // Future is to be Set() by the worker thread. + + thread->cmdbuffer.Produce(); + thread->cmdbuffer_event.Trigger(); + break; + } + } + + if (result) + *result = future_result.Get(); + + return true; + } + MixerVariant *PutCommandAndWaitResult(MixerCommand *cmd) + { + MixerVariant *result; + return PutCommand(cmd, &result) ? result : 0; + } + +public: + +virtual bool Open() + { + if (thread.IsValid()) + return true; + + thread = new _Thread; + return thread->Start(); + } +virtual void Close() + { + PutCommand(new MixerCommand(MixerCommand::Close)); + if (thread.IsValid()) + thread->Join(); + thread = 0; + } + +virtual void SuspendWorkerThread() + { thread->SuspendMixer(); } +virtual void ResumeWorkerThread() + { thread->ResumeMixer(); } + +virtual void SetMasterVolume(float volume = 1.0) + { PutCommand(new MixerCommand(MixerCommand::SetMaster, volume)); } +virtual float GetMasterVolume() + { + AutoPtr v(PutCommandAndWaitResult(new MixerCommand(MixerCommand::GetMaster))); + return v.IsValid() ? v->f_value : 1; + } +virtual bool StartFast(int channel, FutureData *data) + { return data ? PutCommand(new MixerCommand(MixerCommand::Start, channel, data->Get())) : false; } +virtual int Start(int channel, FutureData *data) + { + AutoPtr v(data ? PutCommandAndWaitResult(new MixerCommand(MixerCommand::Start, channel, data->Get())) : 0); + return v.IsValid() ? v->i_value : -1; + } +virtual bool StreamFast(int channel, const char *uri) + { return PutCommand(new MixerCommand(MixerCommand::Stream, channel, uri)); } +virtual int Stream(int channel, const char *uri) + { + AutoPtr v(PutCommandAndWaitResult(new MixerCommand(MixerCommand::Stream, channel, uri))); + return v.IsValid() ? v->i_value : -1; + } + +virtual void Stop(int channel) + { PutCommand(new MixerCommand(MixerCommand::Stop, channel)); } +virtual void Pause(int channel) + { PutCommand(new MixerCommand(MixerCommand::Pause, channel)); } +virtual void Resume(int channel) + { PutCommand(new MixerCommand(MixerCommand::Resume, channel)); } + +virtual int LockChannel() + { + AutoPtr v(PutCommandAndWaitResult(new MixerCommand(MixerCommand::Lock))); + return v.IsValid() ? v->i_value : -1; + } +virtual void UnlockChannel(int channel) + { PutCommand(new MixerCommand(MixerCommand::Unlock, channel)); } +virtual void UnlockAllChannels() + { + for (int n = 0; n < 64; ++n) + PutCommand(new MixerCommand(MixerCommand::Unlock, n)); + } + +virtual float GetChannelPitch(int channel) + { + AutoPtr v(PutCommandAndWaitResult(new MixerCommand(MixerCommand::GetPitch, channel))); + return v.IsValid() ? v->f_value : 1; + } +virtual float GetChannelVolume(int channel) + { + AutoPtr v(PutCommandAndWaitResult(new MixerCommand(MixerCommand::GetVolume, channel))); + return v.IsValid() ? v->f_value : 1; + } +virtual float GetChannelPanning(int channel) + { return -1; } +virtual Loop GetChannelLoopMode(int channel) + { + AutoPtr v(PutCommandAndWaitResult(new MixerCommand(MixerCommand::GetLoopMode, channel))); + return v.IsValid() ? (v->i_value == AL_TRUE ? Repeat : None) : None; + } +virtual int GetChannelLoopPosition(int channel) + { return 0; } + +virtual void SetChannelPitch(int channel, float pitch) + { PutCommand(new MixerCommand(MixerCommand::SetPitch, channel, pitch)); } +virtual void SetChannelVolume(int channel, float volume) + { PutCommand(new MixerCommand(MixerCommand::SetVolume, channel, volume)); } +virtual void SetChannelPanning(int channel, float panning) + { PutCommand(new MixerCommand(MixerCommand::SetPanning, channel, panning)); } +virtual void SetChannelLoopMode(int channel, Loop loop = None) + { PutCommand(new MixerCommand(MixerCommand::SetLoopMode, channel, loop == IMixer::Repeat ? AL_TRUE : AL_FALSE)); } +virtual void SetChannelLoopPosition(int, int ms) + {} + +virtual State GetState(int channel) + { + AutoPtr v(PutCommandAndWaitResult(new MixerCommand(MixerCommand::GetState, channel))); + + if (v.IsValid()) + switch (v->i_value) + { + case AL_INITIAL: + case AL_STOPPED: return Stopped; + case AL_PAUSED: return Paused; + case AL_PLAYING: return Playing; + } + + return Invalid; + } + +virtual FutureData *LoadSound(const char *uri) + { + AutoPtr v(uri ? PutCommandAndWaitResult(new MixerCommand(MixerCommand::LoadSound, uri)) : 0); + return v.IsValid() ? v->future_data.Detach() : 0; + } +virtual void UnloadSound(FutureData *data) + { + AutoPtr v(data ? PutCommandAndWaitResult(new MixerCommand(MixerCommand::UnloadSound, data->Get())) : 0); + } + + ~ThreadedMixer() + { Close(); } +}; + + } // Audio +} // GS + + +#endif // __NMIXER_THREAD_CONTROLLER__ diff --git a/include/engine/core/null_mixer.h b/include/engine/core/null_mixer.h new file mode 100644 index 0000000..3464f7d --- /dev/null +++ b/include/engine/core/null_mixer.h @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NNULLMIXER__ +#define __NNULLMIXER__ + + + #include "core/mixer.h" + + +namespace GS { + namespace Audio { + +/*! + @short Null mixer. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct NullMixer : public IMixer +{ + bool Open() { return true; } + void Close() {} + + void SuspendWorkerThread() {} + void ResumeWorkerThread() {} + + void SetMasterVolume(float = 1.0) {} + float GetMasterVolume() { return 1; } + + bool StartFast(int, FutureData *) { return false; } + int Start(int, FutureData *) { return 0; } + bool StreamFast(int, const char *) { return false; } + int Stream(int, const char *) { return 0; } + void Stop(int) {} + void Pause(int) {} + void Resume(int) {} + + int LockChannel() { return 0; } + void UnlockChannel(int) {} + void UnlockAllChannels() {} + + float GetChannelPitch(int) { return 1; } + float GetChannelVolume(int) { return 1; } + float GetChannelPanning(int) { return 0; } + Loop GetChannelLoopMode(int) { return None; } + int GetChannelLoopPosition(int) { return 0; } + + void SetChannelPitch(int, float) {} + void SetChannelVolume(int, float) {} + void SetChannelPanning(int, float) {} + void SetChannelLoopMode(int, Loop = None) {} + void SetChannelLoopPosition(int, int ms) {} + + State GetState(int) { return Invalid; } + + FutureData *LoadSound(const char *) { return 0; } + void UnloadSound(FutureData *) {} + + ~NullMixer() {} +}; + + } // Audio +} // GS + + +#endif // __NNULLMIXER__ diff --git a/include/engine/core/null_renderer.h b/include/engine/core/null_renderer.h new file mode 100644 index 0000000..9ade1bb --- /dev/null +++ b/include/engine/core/null_renderer.h @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NNULLRENDERER__ +#define __NNULLRENDERER__ + + + #include "core/renderer.h" + + +namespace GS { + namespace Render { + +/*! + @short Null renderer class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct NullRenderer : public Renderer +{ + /// Returns the renderer's name as a C string. + const char *GetName() const { return "Null Renderer."; } + /// Returns a C string describing the renderer. + const char *GetDescription() const { return "A null renderer that render nothing."; } + /// Returns a C string containing the renderer version number. + const char *GetVersion() const { return "0.0"; } + +virtual Geometry *NewGeometry(const char *name = 0) { return 0; } +virtual Material *NewMaterial(const char *name = 0) { return 0; } +virtual Texture *NewTexture(const char *name = 0) { return 0; } +virtual Shader *NewShader(const char *name = 0) { return 0; } + + bool BeginDrawList() { return true; } + void EndDrawList() {} + + /// Open video. + bool Open(uint width, uint height, char nUnused(bpp) = 32, VideoMode = VideoWindowed, const void * nUnused(sys_handle) = 0) + { + dimensions.Set(width, height); + return true; + } + /// Free all renderer resources. + void Free() {} + /// Close video. + void Close() {} + /// Explicitly resize video output. + bool ResizeVideo(uint width, uint height) + { + dimensions.Set(width, height); + return true; + } + /// Switch to/from fullscreen. + void SetFullscreen(bool = true) {} + /// Refresh display output. + void Refresh() {} + /// Render the display queue. + void RenderList() {} + /// Request that the frame be displayed to output. + void ShowFrame() {} + /// Return a pointer to the current subsystem window output. + void *GetCurrentSystemWindowHandle() const { return 0; } + + /// Setup an extra window to use as renderer output. + Window *NewOutputWindow(const void *) { return 0; } + /// Set the output window. Pass NULL to setup the primary window (ie. the renderer initial window). + void SetOutputWindow(Window * = 0) {} + /// Free a rendering window. + void FreeOutputWindow(Window *) {} + + /// Clear the render target + void Clear(float, float, float, float = 1.f, float = 1.f, ClearFunction = ClearAll) {} + /// Grab the frame buffer to a texture. + void GrabDisplay(Texture *) {} + /// Grab the frame buffer to a picture. + void GrabDisplay(Picture &) {} + /// Set a texture as render target. + void SetRenderTarget(Texture *) {} + + /// Display a 3d line. + void DrawLine(uint nUnused(count), const Vector4 *, const Color * = 0, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Shader * = 0) {} + /// Draw a triangle to frame buffer. + void DrawTriangle(uint nUnused(count), const Vector4 *, const ushort *idx = 0, const Color * = 0, const Vector2 * = 0, const Texture * = 0, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Shader * = 0) {} + /// Draw sprite. + void DrawSprite(uint nUnused(count), const Vector4 *, const Color * = 0, const float *size = 0, const Texture * = 0, float nUnused(global_size) = 1.f, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Shader * = 0) {} + + /// Output string to screen. + void Write(const RasterFont &, const char *, float &nUnused(x), float &nUnused(y), const WriterConfig &, float nUnused(scale) = 1, const Color * = 0, WriterAlignment = AlignLeft, bool mirrored=false) {} + + /// Set the view matrix. + void SetViewMatrix(const Matrix4 &, const Matrix4 * = 0) {} + /// Set the projection matrix. + void SetProjectionMatrix(const Matrix4 &) {} + /// Set the world matrix. + void SetWorldMatrix(const Matrix4 &, const Matrix4 * = 0) {} + /// Set viewport. + void SetViewport(const fRect &) {} + /// Get viewport. + fRect GetViewport() const { return fRect(0.f, 0.f, (float)dimensions.x, (float)dimensions.y); } + + /// Clear the user clipping plane. + void ClearClippingPlane() {} + /// Set the user clipping plane. + void SetClippingPlane(const Vector4 &nUnused(p), const Vector4 &nUnused(n)) {} + + /// Set clipping rect. + void SetClippingRect(const fRect *) {} + /// Get clipping rect. + fRect GetClippingRect() const { return fRect(-1, -1, -1, -1); } + +virtual ~NullRenderer() { Close(); } +}; + + } // Render +} // GS + + +#endif // __NNULLRENDERER__ diff --git a/include/engine/core/object.h b/include/engine/core/object.h new file mode 100644 index 0000000..8b38bb9 --- /dev/null +++ b/include/engine/core/object.h @@ -0,0 +1,100 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NOBJECT__ +#define __NOBJECT__ + + + #include "core/renderable.h" + #include "core/skin.h" + #include "core/item.h" + + +namespace GS { + namespace Core { + +/*! + @short Object class. + + This class simply links a geometry with an item and provide some wrapper + functions to render them. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Object : public Item, public Renderable +{ +protected: + + AutoPtr skin; + +public: + +struct RenderData +{ Render::sGeometry geometry; }; + +static float lod_bias; + +/*! + @name Renderable interface. + @{ +*/ + /// Compute the renderable minmax. +virtual void ComputeRenderableMinMax(MinMax &); + /// Get the renderable primitive list for this renderable. +virtual uint GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack &, Renderable::Context = Renderable::Context_Default, bool cull = true); + + /// Setup item render data. +virtual void RenderSetup(ResourceFactories * = 0); +/// @} + + bool cache_geometry; ///< Whether the object should reuse cached geometry or create new instances. + + /// Compute object world axis-aligned bounding box. + void ComputeLocalMinMax(MinMax &) const; + + /// Return the object skin. + Skin *GetSkin() const { return skin; } + + /// Return the binding bone matrix. + bool GetBindMatrix(uint, Matrix4 &) const; + /// Update skin matrices. + void UpdateSkin(); + + /// Has skin. +inline bool HasSkin() const + { return skin.IsValid() && skin->bones.GetCount(); } + +inline uint GetBoneCount() const + { return skin.IsValid() ? skin->bones.GetCount() : 0; } +inline Item *GetBone(uint n) const + { return skin.IsValid() ? skin->bones[n] : 0; } + + /// Allocate skin binding structures. +virtual bool AllocateSkin(uint bone_count); + /// Free skin binding structures. +virtual void FreeSkin(); + /*! + @short Bind a bone to this item's skin. + + @note You can specify the binding matrix for this bone. If you do + not the current bone item matrix will be used. + */ +virtual bool BindBone(uint n, Item *bone); + + String geometry; + AutoPtr render_data; + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + Object(); +}; + + } // Core +} // GS + + +#endif // __NOBJECT__ diff --git a/include/engine/core/octree_renderable.h b/include/engine/core/octree_renderable.h new file mode 100644 index 0000000..38c72e7 --- /dev/null +++ b/include/engine/core/octree_renderable.h @@ -0,0 +1,74 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __OCTREE_RENDERABLE__ +#define __OCTREE_RENDERABLE__ + + + #include "core/renderable.h" + #include "container/narray_list.h" + + +namespace GS { + namespace Core { + +/* + @short Octree for static renderable. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class OctreeCullingSystem : public Renderable +{ +public: + +struct CachedNode +{ + Renderable *renderable; + MinMax minmax; + CachedNode() : renderable(0) {} +}; + +struct Node +{ + Array cached_node; + MinMax minmax; + AutoPtr child[2]; +}; + +private: + + bool dirty; + + Array nodes; + AutoPtr root; + + ArrayList renderable_list; + + /// Perform list insertion into the octree. + Node *InsertList(List &list); + + void GetNodeRenderablePrimitive(Node *, const Camera &view, const Camera &default_view, Stack &, Context); + void CullNodeRenderablePrimitive(Node *, const Camera &view, const Camera &default_view, Stack &, Context); + +public: + + void AddRenderable(Renderable *); + void DeleteRenderable(Renderable *); + + bool Update(); + + /// Compute renderable min-max. +virtual void ComputeRenderableMinMax(MinMax &); + /// Get primitive list. +virtual uint GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack &list, Context context = Context_Default, bool cull = true); + + OctreeCullingSystem() : dirty(true) {} +}; + + } // Core +} // GS + + +#endif // __OCTREE_RENDERABLE__ diff --git a/include/engine/core/path_kdtree.h b/include/engine/core/path_kdtree.h new file mode 100644 index 0000000..68ae1ff --- /dev/null +++ b/include/engine/core/path_kdtree.h @@ -0,0 +1,155 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __nPathKdtree__ +#define __nPathKdtree__ + + + #include "core/geometry_tree.h" + #include "container/narray.h" + #include "container/narray_list.h" + #include "memory/nshared_ptr.h" + + +namespace GS { + namespace Render { class Renderer; } + +struct nMSegment : public SharedObject +{ + Vector4 a,b; + float a_t, b_t; + MinMax bounding_box; + + MinMax GetBoundingBox() + { + Vector4 min; + Vector4 max; + if(a.x > b.x) + { + min.x = b.x; + max.x = a.x; + } + else + { + min.x = a.x; + max.x = b.x; + } + if(a.y > b.y) + { + min.y = b.y; + max.y = a.y; + } + else + { + min.y = a.y; + max.y = b.y; + } + if(a.z > b.z) + { + min.z = b.z; + max.z = a.z; + } + else + { + min.z = a.z; + max.z = b.z; + } + + bounding_box = MinMax(min, max); + return bounding_box; + } +}; + +/*! + @short Geometry polygon KD-tree. + @author Thomas Simonnet (thomas@movida-mail.com) +*/ +class PathKdtree +{ +private: + + struct KDTreeNode + { + char m_KDTREE_NODE_TYPE_SPLIT; + int m_KDTREE_NODE_ID_ROPE[6]; + float m_KDTREE_NODE_AABB[6]; + float m_KDTREE_NODE_VALUE_SPLIT; + int m_KDTREE_NODE_ID; + int m_KDTREE_NODE_ID_CHILD_LEFT; + int m_KDTREE_NODE_ID_CHILD_RIGHT; + bool m_KDTREE_NODE_IS_LEAF; + int m_KDTREE_NODE_COUNT_SEGMENT; + int* m_KDTREE_NODE_ID_SEGMENT; + + KDTreeNode(); + ~KDTreeNode(){delete []m_KDTREE_NODE_ID_SEGMENT;}; + }; + + #define KDTREE_X_AXIS 0 + #define KDTREE_Y_AXIS 1 + #define KDTREE_Z_AXIS 2 + + #define KDTREE_SIDE_LEFT 0 + #define KDTREE_SIDE_RIGHT 1 + #define KDTREE_SIDE_BOTTOM 2 + #define KDTREE_SIDE_TOP 3 + #define KDTREE_SIDE_BACK 4 + #define KDTREE_SIDE_FRONT 5 + + int m_count_bih; + float * m_TempFloatBih; + + KDTreeNode* m_NodeTree; + int m_SizeTree; + +protected: + + void DrawKdtreeNode(Render::Renderer &render, int _CurrentNode, Matrix4& m); + void IncreaseSizeNodeKdtreeBuffer(int _IncreaseSize); + void CreateNodeKdtree(int &_CurrentNode, int *_IdSegment, int _CountSegment, int _CurrentDepth, bool _ForceCreateLeaf=false); + +public: + + SharedArrayList segment_list; + + void draw_scene_debug(Render::Renderer &render, Matrix4& m); + +/*! + @name KD-Tree specific functions. + @{ +*/ + /// Retrieve the index of the closest KD-tree node to a given location in world space. + int InsideKdTreeNode(const Vector4 &p, bool CheckInside=false); + bool InsideKdTree(const Vector4 &p); + +/// @} + +/*! + @name Interface core functions. + @{ +*/ + /// Raytrace the geometry tree. + void NearestQuadtreeTreeNode(Vector4 p, SharedArrayList &list_segment); + + void BuildQuadtree(); + + /// add object to the quadtree. +virtual bool AddSegment(nMSegment* segment); +virtual bool AddSegment(SharedArrayList segment_list); + + /// Free all internal structures. +virtual void Free(); +/// @} + + PathKdtree(); + ~PathKdtree() + { Free(); } +}; + +} // GS + + +#endif // __nPathKdtree__ diff --git a/include/engine/core/physic_material.h b/include/engine/core/physic_material.h new file mode 100644 index 0000000..67956bf --- /dev/null +++ b/include/engine/core/physic_material.h @@ -0,0 +1,66 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NPHYSIC_MATERIAL__ +#define __NPHYSIC_MATERIAL__ + + +namespace GS { + namespace NML { class Tag; } + namespace Core { + +/*! + @short Physic material. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct PhysicMaterial +{ +/*! + @name General physic properties. + @{ +*/ + float mass; ///< Mass. + float dynamic_friction; ///< Dynamic friction. + float static_friction; ///< Static friction. + float restitution; ///< Restitution (inelastic/elastic). + + bool anisotropic_friction; ///< Anisotropic friction. + float v_dynamic_friction; ///< Lateral dynamic friction. + float v_static_friction; ///< Lateral static friction. + + /*! + @short Set material friction. + + @note The static friction is a force opposing external forces + acting on a resting body. The dynamic friction is a force + opposing the motion of a moving body. + @see SetAnisotropicFriction(). + */ + void SetFriction(float dync = 0.5f, float sttc = 0.75f) + { dynamic_friction = dync; static_friction = sttc; } +/// @} + +/*! + @name Soft body properties. + @{ +*/ + float sb_damping; ///< Damping. + float sb_stiffness; ///< Stiffness. + float sb_torsion; ///< Torsion. +/// @} + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + PhysicMaterial(); +virtual ~PhysicMaterial(){} +}; + + } // Core +} // GS + + +#endif // __NPHYSIC_MATERIAL__ diff --git a/include/engine/core/raster_font.h b/include/engine/core/raster_font.h new file mode 100644 index 0000000..67e00f6 --- /dev/null +++ b/include/engine/core/raster_font.h @@ -0,0 +1,94 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRASTERFONT__ +#define __NRASTERFONT__ + + + #include "core/render_data.h" + #include "container/nlist.h" + + +namespace GS { + namespace Render { + struct ResourceFactory; + +/*! + @short Raster font. + + Raster font that can be used by the Write() method of the renderer. + A raster font is of fixed size and stored in one or several texture + pages. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class RasterFont +{ +public: + +/// Raster font glyph. +struct Glyph +{ + bool available; + float u, v; + float w, h; + float offx, offy; + float step; + uint page; + + void Reset() + { + available = false; + u = v = 0; + w = h = 0; + offx = offy = 0; + step = 0; + page = 0; + } + Glyph() { Reset(); } +}; + +private: + + SharedList pages; + + Glyph glyph[256]; ///< Character LUT. + + float baseline; + float height; + +public: + + String name; + + float GetHeight(bool normalized = true) const; + float GetBaseline(bool normalized = true) const; + + /// Return the texture corresponding to a given font page. + Texture *GetPage(uint) const; + + /// Return information structure for a given glyph. + const Glyph *GetGlyphInfos(uchar) const; + + // Return the rect of a single-line string (stops at the first carriage return). + Vector2 ComputeLineRect(const char *s, bool normalized = true) const; + /// Return the rect a multi-line string. + Vector2 ComputeStringRect(const char *s, bool normalized = true) const; + + /*! + @short Load a raster font. + @param nml The font meta file description. + @param base Font page texture base name. + */ + bool Load(ResourceFactory &, const char *nml, const char *base); + void Unload(); +}; + + } // Render +} // GS + + +#endif // __NRASTERFONT__ diff --git a/include/engine/core/render_data.h b/include/engine/core/render_data.h new file mode 100644 index 0000000..c114878 --- /dev/null +++ b/include/engine/core/render_data.h @@ -0,0 +1,205 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRENDERDATA__ +#define __NRENDERDATA__ + + + #include "core/material.h" + #include "core/texture_parm.h" + #include "geometry/bounding_box.h" + #include "memory/bit_field.h" + + +namespace GS { + class Picture; + + namespace Core { + class Geometry; + struct Material; + struct Shader; + } + + namespace Render { + class Renderer; + struct ResourceFactory; + +//------------------------------------------------------------------------------ +struct Material; +typedef SharedPtr sMaterial; +struct Geometry; +typedef SharedPtr sGeometry; +struct Texture; +typedef SharedPtr sTexture; +struct Shader; +typedef SharedPtr sShader; +//------------------------------------------------------------------------------ + +/*! + @short The renderer base data container. + + This is the base structure holding all of a renderer's specific data for + an entity to be setup. This structure is to be derived for each functional + renderer implementation. + + @see nRenderGeometry, nRenderMaterial, nRenderTexture, nLight. +*/ +struct Data : public SharedObject +{ + NPLACEMENT_NEW(Renderer) + + String name; + + /// Load from cooked resource. +virtual bool LoadCooked(const char *uri) + { return false; } +virtual bool ShouldReloadOnDependencyChange(const char *n) const + { return name == n; } + + Data(const char *_name = 0) : name(_name) {} +}; + +//------------------------------------------------------------------------------ +struct Geometry : public Data +{ + Array material_table; + + BitField flag; + Vector4 hotspot; + + MinMax minmax; + + /// Change a material in the material table. +virtual bool SetMaterial(uint nUnused(index), Material *) { return false; } + + /// Create from geometry. +virtual bool Create(ResourceFactory &, const Core::Geometry &) = 0; + + sGeometry lod_proxy; + float lod_distance; + + sGeometry shadow_proxy; + + Array bone_bind_matrix; + Array bone_minmax; + + Geometry(const char *_name = 0) : Data(_name) {} +}; +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +struct MaterialShader : public Data +{ +virtual bool SetUserUniformValue(const char *name, const Vector4 &) = 0; +virtual bool SetUserUniformValue(const char *name, Texture *) = 0; +}; +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +struct Material : public Core::BasicMaterial, public Data +{ + sTexture texture_table[Core::Material::max_texture_stage]; + + /// Get the material shader. +virtual MaterialShader *GetShader() const { return 0; } + + /// Create from material. +virtual bool Create(ResourceFactory &, const Core::Material &) = 0; + + /// Clone this material (create an independent copy). +virtual Material *Clone() const { return NULL; } + + Material(const char *_name = 0) : Data(_name) {} +}; +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +struct Texture : public Data +{ +enum Format +{ + FormatRGBA8 = 0, + FormatBGRA8, + FormatRGBA16, + FormatRGBAF, + FormatDepth, + FormatDepthF, + FormatDepthOculus, + + FormatInvalid +}; +enum AA +{ + NoAA = 0, + + MSAA2x, + MSAA4x, + MSAA8x, + MSAA16x, + + AALast +}; +enum Usage +{ + IsRenderTarget = (1 << 0), ///< used as a render-target + IsShaderResource = (1 << 1), ///< used as a shader resource + + UsageDefault = IsShaderResource +}; + + TextureParm parm; + + Format format; + AA aa; + + bool is_rtt; + + /// Configure texture as a shadow map. +virtual void ConfigureAsShadowMap() = 0; + + bool Create(const Picture &, Usage = UsageDefault); + + /// Create from raw picture data. +virtual bool Create(const char *data, int width, int height, Format = FormatRGBA8, AA = NoAA, Usage = UsageDefault) = 0; +virtual void Free() = 0; + +virtual uint GetWidth() const = 0; +virtual uint GetHeight() const = 0; + + /// Blit CPU data to texture. +virtual void Blit(const char *data, uint w, uint h, uint x = 0, uint y = 0, Format = Texture::FormatRGBA8) = 0; + /// Resize texture, does not preserve content. +virtual void Resize(uint w, uint h) = 0; + +virtual void SetAnisotropy(TextureParm::Anisotropy) = 0; +virtual void SetFiltering(TextureParm::Filtering) = 0; +virtual void SetWrapping(TextureParm::Wrap u, TextureParm::Wrap v) = 0; + + Texture(const char *_name = 0) : Data(_name) + { + format = FormatInvalid; + aa = NoAA; + + is_rtt = false; + } +}; +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +struct Shader : public Data +{ + /// Create from shader. +virtual bool Create(ResourceFactory &, const Core::Shader &) = 0; + + Shader(const char *_name = 0) : Data(_name) {} +}; +//------------------------------------------------------------------------------ + + } // Render +} // GS + + +#endif // __NRENDERDATA__ diff --git a/include/engine/core/render_primitive.h b/include/engine/core/render_primitive.h new file mode 100644 index 0000000..f34338c --- /dev/null +++ b/include/engine/core/render_primitive.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NRENDERPRIMITIVE__ +#define __NRENDERPRIMITIVE__ + + + #include "core/render_data.h" + + +namespace GS { + namespace Core + { + class Item; + class Emitter; + struct Patch; + } + namespace Render { + +/// Render primitive. +struct Primitive +{ +enum Type +{ + Type_Geometry = 0, + Type_Emitter, + Type_TerrainPatch +}; + + Type type; + + const Core::Item *item; + sGeometry geometry; + + union + { + Core::Emitter *emitter; + Core::Patch *patch; + }; + + Primitive(Geometry *g, const Core::Item *i, float) : type(Type_Geometry), item(i), geometry(g), emitter(0) {} + Primitive(Core::Patch *p, const Core::Item *i, float) : type(Type_TerrainPatch), item(i), patch(p) {} + Primitive(Core::Emitter *e, const Core::Item *i, float) : type(Type_Emitter), item(i), emitter(e) {} +}; + + } // Render +} // GS + + +#endif // __NRENDERPRIMITIVE__ diff --git a/include/engine/core/render_resource_factory.h b/include/engine/core/render_resource_factory.h new file mode 100644 index 0000000..414ddd3 --- /dev/null +++ b/include/engine/core/render_resource_factory.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRENDER_RESOURCE_FACTORY__ +#define __NRENDER_RESOURCE_FACTORY__ + + + #include "core/render_data.h" + #include "core/resource_factory_event_interface.h" + + +namespace GS { + namespace Render { + +struct ResourceFactory +{ + sIResourceFactoryEvent event_handler; + +virtual Geometry *NewGeometry() = 0; +virtual Material *NewMaterial() = 0; +virtual Texture *NewTexture() = 0; +virtual Shader *NewShader() = 0; + +virtual Geometry *LoadGeometry(const char *, bool bypass_cache = false, Geometry * = 0) = 0; +virtual Material *LoadMaterial(const char *, bool bypass_cache = false, Material * = 0) = 0; +virtual Texture *LoadTexture(const char *, bool bypass_cache = false, Texture * = 0) = 0; +virtual Shader *LoadShader(const char *, bool bypass_cache = false, Shader * = 0) = 0; + +virtual void ListCachedResources() {} + +virtual uint GetCachedResourceCount() { return 0; } +virtual uint PurgeCache() { return 0; } + + ResourceFactory() : event_handler(new IResourceFactoryEvent) {} +virtual ~ResourceFactory() {} +}; + + } // Render +} // GS + + +#endif // __NRENDER_RESOURCE_FACTORY__ diff --git a/include/engine/core/renderable.h b/include/engine/core/renderable.h new file mode 100644 index 0000000..b1524fa --- /dev/null +++ b/include/engine/core/renderable.h @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NRENDERABLE__ +#define __NRENDERABLE__ + + + #include "core/render_data.h" + #include "core/render_primitive.h" + #include "container/nstack.h" + + +namespace GS { + class MinMax; + + namespace Core { + class Camera; + +/*! + @short Renderer renderable item. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct Renderable +{ +enum Context +{ + Context_Default = 0, + Context_Shadow, + Context_Occlusion +}; + + /// Is this renderable enabled. +virtual inline bool IsRenderable() const { return true; } + + /// Compute the renderable minmax. +virtual void ComputeRenderableMinMax(MinMax &) = 0; + /// Get the renderable primitive list, returns the number of primitive that were considered for addition to the final list. +virtual uint GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack &, Context = Context_Default, bool cull = true) = 0; + +virtual ~Renderable() {} +}; + + } // Core +} // GS + + +#endif // __NRENDERABLE__ diff --git a/include/engine/core/renderer.h b/include/engine/core/renderer.h new file mode 100644 index 0000000..3411d8a --- /dev/null +++ b/include/engine/core/renderer.h @@ -0,0 +1,402 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NBASERENDERER__ +#define __NBASERENDERER__ + + + #include "core/renderable.h" + #include "core/material.h" + #include "timing/benchmark.h" + #include "data/registry.h" + #include "geometry/frustum.h" + #include "geometry/rect.h" + #include "plugin/plugin_manager.h" + #include "async/job_perf.h" + + +namespace GS { + namespace Render { + class RasterFont; + struct IEnvironment; + +/// Video mode settings. +enum VideoMode +{ + VideoWindowed = 0, + VideoFullscreen, + VideoWindowedQuiet, ///< Open windowed output but do not automatically show the window. + VideoRaw, + + VideoGenericPAL, ///< Used by console systems. + VideoGenericNTSC +}; + +/// +struct Window +{ + /// Get handle. +virtual void *GetHandle() const = 0; + /// Get render window size. +virtual void GetSize(uint &w, uint &h) = 0; + +virtual ~Window() {} +}; + +/*! + @short Renderer base class. + + This the base that has to be derived to add support for a new renderer. + For example implementations see NullRenderer or GPURenderer. + nNull_Renderer can be used as a starting point in implementing a + new renderer. + + This class also implements all functions required to maintain the minimum + concept of viewport used by the engine. + + @see S3D::Scene::SetSceneInterface(). + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Renderer : public RegistryListener +{ +public: + + NPLACEMENT_NEW(Renderer) + + /// Return the plugin class. +static const char *GetPluginClass() { return "Renderer"; } + /*! + @short Return the plugin version. + + @note This version number must be increased whenever a modification + is made to the base interface in order to prevent incompatible + plugin from being loaded. + */ +static uint GetPluginVersion() { return 1; } + +/*! + @name Resource factory. + @{ +*/ +virtual Geometry *NewGeometry(const char *name = 0) = 0; +virtual Material *NewMaterial(const char *name = 0) = 0; +virtual Texture *NewTexture(const char *name = 0) = 0; +virtual Shader *NewShader(const char *name = 0) = 0; +/// @} + + /// Clear function +enum ClearFunction +{ + ClearColor = (1 << 0), + ClearDepth = (1 << 1), + ClearAll = ~0 +}; + + /*! + @short Geometry updater control word. + @see UpdateGeometry(). + */ +enum GeoUpdate +{ + GEOUPDATE_NONE = 0, + GEOUPDATE_IDX, + GEOUPDATE_VTX, + GEOUPDATE_VNRM, + GEOUPDATE_PNRM, + GEOUPDATE_SOFTVTX, + GEOUPDATE_RGB +}; + +/// Renderer statistics. +struct Statistics +{ + String adapter, + vendor; + + uint queue_pass, ///< Number of queue pass rendered. + light_processed, ///< Number of light processed. + + renderable_processed, ///< Number of renderable processed. + renderable_drawn, ///< Number of renderable drawn. + list_drawn, ///< Number of display list drawn. + triangle_drawn, ///< Number of triangles drawn. + + texture_memory, ///< Texture memory in use. + geometry_memory; ///< Geometry memory in use. + + ASync::JobPerf bench_prepare_light; + + Benchmark bench_post_process, + bench_render; + + /// Reset statistics. + void Reset() + { + queue_pass = 0; + light_processed = 0; + + renderable_processed = 0; + renderable_drawn = 0; + list_drawn = 0; + triangle_drawn = 0; + + bench_post_process.Reset(); + bench_prepare_light.Reset(); + bench_render.Reset(); + } + + Statistics() + { + texture_memory = 0; + geometry_memory = 0; + + Reset(); + } +}; + + /// Reload managed resources on context change. +virtual void OnContextChanged(ResourceFactory *) {} + /// Get current adapter ideal triangle batch size. +virtual uint GetTriangleIdealBatchSize() const { return 16384; } + +/*! + @name Renderer registry. + @{ +*/ + Registry registry; + +virtual RegistryRValue ProcessMessage(RegistryMessage, const Registry *, const void *parm) { return RegistryReturn_Ok; } +/*! + @} + @name Renderer queue system. + @{ +*/ + List renderable_list; + + /// Delete the renderable list. + void DeleteRenderableList(); + /// Push a renderable to the renderable list. + void PushRenderable(Core::Renderable *); + + /*! + @short Build a renderable primitive list. + + A separate lod view can be provided to ensure selection of the + correct geometry lod when rendering derived views such as shadow + maps. + */ + uint BuildRenderablePrimitiveList(const Core::Camera &view, const Core::Camera &lod_view, Stack &, Core::Renderable::Context = Core::Renderable::Context_Default) const; +/// @} + +protected: + + String error; ///< Last error description. + + /// Request lights to the manager and setup lighting. + void RequestAndSetupLighting(Vector4 &pos); + + // Renderer state. + bool fullscreen; ///< Windowed or fullscreen? + + float output_aspect_ratio; ///< Output aspect ratio override (default: -1 for no override) + + float global_aspect_ratio; ///< Global aspect ratio. + + Core::Camera *view_item; ///< Current view item. + Registry *view_registry; ///< Current view registry. + Frustum frustum; ///< Current frustum. + + sTexture output_texture; ///< Frame buffer output texture. + + List windows; + + Window *output_window; + Window *default_window; + +public: + tVector2 dimensions; ///< Output dimensions. + tVector2 ideal_render_system_vr_resolution; + + tVector2 saved_ideal_render_system_vr_resolution; + + float ipd; + bool use_fix_camera; + + Window* GetOutputWindow(){ return output_window; } + + // Renderer statistics. + Statistics stats; + + /// Set output texture. +virtual void SetOutputTexture(Texture *texture) { output_texture = texture; } + + /// Get output dimensions. + tVector2 GetOutputDimensions() const; + + /// Return the output aspect ratio. + float GetOutputAspectRatio() const; + /// Set the output aspect ratio override (0 to disable), returns the previous aspect ratio. + float SetOutputAspectRatio(float k = 0) { float v = output_aspect_ratio; output_aspect_ratio = k; return v; } + + /// Get renderer global aspect ratio. + float GetGlobalAspectRatio() const { return global_aspect_ratio; } + /// Set renderer global aspect ratio, returns the previous aspect ratio. + float SetGlobalAspectRatio(float k = 1.f) { float v = global_aspect_ratio; global_aspect_ratio = k; return v; } + + /// Is the renderer fullscreen. + bool isFullscreen() const { return fullscreen; } + +virtual void ResetStatistics() { stats.Reset(); } + + /// Display on-screen statistics. +virtual void DrawProfilerText(RasterFont *[2], float &x, float &y); + + /// Return the current camera. + Core::Camera *GetCamera() const; + /// Set the current viewing item. + void SetCamera(Core::Camera *); + /// Apply view. +virtual void ApplyCamera(); + + /// Set view registry. + void SetViewRegistry(Registry *); + + /*! + @short Interface used by the renderer to query environment. + @see SetEnvironmentInterface(). + */ + IEnvironment *environment_interface; + /// Set the scene interface. + void SetEnvironmentInterface(IEnvironment *itf) { environment_interface = itf; } + +/*! + @name Renderer core. + These are the functions to be reimplemented by a capable renderer. + @{ +*/ + /// Start a new frame. +virtual bool BeginDrawList() = 0; + /// End current frame, draw to back-buffer. +virtual void EndDrawList() = 0; + + /// Returns the renderer's name as a C string. +virtual const char *GetName() const = 0; + /// Returns a C string describing the renderer. +virtual const char *GetDescription() const = 0; + /// Returns a C string containing the renderer version number. +virtual const char *GetVersion() const = 0; + /// Returns a C string containing the last error description. +virtual const char *GetError() const { return error; } + + /// Open video. +virtual bool Open(uint width, uint height, char bpp = 32, VideoMode = VideoWindowed, const void *sys_handle = 0) = 0; + /// Free all renderer resources. +virtual void Free() {} + /// Close video. +virtual void Close() {} + + /// Setup core resources. +virtual bool SetupCoreResources(bool support_3d = true) { return true; } + + /// Explicitly resize video output. +virtual bool ResizeVideo(uint width, uint height) = 0; + /// Switch to/from fullscreen. +virtual void SetFullscreen(bool = true) = 0; + /// Refresh display output. +virtual void Refresh() = 0; + /// Return a pointer to the current subsystem window output. +virtual void *GetCurrentSystemWindowHandle() const = 0; + + /// Setup an extra window to use as renderer output. +virtual Window *NewOutputWindow(const void *) = 0; + /// Set the output window. +virtual void SetOutputWindow(Window * = 0) = 0; + /// Free a rendering window. +virtual void FreeOutputWindow(Window *) = 0; + + /// Render the display queue. +virtual void RenderList() = 0; + /// Request that the frame be displayed to current output window. +virtual void ShowFrame() = 0; + + /// Clear the render target. +virtual void Clear(float r, float g, float b, float a = 1.f, float z = 1.f, ClearFunction = ClearAll) = 0; + /// Grab the frame buffer to a texture. +virtual void GrabDisplay(Texture *) = 0; + /// Grab the frame buffer to a picture. +virtual void GrabDisplay(Picture &) = 0; + +virtual void RenderFrame() {}; + + + + /// Set a texture as render target. +virtual void SetRenderTarget(Texture *) = 0; + + /// Draw line. +virtual void DrawLine(uint count, const Vector4 *, const Color * = 0, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Shader * = 0) = 0; + /// Draw triangle. +virtual void DrawTriangle(uint count, const Vector4 *, const ushort *idx = 0, const Color * = 0, const Vector2 * = 0, const Texture * = 0, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Shader * = 0) = 0; + /// Draw sprite. +virtual void DrawSprite(uint count, const Vector4 *, const Color * = 0, const float *size = 0, const Texture * = 0, float global_size = 1.f, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Shader * = 0) = 0; + +// +struct WriterConfig +{ + bool correct_ar; ///< Enforce aspect ratio. + bool normalized; ///< Normalized/absolute coordinates. + + WriterConfig(bool normd = true, bool ar = true) : normalized(normd), correct_ar(ar) {} +}; + +enum WriterAlignment +{ + AlignLeft = 0, + AlignMiddle, + AlignRight +}; + + /// Output string to screen. +virtual void Write(const RasterFont &, const char *, float &x, float &y, const WriterConfig &, float s = 1, const Color * = 0, WriterAlignment = AlignLeft, bool mirrored = false) = 0; + + /// Set the view matrix. +virtual void SetViewMatrix(const Matrix4 &, const Matrix4 *inverse = 0) = 0; + /// Set the projection matrix. +virtual void SetProjectionMatrix(const Matrix4 &) = 0; + /// Set the world matrix. +virtual void SetWorldMatrix(const Matrix4 &, const Matrix4 *inverse = 0) = 0; + + /// Clear the user clipping plane. +virtual void ClearClippingPlane() = 0; + /// Set the user clipping plane. +virtual void SetClippingPlane(const Vector4 &p, const Vector4 &n) = 0; + + /// Set clipping rect. +virtual void SetClippingRect(const fRect *) = 0; + /// Get clipping rect. +virtual fRect GetClippingRect() const = 0; + + /// Set viewport. +virtual void SetViewport(const fRect &) = 0; + /// Get viewport. +virtual fRect GetViewport() const = 0; +/// @} + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); + + Renderer(); +virtual ~Renderer(); +}; + +typedef PluginManager RendererPluginManager; + + } // Render +} // GS + + +#endif // __NBASERENDERER__ diff --git a/include/engine/core/renderer_environment_interface.h b/include/engine/core/renderer_environment_interface.h new file mode 100644 index 0000000..3b5f980 --- /dev/null +++ b/include/engine/core/renderer_environment_interface.h @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRENDERERENVINTERFACE__ +#define __NRENDERERENVINTERFACE__ + + + #include "core/render_data.h" + #include "color/color.h" + #include "container/nlist.h" + + +namespace GS { + struct Vector4; + class Frustum; + + namespace Core { + class Camera; + class Light; + } + namespace Render { + +/* + @short Renderer environment interface. + Used by the renderer to communicate events and query environment informations. +*/ +struct IEnvironment +{ + /// Get environment clock. +virtual float GetClock() const { return 0; } + + /// Get environment time of day. +virtual float GetTimeOfDay() const { return 0.f; } + /// Get user sky box shader. +virtual Shader *GetSkyboxShader() const { return 0; } + /// Get sky box texture layers. +virtual bool GetSkyboxLayers(sTexture [2]) const { return false; } + + /// Get clear color. +virtual Color GetClearColor() const { return Color::Black; } + /// Get ambient color. +virtual Color GetAmbientColor() const { return Color::Black; } + /// Get environment probe. +virtual void GetEnvironmentProbe(sTexture &/*radiance*/, sTexture &/*irradiance*/) const {} + + /// Get current camera. +virtual Core::Camera *GetCurrentCamera() const { return 0; } + + /// Get all lights in frustum. +virtual void GetLightsInFrustum(const Vector4 &/*world_pos*/, const Frustum &/*frustum*/, List &/*list*/, uint /*limit*/ = 0) const = 0; + /// Get closest lights. +virtual void GetClosestLights(const Vector4 &/*world_pos*/, List &/*list*/, uint /*limit*/ = 0) const = 0; + + /// Get fog enabled. +virtual bool IsFogEnabled() const { return false; } + /// Get fog configuration. +virtual bool GetFogConfiguration(Color &color, float &fog_near, float &fog_far) const { return false; } + + /// Render user/debug primitive hook. +virtual void OnRenderUser(Renderer *) const {} + +virtual ~IEnvironment() {} +}; + + } // Render +} // GS + + +#endif // __NRENDERERENVINTERFACE__ diff --git a/include/engine/core/renderer_resource_factory.h b/include/engine/core/renderer_resource_factory.h new file mode 100644 index 0000000..6ceef03 --- /dev/null +++ b/include/engine/core/renderer_resource_factory.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRENDERER_RESOURCE_FACTORY__ +#define __NRENDERER_RESOURCE_FACTORY__ + + + #include "core/render_resource_factory.h" + + +namespace GS { + namespace Render { + class Renderer; + +// +struct RendererResourceFactory : public ResourceFactory +{ + Renderer &renderer; + +virtual Geometry *NewGeometry(); +virtual Material *NewMaterial(); +virtual Texture *NewTexture(); +virtual Shader *NewShader(); + +virtual Geometry *LoadGeometry(const char *, bool bypass_cache = false, Geometry * = 0); +virtual Material *LoadMaterial(const char *, bool bypass_cache = false, Material * = 0); +virtual Texture *LoadTexture(const char *, bool bypass_cache = false, Texture * = 0); +virtual Shader *LoadShader(const char *, bool bypass_cache = false, Shader * = 0); + + RendererResourceFactory(Renderer &r) : renderer(r) {} +}; + + } // Render +} // GS + + +#endif // __NRENDERER_RESOURCE_FACTORY__ \ No newline at end of file diff --git a/include/engine/core/renderer_toolbox.h b/include/engine/core/renderer_toolbox.h new file mode 100644 index 0000000..5a7d629 --- /dev/null +++ b/include/engine/core/renderer_toolbox.h @@ -0,0 +1,66 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRENDERER_TOOLBOX__ +#define __NRENDERER_TOOLBOX__ + + + #include "core/renderer.h" + + +namespace GS { + namespace RendererToolbox { + using Core::Material; + using Render::Renderer; + +/// Wrapper to display a cross in 3D. +void DrawCross(Renderer &, const Vector4 &, float size = Units::Mtr(1), const Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display an axis aligned square in 3D. +void DrawSquare(Renderer &, const Vector4 &, float size = Units::Mtr(1), Material::BlendOperator = Material::Blend_None); +/// Wrapper to display an OOBB using the line function of a derived renderer. +void DrawOBB(Renderer &, const OBB &, const Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display an OOBB using the triangle function of a derived renderer. +void DrawFilledOBB(Renderer &, const OBB &, const Color *, Material::BlendOperator = Material::Blend_None, Material::RenderWord = Material::Render_None); +/// Wrapper to display an AABB in 3D. +void DrawAABB(Renderer &, const MinMax &, const Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display a cube in 3D. +void DrawCube(Renderer &, const Vector4 &, float size = Units::Mtr(1), const Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display a sphere in 3D. +void DrawSphere(Renderer &, const Vector4 &, float radius = Units::Mtr(1), const Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display a ball in 3D. +void DrawBall(Renderer &, const nMatrix4 &, float radius = Units::Mtr(1), Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display a circle in 3D. +void DrawCircle(Renderer &, const Vector4 &, float radius = Units::Mtr(1), const Matrix3 * = 0, const Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display a cylinder in 3D. +void DrawCylinder(Renderer &, const Vector4 &, float radius = Units::Mtr(1), float length = Units::Mtr(1), const Matrix3 * = 0, const Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display a capsule in 3D. +void DrawCapsule(Renderer &, const Vector4 &, float radius = Units::Mtr(1.f), float length = Units::Mtr(1), const Matrix3 * = 0, const Color * = 0, Material::BlendOperator = Material::Blend_None); +/// Wrapper to display a cone in 3D. +void DrawCone(Renderer &, const Vector4 &, float radius = Units::Mtr(1.f), float length = Units::Mtr(1), const Matrix3 * = 0, const Color * = 0, Material::BlendOperator = Material::Blend_None); + +/// Wrapper to line 3D. +void Line3D(Renderer &, const Vector4 &, const Vector4 &, const Color * = 0, Material::BlendOperator = Material::Blend_None, Material::RenderWord = Material::Render_None); +/// Draw triangle. +void Triangle3D(Renderer &, const Vector4 [3], const Color [3] = 0, const Vector2 [3] = 0, const Render::Texture * = 0, Material::BlendOperator = Material::Blend_None, Material::RenderWord = Material::Render_None); + +/// Return nearest but highest power of two from a given value. +template T GetPow2(T v, bool no_shrink = false) +{ + T h = 1; + if (no_shrink) + while (h < v) + h *= 2; + else + while ((h + h / 2) < v) + h *= 2; + return h; +} + + } // RendererToolbox +} // GS + + +#endif // __NRENDERER_TOOLBOX__ diff --git a/include/engine/core/resource_factories.h b/include/engine/core/resource_factories.h new file mode 100644 index 0000000..9a6df7f --- /dev/null +++ b/include/engine/core/resource_factories.h @@ -0,0 +1,32 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRESOURCEFACTORIES__ +#define __NRESOURCEFACTORIES__ + + + #include "core/graphic_resource_factory.h" + #include "core/render_resource_factory.h" + #include "core/mixer_resource_factory.h" + + +namespace GS { + namespace Core { + +struct ResourceFactories : public SharedObject +{ + AutoPtr graphic; + AutoPtr render; + AutoPtr audio; +}; + +typedef SharedPtr sResourceFactories; + + } // Core +} // GS + + +#endif // __NRESOURCEFACTORIES__ diff --git a/include/engine/core/resource_factory_event_interface.h b/include/engine/core/resource_factory_event_interface.h new file mode 100644 index 0000000..b53010e --- /dev/null +++ b/include/engine/core/resource_factory_event_interface.h @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __RESOURCEFACTORYEVENTINTERFACE__ +#define __RESOURCEFACTORYEVENTINTERFACE__ + + + #include "memory/nshared_ptr.h" + + +namespace GS { + +// +struct IResourceFactoryEvent : public SharedObject +{ +virtual void OpenLoad() {} +virtual void LoadProgress(const char *, float = -1) {} +virtual void EndLoad() {} +}; + +typedef SharedPtr sIResourceFactoryEvent; + +} // GS + + +#endif // __RESOURCEFACTORYEVENTINTERFACE__ diff --git a/include/engine/core/resource_geometry_generator.h b/include/engine/core/resource_geometry_generator.h new file mode 100644 index 0000000..3925078 --- /dev/null +++ b/include/engine/core/resource_geometry_generator.h @@ -0,0 +1,27 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __RESOURCE_GEOMETRY_GENERATOR__ +#define __RESOURCE_GEOMETRY_GENERATOR__ + + +namespace GS { + namespace Core { + class Geometry; + + namespace GeometryGenerator { + +/// Is a geometry name referring to a generated resource. +bool IsGenerated(const char *); +/// Generate a geometry. +bool Generate(const char *, Geometry &); + + } // GeometryGenerator + } // Core +} // GS + + +#endif // __RESOURCE_GEOMETRY_GENERATOR__ diff --git a/include/engine/core/shader.h b/include/engine/core/shader.h new file mode 100644 index 0000000..7d57a5f --- /dev/null +++ b/include/engine/core/shader.h @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRENDERERSHADER__ +#define __NRENDERERSHADER__ + + + #include "core/shader_input.h" + #include "container/nlist.h" + #include "memory/nshared_ptr.h" + + +namespace GS { + namespace Core { + +// Shader varying. +struct ShaderVarying +{ + String type, name; +}; + +/*! + @short Shader base class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Shader : public SharedObject +{ + String name; + + String vertex_decl, vertex, + pixel_decl, pixel, + geometry_decl, geometry; + + AutoList input_list; + AutoList varying_list; + + /// Clone this shader to a new object. + bool Clone(Shader &clone) const; + + /// Declare a varying. + ShaderVarying *DeclareVarying(const char *name, const char *type); + /// Declare an input. + ShaderInput *DeclareInput(const char *name, ShaderInput::DataType data_type, ShaderInput::Semantic semantic, ShaderInput::Type parm_type, ShaderInput::Scope parm_scope, uint array_size = 1); + + /// Get a shader input from its semantic. + ShaderInput *GetInput(ShaderInput::Semantic semantic) const; + + /// Set a define. + void Define(const char *, ShaderInput::Scope define_scope); + + /// Declare inputs from a meta tag. + void ParseInputTag(NML::Tag *); + /// Declare varyings from a meta tag. + void ParseVaryingTag(NML::Tag *); + + /// Add an ISL section to this shader. + bool AddISLSection(const char *uri); + + void Clear(); + +/*! + @name Serialization. + @{ +*/ + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; +/// @} + + Shader(const char *name = 0, const char *vertex = 0, const char *fragment = 0, const char *geometry = 0); +}; + + } // Core +} // GS + + +#endif // __NRENDERERSHADER__ diff --git a/include/engine/core/shader_block.h b/include/engine/core/shader_block.h new file mode 100644 index 0000000..4a2aeab --- /dev/null +++ b/include/engine/core/shader_block.h @@ -0,0 +1,859 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSHADER_BLOCK__ +#define __NSHADER_BLOCK__ + + + #include "core/shader.h" + #include "color/color.h" + #include "math/matrix3.h" + #include "math/matrix4.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace NML { class Tag; } + + namespace Core { + struct ShaderBlockPin; + struct ShaderBlock; + +typedef ShaderBlock * pShaderBlock; + +/*! + @short Block shader value. + Used by the raytracer software implementation of the shader blocks. +*/ +struct ShaderBlockValue +{ + enum BlockValueType + { + BlockValueNone = 0, + BlockValueVector, + BlockValueMatrix3, + BlockValueMatrix4, + BlockValueTexture + }; + + BlockValueType type; + + // Can't union those and most of all we don't want runtime allocations here... + Vector4 v; + Matrix3 m3; + Matrix4 m4; + String t; + + void Set(const float &_f) + { v.x = _f; type = BlockValueVector; } + void Set(const Vector4 &_v) + { v = _v; type = BlockValueVector; } + void Set(const Matrix3 &_m) + { m3 = _m; type = BlockValueMatrix3; } + void Set(const Matrix4 &_m) + { m4 = _m; type = BlockValueMatrix4; } + + void Set(const char *_t) + { t = _t; type = BlockValueTexture; } + + ShaderBlockValue() : type(BlockValueNone) {} +}; + +/*! + @short Base render block. + + A render block is a component of a render map. It represents an input, an + operator to the render map. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ShaderBlock +{ +enum BlockType +{ + TypeNone = 0, + + // Input blocks. + TypeGeometryVertex, + TypeGeometryNormal, + TypeGeometryUV, + TypeGeometrySkinning, + TypeGeometryVertexColor, + TypeGeometryTangentFrame, + TypeRenderBuffer, + TypeTexture, + TypeTextureSampler, + TypeConstant, + TypeColor, + TypeMaterialParam, + TypeMaterialTexture, + TypeScreenUV, + TypeViewVector, + TypeViewport, + + // Matrix blocks. + TypeNormalViewMatrix, + TypeNormalMatrix, + TypeModelViewMatrix, + TypeModelMatrix, + + // Operator blocks. + TypeMix, + TypeAdd, + TypeMul, + TypeSub, + TypeDiv, + TypeDot, + TypeCross, + TypeClamp, + TypeNormalize, + TypeSwizzle, + TypeBuild, + TypeSin, + TypeCos, + TypePow, + TypeAbs, + + // Packing operators. + TypeUnpackColorToVector, + TypePackVectorToColor, + + // Engine parameters. + TypeClock, + + TypeInvalid +}; + + /// Verbose block type. +static const char *BlockTypeToString(BlockType type) + { + switch (type) + { + case TypeNone: return "None"; + + case TypeGeometryVertex: return "Geometry Vertex"; + case TypeGeometryNormal: return "Geometry Normal"; + case TypeGeometryUV: return "Geometry UV"; + case TypeGeometrySkinning: return "Geometry Skinning"; + case TypeGeometryVertexColor: return "Geometry RGB"; + case TypeGeometryTangentFrame: return "Geometry Tangent Frame"; + case TypeRenderBuffer: return "Render Buffer"; + case TypeTexture: return "Texture"; + case TypeTextureSampler: return "Texture Sampler"; + case TypeConstant: return "Constant"; + case TypeColor: return "Color"; + case TypeMaterialParam: return "Material Parameter"; + case TypeMaterialTexture: return "Material Texture"; + case TypeScreenUV: return "Screen UV"; + case TypeViewVector: return "View Vector"; + case TypeViewport: return "Viewport"; + + case TypeNormalViewMatrix: return "Normal View Matrix"; + case TypeNormalMatrix: return "Normal Matrix "; ///< ! The additional space is NEEDED! (Normal matrix is the name of a legacy version of this node) + case TypeModelViewMatrix: return "Model View Matrix"; + case TypeModelMatrix: return "Model Matrix"; + + case TypeMix: return "Mix"; + case TypeAdd: return "Add"; + case TypeMul: return "Multiply"; + case TypeSub: return "Subtract"; + case TypeDiv: return "Divide"; + case TypeDot: return "Dot"; + case TypeCross: return "Cross"; + case TypeClamp: return "Clamp"; + case TypeNormalize: return "Normalize"; + case TypeSwizzle: return "Swizzle"; + case TypeBuild: return "Build"; + case TypeSin: return "Sinus"; + case TypeCos: return "Cosinus"; + case TypePow: return "Pow"; + case TypeAbs: return "Abs"; + + case TypeUnpackColorToVector: return "Unpack color to vector"; + case TypePackVectorToColor: return "Pack vector to color"; + + case TypeClock: return "Clock"; + + case TypeInvalid: break; + } + return "Invalid"; + } + + Vector2 pos; + BlockType type; + +/* + @name Block input/output. + @{ +*/ + /// Get input count. +virtual uint GetInputCount() const = 0; + /// Get input block. +virtual ShaderBlock *GetInput(uint n) const = 0; + /// Set input. +virtual bool SetInput(uint n, ShaderBlock *in) = 0; + + /// Get input pin. +virtual const ShaderBlockPin *GetInputPin(uint n) const = 0; + /// Get block output pin. +virtual const ShaderBlockPin *GetOutputPin() const = 0; + + /// Evaluate block output type. +virtual int GetOutputType() const = 0; +/// @} + + /// Get block label. +virtual String GetLabel() const = 0; + /// Get block id. +virtual String GetId() const = 0; + + /// Is this block equivalent to another block. + bool IsEquivalent(const ShaderBlock *input_block) const; + + /// Gather all of this block children. + void GatherChildren(List &children); + + /// Import block map from metatag. +static Array *BlockMapFromMetaTag(NML::Tag &); + /// Import branch from metatag. +static ShaderBlock *BranchFromMetaTag(NML::Tag &, Array *block_map = 0); + +static NML::Tag *BlockMapAsMetaTag(const List &block_map); + NML::Tag *BranchAsMetaTag(List &block_map); + NML::Tag *ParamAsMetaTag() const; + + ShaderBlock() : type(TypeNone) {} +virtual ~ShaderBlock() {} +}; + +//------------------------------------------------------------------------------ +#define __SpecializeBlock(__LABEL__, __INPUT_COUNT__)\ +static ShaderBlockPin input_pin[__INPUT_COUNT__];\ +static ShaderBlockPin output_pin;\ + \ + ShaderBlock *input[__INPUT_COUNT__];\ + \ + String GetLabel() const\ + { return __LABEL__; }\ + uint GetInputCount() const\ + { return __INPUT_COUNT__; }\ + bool SetInput(uint n, ShaderBlock *block)\ + {\ + if (n >= __INPUT_COUNT__)\ + return false;\ + if (block && !(input_pin[n].compatibility & block->GetOutputType()))\ + return false;\ + input[n] = block;\ + return true;\ + }\ + ShaderBlock *GetInput(uint n) const\ + { return (n < __INPUT_COUNT__) ? input[n] : 0; }\ + const ShaderBlockPin *GetInputPin(uint n) const\ + { return (n < __INPUT_COUNT__) ? &input_pin[n] : 0; }\ + const ShaderBlockPin *GetOutputPin() const\ + { return &output_pin; }\ + int GetOutputType() const; + +#define __SpecializeBlockNoInput(__LABEL__)\ +static ShaderBlockPin output_pin;\ + \ + String GetLabel() const\ + { return __LABEL__; }\ + uint GetInputCount() const\ + { return 0; }\ + bool SetInput(uint /*n*/, ShaderBlock */*block*/)\ + { return false; }\ + ShaderBlock *GetInput(uint /*n*/) const\ + { return 0; }\ + const ShaderBlockPin *GetInputPin(uint /*n*/) const\ + { return 0; }\ + const ShaderBlockPin *GetOutputPin() const\ + { return &output_pin; }\ + int GetOutputType() const; + +//------------------------------------------------------------------------------ + +/* + @short Render block pin description. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ShaderBlockPin +{ + const char *name, + *desc; + int compatibility; ///< Pin connection compatibility +}; + +struct SinusShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Sinus", 1) + + String GetId() const + { return "Sin"; } + SinusShaderBlock(ShaderBlock *block = 0) + { + type = TypeSin; + input[0] = block; + } +}; + +struct CosinusShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Cosinus", 1) + + String GetId() const + { return "Cos"; } + CosinusShaderBlock(ShaderBlock *block = 0) + { + type = TypeCos; + input[0] = block; + } +}; + +struct PowShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Pow", 2) + + String GetId() const + { return "Pow"; } + PowShaderBlock(ShaderBlock *v = 0, ShaderBlock *p = 0) + { + type = TypePow; + input[0] = v; + input[1] = p; + } +}; + +struct AbsShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Abs", 1) + + String GetId() const + { return "Abs"; } + AbsShaderBlock(ShaderBlock *v = 0) + { + type = TypeAbs; + input[0] = v; + } +}; + +struct ClockShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Clock") + + String GetId() const + { return "Clock"; } + ClockShaderBlock() + { type = TypeClock; } +}; + +struct ScreenUVShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Screen UV") + + String GetId() const + { return "ScreenUV"; } + ScreenUVShaderBlock() + { type = TypeScreenUV; } +}; + +struct ViewVectorShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("View Vector") + + String GetId() const + { return "ViewV"; } + ViewVectorShaderBlock() + { type = TypeViewVector; } +}; + +struct ViewportShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Viewport") + + String GetId() const + { return "Viewport"; } + ViewportShaderBlock() + { type = TypeViewport; } +}; + +struct NormalViewMatrixShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Normal View Matrix") + + String GetId() const + { return "NormalViewMatrix"; } + NormalViewMatrixShaderBlock() + { type = TypeNormalViewMatrix; } +}; + +struct NormalMatrixShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Normal Matrix ") + + String GetId() const + { return "NormalMatrix"; } + NormalMatrixShaderBlock() + { type = TypeNormalMatrix; } +}; + +struct ModelViewMatrixShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Model View Matrix ") + + String GetId() const + { return "ModelViewMatrix"; } + ModelViewMatrixShaderBlock() + { type = TypeModelViewMatrix; } +}; + +struct ModelMatrixShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Model Matrix") + + String GetId() const + { return "ModelMatrix"; } + ModelMatrixShaderBlock() + { type = TypeModelMatrix; } +}; + +struct UnpackColorToVectorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Unpack Color", 1) + + String GetId() const + { return "UnpackColor"; } + UnpackColorToVectorShaderBlock(ShaderBlock *block = 0) + { + type = TypeUnpackColorToVector; + input[0] = block; + } +}; + +struct PackVectorToColorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Pack Vector", 1) + + String GetId() const + { return "PackVector"; } + PackVectorToColorShaderBlock(ShaderBlock *block = 0) + { + type = TypePackVectorToColor; + input[0] = block; + } +}; + +struct MixOperatorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Mix", 3) + + String GetId() const + { return "Mix"; } + MixOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0, ShaderBlock *k = 0) + { + type = TypeMix; + input[0] = a; input[1] = b; input[2] = k; + } +}; + +struct AddOperatorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Add", 2) + + String GetId() const + { return "Add"; } + AddOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) + { + type = TypeAdd; + input[0] = a; input[1] = b; + } +}; + +struct MulOperatorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Mul", 2) + + String GetId() const + { return "Mul"; } + MulOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) + { + type = TypeMul; + input[0] = a; input[1] = b; + } +}; + +struct SubOperatorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Sub", 2) + + String GetId() const + { return "Sub"; } + SubOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) + { + type = TypeSub; + input[0] = a; input[1] = b; + } +}; + +struct DivOperatorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Div", 2) + + String GetId() const + { return "Div"; } + DivOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) + { + type = TypeDiv; + input[0] = a; input[1] = b; + } +}; + +struct DotOperatorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Dot", 2) + + String GetId() const + { return "Dot"; } + DotOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) + { + type = TypeDot; + input[0] = a; input[1] = b; + } +}; + +struct CrossOperatorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Cross", 2) + + String GetId() const + { return "Cross"; } + CrossOperatorShaderBlock(ShaderBlock *a = 0, ShaderBlock *b = 0) + { + type = TypeCross; + input[0] = a; input[1] = b; + } +}; + +struct NormalizeOperatorShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Normalize", 1) + + String GetId() const + { return "Norm"; } + NormalizeOperatorShaderBlock(ShaderBlock *a = 0) + { + type = TypeNormalize; + input[0] = a; + } +}; + +struct ClampShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Clamp", 3) + + String GetId() const + { return "Clamp"; } + ClampShaderBlock(ShaderBlock *v = 0, ShaderBlock *a = 0, ShaderBlock *b = 0) + { + type = TypeClamp; + input[0] = v; input[1] = a; input[2] = b; + } +}; + +struct SwizzleShaderBlock : public ShaderBlock +{ +enum Swizzle +{ + SwizzleNone = 0, + SwizzleX, + SwizzleY, + SwizzleZ, + SwizzleW +}; + + __SpecializeBlock("Swizzle", 1) + + String GetId() const + { return String::Format("Swizzle%d%d%d%d", swizzle[0], swizzle[1], swizzle[2], swizzle[3]); } + Swizzle swizzle[4]; + SwizzleShaderBlock(ShaderBlock *block = 0, Swizzle x = SwizzleNone, Swizzle y = SwizzleNone, Swizzle z = SwizzleNone, Swizzle w = SwizzleNone) + { + type = TypeSwizzle; + swizzle[0] = x; swizzle[1] = y; swizzle[2] = z; swizzle[3] = w; + input[0] = block; + } +}; + +struct BuildShaderBlock : public ShaderBlock +{ +enum Build +{ + BuildZero = 0, + BuildOne, + BuildX, + BuildY, + BuildZ, + BuildW +}; + + __SpecializeBlock("Build", 4) + + Build build[4]; + String GetId() const + { return String::Format("Build%d%d%d%d", build[0], build[1], build[2], build[3]); } + BuildShaderBlock(ShaderBlock *a = 0, Build x = BuildX, ShaderBlock *b = 0, Build y = BuildY, ShaderBlock *c = 0, Build z = BuildZ, ShaderBlock *d = 0, Build w = BuildW) + { + type = TypeBuild; + build[0] = x; build[1] = y; build[2] = z; build[3] = w; + input[0] = a; input[1] = b; input[2] = c; input[3] = d; + } +}; + +struct GeometryUVShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("UV Stream") + + int channel; + String GetId() const + { return String::Format("UV%d", channel); } + + GeometryUVShaderBlock(int uv_channel = 0) + { + type = TypeGeometryUV; + channel = uv_channel; + } +}; + +struct GeometryVertexShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Vertex Stream") + + String GetId() const + { return String("Vertex"); } + + GeometryVertexShaderBlock() + { type = TypeGeometryVertex; } +}; + +struct GeometryNormalShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Normal Stream") + + bool smooth; + String GetId() const + { return String(smooth ? "NormalSmooth" : "Normal"); } + + GeometryNormalShaderBlock() + { + type = TypeGeometryNormal; + smooth = true; + } +}; + +struct GeometrySkinningShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Skinning Matrix") + + String GetId() const + { return String("SkinMtx"); } + + GeometrySkinningShaderBlock() + { type = TypeGeometrySkinning; } +}; + +struct GeometryVertexColorShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Vertex Color Stream") + + String GetId() const + { return String("VertexColor"); } + GeometryVertexColorShaderBlock() + { type = TypeGeometryVertexColor; } +}; + +struct GeometryTangentFrameShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Tangent Frame") + + String GetId() const + { return String("TangentMtx"); } + + GeometryTangentFrameShaderBlock() + { type = TypeGeometryTangentFrame; } +}; + +struct RenderBufferShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Render Buffer") + +enum RenderBuffer +{ + Depth = 0 +}; + + RenderBuffer buffer; + String GetId() const + { return String("RenderBuffer"); } + + RenderBufferShaderBlock(RenderBuffer _buffer = Depth) + { + type = TypeRenderBuffer; + buffer = _buffer; + } +}; + +struct TextureShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Texture") + + enum TextureType + { + Texture2D = 0, + Texture3D, + TextureCube + }; + TextureType texture_type; + + String texture; + String GetId() const; + + TextureShaderBlock(const char *name = 0) + { + type = TypeTexture; + texture = name; + texture_type = Texture2D; + } +}; + +struct TextureSamplerShaderBlock : public ShaderBlock +{ + __SpecializeBlock("Texture Sampler", 2) + + enum SamplerType + { + Sampler2D = 0, + Sampler3D, + SamplerCube + }; + SamplerType sampler_type; + + String GetId() const + { return String::Format("TexSampler%d", (int)sampler_type); } + + TextureSamplerShaderBlock(ShaderBlock *texture = 0, ShaderBlock *uv = 0) + { + type = TypeTextureSampler; + + sampler_type = Sampler2D; + input[0] = texture; + input[1] = uv; + } +}; + +struct MaterialParamShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Material Parameter") + +enum MaterialParam +{ + MaterialDiffuse = 0, + MaterialSpecular, + MaterialSelf, + MaterialAmbient, + MaterialGlossiness, + MaterialOpacity, + MaterialReflection +}; + + MaterialParam param; + + String GetId() const; + MaterialParamShaderBlock(MaterialParam p = MaterialDiffuse) + { + type = TypeMaterialParam; + param = p; + } +}; + +struct MaterialTextureShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Material Texture") + + enum TextureType + { + Texture2D = 0, + Texture3D, + TextureCube + }; + TextureType texture_type; + int slot; + + String GetId() const; + + MaterialTextureShaderBlock(int n = 0) + { + type = TypeMaterialTexture; + texture_type = Texture2D; + slot = n; + } +}; + +struct ColorShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Color") + + Color color; + + String GetId() const + { return "Color"; } + + ColorShaderBlock(float r = 1, float g = 1, float b = 1, float a = 1) + { + type = TypeColor; + color.Set(r, g, b, a); + } +}; + +struct ConstantShaderBlock : public ShaderBlock +{ + __SpecializeBlockNoInput("Constant") + + float constant[4]; + ShaderInput::DataType constant_type; + String GetId() const; + + ConstantShaderBlock() + { + type = TypeConstant; constant_type = ShaderInput::NoData; + constant[0] = constant[1] = constant[2] = constant[3] = 0; + } + ConstantShaderBlock(float v) + { + type = TypeConstant; constant_type = ShaderInput::Float; + constant[0] = v; constant[1] = constant[2] = constant[3] = 0; + } + ConstantShaderBlock(float u, float v) + { + type = TypeConstant; constant_type = ShaderInput::Vector2; + constant[0] = u; constant[1] = v; constant[2] = constant[3] = 0; + } + ConstantShaderBlock(float x, float y, float z) + { + type = TypeConstant; constant_type = ShaderInput::Vector3; + constant[0] = x; constant[1] = y; constant[2] = z; constant[3] = 0; + } + ConstantShaderBlock(float x, float y, float z, float w) + { + type = TypeConstant; constant_type = ShaderInput::Vector4; + constant[0] = x; constant[1] = y; constant[2] = z; constant[3] = w; + } +}; + + } // Core +} // GS + + +#endif // __NSHADER_BLOCK__ diff --git a/include/engine/core/shader_input.h b/include/engine/core/shader_input.h new file mode 100644 index 0000000..66cf3ab --- /dev/null +++ b/include/engine/core/shader_input.h @@ -0,0 +1,225 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSHADERINPUT__ +#define __NSHADERINPUT__ + + + #include "math/vector.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace Core { + +/// Shader input. +struct ShaderInput +{ +enum Type +{ + None = 0, + + Uniform, ///< User programmed shader variable. + Attribute ///< User bound shader input stream. +}; + +enum Semantic // do not reorder! +{ + // Data attributes. + Position = 0, + Normal, + UV0, + UV1, + UV2, + VertexColor, + Tangent, + Bitangent, + BoneIndex, + BoneWeight, + + // Data uniforms. + Constant, + + Texture2D, + Texture3D, + TextureCube, + + Clock, + TimeOfDay, ///< Environment time of day (eg. skybox) + ViewVector, + ViewPosition, + Viewport, + ZNear, + ZFar, + ZoomFactor, + FxScale, + InverseBufferSize, + InverseViewportSize, + DisplayBufferRatio, + ViewportRatio, + ViewDepthOffset, + AmbientColor, + FogColor, + FogNear, + FogFar, + FogInverseRange, + DepthBuffer, + FrameBuffer, + GBuffer0, + GBuffer1, + GBuffer2, + GBuffer3, + NoiseMap, + + NormalMatrix, + NormalViewMatrix, + ModelMatrix, + ViewMatrix, + ProjectionMatrix, + ModelViewMatrix, + ModelViewProjectionMatrix, + InverseViewProjectionMatrix, + InverseViewProjectionMatrixAtOrigin, // precision hack + + PreviousModelViewMatrix, + PreviousModelViewProjectionMatrix, + + MaterialOpacity, + + MaterialDiffuse, + MaterialSpecular, + MaterialSelf, + MaterialAmbient, + MaterialGlossiness, + MaterialReflection, + MaterialAlphaThreshold, + MaterialDepthBias, + MaterialTexture0, + MaterialTexture1, + MaterialTexture2, + MaterialTexture3, + MaterialTexture4, + MaterialTexture5, + MaterialTexture6, + MaterialTexture7, + + LightRange, + LightSpotEdge, + LightSpotCone, + LightShadowBias, + LightDiffuseColor, + LightSpecularColor, + LightShadowColor, + LightViewPosition, + LightViewDirection, + LightShadowMatrix0, + LightShadowMatrix1, + LightShadowMatrix2, + LightShadowMatrix3, + LightShadowMatrix4, + LightShadowMatrix5, + InverseShadowMapSize, + LightShadowMap0, + LightShadowMap1, + LightShadowMap2, + LightShadowMap3, + LightShadowMap4, + LightShadowMap5, + LightPSSMSliceDistance0, + LightPSSMSliceDistance1, + LightPSSMSliceDistance2, + LightPSSMSliceDistance3, + ViewToLightMatrix, + LightProjectionMap, + + BoneMatrix, + PreviousBoneMatrix, + + LastSemantic +}; + +enum Category +{ + CategoryVertexStream = 0, // keep as category 0 + CategoryConstant, + CategoryTexture, + CategorySkin, + CategoryRenderer, + CategoryMaterialOpacity, + CategoryMaterial, + CategoryTransform, + CategoryPreviousTransform, + CategoryLight, + + CategoryLast +}; + +static const char *GetCategoryName(Category); + +enum Precision +{ + NoP = 0, + + LowP, + MediumP, + HighP +}; + +enum DataType // do not reorder! +{ + NoData = (1 << 0), + Int = (1 << 1), + Float = (1 << 2), + Vector2 = (1 << 3), + Vector3 = (1 << 4), + Vector4 = (1 << 5), + Matrix3 = (1 << 6), + Matrix4 = (1 << 7), + DataTexture2D = (1 << 8), + DataTexture3D = (1 << 9), + DataTextureCube = (1 << 10), + DataTextureShadow = (1 << 11) +}; + +struct SemanticDesc +{ + const char *name; + Category category; + DataType data_type; + Precision precision; +}; + +static SemanticDesc semantic_desc[LastSemantic + 1]; + + bool ConsumesTextureUnit() const; + +enum Scope +{ + Vertex = (1 << 0), + Pixel = (1 << 1), + Geometry = (1 << 2) +}; + + String name; + + int scope; + Type type; + Semantic semantic; + uint array_size; + + String parm_t; + GS::Vector4 parm_v; ///< 16B vector + + ShaderInput::DataType data_type; + + ShaderInput(); +}; + + } //Core +} // GS + + +#endif // __NSHADERINPUT__ diff --git a/include/engine/core/shader_isl_to_glsl.h b/include/engine/core/shader_isl_to_glsl.h new file mode 100644 index 0000000..4c24393 --- /dev/null +++ b/include/engine/core/shader_isl_to_glsl.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NISL_TO_GLSL__ +#define __NISL_TO_GLSL__ + + + #include "core/shader_input.h" + + +namespace GS { + namespace Core { + struct Shader; + namespace ISLtoGLSL { + +enum GLSLVariant +{ + OGL, ///< OpenGL 2.1 (GLSL 100) + OGL32, ///< OpenGL 3.2 (GLSL 130) + EGL20 ///< EGL 2.0 +}; + +/// Get a type name. +bool GetType(ShaderInput::DataType, String &); +/// Convert an ISL shader to a GLSL shader. +bool Translate(const Shader &, String &glsl_vertex, String &glsl_fragment, GLSLVariant = OGL); + + } // ISLtoGLSL + } // Core +} // GS + + +#endif // __NISL_TO_GLSL__ diff --git a/include/engine/core/shader_isl_to_hlsl.h b/include/engine/core/shader_isl_to_hlsl.h new file mode 100644 index 0000000..99fa79c --- /dev/null +++ b/include/engine/core/shader_isl_to_hlsl.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NISL_TO_HLSL__ +#define __NISL_TO_HLSL__ + + + #include "core/shader_input.h" + + +namespace GS { + namespace Core { + struct Shader; + namespace ISLtoHLSL { + +String GetCategoryCBufferName(ShaderInput::Category); + +/// Get a type name. +bool GetType(ShaderInput::DataType, String &); +/// Translate an ISL shader to a HLSL shader. +bool Translate(const Shader &, String &hlsl_vertex, String &hlsl_fragment); + + } // ISLtoHLSL + } // Core +} // GS + + +#endif // __NISL_TO_HLSL__ diff --git a/include/engine/core/shader_tree.h b/include/engine/core/shader_tree.h new file mode 100644 index 0000000..bc1155d --- /dev/null +++ b/include/engine/core/shader_tree.h @@ -0,0 +1,74 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSHADER_TREE__ +#define __NSHADER_TREE__ + + + #include "math/vector.h" + #include "container/nlist.h" + #include "memory/nshared_ptr.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace Core { + struct ShaderBlock; + +/* + @short Shader tree. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class ShaderTree : public SharedObject +{ +protected: + + /// Extract block from the map. + void GatherBlockList(List &block_list, ShaderBlock *root = 0); + +public: + +enum ShaderSinkType +{ + SinkVertex = 0, + + SinkNormal, + SinkDiffuse, + SinkModulate, + SinkSpecular, + SinkGlossiness, + SinkConstant, + SinkOpacity, + SinkReflection, + + SinkInvalid +}; + + String name; + + Vector2 pos; + ShaderBlock *sink[SinkInvalid]; + + /// Return a sink compatibility. + int GetSinkCompatibility(ShaderSinkType) const; + + /// Free map and all blocks. + void Free(); + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + ShaderTree(); + ~ShaderTree(); +}; + +typedef SharedPtr sShaderTree; + + } // Core +} // GS + + +#endif // __NSHADER_TREE__ diff --git a/include/engine/core/shader_tree_compiler.h b/include/engine/core/shader_tree_compiler.h new file mode 100644 index 0000000..755c8f1 --- /dev/null +++ b/include/engine/core/shader_tree_compiler.h @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SHADER_TREE_COMPILER__ +#define __SHADER_TREE_COMPILER__ + + + #include "core/shader.h" + #include "core/shader_block.h" + + +namespace GS { + namespace Core { + +/// Compiled shader block. +struct CShaderBlock +{ + String variable; + const ShaderBlock *block; + ShaderInput::DataType output; + + CShaderBlock(const ShaderBlock *render_block) : block(render_block), output(ShaderInput::NoData) + { + block = render_block; + output = ShaderInput::NoData; + } +}; + +/*! + @short Shader tree compiler. + Compile a shader tree to a shader. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class ShaderTreeCompiler +{ +/*! + @name Specialized interface. + @{ +*/ +protected: + +virtual CShaderBlock *CompileConstantShaderBlock(const ConstantShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileColorShaderBlock(const ColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileMaterialParamShaderBlock(const MaterialParamShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileMaterialTextureShaderBlock(const MaterialTextureShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileGeometryVertexShaderBlock(const GeometryVertexShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileGeometryUVShaderBlock(const GeometryUVShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileGeometryNormalShaderBlock(const GeometryNormalShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileGeometrySkinningShaderBlock(const GeometrySkinningShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileGeometryVertexColorShaderBlock(const GeometryVertexColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileGeometryTangentFrameShaderBlock(const GeometryTangentFrameShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileRenderBufferShaderBlock(const RenderBufferShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileTextureShaderBlock(const TextureShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileTextureSamplerShaderBlock(const TextureSamplerShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileMixShaderBlock(const MixOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileAddShaderBlock(const AddOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileSubShaderBlock(const SubOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileMulShaderBlock(const MulOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileDivShaderBlock(const DivOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileDotShaderBlock(const DotOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileCrossShaderBlock(const CrossOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileClampShaderBlock(const ClampShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileNormalizeBlock(const NormalizeOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileSwizzleShaderBlock(const SwizzleShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileBuildShaderBlock(const BuildShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileCosinusShaderBlock(const CosinusShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileSinusShaderBlock(const SinusShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompilePowShaderBlock(const PowShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileAbsShaderBlock(const AbsShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileUnpackColorToVector(const UnpackColorToVectorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompilePackVectorToColor(const PackVectorToColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileClockShaderBlock(const ClockShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileScreenUVShaderBlock(const ScreenUVShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileViewVectorShaderBlock(const ViewVectorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileViewportShaderBlock(const ViewportShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; + +virtual CShaderBlock *CompileNormalViewMatrixShaderBlock(const NormalViewMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileNormalMatrixShaderBlock(const NormalMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileModelViewMatrixShaderBlock(const ModelViewMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +virtual CShaderBlock *CompileModelMatrixShaderBlock(const ModelMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel) = 0; +/// @} + +protected: + + String id; + + uint variable_count, + texture_count; + + Shader *shader; + + AutoList temporary_block_list; + AutoList compiled_tree_block; + + bool GetNewVariable(String &constant, const char *prefix = 0); + CShaderBlock *GetNewCompiledBlock(const ShaderBlock *); + + String vertex_declaration, + vertex_source, + pixel_declaration, + pixel_source; + +public: + + /// Get current shader id. + const String &GetId() const { return id; } + + /// Restart compiler. Derived implementations should call the base class first. + void RestartCompiler(Shader *); + + /// Compile a shader block. + CShaderBlock *CompileShaderBlock(const ShaderBlock *, const char *prefix = 0, ShaderInput::Scope = ShaderInput::Pixel); + /// Compile a temporary block. Compiler takes ownership of the block. + CShaderBlock *CompileTemporary(ShaderBlock *, const char *prefix = 0, ShaderInput::Scope = ShaderInput::Pixel); + + /// Add a custom prefix to the shader name. + void AddPrefix(const char *); + + /// Add code to the vertex shader declaration. + void AddVertexDeclaration(const char *d) { vertex_declaration += d; } + /// Add code to the vertex shader. + void AddVertexShader(const char *d) { vertex_source += d; } + /// Add code to the fragment shader declaration. + void AddPixelDeclaration(const char *d) { pixel_declaration += d; } + /// Add code to the fragment shader. + void AddPixelShader(const char *d) { pixel_source += d; } + + /// Get vertex program. + const String &GetVertexSource() const { return vertex_source; } + /// Get fragment program. + const String &GetPixelSource() const { return pixel_source; } + + /// Complete a compilation, retrieve the shader. +virtual Shader *Finish() = 0; + + /// Free all compiler stats. + void Free(); + + ShaderTreeCompiler(); +virtual ~ShaderTreeCompiler(); +}; + + } //Core +} // GS + + +#endif // __SHADER_TREE_COMPILER__ diff --git a/include/engine/core/shader_tree_compiler_isl.h b/include/engine/core/shader_tree_compiler_isl.h new file mode 100644 index 0000000..62c68e3 --- /dev/null +++ b/include/engine/core/shader_tree_compiler_isl.h @@ -0,0 +1,83 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ISL_SHADER_TREE_COMPILER__ +#define __ISL_SHADER_TREE_COMPILER__ + + + #include "core/shader_tree_compiler.h" + + +namespace GS { + namespace Core { + +/*! + @short ISL Shader tree compiler. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class ISLShaderTreeCompiler : public ShaderTreeCompiler +{ +protected: + +virtual CShaderBlock *CompileConstantShaderBlock(const ConstantShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileColorShaderBlock(const ColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileMaterialParamShaderBlock(const MaterialParamShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileMaterialTextureShaderBlock(const MaterialTextureShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileGeometryVertexShaderBlock(const GeometryVertexShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileGeometryUVShaderBlock(const GeometryUVShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileGeometryNormalShaderBlock(const GeometryNormalShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileGeometrySkinningShaderBlock(const GeometrySkinningShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileGeometryVertexColorShaderBlock(const GeometryVertexColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileGeometryTangentFrameShaderBlock(const GeometryTangentFrameShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileRenderBufferShaderBlock(const RenderBufferShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileTextureShaderBlock(const TextureShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileTextureSamplerShaderBlock(const TextureSamplerShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileMixShaderBlock(const MixOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileAddShaderBlock(const AddOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileSubShaderBlock(const SubOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileMulShaderBlock(const MulOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileDivShaderBlock(const DivOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileDotShaderBlock(const DotOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileCrossShaderBlock(const CrossOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileClampShaderBlock(const ClampShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileNormalizeBlock(const NormalizeOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileSwizzleShaderBlock(const SwizzleShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileBuildShaderBlock(const BuildShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileCosinusShaderBlock(const CosinusShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileSinusShaderBlock(const SinusShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompilePowShaderBlock(const PowShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileAbsShaderBlock(const AbsShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileUnpackColorToVector(const UnpackColorToVectorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompilePackVectorToColor(const PackVectorToColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileClockShaderBlock(const ClockShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileScreenUVShaderBlock(const ScreenUVShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileViewVectorShaderBlock(const ViewVectorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileViewportShaderBlock(const ViewportShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +virtual CShaderBlock *CompileNormalViewMatrixShaderBlock(const NormalViewMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileNormalMatrixShaderBlock(const NormalMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileModelViewMatrixShaderBlock(const ModelViewMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); +virtual CShaderBlock *CompileModelMatrixShaderBlock(const ModelMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + +public: + + bool GetTypeDeclaration(ShaderInput::DataType, String &declaration); +virtual Shader *Finish(); +}; + + } // Core +} // GS + + +#endif // __ISL_SHADER_TREE_COMPILER__ diff --git a/include/engine/core/shader_tree_compiler_tinyc.h b/include/engine/core/shader_tree_compiler_tinyc.h new file mode 100644 index 0000000..5cf4a98 --- /dev/null +++ b/include/engine/core/shader_tree_compiler_tinyc.h @@ -0,0 +1,109 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __TINYC_SHADER_TREE_COMPILER__ +#define __TINYC_SHADER_TREE_COMPILER__ + + + #include "core/shader_tree_compiler.h" + + +namespace GS { + namespace Core { + struct ResourceFactory; + struct Material; + +/*! + @short TinyC Shader tree compiler. + @author Scorpheus (Scorpheus@hotmail.com) +*/ +class TinyCShaderTreeCompiler : public ShaderTreeCompiler +{ + /*! + @name Specialized interface. + @{ + */ +protected: + + virtual CShaderBlock *CompileConstantShaderBlock(const ConstantShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileColorShaderBlock(const ColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileMaterialParamShaderBlock(const MaterialParamShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileMaterialTextureShaderBlock(const MaterialTextureShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileGeometryVertexShaderBlock(const GeometryVertexShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileGeometryUVShaderBlock(const GeometryUVShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileGeometryNormalShaderBlock(const GeometryNormalShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileGeometrySkinningShaderBlock(const GeometrySkinningShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileGeometryVertexColorShaderBlock(const GeometryVertexColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileGeometryTangentFrameShaderBlock(const GeometryTangentFrameShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileRenderBufferShaderBlock(const RenderBufferShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileTextureShaderBlock(const TextureShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileTextureSamplerShaderBlock(const TextureSamplerShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileMixShaderBlock(const MixOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileAddShaderBlock(const AddOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileSubShaderBlock(const SubOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileMulShaderBlock(const MulOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileDivShaderBlock(const DivOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileDotShaderBlock(const DotOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileCrossShaderBlock(const CrossOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileClampShaderBlock(const ClampShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileNormalizeBlock(const NormalizeOperatorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileSwizzleShaderBlock(const SwizzleShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileBuildShaderBlock(const BuildShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileCosinusShaderBlock(const CosinusShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileSinusShaderBlock(const SinusShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompilePowShaderBlock(const PowShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileAbsShaderBlock(const AbsShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileUnpackColorToVector(const UnpackColorToVectorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompilePackVectorToColor(const PackVectorToColorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileClockShaderBlock(const ClockShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileScreenUVShaderBlock(const ScreenUVShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileViewVectorShaderBlock(const ViewVectorShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileViewportShaderBlock(const ViewportShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + virtual CShaderBlock *CompileNormalViewMatrixShaderBlock(const NormalViewMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileNormalMatrixShaderBlock(const NormalMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileModelViewMatrixShaderBlock(const ModelViewMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + virtual CShaderBlock *CompileModelMatrixShaderBlock(const ModelMatrixShaderBlock *, ShaderInput::Scope = ShaderInput::Pixel); + + /// @} + + +public: + + ResourceFactory &graphic_factory; + + /// Get code to the fragment shader declaration. + String GetFragmentDeclaration() { return pixel_declaration; } + /// Get code to the fragment shader. + String GetFragmentShader() { return pixel_source; } + + /// Declare a varying. + virtual bool DeclareVarying(const char *name, ShaderInput::DataType data_type) {return true;}; + + /// Helper. + bool GetTypeDeclaration(ShaderInput::DataType, String &declaration); + + void SetShaderInputs( const Material &m); + + /// Complete a compilation, retrieve the shader. + virtual Shader *Finish(); + + TinyCShaderTreeCompiler(ResourceFactory &gf) : graphic_factory(gf) {} +}; + + } // Core +} // GS + + +#endif // __TINYC_SHADER_TREE_COMPILER__ diff --git a/include/engine/core/shader_tree_convert_static_texture_block_to_dynamic.h b/include/engine/core/shader_tree_convert_static_texture_block_to_dynamic.h new file mode 100644 index 0000000..53d5f8c --- /dev/null +++ b/include/engine/core/shader_tree_convert_static_texture_block_to_dynamic.h @@ -0,0 +1,23 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SHADERTREECONVERTSTATICTEXTUREBLOCKTODYNAMIC__ +#define __SHADERTREECONVERTSTATICTEXTUREBLOCKTODYNAMIC__ + + +namespace GS { + namespace Core { + struct Material; + class ShaderTree; + +// Convert all static shader texture blocks to dynamic ones. +void ConvertStaticToDynamicTextureBlocks(ShaderTree &, const Material &); + + } // Core +} // GS + + +#endif // __SHADERTREECONVERTSTATICTEXTUREBLOCKTODYNAMIC__ diff --git a/include/engine/core/shader_tree_to_shader.h b/include/engine/core/shader_tree_to_shader.h new file mode 100644 index 0000000..f80c47c --- /dev/null +++ b/include/engine/core/shader_tree_to_shader.h @@ -0,0 +1,23 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSHADERTREETOSHADER__ +#define __NSHADERTREETOSHADER__ + + +namespace GS { + namespace Core { + struct Shader; + class ShaderTree; + +// Convert a shader tree to an ISL shader. +bool ConvertShaderTreeToShader(const ShaderTree &, Shader &); + + } // Core +} // GS + + +#endif // __NSHADERTREETOSHADER__ \ No newline at end of file diff --git a/include/engine/core/simple_list_renderable.h b/include/engine/core/simple_list_renderable.h new file mode 100644 index 0000000..4c8e3a7 --- /dev/null +++ b/include/engine/core/simple_list_renderable.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SIMPLE_LIST_RENDERABLE__ +#define __SIMPLE_LIST_RENDERABLE__ + + + #include "core/renderable.h" + #include "container/narray_list.h" + + +namespace GS { + namespace Core { + +/* + @short Simple list renderable. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class SimpleCullingSystem : public Renderable +{ +protected: + + ArrayList renderable_list; + +public: + + /// Add a renderable to the provider. + void AddRenderable(Renderable *); + /// Delete a renderable from the provider. + void DeleteRenderable(Renderable *); + + /// Compute renderable min-max. +virtual void ComputeRenderableMinMax(MinMax &); + /// Get primitive list. +virtual uint GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack &, Context = Context_Default, bool cull = true); +}; + + } // Core +} // GS + + +#endif // __SIMPLE_LIST_RENDERABLE__ diff --git a/include/engine/core/skin.h b/include/engine/core/skin.h new file mode 100644 index 0000000..6aa8fc6 --- /dev/null +++ b/include/engine/core/skin.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSKIN__ +#define __NSKIN__ + + + #include "math/matrix4.h" + #include "geometry/bounding_box.h" + #include "container/narray.h" + + +namespace GS { + struct OBB; + + namespace Core { + class Item; + +struct Skin +{ + Array bones; + Array bones_mtx, previous_bones_mtx; + Array bones_minmax; + + /// Compute bone skin minmax. + bool ComputeBoneBoundingVolume(uint n, OBB &) const; +}; + + } // Core +} // GS + + +#endif // __NSKIN__ diff --git a/include/engine/core/sound.h b/include/engine/core/sound.h new file mode 100644 index 0000000..9dc85b8 --- /dev/null +++ b/include/engine/core/sound.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSOUND__ +#define __NSOUND__ + + + #include "core/mixer_data.h" + #include "nstring/nstring.h" + #include "memory/nauto_ptr.h" + #include "time/ntime.h" + + +namespace GS { + namespace Audio { + struct IMixer; + +/*! + @short Mixer sound object. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Sound : public SharedObject +{ + NPLACEMENT_NEW(Sound) + + IMixer &mixer; + + String name; + AutoPtr mixer_data; + + Sound(IMixer &m) : mixer(m) {} + ~Sound(); +}; + + } // Audio +} // GS + + +#endif // __NSOUND__ diff --git a/include/engine/core/tangent_frame.h b/include/engine/core/tangent_frame.h new file mode 100644 index 0000000..7fa3a24 --- /dev/null +++ b/include/engine/core/tangent_frame.h @@ -0,0 +1,24 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NTANGENTFRAME__ +#define __NTANGENTFRAME__ + + + #include "math/vector.h" + + +namespace GS { + +struct TangentFrame +{ + Vector4 T, B; +}; + +} // GS + + +#endif // __NTANGENTFRAME__ \ No newline at end of file diff --git a/include/engine/core/terrain.h b/include/engine/core/terrain.h new file mode 100644 index 0000000..03b301a --- /dev/null +++ b/include/engine/core/terrain.h @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NTERRAIN__ +#define __NTERRAIN__ + + + #include "core/renderable.h" + #include "core/item.h" + #include "core/material.h" + #include "geometry/rect.h" + + +namespace GS { + namespace Core { + class Terrain; + class Geometry; + +struct Patch +{ + Terrain *terrain; + + int u, v, w, h; + int decimation; + + MinMax minmax; + + iRect GetRect() const { return iRect(u, v, u + w, v + h); } + + AutoPtr children[4]; + + Patch() : terrain(0) {} +}; + +/* + @short Terrain. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Terrain : public Item, public Renderable +{ +public: + +struct Attrib +{ + char nx, ny, nz; +}; + +struct Layer +{ + bool enabled; + + String diffuse, specular, normal, self; + float angle, tiling; + + Layer() + { + enabled = true; + + angle = 0.f; + tiling = 1.f; + } +}; + +protected: + + float width, depth; + + Array heightmap; + Array attribmap; + + int heightmap_w, heightmap_h; + float unit; + + AutoPtr root_node; + uint node_count; + + void UpdatePatchMinMax(Patch *node) const; + + /// Cull terrain primitive and push to the render queue. + void CullRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack &, Context, Patch *); + /// Helper function to create a geometry object for a given terrain patch. + Geometry *CreateNodeGeometry(const Patch *); + /// Build the terrain quad-tree for a specific terrain part. + Patch *BuildTerrainStaticQuadtree(int u, int v, int w, int h, int decimation, int depth); + + /// Update a quadtree patch. + void UpdateQuadtreePatch(Patch *patch, iRect &update_rect); + + /// Layer to tag. + NML::Tag *LayerAsMetaTag(int index); + +public: + + Layer layer[4]; + +/// Terrain render data. +struct RenderData +{ + struct Layer + { + Render::sTexture diffuse, specular, normal, self; + }; + + Layer layer[4]; + + Render::sTexture blendmap; + Render::sMaterial material; +}; + +/// +struct TraceResult +{ + bool has_hit; + Vector4 w_i; ///< Intersection in world space. + Vector2 uv; +}; + + String material; + + String heightmap_path, + blendmap_path, + shader_path; + + AutoPtr render_data; + + /// Compute the renderable bounding box. +virtual void ComputeRenderableMinMax(MinMax &); + /// Get the renderable primitive list. +virtual uint GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack &, Context = Context_Default, bool cull = true); + + bool Raytrace(const Vector4 &s, const Vector4 &d, TraceResult &, float len = -1.f); + + /*! + @short Apply several blur passes to the heightmap. + @note The normals are not blurred, so you might want to recompute + them when done. + */ + void ApplyBlur(int pass_count = 1); + /// Compute normals from the heightmap. + void ComputeNormals(int u = 0, int v = 0, int w = 0, int h = 0); + + float GetWidth() const { return width; } + float GetDepth() const { return depth; } + + /*! + @short Return the terrain normal for a given sample. + @note For performance critical code you might want to use the + attribute map directly. + */ + Vector4 GetNormalAt(int u, int v) const; + + Attrib *GetAttributesMap() const { return attribmap; } + Attrib *GetAttributesMapAt(int u, int v) const; + + float *GetHeightmap() const { return heightmap; } + int GetHeightmapWidth() const { return heightmap_w; } + int GetHeightmapHeight() const { return heightmap_h; } + int GetHeightmapPitch() const { return heightmap_w + 1; } + float GetUnit() const { return unit; } + + bool LocalToTexture(const Vector4 &, float w, float h, float &u, float &v) const; + bool LocalToHeightmap(const Vector4 &p, float &u, float &v) const; + + /// Sample height in heightmap space. + float SampleHeight(float u, float v) const; + /// Sample height in local space. + float SampleHeight(const Vector4 &) const; + + /// Update a terrain quadtree zone. + void UpdateQuadtree(int u = 0, int v = 0, int w = 0, int h = 0); + + Patch *BuildQuadtree(); + + void RenderSetup(ResourceFactories * = 0); + + /// Set heightmap from file. + bool FromPicture(const char *, int blur_pass_count = 0); + +/*! + @name Height map I/O. + @{ +*/ + bool LoadHeightmap(const char *); + bool SaveHeightmap(const char *); +/// @} + + /*! + @short Allocate terrain. + @note This function does not allocate terrain patches. + */ + bool Allocate(uint w_res, uint h_res, float unit); + void Free(); + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); + + Terrain(); +virtual ~Terrain(); +}; + + } // Core +} // GS + + +#endif // __NTERRAIN__ diff --git a/include/engine/core/terrain_shader_generator.h b/include/engine/core/terrain_shader_generator.h new file mode 100644 index 0000000..89bf1a8 --- /dev/null +++ b/include/engine/core/terrain_shader_generator.h @@ -0,0 +1,26 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __TERRAIN_SHADER_GENERATOR__ + + + #include "core/terrain.h" + + +namespace GS { + namespace Core { + struct Shader; + + namespace TerrainShaderGenerator { + +bool GenerateShader(Shader &shader, const char *t_blend, const Terrain::Layer layers[4]); + + } // TerrainShaderGenerator + } // Core +} // GS + + +#endif // __TERRAIN_SHADER_GENERATOR__ diff --git a/include/engine/core/texture_parm.h b/include/engine/core/texture_parm.h new file mode 100644 index 0000000..9fd8217 --- /dev/null +++ b/include/engine/core/texture_parm.h @@ -0,0 +1,120 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NTEXTUREPARM__ +#define __NTEXTUREPARM__ + + + #include "reflection/c_refl.h" + #include "reflection/nenum_string.h" + #include "nstring/nstring.h" + + +namespace GS { + class Picture; + + namespace NML { class Tag; } + namespace Render { + struct Texture; + +// +struct TextureParm +{ + /// Get texture parameter file name from texture name. +static String GetParmFileName(const char *); + +static Reflection::Property serializable[]; + +enum Filtering +{ + FilterDefault = 0, + FilterNearest, + FilterBilinear, + FilterTrilinear, + + FilterLast +}; +static Reflection::Enum::Dict filtering_dict[]; + +enum Anisotropy +{ + AnisotropyDefault = 0, + AnisotropyNone, + Anisotropy2x, + Anisotropy4x, + Anisotropy8x, + Anisotropy16x, + + AnisotropyLast +}; +static Reflection::Enum::Dict anisotropic_dict[]; + +enum Wrap +{ + WrapDefault = 0, + WrapRepeat, + WrapClamp, + + WrapLast +}; +static Reflection::Enum::Dict wrap_dict[]; + +enum Swizzle +{ + SwizzleRGBA = 0, // identity + SwizzleBGRA, + SwizzleARGB, + SwizzleABGR, + SwizzleXYZ, // identity + SwizzleXZY, + SwizzleYXZ, + SwizzleYZX, + SwizzleZXY, + SwizzleZYX, + + SwizzleLast +}; +static Reflection::Enum::Dict swizzle_dict[]; + +static const char *GetSwizzleFlags(Swizzle); + + Wrap wrap_u, wrap_v; + Filtering filtering; + Anisotropy anisotropy; + + float lod_bias; + + Swizzle swizzle; + + bool invert[4]; + bool flip[2]; + + void Apply(Picture &) const; + void Apply(Texture &) const; + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + TextureParm() + { + wrap_u = wrap_v = WrapDefault; + filtering = FilterDefault; + anisotropy = AnisotropyDefault; + + lod_bias = 0.f; + + swizzle = SwizzleRGBA; + for (uchar n = 0; n < 4; ++n) + invert[n] = false; + flip[0] = flip[1] = false; + } +}; + + } // Render +} // GS + + +#endif // __NTEXTUREPARM__ diff --git a/include/engine/core/tool_mode.h b/include/engine/core/tool_mode.h new file mode 100644 index 0000000..46a3790 --- /dev/null +++ b/include/engine/core/tool_mode.h @@ -0,0 +1,25 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __TOOLMODE__ +#define __TOOLMODE__ + + +namespace GS { + +enum ToolMode +{ + NoTool = 0, + + ToolEdit, ///< Tool edition mode, scripts are ignored. + ToolPreview, ///< Tool scene preview mode, full evaluations. + ToolProjectPreview ///< Tool project preview mode, full evaluations. +}; + +} // GS + + +#endif // __TOOLMODE__ diff --git a/include/engine/core/triangle_list.h b/include/engine/core/triangle_list.h new file mode 100644 index 0000000..331f0ea --- /dev/null +++ b/include/engine/core/triangle_list.h @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOTRILIST__ +#define __NGEOTRILIST__ + + + #include "core/tangent_frame.h" + #include "color/color.h" + #include "container/nlist.h" + #include "container/narray.h" + + +namespace GS { + namespace Core { + +/*! + @short Geometry triangle list. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Trilist +{ +struct Skin +{ + float w[__PV_BONE_LIMIT__]; + uchar bone_index[__PV_BONE_LIMIT__]; ///< Internal maximum of 256 bones per triangle list (indexed via the Trilist::bone_map array). +}; + + Array vtx; + Array idx; ///< Triangle index array. + Array skin; ///< Vertex skinning information. + Array bone; ///< Map referencing items in Item::bone (usually resolved from the Geometry::bone_id array at skin binding time). + + Array nrm; + Array tangent; + Array uv[__UV_PER_GEOMETRY__]; + Array rgb; + + uint mat; ///< Material index. + + /// Return the number of triangle in the list. +inline uint GetTriangleCount() const { return idx.GetCount() / 3; } + + /*! + @short Optimize a given triangle list array. + + The optimizer reorder the triangle list index in order to maximize cache hits. + You can specify the target architecture vertex cache size. + + @note This function can be called several times if needed. The + modifications will however not be applied to the renderer + internals. For this you will need to explicitly recreate + the renderer's representation. + */ +static void Optimize(const List &list, int vtx_cache_size = 16); + + Trilist() : mat(0) {} +}; + +typedef Trilist * pTrilist; + + } // Core +} // GS + + +#endif // __NGEOTRILIST__ diff --git a/include/engine/core/trigger.h b/include/engine/core/trigger.h new file mode 100644 index 0000000..327f80f --- /dev/null +++ b/include/engine/core/trigger.h @@ -0,0 +1,48 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NTRIGGER__ +#define __NTRIGGER__ + + + #include "core/item.h" + + +namespace GS { + namespace Core { + +/*! + @short Trigger class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Trigger : public Item +{ +struct ItemInTrigger +{ + bool inside; ///< Item is inside trigger. + Item *item; + + ItemInTrigger(Item *i) : item(i), inside(true) {} +}; + + List items_in_trigger; + + void ReadyItemList(); + void PurgeItemList(); + +virtual void MarkItem(Item *); +virtual void DropItem(Item *); + + bool IsInside(const Vector4 &); + + void RenderSetup(ResourceFactories * = 0) {} + ~Trigger(); +}; + } // Core +} // GS + + +#endif // __NTRIGGER__ diff --git a/include/engine/gpu/gpu_caps.h b/include/engine/gpu/gpu_caps.h new file mode 100644 index 0000000..359f0b8 --- /dev/null +++ b/include/engine/gpu/gpu_caps.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPUCAPS__ +#define __GPUCAPS__ + + +namespace GS { + namespace GPU { + +enum Caps +{ +/*! + @name Hardware caps. + @{ +*/ + MaxTextureSize, + MaxTextureUnit, + + CanBlitRBO, + TextureTopLeftOrigin, + + MaxAnisotropy, +/*! + @} + @name Performance hints. + @{ +*/ + CheapLights +/// @} +}; + + } // GPU +} // GS + + +#endif // __GPUCAPS__ diff --git a/include/engine/gpu/gpu_config.h b/include/engine/gpu/gpu_config.h new file mode 100644 index 0000000..fb64308 --- /dev/null +++ b/include/engine/gpu/gpu_config.h @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __GPUCONFIG__ +#define __GPUCONFIG__ + + + #include "ntypes.h" + #include "alloc/ialloc.h" + + +namespace GS { + namespace GPU { + +struct RendererConfig +{ + NPLACEMENT_NEW(Renderer) + +enum NPOTSupport +{ + NPOT_None = 0, + NPOT_Limited, // NPOT support with no mipmap and wrap as clamp to edge only. + NPOT_Full +}; + + uint npot; + uint shadow_size; + uint max_anisotropy; + + bool use_rtt; + + bool can_resolve_msaa; + bool can_stream_vertex_from_memory; + + bool enable_aa; + bool enable_shadow; + bool tex_origin_is_top_left; + + RendererConfig() + { + npot = NPOT_Full; + shadow_size = 1024; + max_anisotropy = 1; + + use_rtt = true; + + can_resolve_msaa = true; + can_stream_vertex_from_memory = true; + + enable_aa = false; + enable_shadow = true; + + tex_origin_is_top_left = true; + } +}; + + } // GPU +} // GS + + +#endif // __GPUCONFIG__ diff --git a/include/engine/gpu/gpu_display_list.h b/include/engine/gpu/gpu_display_list.h new file mode 100644 index 0000000..6d54d3c --- /dev/null +++ b/include/engine/gpu/gpu_display_list.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPUDISPLAYLIST__ +#define __GPUDISPLAYLIST__ + + + #include "gpu/gpu_vbo.h" + #include "core/render_data.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + + namespace Core { + struct Trilist; + struct Patch; + class Emitter; + class Item; + } + namespace GPU { + class Renderer; + +// +struct DisplayList +{ + NPLACEMENT_NEW(Renderer) + + Renderer &renderer; + + AutoPtr idx, vtx; + Array idx_map; + Array vtx_map; + size_t stride; + + MinMax minmax; + + uint index_count; + + size_t vertex_offset, + normal_offset, + rgb_offset, + uv_offset[__UV_PER_GEOMETRY__], + tangent_offset, + skinning_offset; + + Array bone; + + Render::sMaterial material; + + /// Create display list from a triangle list. +virtual bool Create(Core::Trilist *, Render::Material *); + /// Draw display list. +virtual void Draw() = 0; + + DisplayList(Renderer &r) : renderer(r) + { + idx = 0; + vtx = 0; + + index_count = 0; + + vertex_offset = (size_t)-1; + normal_offset = (size_t)-1; + rgb_offset = (size_t)-1; + for (uint n = 0; n < __UV_PER_GEOMETRY__; ++n) + uv_offset[n] = (size_t)-1; + tangent_offset = (size_t)-1; + skinning_offset = (size_t)-1; + + stride = 0; + } +virtual ~DisplayList() {} +}; + +// +struct RenderPrimitive +{ + NPLACEMENT_NEW(Renderer) + +enum Type +{ + TypeDisplayList = 0, + TypeEmitter, + TypeTerrainPatch +}; + + Type type; + const Core::Item *item; + + union + { + DisplayList *dlst; + Core::Emitter *emitter; + Core::Patch *patch; + }; + + bool operator == (const RenderPrimitive &b) + { return (type == b.type) && (item == b.item) && (dlst == b.dlst); } + + RenderPrimitive(const Core::Item *i, DisplayList *d) : type(TypeDisplayList), item(i), dlst(d) {} + RenderPrimitive(const Core::Item *i, Core::Emitter *e) : type(TypeEmitter), item(i), emitter(e) {} + RenderPrimitive(const Core::Item *i, Core::Patch *p) : type(TypeTerrainPatch), item(i), patch(p) {} +}; + + } // GPU +} // GS + + +#endif // __GPUDISPLAYLIST__ diff --git a/include/engine/gpu/gpu_draw_context.h b/include/engine/gpu/gpu_draw_context.h new file mode 100644 index 0000000..06e494d --- /dev/null +++ b/include/engine/gpu/gpu_draw_context.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __GPUDRAWCONTEXT__ +#define __GPUDRAWCONTEXT__ + + + #include "gpu/gpu_material.h" + + +namespace GS { + + namespace Core { class Light; } + namespace GPU { + +// +struct DrawContext +{ + NPLACEMENT_NEW(Renderer) + +enum Render +{ + Deferred = 0, + Opaque, + Alpha +}; +enum Draw +{ + Base = 0, + Light +}; + +struct Context +{ + Draw draw; + Render render; + MaterialShader::Variant variant; +}; + + Context ctx; + + Core::Light *light; + + void SetContext(Render rc, Draw dc, MaterialShader::Variant prg) + { + ctx.render = rc; + ctx.draw = dc; + ctx.variant = prg; + } + + DrawContext(Render rc, Draw dc, MaterialShader::Variant prg = MaterialShader::Depth) + { + SetContext(rc, dc, prg); + light = 0; + } +}; + + } // GPU +} // GS + + +#endif // __GPUDRAWCONTEXT__ diff --git a/include/engine/gpu/gpu_fbo.h b/include/engine/gpu/gpu_fbo.h new file mode 100644 index 0000000..7cfd634 --- /dev/null +++ b/include/engine/gpu/gpu_fbo.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPUFBO__ +#define __GPUFBO__ + + + #include "ntypes.h" + #include "geometry/rect.h" + #include "alloc/ialloc.h" + + +namespace GS { + namespace Render { struct Texture; } + namespace GPU { + class Renderer; + +/*! + @short GPU frame buffer object. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct FBO +{ + NPLACEMENT_NEW(Renderer) + + Renderer &renderer; + + uint color_texture_count; + + Render::Texture *color_texture[8], *depth_texture; + + /// Set output color texture. +virtual void SetColorTexture(Render::Texture *t) + { + color_texture[0] = t; + color_texture_count = 1; + } + /// Set output color texture. +virtual void SetColorTexture(Render::Texture *t[], uint n) + { + for (color_texture_count = 0; color_texture_count < n; ++color_texture_count) + color_texture[color_texture_count] = t[color_texture_count]; + } + /// Set output depth texture. +virtual void SetDepthTexture(Render::Texture *t) + { depth_texture = t; } + + /// Blit attachment to another FBO attachment. +virtual void Blit(FBO *out, const iRect &src, const iRect &dst, bool color = true, bool depth = true) = 0; + /// Transfer color pixels into a CPU based buffer, this buffer is expected to be big enough to hold the required region in RGBA format. +virtual void ReadColorPixels(char *out, int x, int y, int w, int h) = 0; + + /// Create FBO. +virtual bool Create() = 0; + /// Free FBO. +virtual void Free() = 0; + + FBO(Renderer &r) : renderer(r) + { + for (uint n = 0; n < 8; ++n) + color_texture[n] = 0; + color_texture_count = 0; + depth_texture = 0; + } +virtual ~FBO() {} +}; + + } // GPU +} // GS + + +#endif // __GPUFBO__ diff --git a/include/engine/gpu/gpu_geometry.h b/include/engine/gpu/gpu_geometry.h new file mode 100644 index 0000000..4887de3 --- /dev/null +++ b/include/engine/gpu/gpu_geometry.h @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPUGEOMETRY__ +#define __GPUGEOMETRY__ + + + #include "gpu/gpu_display_list.h" + + +namespace GS { + namespace Render { struct Material; } + namespace GPU { + +struct Geometry : public Render::Geometry +{ + Renderer &renderer; + + Array > vbo; + Array > display_list; + + /// Allocate geometry VBO. +virtual bool AllocateVBO(uint); + /// Get geometry VBO count. +virtual uint GetVBOCount() const { return vbo.GetCount(); } + /// Get geometry VBO. +virtual VBO *GetVBO(uint n) { return (VBO *)&vbo[n]; } + + /// Change a material in the material table. +virtual bool SetMaterial(uint index, Render::Material *); + +virtual bool Create(Render::ResourceFactory &, const Core::Geometry &); + +virtual bool ShouldReloadOnDependencyChange(const char *) const; + + Geometry(Renderer &r, const char *name) : Render::Geometry(name), renderer(r) {} +}; + + } // GPU +} // GS + + +#endif // __GPUGEOMETRY__ diff --git a/include/engine/gpu/gpu_material.h b/include/engine/gpu/gpu_material.h new file mode 100644 index 0000000..4e91821 --- /dev/null +++ b/include/engine/gpu/gpu_material.h @@ -0,0 +1,71 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPUMATERIAL__ +#define __GPUMATERIAL__ + + + #include "gpu/gpu_material_shader.h" + + +namespace GS { + namespace GPU { + class Renderer; + struct DrawContext; + +// +struct Material : public Render::Material +{ + Renderer &renderer; + +enum SpecularState +{ + SpecularNone = 0, + SpecularEnabled, + + SpecularStateCount +}; + +enum FogState +{ + FogNone = 0, + FogLinear, + + FogStateCount +}; + +struct State +{ + SpecularState specular; + FogState fog; + + State(FogState _f = FogNone, SpecularState _s = SpecularNone) + { + fog = _f; + specular = _s; + } +}; + + sMaterialShader shader; + + bool LoadTextureTable(Render::ResourceFactory &, const Core::Material &); + +virtual Render::MaterialShader *GetShader() const { return shader; } + +virtual bool Create(Render::ResourceFactory &, const Core::Material &); + +virtual bool ShouldReloadOnDependencyChange(const char *) const; + +virtual Render::Material *Clone() const; + + Material(Renderer &r, const char *name = 0) : Render::Material(name), renderer(r) {} +}; + + } // GPU +} // GS + + +#endif // __GPUMATERIAL__ diff --git a/include/engine/gpu/gpu_material_shader.h b/include/engine/gpu/gpu_material_shader.h new file mode 100644 index 0000000..4f86ded --- /dev/null +++ b/include/engine/gpu/gpu_material_shader.h @@ -0,0 +1,105 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __GPUMATERIALSHADER__ +#define __GPUMATERIALSHADER__ + + + #include "gpu/gpu_shader.h" + + +namespace GS { + namespace GPU { + +// Static parameters influencing a material shader. +struct MaterialShaderStaticParm +{ + bool no_lighting; + bool use_alpha_test; + bool use_depth_bias; + bool use_skinning; + + bool operator == (const MaterialShaderStaticParm &p) const + { return (no_lighting == p.no_lighting) && (use_alpha_test == p.use_alpha_test) && (use_depth_bias == p.use_depth_bias) && (use_skinning == p.use_skinning); } +}; + +// Shader compiled for a material. +class MaterialShader : public Render::MaterialShader +{ + Renderer &renderer; + + String name; + + MaterialShaderStaticParm parm; + + void CompileForwardPointLight(Core::Shader &, bool shadow); + void CompileForwardSpotLight(Core::Shader &, bool shadow, bool projection_map); + void CompileForwardLinearLight(Core::Shader &, bool shadow); + bool CompileShaderSection(const char *, Core::Shader &); + +public: + +enum Variant +{ + Depth, // Shadow map program. + +/*! + @name Deferred shading programs. + @{ +*/ + DS_GBufferMRT4, +/*! + @} + @name Forward shading programs. + @{ +*/ + FS_Constant, + + FS_PointLight, + FS_PointLightShadowMapping, + + FS_LinearLight, + FS_LinearLightShadowMapping, + + FS_SpotLight, + FS_SpotLightShadowMapping, + FS_SpotLightProjection, + FS_SpotLightProjectionShadowMapping, + + PP_NormalDepth, // Used by the SSAO post-process. +/*! + @} + @name Common programs. + @{ +*/ + PP_Velocity, +/// @} + + Last +}; + + const String &GetName() const { return name; } + const MaterialShaderStaticParm &GetStaticParm() const { return parm; } + + Array > variants; + +virtual bool SetUserUniformValue(const char *name, const Vector4 &); +virtual bool SetUserUniformValue(const char *name, Render::Texture *); + + bool SetupMaterialProgram(Variant, Core::Shader &); + bool Create(Render::ResourceFactory &, const Core::Shader &, const MaterialShaderStaticParm &); + + MaterialShader(Renderer &); + ~MaterialShader(); +}; + +typedef SharedPtr sMaterialShader; + + } // GPU +} // GS + + +#endif // __GPUMATERIALSHADER__ \ No newline at end of file diff --git a/include/engine/gpu/gpu_perf_tools.h b/include/engine/gpu/gpu_perf_tools.h new file mode 100644 index 0000000..87e3041 --- /dev/null +++ b/include/engine/gpu/gpu_perf_tools.h @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __GPUPERFTOOLS__ +#define __GPUPERFTOOLS__ + + + #include "ntypes.h" + + +namespace GS { + namespace GPU { + +struct PerformanceTools +{ + NPLACEMENT_NEW(Renderer) + + bool show_wireframe; + bool disable_fog; + + PerformanceTools() + { + show_wireframe = false; + disable_fog = false; + } +}; + +struct RendererStatistics +{ + NPLACEMENT_NEW(Renderer) + + uint terrain_page_query_count, + terrain_page_query_miss; + + uint prg_change, + dls_change, + mat_change, + item_change; + + void Reset() + { + terrain_page_query_count = 0; + terrain_page_query_miss = 0; + + prg_change = 0; + dls_change = 0; + mat_change = 0; + item_change = 0; + } + RendererStatistics() + { Reset(); } +}; + + } // GPU +} // GS + + +#endif // __GPUPERFTOOLS__ diff --git a/include/engine/gpu/gpu_render_list.h b/include/engine/gpu/gpu_render_list.h new file mode 100644 index 0000000..0e674bc --- /dev/null +++ b/include/engine/gpu/gpu_render_list.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __GPU_RENDER_LIST__ +#define __GPU_RENDER_LIST__ + + + #include "gpu/gpu_display_list.h" + #include "core/renderable.h" + + +namespace GS { + namespace GPU { + +struct RenderableList +{ + AutoStack primitive_list; + AutoStack display_lists[3]; + + // 0 - opaque, 1 - transparent, 2 - framebuffer dependent + void Clear(bool free_internals = true) + { + primitive_list.Clear(free_internals); + for (int n = 0; n < 3; ++n) + display_lists[n].Clear(free_internals); + } +}; + + } // GPU +} // GS + + +#endif // __GPU_RENDER_LIST__ diff --git a/include/engine/gpu/gpu_renderer.h b/include/engine/gpu/gpu_renderer.h new file mode 100644 index 0000000..d244a74 --- /dev/null +++ b/include/engine/gpu/gpu_renderer.h @@ -0,0 +1,647 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPURENDERER__ +#define __GPURENDERER__ + + + #include "gpu/gpu_shader_object.h" + #include "gpu/gpu_fbo.h" + #include "gpu/gpu_vbo.h" + #include "gpu/gpu_render_list.h" + #include "gpu/gpu_draw_context.h" + #include "gpu/gpu_config.h" + #include "gpu/gpu_shader_compiler.h" + #include "gpu/gpu_perf_tools.h" + #include "gpu/gpu_terrain.h" + #include "gpu/gpu_caps.h" + #include "core/render_resource_factory.h" + #include "core/renderer.h" + #include "core/camera.h" + #include "memory/nweak_ptr.h" + + +namespace GS { + namespace GPU { + class PrepareLightJob; + +/*! + @short GPU based renderer class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Renderer : public Render::Renderer +{ + AutoPtr core_resource_factory; + +public: + +/*! + @name Factories. + @{ +*/ +virtual FBO *NewFBO() = 0; +virtual VBO *NewVBO() = 0; +virtual DisplayList *NewDisplayList() = 0; +virtual ShaderObject *NewGPUShaderObject() = 0; +/*! + @} + @name Render path. + @{ +*/ + bool pending_shadow_map_refresh, + pending_core_shader_refresh, + pending_technique_refresh, + pending_fx_refresh; + + RendererConfig gpu_config; + PerformanceTools performance_tools; + + /// Process registry message. +virtual RegistryRValue ProcessMessage(RegistryMessage message, const Registry *, const void *parm); + + /// Query a caps on the renderer. +virtual bool QueryCaps(Caps, Variant &) { return false; } + /// Discover and apply the GPU configuration. +virtual void DiscoverGPUConfiguration(); +/// @} + +enum RenderTechnique +{ + TechniqueDefault = 0, + TechniqueForward, ///< Forward rendering + TechniqueDeferred ///< Deferred rendering for opaque polygons, forward for alpha polygons. +}; + + RenderTechnique render_technique; + + /// Return the default render technique. + RenderTechnique GetDefaultRenderTechnique() const; + + /// Refresh render technique. + void RefreshRenderTechnique(); + /// Free render technique objects. + void FreeRenderTechnique(); + /// Switch to a specific render technique. + void SetRenderTechnique(RenderTechnique = TechniqueDefault); + + /// Setup post-process system. + void SetPostProcess(uint k = 0); + +/*! + @name Statistics. + @{ +*/ + RendererStatistics gpu_stats; + + /// Draw the renderer profiler output. +virtual void DrawProfilerText(Render::RasterFont *font[2], float &x, float &y); + /// Reset statistics. +virtual void ResetStatistics() + { + gpu_stats.Reset(); + stats.Reset(); + } +/// @} + +/*! + @name State functions. + @{ +*/ +enum GPUFillMode +{ + FillSolid = 0, + FillWireframe, + FillLast +}; + + /// Set primitive fill mode. +virtual void SetFillMode(GPUFillMode) = 0; + +enum GPUCullFunc +{ + CullFront = 0, + CullBack, + CullLast +}; + + /// Set culling function. +virtual void SetCullFunc(GPUCullFunc) = 0; + /// Enable culling. +virtual void EnableCulling(bool) = 0; + +enum GPUDepthFunc +{ + DepthNever = 0, + DepthLess, + DepthEqual, + DepthLessEqual, + DepthGreater, + DepthNotEqual, + DepthGreaterEqual, + DepthAlways, + DepthFuncLast +}; + + /// Set depth function. +virtual void SetDepthFunc(GPUDepthFunc) = 0; + /// Set depth read. +virtual void EnableDepthTest(bool) = 0; + /// Set depth write. +virtual void EnableDepthWrite(bool) = 0; + +enum BlendFunc +{ + BlendZero = 0, + BlendOne, + BlendSrcAlpha, + BlendOneMinusSrcAlpha, + BlendDstAlpha, + BlendOneMinusDstAlpha, + BlendLast +}; + + /// Set blend function. +virtual void SetBlendFunc(BlendFunc src, BlendFunc dst) = 0; + /// Enable blend. +virtual void EnableBlending(bool) = 0; + + /// Enable alpha to coverage. +virtual void EnableAlphaToCoverage(bool) = 0; + /// Enable alpha testing. +virtual void EnableAlphaTest(bool, float threshold = 0.f) = 0; + + /// Set vertex buffer object. +virtual void SetVertexSource(VBO *, size_t stride) = 0; + /// Set index buffer object. +virtual void SetIndexSource(VBO *) = 0; + + /// Set shader object. +virtual bool SetShaderProgram(Shader *, Shader *unset = 0) = 0; + + /// Set display list. +virtual void SetDisplayList(DisplayList *); + +protected: + + Matrix4 m_projection, + m_view, m_iview, + m_world, m_iworld; + + Matrix4 m_previous_iview, // Motion blur specific. + m_previous_world; +/// @} + + SharedPtr + single_texture_color_program, + single_texture_program, + single_color_program, + simple_program, + + tone_mapping_program, + single_texture_cutoff_program, + single_texture_fx_program, + shader_program, + + fx_blur_program, + noise_program, + sharpen_program, + hsl_program, + chromatic_dispersion_program, + + ssaa_program, + ssao_program, + ssao_blur_program, + + radial_blur_program, + motion_blur_program, + + skybox_program; + +/*! + @name Terrain system. + @{ +*/ + Array terrain_patch_vtx; + Array terrain_patch_cache; + + /// Ensure lower entries will get out of cache. + void DecayTerrainCache(); + /// Upload a terrain patch to a cache page. + void UploadTerrainPatchToPage(CachedTerrainPatch &page, const Core::Item &item, const Core::Patch &patch, const DrawContext &dc); + /// Render a terrain patch. + void RenderTerrainPatch(const Core::Patch &, const Core::Item &, const DrawContext &); + +public: + + /// Set default states. + void SetDefaultStates(); + /// Setup core resources. + bool SetupCoreResources(bool support_3d = true); + + /// Invalidate the terrain cache. + void InvalidateTerrainCache(int u = 0, int v = 0, int w = 0, int h = 0); + /// Create the static terrain patch. + bool CreateTerrainPatch(); +/// @} + +/*! + @name Core shader. + @{ +*/ +protected: + + NML::File shader_dict, + material_dict; + + /// Marshall core shader source. + void MarshallCoreShader(String &source); + + /// Load a shader from a resource file. + Shader *SetupCoreShader(const char *name); + + bool LoadCoreShaders(bool support_3d = true); + void UnloadCoreShaders(); + +public: + + AutoPtr shader_compiler; + + List material_shaders; + + List textures; + List shaders; + + NML::Tag *GetPCFShaderTag() const; + NML::Tag *GetPSMShaderTag() const; + NML::Tag *GetPSSMShaderTag() const; + + const NML::File &GetShaderDictionary() const + { return shader_dict; } + const NML::File &GetMaterialDict() const + { return material_dict; } + + uint fx_scale; + FBO *render_fbo; + + bool normal_depth_updated; + + AutoPtr buffer_fbo, fx_fbo; + Render::sTexture t_compose[2], t_depth; ///< 1:1 + Render::sTexture t_color_aa, t_depth_aa; ///< 1:1 + Render::sTexture t_fx[3], t_fx_depth; ///< Downscaled FX render targets. + + AutoPtr resolve_fbo; ///< For MSAA support. + + FBO *output_fbo; + iRect output_fbo_rect; + + AutoPtr shadow_map_fbo; + Render::sTexture shadow_map; + + float pcf_radius; + float frame_clock; + + Render::sTexture t_noise; +/// @} + +/*! + @name Post-processes. + @{ +*/ + Render::Texture *t_final; + + /// Apply directional blur to a texture. + void ApplyDirectionalBlur(Render::Texture *t[2], const Vector2 &d, float attn = 0.975f); + + void ApplyBloomFilter(Render::Texture *t, float strength, float threshold, float exponent, float radius, float strength_white_screen); + bool ApplyNoiseFilter(Render::Texture *t_in, Render::Texture *t_out, float strength, float monochromatic, float bias); + bool ApplySharpenFilter(Render::Texture *t_in, Render::Texture *t_out, float strength); + bool ApplyHSL(Render::Texture *t_in, Render::Texture *t_out, float H, float S, float L); + bool ApplyChromaticDispersion(Render::Texture *t_in, Render::Texture *t_out, float width); + bool ApplySSAAFilter(Render::Texture *t_in, Render::Texture *t_out); + bool ApplySSAOFilter(Render::Texture *t_in, Render::Texture *t_out, const Stack [2], float strength, float radius, float clip_distance, float blur_radius); + bool ApplyRadialBlur(Render::Texture *t_in, Render::Texture *t_out, float strength, float center_x, float center_y); + bool ApplyMotionBlur(Render::Texture *t_in, Render::Texture *t_out, const Stack [2], float strength, int quality = 1); + + void GetPostProcessNormalDepth(const Stack display_lists[2]); + + /// Apply post-processes. + Render::Texture *ApplyPostProcessChain(const Stack [2]); +/// @} + +/*! + @name Deferred shading. + @{ +*/ + + Render::sTexture t_gbuffer[4]; + +protected: + +struct ViewConfig +{ + Core::Camera *camera; + fRect viewport; + + ViewConfig(Core::Camera *c, const fRect &v) : camera(c), viewport(v) {} +}; + + fRect viewport; + fRect clipping; + + /// Backup the current view configuration. + ViewConfig BackupView() const; + /// Restore a view configuration. + void RestoreView(const ViewConfig &); + /// Restore a view configuration viewport. + void RestoreViewport(const ViewConfig &); + + /// Allocate shadow map. + void CreateShadowMaps(); + /// Free shadow map. + void FreeShadowMaps(); + + AutoPtr ambient_program, + pointlight_program, + pointlight_shadow_program, + spotlight_program, + spotlight_shadow_program, + linearlight_program, + linearlight_shadow_program; + + AutoPtr ds_fog_program; + + /// Render fullscreen light volume. + void RenderFullscreenLight(Shader &, Core::Light &); + /// Render point light volume. + void RenderPointLight(Core::Light &, const DrawContext &); + /// Render spot light volume. + void RenderSpotLight(Core::Light &, const DrawContext &); + /// Render linear light volume. + void RenderLinearLight(Core::Light &, const DrawContext &); + +public: + +struct ShadowMapSplit +{ + Core::Camera view; + RenderableList list; + fRect rect; +}; + + bool LightPreparePSM(const Core::Light &, bool build_dlist) const; + bool LightPreparePSSM(const Core::Light &, bool build_dlist) const; + bool LightPrepareSSM(const Core::Light &, bool build_dlist) const; + + /// Prepare shadow map for a light. + bool PrepareShadowMap(const Core::Light &, bool build_dlist) const; + + void LightRenderPSM(Core::Light &); + void LightRenderSSM(Core::Light &); + void LightRenderPSSM(Core::Light &); + + /// Render shadow map for a light. + void RenderShadowMap(Core::Light &); +/*! + @} + @name Deferred render pass. + @{ +*/ +protected: + + /// Render G-buffer map. + void RenderGBufferPass(const Stack &); + /// Render light accumulation map. + void RenderDeferredLightPass(const Stack &); + + /// Render primitive list using deferred shading. + void RenderListDeferred(const Stack &); +/// @} + +/*! + @} + @name Forward render pass. + @{ +*/ + void SetupForwardContext(const DrawContext::Context &); + + /// Cull display lists against a given light volume. + void LightCullDisplayList(const Core::Light &, const Stack &in, Stack &out); + /// Render primitive list using forward rendering. + void RenderListForward(Stack &, DrawContext::Render); + + void DrawForwardLightContribution(DrawContext::Render, const List &, const AutoStack &, const Array > &); + void DrawForwardBaseConstant(DrawContext::Render, const Stack &); +/// @} + +/*! + @name Common render pass. + @{ +*/ + RenderableList frustum_rlist, shadow_rlist; + +struct DisplayListCache +{ + DrawContext::Context ctx; + + DisplayList *dls; + Material *mat; + Shader *shd; + + const Core::Item *item; + float opacity; + + DisplayListCache() : dls(0), mat(0), shd(0), item(0), opacity(-1.f) {} +}; + + DisplayListCache dls_cache; + + /// Reset the display list cache. + void ResetDisplayListCache(); + /// Set draw context. + bool SetDrawContext(DisplayList &, const Core::Item &, const DrawContext &); + /// Draw a display list using the current renderer cache state. + void DrawDisplayListCached(DisplayList &, const Core::Item &, const DrawContext &); + + /// Set direct primitive draw state. + void DrawSetState(Core::Material::BlendOperator bo, Core::Material::RenderWord f); + /// Restore direct primitive draw state. + void DrawRestoreState(Core::Material::BlendOperator bo, Core::Material::RenderWord f); + + /// Render skybox. + void DrawSkybox(Render::sTexture [2], Render::Shader * = 0); + +public: + + /// Draw primitive list using a specific program. + void DrawList(const Stack &, const DrawContext &); + /// Build display lists. + void BuildDisplayLists(const AutoStack &, AutoStack *) const; + /// Sort display list per render attributes. + void SortDisplayList(AutoStack &) const; +/// @} + +/*! + @name Helper functions. + @{ +*/ + AutoPtr helper_idx_vbo, helper_vtx_vbo; + AutoPtr skybox_idx_vbo, skybox_vtx_vbo; + + AutoPtr direct_idx_vbo, direct_vtx_vbo; + + AutoPtr box_idx_vbo; // for deferred light volume drawing + + /// Render a fullscreen quad. + void RenderFullscreenQuad(Shader &, float k_x, float k_y, Render::Texture * = 0, Core::Light * = 0); + void RenderFullscreenQuad(Shader &, const fRect &nUnused(src_rect), const fRect &nUnused(dst_rect), Render::Texture * = 0, Core::Light * = 0); + + /// Translate a shader from ISL to the target platform language. +virtual bool TranslateShader(const Core::Shader &, String &, String &) const = 0; + + /// Set output FBO object (the current frame buffer is blit over this FBO color attachment in EndDrawList). + void SetOutputFBO(FBO *fbo = 0, const iRect *rect = 0) + { + output_fbo = fbo; + if (rect) + output_fbo_rect = *rect; + } + + int GetAnisotropySampleCount(Render::TextureParm::Anisotropy) const; + + /// Set current FBO. +virtual void SetCurrentFBO(FBO * = 0) = 0; + /// Check the current FBO state. +virtual bool CheckCurrentFBO() = 0; + +struct DirectVertexLayout +{ + size_t stride; + size_t vtx_offset, color_offset, uv_offset; +}; + + /// Helper to build a direct vertex layout from distinct input streams. + bool BuildDirectVertexLayout(uint idx_count, const ushort *idx, const Vector4 *v, const Color *c, const Vector2 *uv, DirectVertexLayout &, VBO *idx_vbo = 0, VBO *vtx_vbo = 0); +/// @} + +/*! + @name Performance functions. + @{ +*/ + /// Set a single shot event. +virtual void PerfSetMarker(const char *name, const Color &) {} + + /// Start a performance event. +virtual void PerfBeginEvent(const char *name, const Color &) {} + /// End a performance event. +virtual void PerfEndEvent() {} + +// +struct ScopedPerfEvent +{ + Renderer *renderer; + + ScopedPerfEvent(Renderer *_renderer, const char *name, const Color &color) : renderer(_renderer) + { renderer->PerfBeginEvent(name, color); } + ~ScopedPerfEvent() + { renderer->PerfEndEvent(); } +}; +/// @} + +/*! + @name Low-level draw. + @{ +*/ + /// Set material. + void SetMaterial(const Material &, const DrawContext::Context &, bool force_alpha = false); + /// Unset material. + void UnsetMaterial(const Material &, const DrawContext::Context &); + + /// Draw elements. +virtual void DrawElements(Types::PrimitiveType p_type, int index_count, Types::ValueType i_type = Types::ValueLast, const void *indice = 0) = 0; +/// @} + + /// Set the view matrix. + void SetViewMatrix(const Matrix4 &, const Matrix4 *inverse = 0); + /// Set the projection matrix. + void SetProjectionMatrix(const Matrix4 &); + /// Set the world matrix. + void SetWorldMatrix(const Matrix4 &, const Matrix4 *inverse = 0); + + /// Draw a line to the frame buffer. +virtual void DrawLine(uint count, const Vector4 *, const Color * = 0, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Render::Shader * = 0); + /// Draw a triangle to frame buffer. +virtual void DrawTriangle(uint count, const Vector4 *, const ushort * = 0, const Color * = 0, const Vector2 * = 0, const Render::Texture * = 0, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Render::Shader * = 0); + /// Draw sprite. +virtual void DrawSprite(uint count, const Vector4 *, const Color * = 0, const float *size = 0, const Render::Texture * = 0, float global_size = 1.f, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Render::Shader * = 0); + +/*! + @name Render-to-texture and spline rendering. + @author Nicolas RACOT + @{ +*/ + /// Create a render-target texture. + Render::Texture *CreateRenderTexture(const char *name, uint width, uint height, Render::Texture::Format format = Render::Texture::FormatRGBA8, Render::Texture::AA aa = Render::Texture::NoAA); + /// Clear a texture with a solid color. + void ClearTexture(Render::Texture *target, const Color &clear_color = Color(0,0,0,0)); + /// Copy/blit a source texture to a destination texture. + void BlitTextureToTexture(Render::Texture *src, Render::Texture *dst, const fRect *src_rect = 0, const fRect *dst_rect = 0); + /// Draw an interpolated spline on a texture with configurable width and color. + void DrawSplineToTexture(Render::Texture *target, const Array &control_points, float width_pixels, const Color &color, int samples_per_segment = 16, bool clear_target = false, bool soft_edge = true, const Color *border_color = nullptr, float border_width = 0.0f, float margin = 0.0f); + +private: + /// Helper structure for spline tessellation. + struct SplineRibbon + { + Array positions; + Array indices; + Array colors; + Array uvs; // for soft edge (distance from centerline) + }; + + /// Catmull-Rom spline interpolation. + Vector2 CatmullRomInterpolate(const Vector2 &p0, const Vector2 &p1, const Vector2 &p2, const Vector2 &p3, float t) const; + /// Tessellate a spline into ribbon geometry. + void TessellateSplineRibbon(const Array &control_points, float width_normalized, const Color &color, int samples_per_segment, bool soft_edge, SplineRibbon &out_ribbon); + +public: +/// @} + + /// Initialize platform. +virtual bool InitializePlatform() = 0; + /// Open platform video system. +virtual bool OpenPlatformVideo(uint w, uint h, char d, Render::VideoMode m, const void *sys_handle = 0) = 0; + /// Close platform video system. +virtual void ClosePlatformVideo() = 0; + + /// Render the display list. + void RenderList(); + + /// Output string to screen. +virtual void Write(const Render::RasterFont &, const char *, float &x, float &y, const WriterConfig &, float s = 1, const Color *c = 0, WriterAlignment a = AlignLeft, bool mirrored = false); + + /// Open video. +virtual bool Open(uint w, uint h, char d = 32, Render::VideoMode m = Render::VideoWindowed, const void *sys_handle = 0); + /// Free all renderer resources. +virtual void Free(); + /// Close video. +virtual void Close(); + /// Explicitly resize video output. +virtual bool ResizeVideo(uint w, uint h); + + /// Begin a drawing operation. + bool BeginDrawList(); + /// End a drawing operation. + void EndDrawList(); + + Renderer(); +}; + + } // GPU +} // GS + + +#endif // __GPURENDERER__ diff --git a/include/engine/gpu/gpu_shader.h b/include/engine/gpu/gpu_shader.h new file mode 100644 index 0000000..44dcf9d --- /dev/null +++ b/include/engine/gpu/gpu_shader.h @@ -0,0 +1,165 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPUSHADER__ +#define __GPUSHADER__ + + + #include "gpu/gpu_types.h" + #include "gpu/gpu_shader_object.h" + #include "core/render_data.h" + #include "core/shader_tree_compiler.h" + + +namespace GS { + + namespace Core { + class Item; + class Camera; + class Light; + struct Skin; + } + namespace GPU { + class Renderer; + struct DisplayList; + struct Material; + struct DrawContext; + +// +struct ShaderInputLocation +{ + NPLACEMENT_NEW(Renderer) +virtual ~ShaderInputLocation() {} +}; + +// +struct ShaderInput +{ + NPLACEMENT_NEW(Renderer) + + String name; + + Core::ShaderInput::Type type; + Core::ShaderInput::Semantic semantic; + Core::ShaderInput::DataType data_type; + + Render::sTexture parm_t; ///< 4B texture + Vector4 parm_v; ///< 16B vector + + int index; + + AutoPtr location; + + void SetValue(float v) { parm_v.Set(v); } + void SetValue(float x, float y) { parm_v.Set(x, y); } + void SetValue(float x, float y, float z) { parm_v.Set(x, y, z); } + void SetValue(const Vector2 &v) { parm_v.Set(v.x, v.y); } + void SetValue(const Vector4 &v) { parm_v = v; } + void SetValue(Render::Texture *t) { parm_t = t; } + + void Set(Core::ShaderInput *input) + { + index = -1; + + name = input->name; + parm_v = input->parm_v; + data_type = input->data_type; + + semantic = input->semantic; + type = input->type; + } + + ShaderInput() + { + index = -1; + data_type = Core::ShaderInput::NoData; + } +}; + +/*! + @short GPU shader. +*/ +struct Shader : public Render::Shader +{ + Renderer &renderer; + + /// Get the input list index for a given semantic. +static uint GetSemanticInputList(Core::ShaderInput::Semantic); + + AutoPtr vertex, pixel; + Array input_list[Core::ShaderInput::CategoryLast]; ///< Attributes and uniforms list are split per category. + + /// Get a program parameter from its semantic. + ShaderInput *GetInput(Core::ShaderInput::Semantic) const; + /// Get a program parameter from its name. + ShaderInput *GetInput(const char *) const; + + /// Set vertex stream inputs. + void SetVertexStreamInputs(DisplayList &); + /// Set skin inputs. + void SetSkinInputs(DisplayList &, Core::Skin &); + /// Set program inputs. + void SetConstantInputs(); + /// Set texture inputs. + void SetTextureInputs(); + /// Set renderer inputs. + void SetRendererInputs(Renderer &, Material * = 0); + /// Set transformation inputs. + void SetTransformInputs(const Matrix4 &v_pm, const Matrix4 &v_m, const Matrix4 &v_im, const Matrix4 *i_m, const Matrix4 *i_im, uint count = 1); + /// Set previous transformation inputs. + void SetPreviousTransformInputs(const Matrix4 &v_pm, const Matrix4 &v_im, const Matrix4 *i_m, uint count = 1); + /// Set material opacity inputs. + void SetMaterialOpacityInputs(Material &, float opacity); + /// Set material inputs. + void SetMaterialInputs(Material &); + /// Set light inputs. + void SetLightInputs(Renderer &, Core::Camera &, Core::Light &); + + /// Commit inputs. +virtual void CommitInputs() = 0; + + /// New GPU shader location. +virtual ShaderInputLocation *NewGPUShaderLocation() = 0; + /// Retrieve the location of any program parameter from its declaration name. +virtual bool GetLocation(const char *name, ShaderInputLocation &, Core::ShaderInput::Type = Core::ShaderInput::Uniform) = 0; + +/*! + @name Uniform accessors. + @{ +*/ +virtual void Set(const ShaderInputLocation &, const Render::Texture &, int unit) = 0; +virtual void Set(const ShaderInputLocation &, const Matrix3 *, int n = 1) = 0; +virtual void Set(const ShaderInputLocation &, const Matrix4 *, int n = 1) = 0; +virtual void Set(const ShaderInputLocation &, const float *, int n = 1) = 0; +virtual void Set(const ShaderInputLocation &, const int *, int n = 1) = 0; + + void Set(const ShaderInputLocation &l, int v) { Set(l, &v); } + void Set(const ShaderInputLocation &l, float v) { Set(l, &v); } + void Set(const ShaderInputLocation &l, const Matrix3 &m) { Set(l, &m); } + void Set(const ShaderInputLocation &l, const Matrix4 &m) { Set(l, &m); } +/// @} + +/*! + @name Attribute accessors. + @{ +*/ +virtual void Set(const ShaderInputLocation &, int elem_count, Types::ValueType, bool normalized, size_t stride, const void *offset) = 0; +/// @} + + /// Create program. +virtual bool Create(Render::ResourceFactory &, const Core::Shader &); + + /// Free program. +virtual void Free() = 0; + + Shader(Renderer &r, const char *name) : Render::Shader(name), renderer(r) {} +}; + + } // GPU +} // GS + + +#endif // __GPUSHADER__ diff --git a/include/engine/gpu/gpu_shader_compiler.h b/include/engine/gpu/gpu_shader_compiler.h new file mode 100644 index 0000000..74ba7e9 --- /dev/null +++ b/include/engine/gpu/gpu_shader_compiler.h @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------------- + nEngine - GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPU_SHADER_COMPILER__ +#define __GPU_SHADER_COMPILER__ + + + #include "gpu/gpu_shader_object.h" + + +namespace GS { + class String; + + namespace Core { struct Shader; } + namespace GPU { + struct Shader; + class Renderer; + +/*! + @short GPU shader compiler interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class IShaderCompiler +{ +protected: + + Renderer &renderer; + +virtual bool Link(const Core::Shader &, Shader &) = 0; +virtual bool CompileObject(const char *source, ShaderObject &, ShaderObject::Type, const char *source_name, String *error_log) = 0; + +public: + +virtual bool Compile(const Core::Shader &, Shader &, const char *binary_cache_id = 0); + + IShaderCompiler(Renderer &r) : renderer(r) {} +virtual ~IShaderCompiler() {} +}; + + } // GPU +} // GS + + +#endif // __GPU_SHADER_COMPILER__ diff --git a/include/engine/gpu/gpu_shader_object.h b/include/engine/gpu/gpu_shader_object.h new file mode 100644 index 0000000..e9cde55 --- /dev/null +++ b/include/engine/gpu/gpu_shader_object.h @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPUSHADEROBJECT__ +#define __GPUSHADEROBJECT__ + + + #include "alloc/ialloc.h" + + +namespace GS { + namespace GPU { + +// +struct ShaderObject +{ + NPLACEMENT_NEW(Renderer) + +enum Type +{ + Vertex = 0, + Pixel, + + TypeLast +}; + +virtual void Free() = 0; + +virtual ~ShaderObject() {} +}; + + } // GPU +} // GS + + +#endif // __GPUSHADEROBJECT__ diff --git a/include/engine/gpu/gpu_terrain.h b/include/engine/gpu/gpu_terrain.h new file mode 100644 index 0000000..e9974be --- /dev/null +++ b/include/engine/gpu/gpu_terrain.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __GPUTERRAIN__ +#define __GPUTERRAIN__ + + + #include "gpu/gpu_display_list.h" + + +namespace GS { + namespace Core { class Terrain; } + namespace GPU { + struct DisplayList; + +// +struct CachedTerrainPatch +{ + NPLACEMENT_NEW(RendererTerrain) + + Core::Terrain *terrain; + + int u, v, w, h; + int decimation; + + uint score; + + AutoPtr patch; + + CachedTerrainPatch() : terrain(0), u(0), v(0), w(-1), h(-1), decimation(0), score(0) {} +}; + + } // GPU +} // GS + + +#endif // __GPUTERRAIN__ diff --git a/include/engine/gpu/gpu_texture.h b/include/engine/gpu/gpu_texture.h new file mode 100644 index 0000000..4b7711f --- /dev/null +++ b/include/engine/gpu/gpu_texture.h @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGPUTEXTURE__ +#define __NGPUTEXTURE__ + + + #include "core/render_data.h" + + +namespace GS { + namespace GPU { + class Renderer; + +/// GPU Texture +struct Texture : public Render::Texture +{ + Renderer &renderer; + Texture(Renderer &r, const char *name = 0) : Render::Texture(name), renderer(r) {} +}; + + } // GPU +} // GS + + +#endif // __NGPUTEXTURE__ diff --git a/include/engine/gpu/gpu_triangle_batch.h b/include/engine/gpu/gpu_triangle_batch.h new file mode 100644 index 0000000..e253cb9 --- /dev/null +++ b/include/engine/gpu/gpu_triangle_batch.h @@ -0,0 +1,52 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GPUTRIANGLEBATCH__ +#define __GPUTRIANGLEBATCH__ + + + #include "core/material.h" + #include "core/render_data.h" + #include "math/vector.h" + #include "color/color.h" + #include "container/narray.h" + #include "ntypes.h" + + +namespace GS { + namespace GPU { + class Renderer; + +class TriangleBatch +{ + Renderer &renderer; + + uint batch_max_triangle_count; + uint batch_triangle_count, batch_attrib_offset; + + Array batch_idx; + Array batch_vtx; + Array batch_col; + Array batch_uv; + + const Render::Texture *batch_t; + + Core::Material::BlendOperator batch_blend_op; + Core::Material::RenderWord batch_render_word; + +public: + + void DrawTriangle(uint triangle_count, uint attrib_count, const Vector4 *, const ushort *, const Color *, const Vector2 *uv, const Render::Texture *, Core::Material::BlendOperator, Core::Material::RenderWord); + void Flush(); + + TriangleBatch(Renderer &, uint batch_max_tri = 1024); +}; + + } // GPU +} // GS + + +#endif // __GPUTRIANGLEBATCH__ diff --git a/include/engine/gpu/gpu_types.h b/include/engine/gpu/gpu_types.h new file mode 100644 index 0000000..784582c --- /dev/null +++ b/include/engine/gpu/gpu_types.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __GPUTYPES__ +#define __GPUTYPES__ + + +#if __PLATFORM_ANDROID_NDK__ || __PLATFORM_IOS__ +//#define EGL_HALF_FLOAT_SUPPORT +#endif + +#ifdef EGL_HALF_FLOAT_SUPPORT +typedef unsigned short hfloat; +#define EGL_HFLOAT GL_HALF_FLOAT_OES +#else +typedef float hfloat; +#define EGL_HFLOAT GL_FLOAT +#endif + +namespace GS { + namespace GPU { + namespace Types { + +enum ValueType +{ + ValueByte, + ValueUByte, + ValueShort, + ValueUShort, + ValueFloat, + ValueHalfFloat, + + ValueLast +}; + +enum PrimitiveType +{ + PrimitiveLine, + PrimitiveTriangle, + + PrimitiveLast +}; + + /// Convert float to half-float. + hfloat FloatToHFloat(float f); + /// Convert float to half-float. + float HFloatToFloat(hfloat hf); + + } // Types + } // Types +} // GS + + +#endif // __GPUTYPES__ diff --git a/include/engine/gpu/gpu_vbo.h b/include/engine/gpu/gpu_vbo.h new file mode 100644 index 0000000..2559057 --- /dev/null +++ b/include/engine/gpu/gpu_vbo.h @@ -0,0 +1,78 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __GPUVBO__ +#define __GPUVBO__ + + + #include "memory/memory.h" + #include "alloc/ialloc.h" + + +namespace GS { + namespace GPU { + class Renderer; + +/*! + @short GPU data buffer object. +*/ +struct VBO +{ + NPLACEMENT_NEW(Renderer) + +enum Usage +{ + Static = 0, + Dynamic +}; +enum Type +{ + Index = 0, + Vertex +}; + + Renderer &renderer; + + /// Get VBO size. +virtual size_t GetSize() const = 0; + + /// Map VBO to main memory. +virtual void *Map() = 0; + /// Unmap VBO. +virtual void Unmap() = 0; + + /// Update VBO content. +virtual bool Update(const void *, size_t start = 0, size_t size = 0) = 0; + + /// Create VBO. +virtual bool Create(size_t size, Type = Vertex, Usage = Static) = 0; + /// Create VBO, map and set data. +virtual bool Create(const void *data, size_t size, Type type = Vertex, Usage usage = Static) + { + if (!Create(size, type, usage)) + return false; + + void *p = Map(); + if (!p) + return false; + + Memory::Copy(p, data, size); + Unmap(); + return true; + } + + /// Free VBO. +virtual void Free() = 0; + + VBO(Renderer &r) : renderer(r) {} +virtual ~VBO() {} +}; + + } // GPU +} // GS + + +#endif // __GPUVBO__ diff --git a/include/engine/import/import_interface.h b/include/engine/import/import_interface.h new file mode 100644 index 0000000..18b9918 --- /dev/null +++ b/include/engine/import/import_interface.h @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIIMPORT__ +#define __NIIMPORT__ + + + #include "core/resource_factory_event_interface.h" + #include "nstring/nstring.h" + + +namespace GS { + + namespace S3D { + class Scene; + class Group; + +// +struct IImport +{ +struct Config +{ +enum PathExistsPolicy +{ + Skip = 0, + Overwrite, + Rename +}; + + sIResourceFactoryEvent event_handler; + + String base_path; + + float scale; + int frame_per_second; + + bool import_animation; + + PathExistsPolicy exists_policy_geometry, + exists_policy_material, + exists_policy_texture; + + Config() : scale(1.f), frame_per_second(24), import_animation(true), exists_policy_geometry(Skip), exists_policy_material(Skip), exists_policy_texture(Skip) {} +}; + + /// Helper function to determine an imported resource path. + bool GetOutputPath(String &out, const String &base, const char *name, const char *dflt, const char *ext, Config::PathExistsPolicy = Config::Skip) const; + + /// Test importer on a file. +virtual bool TestImport(const char *uri) = 0; + /// Import scene from file. +virtual bool ImportScene(Scene *, const char *uri, const Config &, Group ** = 0) = 0; + +virtual ~IImport() {} +}; + + } // S3D +} // GS + + +#endif // __NIIMPORT__ diff --git a/include/engine/motion/motion.h b/include/engine/motion/motion.h new file mode 100644 index 0000000..b69ba70 --- /dev/null +++ b/include/engine/motion/motion.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMOTION__ +#define __NMOTION__ + + + #include "motion/quaternion_channel.h" + #include "motion/motion_channel.h" + #include "core/path_kdtree.h" + #include "container/nlist.h" + #include "memory/nshared_ptr.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace Automation { class Player; } + namespace Core { + +/*! + @short Motion. + A motion holds together a group of channels. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Motion : public SharedObject +{ + friend class Automation::Player; + +protected: + +struct SDataPoint +{ + Time t; + Variant data; +}; + + ArrayList data_point; ///< data per point. + AutoList channel_list; + + bool use_quaternion; + QuaternionChannel quaternion; + +public: + + NPLACEMENT_NEW(Motion) + + String name; + + AutoPtr quadtree; + + /// Clone a motion, optionally specify the range to clone. + void Clone(const Motion &, const TimeRange &, bool enforce_loop); + + /// Sample time from position + bool GetClosestPoint(const Vector4 &p, Vector4 &closest, float *closest_t = 0); + + void EvaluateData(const Time &t, Variant &sample); + void EvaluatePosition(const Time &t, Vector4 &sample, Curve::LoopMode loop_mode = Curve::Reset); + void EvaluateRotation(const Time &t, Vector4 &sample, Curve::LoopMode loop_mode = Curve::Reset); + + /// Get transformation channels. + void GetTransformationChannels(MotionChannel *t[3], MotionChannel *r[3], MotionChannel *s[3]); + + bool HasKey(const TimeRange &t) const; + void MoveKey(const TimeRange &t, const Time &offset) const; + void DeleteKey(const TimeRange &t); + + /// Add a new channel controlling a given property to the motion. + MotionChannel *AddChannel(MotionChannel::Type); + /// Add several channels at once. + void AddChannels(uint channel_count); + + const AutoList &GetChannelList() const { return channel_list; } + + const QuaternionChannel &GetQuaternion() const { return quaternion; } + QuaternionChannel &GetQuaternion() { return quaternion; } + + bool GetUseQuaternion() const; + void SetUseQuaternion(bool use) { use_quaternion = use; } + + MotionChannel *GetChannel(MotionChannel::Type) const; + MotionChannel *GetChannel(uint index) const; + + /// Return the motion duration. + Time GetDuration() const; + /// Return the motion time range. + TimeRange GetTimeRange() const; + + /// Return the memory footprint in bytes of the channel. + size_t MemoryFootPrint() const; + /*! + @short Optimize motion. + Remove keys influencing output below a given threshold. + + @note This function calls Optimize() for all of the motion channels. + */ + uint Optimize(float threshold = DefaultCurveOptimizationThreshold); + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); + + ~Motion() { + ArrayListDeleteAllPtr(SDataPoint *, data_point) + } +}; + + } // Core +} // GS + + +#endif // __NMOTION__ diff --git a/include/engine/motion/motion_automation_source.h b/include/engine/motion/motion_automation_source.h new file mode 100644 index 0000000..001ccb7 --- /dev/null +++ b/include/engine/motion/motion_automation_source.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __MOTION_AUTOMATION_SOURCE__ +#define __MOTION_AUTOMATION_SOURCE__ + + + #include "automation/automation_source.h" + + +namespace GS { + namespace Core { class Motion; } + namespace Automation { + struct SourceGroup; + + using Core::Motion; + +/*! + @short Motion based automation source. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class MotionSource : public Source +{ + friend class Player; + +protected: + + SourceGroup *group; + + bool active; + Motion *motion; + + Curve::LoopMode loop_mode; + Time loop_start, loop_end; + +public: + + /// Set loop mode. +virtual void SetLoopMode(Curve::LoopMode loop = Curve::Reset) { loop_mode = loop; } + /// Set loop point. +virtual void SetLoop(const Time &start = Time::Inf, const Time &end = Time::Inf) + { + loop_start = start; + loop_end = end; + } + + void Evaluate(Player &); + bool EvaluateRotation(Quaternion &); + + /// Is motion done. + bool IsDone() const; + + MotionSource(Motion *, SourceGroup * = 0); +}; + + } // Automation +} // GS + + +#endif // __MOTION_AUTOMATION_SOURCE__ diff --git a/include/engine/motion/motion_channel.h b/include/engine/motion/motion_channel.h new file mode 100644 index 0000000..14c0ee0 --- /dev/null +++ b/include/engine/motion/motion_channel.h @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __MOTION_CHANNEL__ +#define __MOTION_CHANNEL__ + + + #include "geometry/curve.h" + + +namespace GS { + namespace Core { + +/*! + @short Motion channel object. + + This class extends the curve class holding together a set of key frames and + able to evaluate the underlying curve object at a specific position. + A channel should be used on a specific value declared by the enumeration + Type. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MotionChannel : public Curve +{ +enum Type +{ + NoType = 0, + Undf = 0, + + // Transformation block. + XPos, YPos, ZPos, + XRot, YRot, ZRot, + XScl, YScl, ZScl, + XPiv, YPiv, ZPiv, + // + + RDif, GDif, BDif, + RSpc, GSpc, BSpc, + + DiffuseIntensity, SpecularIntensity, + + ConeAngle, EdgeAngle, + + Alpha, + + ZoomFactor, + + Range, + + FogStart, FogEnd, + RFog, GFog, BFog, + + Last +}; + + Type type; + + /// Return the channel memory footprint. + size_t MemoryFootPrint() const { return Curve::MemoryFootPrint() + sizeof(MotionChannel); } + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + MotionChannel(); + ~MotionChannel(); +}; + + } // Core +} // GS + + +#endif // __MOTION_CHANNEL__ diff --git a/include/engine/motion/quaternion_channel.h b/include/engine/motion/quaternion_channel.h new file mode 100644 index 0000000..1a82ad2 --- /dev/null +++ b/include/engine/motion/quaternion_channel.h @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NQUATERNIONCHANNEL__ +#define __NQUATERNIONCHANNEL__ + + + #include "geometry/curve.h" + #include "math/quaternion.h" + #include "container/narray.h" + + +namespace GS { + + static const float DefaultChannelOptimizationThresholdQuaternion = 0.01f; + +/// Quaternion key. +struct QuaternionKey +{ + Time t; + Quaternion q; + + QuaternionKey(const Time &_t, const Quaternion &_q) : t(_t), q(_q) {} + QuaternionKey() { q.Set(); } +}; + +/*! + @short Quaternion channel. + + This class hold a set of quaternion keys and can interpolate inside the set + to determine a particular quaternion at a given time. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class QuaternionChannel +{ +private: + + ArrayList keys; + + uint PerformChannelOptimize(uint count, QuaternionKey *src, QuaternionKey *dst, float threshold); + +public: + + const ArrayList &GetKeys() const { return keys; } + + TimeRange GetTimeRange() const; + Time GetDuration() const { return GetTimeRange().valueRange(); } + + /// Insert a key, sort by time. + bool Insert(const QuaternionKey &key); + /// Evaluate channel. + void Evaluate(Time t, Quaternion &q, Curve::LoopMode loop = Curve::Constant, Time loop_start = Time::Inf, Time loop_end = Time::Inf) const; + + /// Optimize channel. + uint Optimize(float threshold = DefaultChannelOptimizationThresholdQuaternion); + /// Delete all keys in channel. + void Clear(); + + /// Return the memory usage for the channel. + size_t MemoryFootPrint() const { return size_t(keys.GetCount()) * sizeof(QuaternionKey) + sizeof(QuaternionChannel); } + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); + + QuaternionChannel(); + ~QuaternionChannel(); +}; + +} // GS + + +#endif // __NQUATERNIONCHANNEL__ diff --git a/include/engine/motion/scene_motion.h b/include/engine/motion/scene_motion.h new file mode 100644 index 0000000..fc19bd0 --- /dev/null +++ b/include/engine/motion/scene_motion.h @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMOTIONSET__ +#define __NMOTIONSET__ + + + #include "motion/motion.h" + #include "container/nmap.h" + + +namespace GS { + namespace Core { + +/// A motion set holds a reference to several motions. +struct SceneMotion +{ + String name; + + struct ItemMotion + { + uint uid; + SharedPtr motion; + }; + + AutoList item_motions; + + void Clone(const SceneMotion &src, const TimeRange &range, bool enforce_loop); + + Motion *GetItemMotion(uint uid, bool create_if_missing = false); + + TimeRange GetTimeRange() const; + Time GetDuration() const { return GetTimeRange().valueRange(); } + + bool FromMetaTag(NML::Tag &, const Map *uid_map = 0); + NML::Tag *AsMetaTag(); +}; + + } // Core +} // GS + + +#endif // __NMOTIONSET__ diff --git a/include/engine/motion/scene_motion_container.h b/include/engine/motion/scene_motion_container.h new file mode 100644 index 0000000..aa9285d --- /dev/null +++ b/include/engine/motion/scene_motion_container.h @@ -0,0 +1,30 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCENEMOTIONCONTAINER__ +#define __SCENEMOTIONCONTAINER__ + + + #include "motion/scene_motion.h" + + +namespace GS { + namespace Core { + +/// Container for scene motions (3D/2D). +struct SceneMotionContainer +{ + AutoList motions; + + bool FromMetaTag(NML::Tag &, const Map *uid_map = 0); + NML::Tag *AsMetaTag() const; +}; + + } // Core +} // GS + + +#endif // __NMOTIONSETCONTAINER__ diff --git a/include/engine/physic/physic_constraint.h b/include/engine/physic/physic_constraint.h new file mode 100644 index 0000000..847dbf1 --- /dev/null +++ b/include/engine/physic/physic_constraint.h @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPHYSIC_CONSTRAINT__ +#define __NPHYSIC_CONSTRAINT__ + + + #include "physic/physic_item.h" + #include "physic/physic_constraint_desc.h" + +namespace GS { + class Matrix4; + namespace S3D { + +/* + @short Base physic constraint. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class PhysicConstraint +{ +protected: + + PhysicConstraintDesc::Type type; + sPhysicItem item_a, item_b; + +public: + +virtual void SetPivotA(const Matrix4 &) = 0; +virtual void SetPivotB(const Matrix4 &) = 0; + +virtual bool SetupConstraint(const PhysicConstraintDesc &) = 0; +virtual void DeleteConstraint() = 0; + +virtual void Enable(bool = true) = 0; + + PhysicConstraint() : type(PhysicConstraintDesc::TypeNone) {} +virtual ~PhysicConstraint() {} +}; + + } // S3D +} // GS + + +#endif // __NPHYSIC_CONSTRAINT__ diff --git a/include/engine/physic/physic_constraint_desc.h b/include/engine/physic/physic_constraint_desc.h new file mode 100644 index 0000000..dc72b5e --- /dev/null +++ b/include/engine/physic/physic_constraint_desc.h @@ -0,0 +1,43 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPHYSIC_CONSTRAINT_DESC__ +#define __NPHYSIC_CONSTRAINT_DESC__ + + + #include "scene3d/mitem.h" + #include "math/matrix4.h" + #include "memory/nweak_ptr.h" + + +namespace GS { + namespace NML { class Tag; } + namespace S3D { + +// +struct PhysicConstraintDesc +{ +enum Type +{ + TypeNone = 0, + TypePoint, + TypeHinge +}; + + Type type; + + WeakPtr item_a, item_b; + Matrix4 pivot_a, pivot_b; + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; +}; + + } // S3D +} // GS + + +#endif // __NPHYSIC_CONSTRAINT_DESC__ diff --git a/include/engine/physic/physic_item.h b/include/engine/physic/physic_item.h new file mode 100644 index 0000000..9652491 --- /dev/null +++ b/include/engine/physic/physic_item.h @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPHYSICITEM__ +#define __NPHYSICITEM__ + + + #include "memory/nshared_ptr.h" + #include "ntypes.h" + + +namespace GS { + struct Vector4; + class Matrix3; + class Matrix4; + + namespace S3D { + struct PhysicItemDesc; + class PhysicWorld; + +/*! + @short Abstract physic item. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class PhysicItem : public SharedObject +{ +protected: + + void *user_ptr; + +public: + + void SetUserPointer(void *p) { user_ptr = p; } + void *GetUserPointer() const { return user_ptr; } + +virtual void SetSelfMask(uint) = 0; +virtual void SetCollisionMask(uint) = 0; + +virtual void SetLinearFactor(const Vector4 &) = 0; +virtual void SetAngularFactor(const Vector4 &) = 0; + +virtual void SetScale(const Vector4 &) = 0; +virtual Vector4 GetScale() const = 0; + +virtual void SetGravity(const Vector4 &) = 0; +virtual Vector4 GetGravity() const = 0; +virtual void ApplyImpulse(const Vector4 &I, const Vector4 *p = 0) = 0; +virtual void ApplyForce(const Vector4 &F, const Vector4 *p = 0) = 0; +virtual void ApplyTorque(const Vector4 &) = 0; + +virtual void SetAngularVelocity(const Vector4 &) = 0; +virtual Vector4 GetAngularVelocity() const = 0; +virtual void SetLinearVelocity(const Vector4 &) = 0; +virtual Vector4 GetLinearVelocity() const = 0; + +virtual Vector4 GetLocalPointVelocity(const Vector4 &) const = 0; +virtual Vector4 GetWorldPointVelocity(const Vector4 &) const = 0; + +virtual void SetLinearDamping(float) = 0; +virtual float GetLinearDamping() const = 0; +virtual void SetAngularDamping(float) = 0; +virtual float GetAngularDamping() const = 0; + +virtual Vector4 GetCenterOfMass() const = 0; + +/*! + @short Vehicle. + @{ +*/ +virtual void VehicleSetForce(float nUnused(F), uint nUnused(wheel_index)) = 0; +virtual void VehicleSetBrake(float nUnused(F), uint nUnused(wheel_index)) = 0; +virtual void VehicleSetSteering(float nUnused(v), uint nUnused(wheel_index)) = 0; +virtual void VehicleSetFriction(float nUnused(f), uint nUnused(wheel_index)) = 0; + + /// Get wheel matrix as returned by the model. +virtual Matrix4 VehicleGetWheelMatrix(uint nUnused(wheel_index)) = 0; +/// @} + +/*! + @short Character. + @{ +*/ +virtual void CharacterSetRotationMatrix(const Matrix3 &) = 0; +virtual void CharacterSetVelocity(const Vector4 &) = 0; +/// @} + + /*! + @short Get graphic matrix. + + This is usually an interpolated version of the internal + current and previous matrices. + */ +virtual void GetGraphicMatrix(Matrix4 &) = 0; +virtual void SetEngineMatrix(const Matrix4 &) = 0; +virtual void GetMatrix(Matrix4 &) = 0; +virtual void SetMatrix(const Matrix4 &) = 0; + +virtual void SetSleeping(bool = false) = 0; +virtual bool IsSleeping() const = 0; +virtual void SetActive(bool = true) = 0; +virtual bool GetActive() const = 0; + +virtual void ResetBody() = 0; + +virtual bool SetupBody(const PhysicItemDesc &, PhysicWorld *) = 0; +virtual void ForceUpdateMassShapePhysic(const PhysicItemDesc &, PhysicWorld *) = 0; +virtual void DeleteBody() = 0; + + PhysicItem() : user_ptr(0) {} +virtual ~PhysicItem() {} +}; + +typedef SharedPtr sPhysicItem; + + } // S3D +} // GS + + +#endif // __NPHYSICITEM__ diff --git a/include/engine/physic/physic_item_desc.h b/include/engine/physic/physic_item_desc.h new file mode 100644 index 0000000..09e77be --- /dev/null +++ b/include/engine/physic/physic_item_desc.h @@ -0,0 +1,89 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPHYSICITEMDESC__ +#define __NPHYSICITEMDESC__ + + + #include "physic/physic_shape.h" + #include "physic/physic_wheel.h" + #include "memory/bit_field.h" + + +namespace GS { + namespace S3D { + +// +struct PhysicItemDesc +{ + /// Physic mode. +enum Mode +{ + Mode_None = 0, + Mode_Static, + Mode_Kinematic, + Mode_Dynamic, + Mode_Character, + Mode_Vehicle +}; + + /// Physic flag. +enum +{ + PhysicFlag_None = 0, + PhysicFlag_NoGravity = (1 << 0), + PhysicFlag_Ghost = (1 << 1) +}; + + Mode physic_mode; + BitField physic_flags; + + uint self_mask, collision_mask; + + AutoList shape_list; + + float linear_damping, angular_damping; + Vector4 linear_factor, angular_factor; + +struct Vehicle +{ + AutoList wheel_list; +}; + Vehicle vehicle; + +struct Character +{ + float radius; + float height; + float max_step; + + Character() : radius(1), height(1), max_step(0.2f) {} +}; + Character character; + + float GetMass() const; + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + PhysicItemDesc() + { + physic_mode = Mode_None; + + linear_factor.Set(1, 1, 1); + angular_factor.Set(1, 1, 1); + linear_damping = 1; + angular_damping = 1; + + self_mask = collision_mask = 1; + } +}; + + } // S3D +} // GS + + +#endif // __NPHYSICITEMDESC__ diff --git a/include/engine/physic/physic_message.h b/include/engine/physic/physic_message.h new file mode 100644 index 0000000..c55cbba --- /dev/null +++ b/include/engine/physic/physic_message.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPHYSIC_MESSAGE__ +#define __NPHYSIC_MESSAGE__ + + +class nPhysicConstraint; +class nPhysicItem; + + +/* + @short Physic message enum. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +enum nPhysicMessage +{ + PhysicMsg_None = 0, ///< No message. + + PhysicMsg_AddingConstraint, + PhysicMsg_ConstraintAdded, + PhysicMsg_DeletingConstraint, + PhysicMsg_ConstraintDeleted, + + PhysicMsg_LastMessage +}; + +/* + @short Physic message return value. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +enum nPhysicReturnValue +{ + PhysicReturn_Ok = 0 +}; + +// +struct nPhysicConstraintMessage +{ + nPhysicConstraint *c; + nPhysicConstraintMessage(nPhysicConstraint *_c) + { c = _c; } +}; + +/// Physic listener. +class nPhysicListener +{ +public: + +virtual nPhysicReturnValue ProcessMessage(nPhysicMessage message, void *parm) = 0; +}; + + +#endif // __NPHYSIC_MESSAGE__ diff --git a/include/engine/physic/physic_shape.h b/include/engine/physic/physic_shape.h new file mode 100644 index 0000000..3d145a6 --- /dev/null +++ b/include/engine/physic/physic_shape.h @@ -0,0 +1,89 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPHYSICSHAPE__ +#define __NPHYSICSHAPE__ + + + #include "physic/physic_wheel.h" + #include "container/narray.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace NML { class Tag; } + namespace S3D { + +/*! + @short Physic shape. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct PhysicShape +{ +enum Type +{ + TypeNone = 0, + TypeBox, + TypeSphere, + TypeConvex, + TypeCylinder, + TypeCone, + TypeCapsule, + TypeMesh, + TypeHeightmap +}; + +protected: + + Type type; + + int width, height; + Array heightmap; + + float resolution; + +public: + + void Free(); + + Matrix4 GetMatrix(); + void SetMatrix(const Matrix4 &); + + String path; + + Vector4 position, ///< Position. + rotation, ///< Rotation. + scale, ///< Scale. + dimensions; ///< Dimensions. + + float mass, + restitution, + dynamic_friction, + static_friction; + + float *GetHeightmap() const { return heightmap; } + int GetWidth() const { return width; } + int GetHeight() const { return height; } + float GetResolution() const { return resolution; } + + bool Set(float *heightmap, int width, int height, float resolution); + bool Set(Type, const char *path); + bool Set(Type = TypeNone, const Vector4 & = Vector4(1, 1, 1)); + + Type GetType() const { return type; } + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + PhysicShape(); + ~PhysicShape(); +}; + + } // S3D +} // GS + + +#endif // __NPHYSICSHAPE__ diff --git a/include/engine/physic/physic_wheel.h b/include/engine/physic/physic_wheel.h new file mode 100644 index 0000000..18012aa --- /dev/null +++ b/include/engine/physic/physic_wheel.h @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPHYSICWHEEL__ +#define __NPHYSICWHEEL__ + + + #include "math/matrix4.h" + #include "memory/nshared_ptr.h" + #include "container/nlist.h" + + +namespace GS { + namespace NML { class Tag; } + namespace S3D { + +/*! + @short Abstract physic wheel for the physic vehicle model. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct PhysicWheel +{ +/*! + @name Wheel section. + @{ +*/ + float friction, radius; +/*! + @} + @name Suspension section. + @{ +*/ + Matrix4 ref_matrix; ///< Suspension origin in vehicle body space. + + float rest_length, + max_compression, + stiffness, + damping; +/// @} + +/*! + @name Serialization. + @{ +*/ + bool FromMetaTag(NML::Tag &tag); + NML::Tag *AsMetaTag() const; +/// @} + + PhysicWheel(); +}; + +typedef List PhysicWheelList; + + } // S3D +} // GS + + +#endif // __NPHYSICWHEEL__ diff --git a/include/engine/physic/physic_world.h b/include/engine/physic/physic_world.h new file mode 100644 index 0000000..a1799a6 --- /dev/null +++ b/include/engine/physic/physic_world.h @@ -0,0 +1,137 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPHYSICWORLD__ +#define __NPHYSICWORLD__ + + + #include "physic/physic_world_interface.h" + #include "physic/physic_message.h" + #include "math/vector.h" + #include "timing/benchmark.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + + +namespace GS { + + namespace Core { class Camera; } + + namespace Render { + class Renderer; + class RasterFont; + } + namespace S3D { + class PhysicItem; + class PhysicConstraint; + struct PhysicShape; + + using Core::Camera; + using Render::Renderer; + using Render::RasterFont; + +/// Raytrace hit result structure. +struct PhysicTrace +{ + Vector4 n, p; ///< Intersection normal and point in world space. + String m; ///< Material name at intersection point. + PhysicShape *s; + PhysicItem *i; + + PhysicTrace() : m(0), s(0), i(0) {} +}; + +/// Collision pair. +struct CollisionPair +{ + PhysicItem *a, *b; + uint contact_count; + Vector4 contact[4], normal[4]; + + CollisionPair() : a(0), b(0), contact_count(0) {} +}; + +/* + @short Abstract physic world. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class PhysicWorld +{ +protected: + + float timestep, + substep_dt; + Vector4 gravity; + + IPhysicWorld *world_interface; + +public: + + Benchmark bench_step; + +virtual PhysicItem *NewItem() = 0; +virtual PhysicConstraint *NewConstraint() = 0; + + /// Clear convex/mesh cache. +virtual void ClearConvexMeshCache() = 0; + +virtual bool HasDebugger() const { return false; } +virtual void CreateDebugger(Renderer * = 0) {} + + /// Draw debug informations (native library display). +virtual void DrawDebug(Renderer &, Camera *, RasterFont *, bool xray_first_pass) {} + + void SetWorldInterface(IPhysicWorld *i) { world_interface = i; } + IPhysicWorld *GetWorldInterface() const { return world_interface; } + + void SetTimestep(float t = 1.f / 60.f) { timestep = t; } + float GetTimestep() const { return timestep; } + + void SetGravity(const Vector4 &g) { gravity = g; } +const Vector4 &GetGravity() const { return gravity; } + +virtual bool Create() = 0; +virtual void Delete() = 0; + + /// Raytrace world. +virtual bool Raytrace(const Vector4 &s, const Vector4 &d, PhysicTrace &hit, int collision_mask = ~0, int shape_mask = ~0, float max_distance = -1.f) = 0; + + /// Return the number of collision pair in the previous step. +virtual uint GetCollisionPairCount() = 0; + /// Return the number of collision pair in the previous step. +virtual bool GetCollisionPair(uint n, CollisionPair &) = 0; + +virtual void Step(const Time &dt) = 0; + +/*! + @name Low-level message broadcasting system. + @{ +*/ +protected: + + /// Physics message listener. + List listener_list; + +public: + + bool RegisterMessageListener(nPhysicListener *listener) { return asbool(listener_list.Add(listener)); } + bool UnregisterMessageListener(nPhysicListener *listener) { return listener_list.Remove(listener); } + void BroadcastMessage(nPhysicMessage msg, void *parm = 0) + { + ListForeachPtr(nPhysicListener *, listener, listener_list) + listener->ProcessMessage(msg, parm); + } +/// @} + + PhysicWorld(); +virtual ~PhysicWorld() {} +}; + + } // S3D +} // GS + + +#endif // __NPHYSICWORLD__ diff --git a/include/engine/physic/physic_world_interface.h b/include/engine/physic/physic_world_interface.h new file mode 100644 index 0000000..975b333 --- /dev/null +++ b/include/engine/physic/physic_world_interface.h @@ -0,0 +1,30 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __PHYSICWORLDINTERFACE__ +#define __PHYSICWORLDINTERFACE__ + + +namespace GS { + namespace S3D { + +/* + @short Physic world interface. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct IPhysicWorld +{ + /// Called whenever a physic tick is done. +virtual void PhysicStep(float, bool = true) {} + +virtual ~IPhysicWorld() {} +}; + + } // S3D +} // GS + + +#endif // __PHYSICWORLDINTERFACE__ diff --git a/include/engine/project/project.h b/include/engine/project/project.h new file mode 100644 index 0000000..898b820 --- /dev/null +++ b/include/engine/project/project.h @@ -0,0 +1,145 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPROJECT__ +#define __NPROJECT__ + + + #include "project/project_factory_interface.h" + #include "project/project_scene_instance.h" + #include "project/project_script_unit.h" + #include "project/project_layer.h" + #include "core/resource_factories.h" + #include "core/raster_font.h" + #include "core/clock.h" + #include "script/script_unit.h" + #include "script/script_vm.h" + #include "font/font_factory.h" + #include "font/font_cache.h" + + +namespace GS { + + namespace Audio { struct IMixer; } + namespace Render { class Renderer; } + + namespace Core { + using Audio::IMixer; + using Render::Renderer; + +// +class Project +{ +protected: + + sResourceFactories factories; + + AutoList instance_list; + + bool prohibit_project_action; ///< Disable all instance creation and layer stack modifications. + + /// Check whether project action are allowed. + bool IsProjectActionAllowed(const char *f); + +public: + + String file_path; + String name, authors, description, company; + + Script::sVM vm; + + sClock clock; + sFontCache font_cache; + + //---------------------------------------------------------------------- + /// @short Render flags. +enum RenderFlag +{ + FlagNone = 0, + FlagDisableScript = (1 << 0), + + FlagDefault = FlagNone +}; + +enum ProjectFlag +{ + ProjectFlagNone = 0, + ProjectFlagEnd = (1 << 0), + ProjectFlagDebugPhysics = (1 << 1) +}; + + BitField flags; + + AutoList layer_list; + + void Update(uint scene_update_flag); + void Render(Renderer &, RenderFlag = FlagDefault); + //---------------------------------------------------------------------- + + /// Draw profiler. + void DrawProfilerText(Renderer &, Render::RasterFont *font[2], float &x, float &y); + + //---------------------------------------------------------------------- + StringList root_script_list, search_path; + + bool CompileRootScripts(); + + AutoPtr script_unit; + + void UpdateScriptClock(); + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + AutoPtr iproject_factory; + + ProjectSceneInstance *FindSceneInstance(const char *) const; + ProjectSceneInstance *FindSceneInstance(const S3D::Scene *) const; + ProjectSceneInstance *FindSceneInstance(const S2D::Scene *) const; + + ProjectSceneInstance *Instantiate(const char *name); + ProjectSceneInstance *Instantiate(S3D::Scene *); + ProjectSceneInstance *Instantiate(S2D::Scene *); + + void Delete(ProjectSceneInstance *scene); + + /// Create a layer for a given project scene. + ProjectLayer *AddLayer(ProjectSceneInstance *, float zorder = 0.5); + + bool IsActive(const ProjectSceneInstance &inst) const { return inst.active; } + void Activate(ProjectSceneInstance &, bool activate); + + /// Return the number of instantiated layer in the display stack. + uint GetInstanceCount() const { return instance_list.GetCount(); } + /// Get scene instance list. + const AutoList &GetInstanceList() const { return instance_list; } + /// Return the number of active layer in the display stack. + uint GetActiveCount() const; + //---------------------------------------------------------------------- + + void ResetStatistics(); + + void New(); + + bool Open(bool project_mode = true); + bool Setup(); + void Close(); + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + Project(ResourceFactories *, IFontFactory *, Script::IVM * = 0); +virtual ~Project(); +}; + + } // Core +} // GS + +//------------------------------------------------------------------------------ +#define __PROJECT_ACTION_SAFETY_CHECK(__RET__) { if (!IsProjectActionAllowed(__FUNCTION__)) return __RET__; } +#define __PROJECT_ACTION_SAFETY_CHECK_RAW { if (!IsProjectActionAllowed(__FUNCTION__)) return; } + + +#endif // __NPROJECT__ diff --git a/include/engine/project/project_factory_interface.h b/include/engine/project/project_factory_interface.h new file mode 100644 index 0000000..5ed487c --- /dev/null +++ b/include/engine/project/project_factory_interface.h @@ -0,0 +1,28 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPROJECTFACTORYINTERFACE__ +#define __NPROJECTFACTORYINTERFACE__ + + +namespace GS { + namespace S3D { class PhysicWorld; } + namespace Core { + +/// Project factory abstract interface. +struct IProjectFactory +{ + /// Return a new physic world interface. +virtual S3D::PhysicWorld *NewPhysicWorld() const { return 0; } + +virtual ~IProjectFactory() {} +}; + + } // Core +} // GS + + +#endif // __NPROJECTFACTORYINTERFACE__ diff --git a/include/engine/project/project_layer.h b/include/engine/project/project_layer.h new file mode 100644 index 0000000..4204cb6 --- /dev/null +++ b/include/engine/project/project_layer.h @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPROJECTLAYER__ +#define __NPROJECTLAYER__ + + +namespace GS { + namespace Core { + class ProjectSceneInstance; + +/// Project layer to display a scene instance. +struct ProjectLayer +{ + ProjectSceneInstance *inst; + float zorder; + + ProjectLayer(ProjectSceneInstance *i, float _zorder = 0.5) : inst(i) + { zorder = _zorder; } +}; + + } // Core +} // GS + + +#endif // __NPROJECTLAYER__ diff --git a/include/engine/project/project_scene_instance.h b/include/engine/project/project_scene_instance.h new file mode 100644 index 0000000..db39c35 --- /dev/null +++ b/include/engine/project/project_scene_instance.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPROJECTSCENEINSTANCE__ +#define __NPROJECTSCENEINSTANCE__ + + + #include "nstring/nstring.h" + + +namespace GS { + namespace S2D { class Scene; } + namespace S3D { class Scene; } + namespace Core { + +// Project scene instance. +class ProjectSceneInstance +{ + friend class Project; + +public: + +enum Type +{ + Type_Scene3d = 0, + Type_Scene2d +}; + +protected: + + bool active; + Type type; + +public: + + union + { + void *instance; + S2D::Scene *instance_2d; + S3D::Scene *instance_3d; + }; + + String GetPath() const; + + Type GetType() const { return type; } + bool IsActive() const { return active; } + + void Free(); + + ~ProjectSceneInstance(); + +protected: + + ProjectSceneInstance(S3D::Scene *inst) + { + active = true; + type = Type_Scene3d; + instance_3d = inst; + } + ProjectSceneInstance(S2D::Scene *inst) + { + active = true; + type = Type_Scene2d; + instance_2d = inst; + } +}; + + } // Core +} // GS + + +#endif // __NPROJECTSCENEINSTANCE__ diff --git a/include/engine/project/project_script_unit.h b/include/engine/project/project_script_unit.h new file mode 100644 index 0000000..8557e94 --- /dev/null +++ b/include/engine/project/project_script_unit.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __PROJECTSCRIPTUNIT__ +#define __PROJECTSCRIPTUNIT__ + + + #include "script/script_unit.h" + #include "script/script_object.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace Core { + +/*! + @short Project script unit. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ProjectScriptUnit : public GS::Script::Unit +{ + AutoPtr setup_callback, update_callback; + + bool Open(); + void Close(); + + ProjectScriptUnit(Script::IVM *); + ~ProjectScriptUnit(); +}; + + } // Core +} // GS + + +#endif // __PROJECTSCRIPTUNIT__ diff --git a/include/engine/scene3d/group.h b/include/engine/scene3d/group.h new file mode 100644 index 0000000..bcb5aa4 --- /dev/null +++ b/include/engine/scene3d/group.h @@ -0,0 +1,95 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGROUP__ +#define __NGROUP__ + + + #include "scene3d/mitem.h" + #include "motion/scene_motion_container.h" + #include "automation/automation_player.h" + #include "memory/bit_field.h" + + +namespace GS { + class Matrix4; + + namespace Core { struct ResourceFactories; } + namespace S3D { + class MItem; + +/*! + @short Group of managed items. + @Note The group root item is not part of the group. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Group : public SharedObject +{ + MItem *root; + + SharedList item_list; + SharedList group_list; + +public: + +enum +{ + Hidden = (1 << 0), + Locked = (1 << 1) +}; + + String name; + BitField flags; + +inline MItem *GetRootItem() const { return root; } + void SetRootItem(MItem *); + + /// Return the group item member list. +inline const SharedList &GetItemList() const { return item_list; } + + /// Return the number of members in group. +inline uint GetMemberCount() const { return item_list.GetCount(); } + + MItem *Item(const char *) const; + MItem *ItemFromUid(uint uid) const; + bool IsMember(const MItem *) const; + + MItem *Add(MItem *, bool block_duplicate = false); + bool Remove(MItem *); + + Group *GetGroup(const char *) const; + bool IsMember(const Group *) const; + + Group *Add(Group *, bool block_duplicate = false); + bool Remove(Group *); + + /// Append a group content to this group. + bool AppendGroup(const Group &); + + /// Set the invisible flag of all items in group. + void SetInvisible(bool invisible); + + void Offset(const Matrix4 &); + void Translate(float, float, float); + void Rotate(float, float, float); + + Core::SceneMotionContainer motion; + + /// Set motion on all group items. + void SetMotion(const char *name, Automation::SourceGroup ** = 0, float blend = Units::Sec(0.1), Automation::Player::AddSourceMode = Automation::Player::SourceSet, float weight = 1); + + void RenderSetup(Core::ResourceFactories *); + void Setup(); + void Reset(); + + Group() : root(0) {} +}; + + } // S3D +} // GS + + +#endif // __NGROUP__ diff --git a/include/engine/scene3d/instance.h b/include/engine/scene3d/instance.h new file mode 100644 index 0000000..d7450b1 --- /dev/null +++ b/include/engine/scene3d/instance.h @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NINSTANCE__ +#define __NINSTANCE__ + + + #include "scene3d/mitem.h" + + +namespace GS { + namespace S3D { + class Group; + +/*! + @short Scene instance proxy. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Instance : public MItem, public Core::Item +{ +static MItemType GetMItemClassType() { return Type_Instance; } + + String template_path; + bool do_not_parent; + + Group *instance_group; + + bool Instantiate(Scene *); + +virtual Core::Item *GetBaseItem() { return this; } +virtual Core::Renderable *GetRenderable() { return 0; } + +virtual void RenderSetup(Core::ResourceFactories * = 0); + + void ComputeMinMax(MinMax &) const; + +/*! + @name Editor specific. + @{ +*/ + AutoPtr instance_scene; ///< Used by the editor. + + void FreeEditorInstance(); +/// @} + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); + + Instance(); + ~Instance(); +}; + + } // S3D +} // GS + + +#endif // __NINSTANCE__ diff --git a/include/engine/scene3d/item_automated_property_provider.h b/include/engine/scene3d/item_automated_property_provider.h new file mode 100644 index 0000000..ecf196b --- /dev/null +++ b/include/engine/scene3d/item_automated_property_provider.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NITEMAUTOMATEDPROPERTYPROVIDER__ +#define __NITEMAUTOMATEDPROPERTYPROVIDER__ + + + #include "automation/automated_property_provider.h" + + +namespace GS { + + namespace Core { class Item; } + namespace S3D { + namespace Automation { + +/*! + @short Item automated property provider. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct ItemPropertyProvider : public GS::Automation::IPropertyProvider +{ + Core::Item *item; + +virtual bool GetProperty(Core::MotionChannel::Type, float &); +virtual bool SetProperty(Core::MotionChannel::Type, float); +virtual Quaternion GetRotation() const; +virtual bool SetRotation(const Quaternion &); + + ItemPropertyProvider(Core::Item *i) : item(i) {} +}; + + } // Automation + } // S3D +} // GS + + +#endif // __NITEMAUTOMATEDPROPERTYPROVIDER__ diff --git a/include/engine/scene3d/mcamera.h b/include/engine/scene3d/mcamera.h new file mode 100644 index 0000000..5194545 --- /dev/null +++ b/include/engine/scene3d/mcamera.h @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMCAMERA__ +#define __NMCAMERA__ + + + #include "core/camera.h" + #include "scene3d/mitem.h" + + +namespace GS { + namespace S3D { + +/*! + @short Managed camera. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MCamera: public MItem, public Core::Camera +{ +static MItemType GetMItemClassType() { return Type_Camera; } + +virtual Core::Item *GetBaseItem() { return this; } +virtual Core::Renderable *GetRenderable() { return 0; } + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag(); + + MCamera(); +}; + + } // S3D +} // GS + + +#endif // __NMCAMERA__ diff --git a/include/engine/scene3d/mconstraint.h b/include/engine/scene3d/mconstraint.h new file mode 100644 index 0000000..45f315f --- /dev/null +++ b/include/engine/scene3d/mconstraint.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __MCONSTRAINT__ +#define __MCONSTRAINT__ + + + #include "scene3d/mitem.h" + #include "physic/physic_constraint.h" + + +namespace GS { + namespace S3D { + +/// Managed physic constraint. +struct MConstraint : public MItem +{ + PhysicConstraintDesc desc; + AutoPtr physic_data; + +static MItemType GetMItemClassType() { return Type_Constraint; } + + void Setup(PhysicWorld *); + +virtual Core::Item *GetBaseItem() { return 0; } +virtual Core::Renderable *GetRenderable() { return 0; } + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag(); + + MConstraint(PhysicConstraint *); +}; + + } // S3D +} // GS + + +#endif // __MCONSTRAINT__ diff --git a/include/engine/scene3d/memitter.h b/include/engine/scene3d/memitter.h new file mode 100644 index 0000000..7186154 --- /dev/null +++ b/include/engine/scene3d/memitter.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMEMITTER__ +#define __NMEMITTER__ + + + #include "scene3d/mitem.h" + #include "core/emitter.h" + + +namespace GS { + namespace S3D { + +/*! + @short Managed emitter. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MEmitter : public MItem, public Core::Emitter +{ +static MItemType GetMItemClassType() { return Type_Emitter; } + + void Update(const Time &); + void Setup(PhysicWorld *); + +virtual Core::Item *GetBaseItem() { return this; } +virtual Core::Renderable *GetRenderable() { return this; } + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag(); + + MEmitter(); +}; + + } // S3D +} // GS + + +#endif // __NMEMITTER__ diff --git a/include/engine/scene3d/mitem.h b/include/engine/scene3d/mitem.h new file mode 100644 index 0000000..a5e041e --- /dev/null +++ b/include/engine/scene3d/mitem.h @@ -0,0 +1,138 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMITEM__ +#define __NMITEM__ + + + #include "physic/physic_item_desc.h" + #include "physic/physic_item.h" + #include "scene3d/mitem_event_interface.h" + #include "scene3d/mitem_type.h" + #include "core/ace.h" + #include "core/item.h" + #include "script/scripted_object.h" + #include "automation/automation_player.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + class Time; + + namespace Script { class VM; } + + namespace Core { + class Item; + struct Renderable; + } + + namespace S3D { + class Scene; + class PhysicWorld; + +/*! + @short Managed item. + + The scene graph base node class. It also provide a mean to key frame any + base properties of derived entities such as colors, ranges, intensities, etc... + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class MItem : public ACE::Unit, public SharedObject +{ + friend class Scene; + +public: + +enum Flag +{ + Flag_None = 0, + + Flag_Billboard = (1 << 0), + Flag_SolveOverlap = (1 << 1), + Flag_Ghost = (1 << 2), + Flag_Physic = (1 << 3), + Flag_TriggerDetected = (1 << 4), + + Flag_IsActive = (1 << 5), + Flag_IsStatic = (1 << 6), + Flag_IsHelper = (1 << 7), + + // Non-serialized. + Flag_EditorHidden = (1 << 8), + Flag_EditorLocked = (1 << 9) +}; + +protected: + + MItemType item_type; + + bool initial_state_set; ///< Is item initial state set? + Matrix4 initial_matrix; ///< Initial matrix. + + uint uid; ///< Item scene unique identifier. + float priority; ///< Heuristic bias value. + +/*! + @name General section. + @{ +*/ +public: + + String name; ///< Item name. + + BitField mitem_flags; + + float global_alpha; + + uint GetUid() const { return uid; } + MItemType GetItemType() const { return item_type; } + +virtual Core::Item *GetBaseItem() = 0; +virtual Core::Renderable *GetRenderable() = 0; + + float GetPriority() const { return priority; } + void SetPriority(float p = 0.5f) { priority = p; } + + /// Store the current transformation as the initial transformation. + void SetInitialTransformation(); + /// Reset to initial transformation. + void ResetToInitialTransformation(); + + /// Return the active state of the item. +virtual inline bool isActive() const { return mitem_flags.IsSet(Flag_IsActive); } + /// Return the static state of the item. +virtual bool isStatic() const { return mitem_flags.IsSet(Flag_IsStatic); } + +virtual void Update(const Time &dt); +virtual void Setup(PhysicWorld *); +void ForceUpdateMassShapePhysic(PhysicWorld *physic_world); + void Reset(); +/// @} + + bool ExecCommand(ACE::Command *, float dt); + + PhysicItemDesc physic_item_desc; + sPhysicItem physic_item; + + AutoPtr item_event; + AutoPtr scripted_object; + AutoPtr automation_player; + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag(); + + MItem(); +virtual ~MItem() {} +}; + +typedef SharedPtr sMItem; + + } // S3D +} // GS + + +#endif // __NMITEM__ diff --git a/include/engine/scene3d/mitem_event_interface.h b/include/engine/scene3d/mitem_event_interface.h new file mode 100644 index 0000000..f716916 --- /dev/null +++ b/include/engine/scene3d/mitem_event_interface.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __IITEMEVENT__ +#define __IITEMEVENT__ + + +namespace GS { + namespace S3D { + class MItem; + struct MTrigger; + struct CollisionPair; + +/*! + @short Item event interface. + + Implement this class if you wish to process item events. + The default implementation forwards events to the item active script units. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct IItemEvent +{ +virtual void OnSetup(MItem *) {} +virtual void OnSetupDone(MItem *) {} +virtual void OnReset(MItem *) {} + +virtual void OnActivate(MItem *, bool) {} + +virtual void OnPhysicStep(MItem *, bool /*step_taken*/) {} + +virtual void OnItemEnter(MTrigger *, MItem *) {} +virtual void OnItemExit(MTrigger *, MItem *) {} + +virtual void OnEnterTrigger(MItem *, MTrigger *) {} +virtual void OnTrigger(MItem *, MTrigger *) {} +virtual void OnExitTrigger(MItem *, MTrigger *) {} + +virtual void OnUpdate(MItem *) {} +virtual void OnDelete(MItem *) {} + +virtual void OnRenderDone(MItem *) {} +virtual void OnRenderUser(MItem *) {} + +virtual void OnCollision(MItem *, MItem * /*with*/, const CollisionPair &) {} + +virtual ~IItemEvent() {} +}; + + } // S3D +} // GS + + +#endif // __IITEMEVENT__ diff --git a/include/engine/scene3d/mitem_event_script_interface.h b/include/engine/scene3d/mitem_event_script_interface.h new file mode 100644 index 0000000..4c1117b --- /dev/null +++ b/include/engine/scene3d/mitem_event_script_interface.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NITEMSCRIPTEVENT__ +#define __NITEMSCRIPTEVENT__ + + + #include "scene3d/mitem_event_interface.h" + + +namespace GS { + namespace S3D { + +/*! + @short Item script event. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MItemScriptEvent : public IItemEvent +{ +virtual void OnSetup(MItem *); +virtual void OnSetupDone(MItem *); +virtual void OnReset(MItem *); + +virtual void OnActivate(MItem *, bool activate); + +virtual void OnPhysicStep(MItem *, bool step_taken); + +virtual void OnItemEnter(MTrigger *, MItem *); +virtual void OnItemExit(MTrigger *, MItem *); + +virtual void OnEnterTrigger(MItem *, MTrigger *); +virtual void OnTrigger(MItem *, MTrigger *); +virtual void OnExitTrigger(MItem *, MTrigger *); + +virtual void OnUpdate(MItem *); +virtual void OnDelete(MItem *); + +virtual void OnRenderDone(MItem *); +virtual void OnRenderUser(MItem *); + +virtual void OnCollision(MItem *, MItem *with, const CollisionPair &); +}; + + } // S3D +} // GS + + +#endif // __NITEMSCRIPTEVENT__ diff --git a/include/engine/scene3d/mitem_script_unit.h b/include/engine/scene3d/mitem_script_unit.h new file mode 100644 index 0000000..1b14265 --- /dev/null +++ b/include/engine/scene3d/mitem_script_unit.h @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __MITEMSCRIPTUNIT__ +#define __MITEMSCRIPTUNIT__ + + + #include "script/script_unit.h" + #include "script/script_object.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace S3D { + +/*! + @short Managed item script unit. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MItemScriptUnit : public Script::Unit +{ + AutoPtr + update_callback, + trigger_callback, + activation_callback, + physic_callback, + physic_sleep_callback, + collision_callback, + collisionex_callback, + render_user_callback; + + bool Open(); + void Close(); + + MItemScriptUnit(Script::IVM *); + ~MItemScriptUnit(); +}; + + } // S3D +} // GS + + +#endif // __MITEMSCRIPTUNIT__ diff --git a/include/engine/scene3d/mitem_scripted_object.h b/include/engine/scene3d/mitem_scripted_object.h new file mode 100644 index 0000000..d7f4815 --- /dev/null +++ b/include/engine/scene3d/mitem_scripted_object.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMITEMSCRIPTEDOBJECT__ +#define __NMITEMSCRIPTEDOBJECT__ + + + #include "script/scripted_object.h" + + +namespace GS { + namespace S3D { + class MItem; + +/*! + @short Managed item scripted object. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class MItemScriptedObject : public Script::ScriptedObject +{ + MItem *item; + +public: + +virtual Script::Unit *NewUnit() const; + + MItemScriptedObject(MItem *i, Script::IVM *vm = 0) : Script::ScriptedObject(vm), item(i) {} +}; + + } // S3D +} // GS + + +#endif // __NMITEMSCRIPTEDOBJECT__ diff --git a/include/engine/scene3d/mitem_type.h b/include/engine/scene3d/mitem_type.h new file mode 100644 index 0000000..4e0516d --- /dev/null +++ b/include/engine/scene3d/mitem_type.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMITEMTYPE__ +#define __NMITEMTYPE__ + + +namespace GS { + namespace S3D { + +enum MItemType +{ + Type_None = 0, + Type_Camera, + Type_Object, + Type_Light, + Type_Trigger, + Type_Emitter, + Type_Instance, + Type_Terrain, + Type_Constraint +}; + + } // S3D +} // GS + + +#endif // __NMITEMTYPE__ diff --git a/include/engine/scene3d/mlight.h b/include/engine/scene3d/mlight.h new file mode 100644 index 0000000..939bf98 --- /dev/null +++ b/include/engine/scene3d/mlight.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMLIGHT__ +#define __NMLIGHT__ + + + #include "core/light.h" + #include "scene3d/mitem.h" + + +namespace GS { + namespace S3D { + +/*! + @short Managed light. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MLight : public MItem, public Core::Light +{ +static MItemType GetMItemClassType() { return Type_Light; } + + bool isActive() const; + +virtual Core::Item *GetBaseItem() { return this; } +virtual Core::Renderable *GetRenderable() { return 0; } + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag(); + + MLight(); +}; + + } // S3D +} // GS + + +#endif // __NMLIGHT__ diff --git a/include/engine/scene3d/mobject.h b/include/engine/scene3d/mobject.h new file mode 100644 index 0000000..c98cba0 --- /dev/null +++ b/include/engine/scene3d/mobject.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMOBJECT__ +#define __NMOBJECT__ + + + #include "core/object.h" + #include "scene3d/mitem.h" + + +namespace GS { + namespace S3D { + +/*! + @short Managed object. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MObject : public MItem, public Core::Object +{ +static MItemType GetMItemClassType() { return Type_Object; } + +virtual inline bool IsRenderable() const { return isActive(); } + +virtual Core::Item *GetBaseItem() { return this; } +virtual Core::Renderable *GetRenderable() { return this; } + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag(); + + MObject(); +}; + + } // S3D +} // GS + + +#endif // __NMOBJECT__ diff --git a/include/engine/scene3d/mterrain.h b/include/engine/scene3d/mterrain.h new file mode 100644 index 0000000..48ffacc --- /dev/null +++ b/include/engine/scene3d/mterrain.h @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMTERRAIN__ +#define __NMTERRAIN__ + + + #include "core/terrain.h" + #include "scene3d/mitem.h" + + +namespace GS { + namespace S3D { + +/*! + @short Managed terrain. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MTerrain : public MItem, public Core::Terrain +{ +static MItemType GetMItemClassType() { return Type_Terrain; } + +virtual Core::Item *GetBaseItem() { return this; } +virtual Core::Renderable *GetRenderable() { return 0; } + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag(); + + MTerrain(); +}; + + } // S3D +} // GS + + +#endif // __NMTERRAIN__ diff --git a/include/engine/scene3d/mtrigger.h b/include/engine/scene3d/mtrigger.h new file mode 100644 index 0000000..632a9fb --- /dev/null +++ b/include/engine/scene3d/mtrigger.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMTRIGGER__ +#define __NMTRIGGER__ + + + #include "scene3d/mitem.h" + #include "core/trigger.h" + + +namespace GS { + namespace S3D { + struct MTrigger; + +/// Managed trigger proxy item. +class MTriggerProxy : public Core::Trigger +{ + MTrigger *mtrigger; + +public: + +virtual void MarkItem(Core::Item *); +virtual void DropItem(Core::Item *); + + MTriggerProxy(MTrigger *t) : mtrigger(t) {} +}; + +/*! + @short Managed trigger. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct MTrigger : public MItem, public MTriggerProxy +{ +static MItemType GetMItemClassType() { return Type_Trigger; } + +virtual Core::Item *GetBaseItem() { return this; } +virtual Core::Renderable *GetRenderable() { return 0; } + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag(); + + MTrigger(); +}; + + } // S3D +} // GS + + +#endif // __NMTRIGGER__ diff --git a/include/engine/scene3d/scene.h b/include/engine/scene3d/scene.h new file mode 100644 index 0000000..637cbf6 --- /dev/null +++ b/include/engine/scene3d/scene.h @@ -0,0 +1,336 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCENE__ +#define __NSCENE__ + + + #include "scene3d/scene_message.h" + #include "scene3d/scene_event_interface.h" + #include "scene3d/group.h" + #include "scene3d/scene_io_flag.h" + #include "scene3d/scene_profiler.h" + #include "core/core_profiler.h" + #include "core/renderer_environment_interface.h" + #include "core/simple_list_renderable.h" + #include "core/octree_renderable.h" + #include "core/tool_mode.h" + #include "core/clock.h" + #include "script/script_vm.h" + #include "timing/profiler.h" + #include "reflection/c_refl.h" + + +/// Debug display flags. +#define SceneDebugDisplayItems (1 << 0) +#define SceneDebugDisplayBones (1 << 1) +#define SceneDebugDisplayBoundingVolumes (1 << 2) +#define SceneDebugDisplayOctreeVolumes (1 << 3) +#define SceneDebugDisplayMotions (1 << 4) + +/// Scene update flags. +#define SceneUpdateNone 0 +#define SceneUpdateMotion (1 << 0) +#define SceneUpdatePhysic (1 << 1) +#define SceneUpdateEvent (1 << 2) +#define SceneUpdateTrigger (1 << 3) +#define SceneUpdateAll uint(~0) + +namespace GS { + + namespace GPU { class TriangleBatch; } + namespace S2D { class Scene; } + + namespace S3D { + struct MLight; + struct MObject; + struct MTrigger; + struct IPhysicWorld; + class PhysicWorld; + + using Render::Renderer; + using Render::RasterFont; + +/*! + @short Scene object. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Scene : public SharedObject +{ + uint current_item_uid; + +struct RenderData +{ + Render::sShader skybox_shader; + Render::sTexture skybox_layer[2]; + Render::sTexture irradiance_probe, radiance_probe; +}; + +public: + + /// Scene-wide flag. +enum SceneFlag +{ + FlagNone = 0, + FlagEnd = (1 << 0), + FlagRenderless = (1 << 1), + FlagDebugPhysics = (1 << 2) +}; + +protected: + + Core::sClock clock; + + SharedList activation_queue, deactivation_queue; + SharedList item_list, removal_queue; + + SharedArrayList active_list; // faster traversal than a shared list + + SharedList group_list; + + List light_list; + List trigger_list; + + /// Evaluate item. + void UpdateItem(float dt, MItem *, Core::Item *, uint eval_flag = SceneUpdateAll); + +public: + + String name; + + BitField flags; ///< Scene flags. + + AutoPtr ui; + void Render(Renderer &); + void RenderUI(Renderer &, GPU::TriangleBatch * = 0); + + Core::Clock *GetClock() const { return clock; } + void SetClock(Core::Clock * = 0, bool set_ui = true); + + /// Dump scene content to log. + void DumpContentToLog() const; + + Core::Camera *current_camera; + +/*! + @name Core::Item management. + @{ +*/ + void SetupItemComponents(MItem *); + void AddItem(MItem *, bool setup_components); + bool RemoveItem(MItem *); + + void QueueItemRemoval(MItem *); + void ProcessItemRemovalQueue(); + + bool ActivateItem(MItem *, bool activate); + void SetItemStatic(MItem *, bool is_static = true); + + void QueueItemActivation(MItem *, bool activate = true, bool propagate = false); + void ProcessItemActivationQueue(); + + MItem *DuplicateItem(MItem *); + + MItemType LocateItem(const Core::Item *, MItem **entity = 0) const; +static MItem *LocateManagedItem(Core::Item *); + + MItem *Item(const char *name, MItem * = 0) const; + MItem *ItemFromUid(uint uid) const; + + const List &GetLightList() const { return light_list; } + + const SharedList &GetItemList() const { return item_list; } + const SharedArrayList &GetActiveList() const { return active_list; } + + uint GetItemCountByType(MItemType type) const; + + // Filter item list and extract items of a give type. + template uint GetItemListByType(SharedList &out) const + { + out.Clear(); + ListForeachPtr(MItem *, i, item_list) + if (i->GetItemType() == C::GetMItemClassType()) + out.Add((C *)i); + return out.GetCount(); + } + // Find item by type. + template C *FindItemByType(const char *name) const + { + ListForeachPtr(MItem *, i, item_list) + if (i->GetItemType() == C::GetMItemClassType()) + if (i->name == name) + return (C *)i; + return 0; + } +/*! + @} + @name Group management. + @{ +*/ + Group *AddGroup(Group *); + bool RemoveGroup(Group *); + + Group *FindGroup(const char *name) const; + + uint GetItemGroupList(const MItem *, SharedList &) const; + void UnregisterItemFromGroups(MItem *) const; + + const SharedList &GetGroupList() const { return group_list; } + + void GroupMembersSetActive(Group *, bool = true); + void DeleteGroupAndMembers(Group *); +/*! + @} + @name Profiling. + @{ +*/ + SceneProfiler profiler; + + /// Display the profiler to screen using the renderer writer. + void DrawProfilerText(Renderer &, RasterFont *font[2], float &x, float &y); +/*! + @} + @name Culling system. + @{ +*/ +protected: + + Core::SimpleCullingSystem simple_culling_system; + Core::OctreeCullingSystem octree_culling_system; + +public: + + void AddRenderable(Core::Renderable *, bool is_static = false); + void RemoveRenderable(Core::Renderable *); + + /// Push this scene renderable onto the renderer display queue. + void PushRenderable(Renderer &); +/*! + @} + @name Environment. + @{ +*/ + Color background_color, ambient_color; + float ambient_intensity, target_exposure; + + float time_of_day; + String skybox_shader; + String skybox_layer[2]; + + String irradiance_probe, radiance_probe; + + float fog_near, fog_far; + Color fog_color; + + AutoPtr irenderer_environment; +/*! + @} + @name Script system. + @{ +*/ +protected: + + Script::sVM vm; + +public: + + Script::IVM *GetVM() const { return vm; } + + AutoPtr scene_event; + AutoPtr scripted_object; + + /// Set as the script master global scene. + void SetAsScriptGlobalScene(Script::IVM * = 0); +/// @} + +/*! + @name Motion system. + @{ +*/ + Core::SceneMotionContainer motion; + + /*! + @short Start a motion on the scene items. + @note Request an animation source group if you need control on the + started animation sources. + */ + void SetMotion(const char *name, Automation::SourceGroup ** = 0, float blend = Units::Sec(0.1), Automation::Player::AddSourceMode = Automation::Player::SourceSet, float weight = 1); +/*! + @} + @name Physic system. + @{ +*/ + void SynchronizePhysics(); + + AutoPtr physic_world; + AutoPtr iphysic_world; + + MTrigger *RaytraceTriggerList(Vector4 &s, Vector4 &d, float l = -1.f, Vector4 *i = 0); +/* + @} + @name Scene Management. + @{ +*/ + bool Create(PhysicWorld *); + void Reset(); + void Clear(bool keep_script = false); + + void InstanceSetup(); + void RenderSetup(Core::ResourceFactories *, bool setup_items = true); + void Setup(ToolMode); + + void RecordAllItemLocation(); +/// @} + + void GetMinMax(MinMax &) const; + +protected: + + void TestOptimizeGeometry(Render::Geometry *, uint octree_node_size); + void UpdateItemTransformation(MItem *, const Time &dt); + +public: + + void OptimizeForRealtime(uint octree_node_size = 1024); + + void UpdateTriggers(); + void Update(uint = SceneUpdateAll); + +/*! + @name Scene serialization + @{ +*/ +protected: + + bool IsItemToBeSaved(MItem *, const Group *, uint flag) const; + NML::Tag *LinkInfoAsMetaTag(MItem *, const Group * = 0, uint = SceneIOAll) const; + NML::Tag *SkinInfoAsMetaTag(MObject *o, const Group * = 0, uint = SceneIOAll) const; + +public: + + /// Load all scene resources in render cache. +static bool PreloadResources(Render::ResourceFactory &, const char *uri); + + /// Load scene from meta file, store content to group. + bool FromMetaTagStoreGroup(const NML::Tag &, Group ** = 0, uint = SceneIOAll, ToolMode = NoTool, int load_level = 0); + bool FromMetaFileStoreGroup(const char *, Group ** = 0, uint = SceneIOAll, ToolMode = NoTool, int load_level = 0); + bool FromMetaTag(const NML::Tag &tag, ToolMode tool = NoTool) { return FromMetaTagStoreGroup(tag, 0, SceneIOAll, tool); } + + NML::Tag *AsMetaTag(const Group *, uint = SceneIOAll, ToolMode = NoTool) const; + NML::Tag *AsMetaTag() const { return AsMetaTag(0); } +/// @} + + AutoPtr render_data; + + Scene(Script::IVM *vm = 0); +virtual ~Scene(); +}; + + } // S3D +} // GS + + +#endif // __NSCENE__ diff --git a/include/engine/scene3d/scene_ace_manager.h b/include/engine/scene3d/scene_ace_manager.h new file mode 100644 index 0000000..026e83e --- /dev/null +++ b/include/engine/scene3d/scene_ace_manager.h @@ -0,0 +1,34 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCENEACEMANAGER__ +#define __SCENEACEMANAGER__ + + +namespace GS { + namespace ACE { class Manager; } + namespace S3D { + +enum +{ + ACESN_toposition = 0, + ACESN_offsetposition, + ACESN_tooffset, + ACESN_toscale, + ACESN_torotation, + ACESN_toalpha +}; + +struct ACEManager +{ +static ACE::Manager *Get(); +}; + + } // S3D +} // GS + + +#endif // __SCENEACEMANAGER__ diff --git a/include/engine/scene3d/scene_debug.h b/include/engine/scene3d/scene_debug.h new file mode 100644 index 0000000..4ffca3d --- /dev/null +++ b/include/engine/scene3d/scene_debug.h @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCENE_DEBUG__ +#define __SCENE_DEBUG__ + + + #include "memory/nshared_ptr.h" + #include "core/geometry.h" + + +namespace GS { + namespace Render { class Renderer; } + namespace S3D { + class MItem; + class Scene; + + using Render::Renderer; + +/*! + @short Scene debugger interface. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class SceneDebugger +{ +protected: + + Scene *scene; + Core::sGeometry pointlight, spotlight, linearlight, camera, object, trigger; + + /// Draw item bounding volume. + void DrawItemBoundingVolume(Renderer &, MItem *, uint display_flags = ~0); + /// Draw figure. + void DrawFigure(Renderer &, Core::Geometry *, const Matrix4 &, Color &); + /// Display managed item informations. + void DrawItem(Renderer &, MItem *, uint display_flags = ~0, Color * = 0); + /// Display item identifier. + void DrawItemName(Renderer &, MItem *); + +public: + + float scale; + + /// Display scene items schematics. + void DrawScene(Renderer &, const List * = 0, const List *blacklist = 0, uint display_flags = ~0); + + /// Load schematic figures. + bool LoadSchematicFigures(const char *pointlight, const char *spotlight, const char *linearlight, const char *camera, const char *object, const char *trigger); + /// Set scene. + void SetScene(Scene *); + + SceneDebugger(); +}; + + } // S3D +} // GS + + +#endif // __SCENE_DEBUG__ diff --git a/include/engine/scene3d/scene_event_interface.h b/include/engine/scene3d/scene_event_interface.h new file mode 100644 index 0000000..80b2614 --- /dev/null +++ b/include/engine/scene3d/scene_event_interface.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NISCENEEVENT__ +#define __NISCENEEVENT__ + + +namespace GS { + namespace S3D { + class Scene; + +/*! + @short Scene event handler. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ISceneEvent +{ +virtual void OnSetup(Scene *) {} +virtual void OnSetupDone(Scene *) {} +virtual void OnDelete(Scene *) {} + +virtual void OnRender(Scene *) {} +virtual void OnRenderDone(Scene *) {} +virtual void OnRenderUser(Scene *) {} +virtual void OnRenderUIDone(Scene *) {} + +virtual void OnReset(Scene *) {} +virtual void OnUpdate(Scene *) {} +virtual void OnPhysicStep(Scene *, bool /*step_taken*/) {} + +virtual ~ISceneEvent() {} +}; + + } // S3D +} // GS + + +#endif // __NISCENEEVENT__ diff --git a/include/engine/scene3d/scene_event_script_interface.h b/include/engine/scene3d/scene_event_script_interface.h new file mode 100644 index 0000000..a42d011 --- /dev/null +++ b/include/engine/scene3d/scene_event_script_interface.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCENESCRIPTEVENT__ +#define __NSCENESCRIPTEVENT__ + + + #include "scene3d/scene_event_interface.h" + + +namespace GS { + namespace S3D { + +/*! + @short Scene script event. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct SceneScriptEvent : public ISceneEvent +{ +virtual void OnSetup(Scene *); +virtual void OnSetupDone(Scene *); +virtual void OnDelete(Scene *); + +virtual void OnRender(Scene *); +virtual void OnRenderDone(Scene *); +virtual void OnRenderUser(Scene *); +virtual void OnRenderUIDone(Scene *); + +virtual void OnReset(Scene *); +virtual void OnUpdate(Scene *); +virtual void OnPhysicStep(Scene *, bool step_taken); +}; + + } // S3D +} // GS + + +#endif // __NSCENESCRIPTEVENT__ diff --git a/include/engine/scene3d/scene_info.h b/include/engine/scene3d/scene_info.h new file mode 100644 index 0000000..9b611e0 --- /dev/null +++ b/include/engine/scene3d/scene_info.h @@ -0,0 +1,20 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCENEINFO__ +#define __NSCENEINFO__ + + +namespace GS { + namespace S3D { + +void DumpMemoryLayout(); + + } // S3D +} // GS + + +#endif // __NSCENEINFO__ diff --git a/include/engine/scene3d/scene_io_flag.h b/include/engine/scene3d/scene_io_flag.h new file mode 100644 index 0000000..8c318dd --- /dev/null +++ b/include/engine/scene3d/scene_io_flag.h @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCENEIOFLAG__ +#define __NSCENEIOFLAG__ + + +#define SceneIONone uint(0) +#define SceneIOCamera uint(1 << 0) +#define SceneIOLight uint(1 << 1) +#define SceneIOObject uint(1 << 2) +#define SceneIOTrigger uint(1 << 3) +#define SceneIOInstance uint(1 << 4) +#define SceneIOGroup uint(1 << 5) +#define SceneIOMotion uint(1 << 6) +#define SceneIOSettings uint(1 << 7) +#define SceneIOGlobals uint(1 << 8) +#define SceneIOCollision uint(1 << 9) +#define SceneIOPhysic uint(1 << 10) +#define SceneIOPath uint(1 << 11) +#define SceneIOHelper uint(1 << 12) +#define SceneIOScript uint(1 << 13) +#define SceneIOEmitter uint(1 << 14) +#define SceneIOTerrain uint(1 << 15) +#define SceneIOConstraint uint(1 << 16) +#define SceneIOSprite uint(1 << 17) +#define SceneIOWindow uint(1 << 18) + +#define SceneIOAll uint(~0) + + +#endif // __NSCENEIOFLAG__ diff --git a/include/engine/scene3d/scene_message.h b/include/engine/scene3d/scene_message.h new file mode 100644 index 0000000..c79d811 --- /dev/null +++ b/include/engine/scene3d/scene_message.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCENE_MESSAGE__ +#define __NSCENE_MESSAGE__ + + + #include "messaging/messaging.h" + + +namespace GS { + namespace S3D { + class Scene; + +/* + @short Scene message enum. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +enum SceneMessage +{ + SceneMsg_None = 0, ///< No message. + + SceneMsg_AddingItem, + SceneMsg_ItemAdded, + SceneMsg_DeletingItem, + SceneMsg_ItemDeleted, + + SceneMsg_AddingGroup, + SceneMsg_GroupAdded, + SceneMsg_DeletingGroup, + SceneMsg_GroupDeleted, + + SceneMsg_Clearing, + SceneMsg_Cleared, + SceneMsg_Loading, + SceneMsg_Loaded, + + SceneMsg_LastMessage +}; + +/* + @short Scene message return value. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +enum SceneReturnValue +{ + SceneReturn_Ok = 0 +}; + +/// Scene listener. +struct SceneListener +{ +virtual SceneReturnValue ProcessMessage(SceneMessage, const Scene *, const void *) = 0; +}; + +extern Messaging::Broadcaster g_scene_messenger; + + } // S3D +} // GS + + +#endif // __NSCENE_MESSAGE__ diff --git a/include/engine/scene3d/scene_physic_world_interface.h b/include/engine/scene3d/scene_physic_world_interface.h new file mode 100644 index 0000000..83d3bc4 --- /dev/null +++ b/include/engine/scene3d/scene_physic_world_interface.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCENEPHYSICWORLDINTERFACE__ +#define __SCENEPHYSICWORLDINTERFACE__ + + + #include "physic/physic_world_interface.h" + + +namespace GS { + namespace S3D { + class Scene; + +/*! + @short The scene physic world interface. +*/ +class IScenePhysicWorld : public IPhysicWorld +{ + Scene *scene; + +public: + + void PhysicStep(float, bool = true); + + IScenePhysicWorld(Scene *s) : scene(s) {} +}; + + } // S3D +} // GS + + +#endif // __SCENEPHYSICWORLDINTERFACE__ diff --git a/include/engine/scene3d/scene_profiler.h b/include/engine/scene3d/scene_profiler.h new file mode 100644 index 0000000..84f11ec --- /dev/null +++ b/include/engine/scene3d/scene_profiler.h @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCENEPROFILER__ +#define __NSCENEPROFILER__ + + + #include "timing/profiler.h" + + +namespace GS { + namespace S3D { class Scene; } + +/*! + @short Scene profiler. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct SceneProfiler : public Profiler +{ + S3D::Scene &scene; + +public: + + System *update, *process_queues, *update_triggers, *update_item_transformation, *update_skin, *scene_on_update, *items_on_update, *physic_step, *synchronize_physics, *ui_update; + System *push_to_render, *push_active_list, *push_simple_culling, *push_octree_culling; + +virtual void ResetProfiles(); + + SceneProfiler(S3D::Scene &s) : scene(s) + { + // Update + update = DeclareSystem("Update"); + + process_queues = DeclareSystem("Process queues", update); + update_triggers = DeclareSystem("Update triggers", update); + update_item_transformation = DeclareSystem("Update item transformation", update); + update_skin = DeclareSystem("Update item skin", update); + + scene_on_update = DeclareSystem("Script scene OnUpdate()", update); + items_on_update = DeclareSystem("Script items OnUpdate()", update); + + physic_step = DeclareSystem("Physic step", update); + synchronize_physics = DeclareSystem("Physics synchronization", update); + + ui_update = DeclareSystem("Update UI", update); + + // Push to render + push_to_render = DeclareSystem("Push to render"); + + push_active_list = DeclareSystem("Push active list", push_to_render); + push_simple_culling = DeclareSystem("Push simple renderable", push_to_render); + push_octree_culling = DeclareSystem("Push octree renderable", push_to_render); + } +}; + +} // GS + + +#endif // __NSCENEPROFILER__ diff --git a/include/engine/scene3d/scene_renderer_environment_interface.h b/include/engine/scene3d/scene_renderer_environment_interface.h new file mode 100644 index 0000000..0dd54f3 --- /dev/null +++ b/include/engine/scene3d/scene_renderer_environment_interface.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCENERENDERERENVINTERFACE__ +#define __NSCENERENDERERENVINTERFACE__ + + + #include "core/renderer_environment_interface.h" + + +namespace GS { + namespace S3D { + class Scene; + +/* + @short Scene renderer environment. + Used to query environment informations. +*/ +struct IEnvironment : public Render::IEnvironment +{ + Scene *scene; + +virtual float GetClock() const; + +virtual float GetTimeOfDay() const; +virtual Render::Shader *GetSkyboxShader() const; +virtual bool GetSkyboxLayers(Render::sTexture [2]) const; + +virtual Color GetClearColor() const; +virtual Color GetAmbientColor() const; +virtual void GetEnvironmentProbe(Render::sTexture &/*radiance*/, Render::sTexture &/*irradiance*/) const; + +virtual Core::Camera *GetCurrentCamera() const; + +virtual void GetLightsInFrustum(const Vector4 &/*world_pos*/, const Frustum &/*frustum*/, List &/*list*/, uint /*limit*/ = 0) const; +virtual void GetClosestLights(const Vector4 &/*world_pos*/, List &/*list*/, uint /*limit*/ = 0) const; + +virtual bool IsFogEnabled() const; +virtual bool GetFogConfiguration(Color &color, float &fog_near, float &fog_far) const; + +virtual void OnRenderUser(Render::Renderer *) const; + + IEnvironment(Scene *s) : scene(s) {} +}; + + } // S3D +} // GS + + +#endif // __NSCENERENDERERENVINTERFACE__ diff --git a/include/engine/scene3d/scene_script_unit.h b/include/engine/scene3d/scene_script_unit.h new file mode 100644 index 0000000..e868291 --- /dev/null +++ b/include/engine/scene3d/scene_script_unit.h @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCENESCRIPTUNIT__ +#define __SCENESCRIPTUNIT__ + + + #include "script/script_unit.h" + #include "script/script_object.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace S3D { + +/*! + @short Scene script unit. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class SceneScriptUnit : public Script::Unit +{ + int suspend_update; + +public: + + AutoPtr + render_callback, + render_done_callback, + render_user_callback, + render_ui_done_callback, + physic_step_callback, + update_callback; + + /// Update and return the state of the suspend flag. + bool IsSuspended(int dt); + /*! + @short Suspend update calls for a given duration. + Resume updates by passing a zero delay. + */ + void SuspendUpdate(int ms = 0); + + bool Open(); + void Close(); + + SceneScriptUnit(Script::IVM *); + ~SceneScriptUnit(); +}; + + } // S3D +} //GS + + +#endif // __SCENESCRIPTUNIT__ diff --git a/include/engine/scene3d/scene_scripted_object.h b/include/engine/scene3d/scene_scripted_object.h new file mode 100644 index 0000000..967dc36 --- /dev/null +++ b/include/engine/scene3d/scene_scripted_object.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCENESCRIPTEDOBJECT__ +#define __NSCENESCRIPTEDOBJECT__ + + + #include "script/scripted_object.h" + + +namespace GS { + namespace S3D { + class Scene; + +/*! + @short Scene scripted object. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class SceneScriptedObject : public Script::ScriptedObject +{ + Scene *scene; + +public: + +virtual Script::Unit *NewUnit() const; + + SceneScriptedObject(Script::IVM *vm, Scene *s) : Script::ScriptedObject(vm), scene(s) {} +}; + + } // S3D +} // GS + + +#endif // __NSCENESCRIPTEDOBJECT__ diff --git a/include/engine/script/script_binding_interface.h b/include/engine/script/script_binding_interface.h new file mode 100644 index 0000000..0e8e9dd --- /dev/null +++ b/include/engine/script/script_binding_interface.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCRIPTBINDINGINTERFACE__ +#define __SCRIPTBINDINGINTERFACE__ + + + #include "plugin/plugin_manager.h" + + +namespace GS { + namespace Script { + class IVM; + +/// Interface to provide additional script binding to a VM. +struct IScriptBinding +{ + /// Return the plugin class. +static const char *GetPluginClass() { return "ScriptBinding"; } + /*! + @short Return the plugin version. + + @note This version number must be increased whenever a modification + is made to the base interface in order to prevent an incompatible + plugin from being loaded. + */ +static uint GetPluginVersion() { return 1; } + + /// Register the new script binding code into the VM. +virtual void RegisterBinding(IVM &) = 0; +}; + +typedef PluginManager BindingPluginManager; + + } // Script +} // GS + + +#endif // __SCRIPTBINDINGINTERFACE__ diff --git a/include/engine/script/script_debugger.h b/include/engine/script/script_debugger.h new file mode 100644 index 0000000..7089114 --- /dev/null +++ b/include/engine/script/script_debugger.h @@ -0,0 +1,169 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCRIPT_DEBUGGER__ +#define __SCRIPT_DEBUGGER__ + + + #include "script/script_vm.h" + #include "script/script_engine_types.h" + + +namespace GS { + namespace NML { class Tag; } + namespace Script { + +/// Debugger variable. +struct DebuggerVariable +{ + String id; + uint type; + String type_string; + + bool referenced; + bool modified; + + AutoList member_list; + + union + { + bool v_bool; + int v_int; + float v_float; + }; + + String v_string; + String value; + + DebuggerVariable() + { + type = 0; + referenced = false; + } +}; + +/// Source breakpoint. +struct SourceBreakpoint +{ + String source; + int line; + + SourceBreakpoint(const char *s, int l) + { source = s; line = l; } +}; + +/* + @short Script debugger interface. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class IDebugger +{ +protected: + + bool is_suspended, + is_stepping; + + int debug_stack_frame, + step_to_callstack_depth; + + DebuggerVariable *locals_root; + + AutoList local_var_tree; + AutoList source_breakpoint_list; + + /// Mark all variables in tree as non-referenced. + void DereferenceVarTree(const List &tree); + +public: + +/*! + @name Interface + @{ +*/ + /// Format variable parameter. +virtual String FormatParameter(DebuggerVariable *variable) = 0; + /// Format safe ptr parameter. +virtual String FormatUserObjectParameter(CObjectType type) = 0; + /// Convert a debugger variable to a meta string. +virtual void VariableToMetatagString(DebuggerVariable *, String &) = 0; + + /// Get call stack depth. +virtual int GetCallstackDepth() = 0; + /// Get current script execution call frame index. +virtual int GetStackFrameIndex() = 0; + + /// Refresh stack locals list. +virtual void RefreshStackFrameLocalsCache() = 0; + /// Get source/line info for the current debug stack frame. +virtual void GetStackFrameSource(const char *&, int &) = 0; +/// @} + +/*! + @name Breakpoint. + @{ +*/ + /// Check for suspend on breakpoint. + void CheckSuspendOnBreakpoint(const char *source, int line); + /// Check for suspend on step. + void CheckSuspendOnStep(); + + /// Find a source breakpoint. + SourceBreakpoint *FindSourceBreakpoint(const char *source, int line); + /// Add a new source breakpoint. + SourceBreakpoint *AddSourceBreakpoint(const char *source, int line); + /// Remove a source breakpoint. + bool RemoveSourceBreakpoint(SourceBreakpoint *breakpoint); + + /// Set breakpoints from a tag. + bool SetBreakpoints(const NML::Tag &tag); +/// @} + +/*! + @name Execution control. + @{ +*/ + /// Suspend execution. + void Suspend(); + /// Resume execution. + void Resume(); + + /// Step to the next instruction. + void Step(); + /// Step into the next call. + void StepInto(); + /// Step out of the current call. + void StepOut(); + + /// Return whether the current scene script execution is suspended or not. + bool IsSuspended() const { return is_suspended; } + /// Is the debugger stepping. + bool IsStepping() const { return is_stepping; } +/// @} + +/*! + @name Interface control. + @{ +*/ + /// Set the call stack debug depth. + void SetDebugStackFrame(int depth); + /// Get call stack debug depth. + int GetDebugStackFrame() const { return debug_stack_frame; } + + /// Get stack locals as a meta string. + String GetStackFrameLocals(); + + void Reset(); +/// @} + + IDebugger(); +virtual ~IDebugger(); +}; + + } // Script +} // GS + + +#endif // __SCRIPT_DEBUGGER__ diff --git a/include/engine/script/script_engine_types.h b/include/engine/script/script_engine_types.h new file mode 100644 index 0000000..81bfc39 --- /dev/null +++ b/include/engine/script/script_engine_types.h @@ -0,0 +1,99 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCRIPTENGINETYPES__ +#define __SCRIPTENGINETYPES__ + + +namespace GS { + namespace Script { + +/// Native C object types that the VM can interact with. +enum CObjectType +{ + typetag_Undefined = 0, + typetag_Deleted, // The native object was deleted. + + typetag_Engine, + typetag_ScriptVM, + typetag_ResourceSet, + typetag_Project, + typetag_Renderer, + typetag_Raytracer, + typetag_Mixer, + typetag_Scene3d, + typetag_Clock, + + typetag_Font, + typetag_RasterFont, + typetag_Scene2d, + typetag_UICursor, + typetag_UIItem, + typetag_UISprite, + typetag_Window, + typetag_Widget, + typetag_SizerWidget, + typetag_ContainerWidget, + typetag_SpacerWidget, + typetag_CanvasWidget, + typetag_TextWidget, + typetag_BitmapWidget, + typetag_CheckWidget, + typetag_Picture, + + typetag_Group, + typetag_Item, + typetag_Camera, + typetag_Object, + typetag_Light, + typetag_Instance, + typetag_Emitter, + typetag_ParticleModel, + typetag_Motion, + typetag_Trigger, + typetag_Path, + + typetag_Sound, + typetag_Shader, + typetag_Texture, + typetag_Geometry, + typetag_GeometryTemplate, + typetag_Material, + typetag_MaterialShader, + typetag_ColShape, + typetag_Constraint, + + typetag_Metafile, + typetag_Metatag, + typetag_FileHandle, + + typetag_InputDevice, + + typetag_EditorPlugin, + + typetag_ProjectScene, + typetag_ProjectLayer, + + typetag_AutomationSource, + typetag_AutomationSourceGroup, + + typetag_ResourceFactories, + + typetag_PeerController, + typetag_Peer, + + typetag_WebSocketManager, + + typetag_End +}; + +const char *CObjectTypeToString(CObjectType type); + + } // Script +} // GS + + +#endif // __SCRIPTENGINETYPES__ diff --git a/include/engine/script/script_object.h b/include/engine/script/script_object.h new file mode 100644 index 0000000..88ce4d9 --- /dev/null +++ b/include/engine/script/script_object.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCRIPTOBJECT__ +#define __NSCRIPTOBJECT__ + + + #include "script/script_vm.h" + + +namespace GS { + namespace Script { + +/* + @short Abstract script object. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Object +{ +protected: + + IVM &vm; + +public: + + IVM &GetVM() const { return vm; } + + /// Perform a set operation on this object. + bool Set(const char *name, const Variant &p) { return vm.Set(name, p, this); } + /// Perform a get operation on this object. + bool Get(const char *name, Variant &p) { return vm.Get(name, p, this); } + /// Append a variant to this object. + bool Append(const Variant &p) { return vm.Append(p, this); } + + /// Setup a function call on this object. + bool SetupFunctionCall(const char *func, const Object *function_object = 0) + { return vm.SetupFunctionCall(func, function_object, this); } + /// Push null function call argument. + bool PushFunctionCallNullArgument() + { return vm.PushNullArgument(); } + /// Push function call argument. + bool PushFunctionCallArgument(const Variant &arg) + { return vm.PushArgument(arg); } + /// Execute a function call on this object, return value as a variant. + bool DoFunctionCall(Variant *return_value = 0) + { return vm.DoFunctionCall(return_value); } + + Object &operator= (const Object &b) + { + vm = b.GetVM(); + return *this; + } + + Object(IVM &v) : vm(v) {} +virtual ~Object() {} +}; + + } // Script +} // GS + + +#endif // __NSCRIPTOBJECT__ diff --git a/include/engine/script/script_profiler.h b/include/engine/script/script_profiler.h new file mode 100644 index 0000000..cc2c8a8 --- /dev/null +++ b/include/engine/script/script_profiler.h @@ -0,0 +1,100 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCRIPTPROFILER__ +#define __NSCRIPTPROFILER__ + + + #include "nstring/nstring.h" + #include "container/nlist.h" + + +namespace GS { + namespace Script { + +/* + @short Script VM profiler. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Profiler +{ +public: + +struct FunctionProfile +{ + String func, ///< The function name. + source; ///< The source name. + int line; ///< Function start line. + + int hit_count, ///< Number of total call to this function. + total_clock, ///< Total execution clock. + self_clock; + + List callee_function; + FunctionProfile *caller_function; + + /// Hit function profile. + void Hit() { hit_count++; } + /// Update function profile. + void Update(int dt_clock, int /*line*/) { self_clock += dt_clock; } + + FunctionProfile(const char *sourcename, const char *funcname, int _line) + { + source = sourcename; + func = funcname; + line = _line; + + caller_function = 0; + hit_count = 0; + total_clock = 0; + self_clock = 0; + } +}; + +protected: + + int profiler_clock, + total_clock; + bool profiling; + + FunctionProfile *current_function_profile; + +public: + + String id; ///< Profiler session id. + + /// Profiled function stack. + List function_map; ///< The profiled function map (all profiles from the call graph). + List function_list; ///< The profiled function list (each function figures only once in this list). + + /// Get child total clock. + int GetChildTotalClock(FunctionProfile *profile); + /// Get the last profile session total running clock. + int GetTotalClock() const { return total_clock; } + + /// Is a profiler session opened. + bool IsProfiling() const { return profiling; } + + /// Request a function profile. + FunctionProfile *GetFunctionProfile(const char *source, const char *func, int line, FunctionProfile *caller); + /// Invalidate the current function profile. + void InvalidateCurrentFunctionProfile() { current_function_profile = 0; } + + /// Start a profiler session. + void Start(const char *session_id); + /// Update profiler. + void Update(int type, FunctionProfile *profile); + /// End a profiler session. + void End(); + + Profiler(); +}; + + } // Script +} // GS + + +#endif // __NSCRIPTPROFILER__ diff --git a/include/engine/script/script_unit.h b/include/engine/script/script_unit.h new file mode 100644 index 0000000..94a221d --- /dev/null +++ b/include/engine/script/script_unit.h @@ -0,0 +1,88 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCRIPTUNIT__ +#define __NSCRIPTUNIT__ + + + #include "script/script_vm.h" + #include "data/nvariant.h" + + +namespace GS { + namespace NML { class Tag; } + namespace Script { + +/*! + @short Script unit. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Unit +{ +protected: + + Object *self; + + uint iface_type; ///< Interface object type. + void *iface_object; ///< Interface object. + +public: + + sVM vm; + + const Object *Self() const { return self; } + + List parm_list; + + String script_file, ///< Script file to process. + script_class; ///< Class to instantiate upon setup. + + /// Set unit interface object. + void SetInterfaceObject(void *p, uint type) + { + iface_object = p; + iface_type = type; + } + /// Get unit interface object. + void GetInterfaceObject(void *&p, uint &type) + { + p = iface_object; + type = iface_type; + } + +/*! + @name Runtime. + @{ +*/ + /// Open component. +virtual bool Open(); + /// Close component. +virtual void Close(); + /// Is unit open. + bool IsOpen() const { return asbool(self); } + + /// Setup a function call in the VM. +virtual bool SetupFunctionCall(const char *func, const Object *func_object = 0); + /// Push user object function call argument. +virtual bool PushUserObjectFunctionCallArgument(void *, uint, bool managed = false); + /// Push function call argument. +virtual bool PushFunctionCallArgument(const Variant &); + /// Execute a function call in the VM, return value as a variant. +virtual bool DoFunctionCall(Variant *return_value = 0); +/// @} + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + + Unit(IVM *); +virtual ~Unit(); +}; + + } // Script +} // GS + + +#endif // __NSCRIPTUNIT__ diff --git a/include/engine/script/script_variant.h b/include/engine/script/script_variant.h new file mode 100644 index 0000000..0abcca2 --- /dev/null +++ b/include/engine/script/script_variant.h @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCRIPTVARIANT__ +#define __NSCRIPTVARIANT__ + + #include "data/nvariant.h" + #include "script/script_vm.h" + +namespace GS { + namespace Script { + class Object; + +/// Script variant. +struct Variant +{ +enum Type +{ + Type_None = 0, + Type_Variant, + Type_ScriptObject, + Type_UserObject +}; + + Type type; + + GS::Variant variant; + + bool object_owner; + Object *object; + void *ptr; + uint typetag; + + bool operator == (const Variant &) const; + bool operator != (const Variant &) const; + + void Set(); + void Set(bool v); + void Set(int v); + void Set(uint v); + void Set(float v); + void Set(const char *v); + void Set(const GS::Variant &v); + void Set(Object *object, bool object_owner = false); + void Set(const void *p, size_t size); + void Set(void *ptr, uint typetag); + + Variant(); + Variant(bool v); + Variant(int v); + Variant(uint v); + Variant(float v); + Variant(const char *v); + Variant(const GS::Variant &v); + Variant(Object *object, bool object_owner = false); + Variant(const void *p, size_t size); + Variant(void *ptr, uint typetag); + + ~Variant(); +}; + + } // Script +} // GS + + +#endif // __NSCRIPTVARIANT__ diff --git a/include/engine/script/script_vm.h b/include/engine/script/script_vm.h new file mode 100644 index 0000000..dc2dc9c --- /dev/null +++ b/include/engine/script/script_vm.h @@ -0,0 +1,145 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCRIPTVMINTERFACE__ +#define __SCRIPTVMINTERFACE__ + + + #include "script/script_binding_interface.h" + #include "http/http_interface.h" + #include "network/network_interface.h" + #include "memory/nshared_ptr.h" + + +namespace GS { + namespace Script { + struct Variant; + class Object; + +/* + @short Script virtual machine abstract interface. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class IVM : public SharedObject +{ +public: + +enum State +{ + StateOk = 0, + StateExceptionThrown, ///< Crashed and open for inspection. + StateDead ///< Crashed with no hope for inspection. +}; + +struct IDebug +{ + /// Handle a runtime debug step. +virtual void OnStep(char type, const char *source, int line, const char *funcname) = 0; + /// Handle a VM kill event. +virtual void OnFatalError(const char *reason) = 0; + /// Handle a compiler error. +virtual void OnCompilerError(const char *error, const char *source, int line) = 0; + /// Handle a runtime error. +virtual void OnRuntimeException(const char *error) = 0; + +virtual ~IDebug() {} +}; + +protected: + + State state; + AutoPtr debug_interface; + +public: + + BindingPluginManager binding_plugins; + + AutoPtr peer_net; + AutoPtr http; + +/*! + @name Debugging interface. + @{ +*/ +struct CallStackEntry +{ + String source, function; + int line; + + CallStackEntry(const char *s, const char *f, int l) : source(s), function(f), line(l) {} +}; + + /// Get VM call stack. +virtual void GetCallStack(AutoList &callstack) { callstack.Clear(); } +/// @} + + /// Set VM state. + void SetState(State s) { state = s; } + /// Get VM state. + State GetState() const { return state; } + + /// Get virtual machine name. +virtual const char *GetName() const = 0; + + /// Set VM event hook table. +virtual void SetDebugInterface(IDebug *, bool enable_debugging = false); + /// Get the VM event hook table. + IDebug *GetEventHandler() const { return debug_interface; } + + /// Get a VM object. +virtual Object *GetObjectFromName(const char *name, const Object *context = 0) = 0; + + /// Compile a script. +virtual bool Compile(const char *source, uint size, const Object *context = 0, const char *sourcename = 0) = 0; + /// Compile a script from file. +virtual bool CompileFile(const char *uri, const Object *context = 0); + + /// Create a script table. +virtual Object *CreateTable() = 0; + /// Set a VM variable. +virtual bool Set(const char *name, const Variant &prop, const Object *context = 0) = 0; + /// Get a VM variable. +virtual bool Get(const char *name, Variant &prop, const Object *context = 0) = 0; + + /// Create a script array. +virtual Object *CreateArray() = 0; + /// Append a value to an array. +virtual bool Append(const Variant &, const Object *context = 0) = 0; + + /// Setup a function call in the VM. +virtual bool SetupFunctionCall(const char *func, const Object *function_object = 0, const Object *search_context = 0) = 0; + /// Set function call context. +virtual bool SetFunctionCallContext(const Variant &) = 0; + /// Push function call null argument. +virtual bool PushNullArgument() = 0; + /// Push function call argument. +virtual bool PushArgument(const Variant &) = 0; + /// Execute a function call in the VM, return value as a variant. +virtual bool DoFunctionCall(Variant *return_value = 0) = 0; + + /// Invalidate all references to a user object. +virtual int InvalidateNativeReference(void *) = 0; + + /// Is the VM open. +virtual bool IsOpen() const = 0; + /// Open the script VM. +virtual bool Open() = 0; + /// Crash the VM. +virtual void Kill(const char *reason); + /// Close the script VM. +virtual void Close() = 0; + + IVM(); +virtual ~IVM(); +}; + +typedef SharedPtr sVM; + + } // Script +} // GS + + +#endif // __SCRIPTVMINTERFACE__ diff --git a/include/engine/script/script_vm_debug_profile_base.h b/include/engine/script/script_vm_debug_profile_base.h new file mode 100644 index 0000000..0f9242a --- /dev/null +++ b/include/engine/script/script_vm_debug_profile_base.h @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCRIPT_VM_DEBUG_PROFILE_EVENT_HANDLER__ +#define __SCRIPT_VM_DEBUG_PROFILE_EVENT_HANDLER__ + + + #include "script/script_vm.h" + #include "script/script_debugger.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace Script { + +/*! + @short Debugger/profiling VM event handler. + + This handler provides basic functionality such as VM stepping and profiling. + This class should be further derived to implement complete control over the VM. + + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class IDebuggerProfiler : public IVM::IDebug +{ +static String ConvertCallStackToMetaString(const AutoList &, int stack_frame_index); + +protected: + + sVM vm; + +public: + + AutoPtr debugger; + + String GetCallstack(); + String GetDebugStackFrameLocals(); + + void Kill(); + + // Debugger interface. +virtual void OnSuspendExecution(const char *source, int line) = 0; +virtual bool OnUpdateSuspendedExecution() = 0; + + // VM interface implementation. + void OnStep(char type, const char *source, int line, const char *func); + + IDebuggerProfiler(IVM *vm, IDebugger *debugger); +}; + + } // Script +} // GS + + +#endif // __SCRIPT_VM_DEBUG_PROFILE_EVENT_HANDLER__ diff --git a/include/engine/script/scripted_object.h b/include/engine/script/scripted_object.h new file mode 100644 index 0000000..34bd984 --- /dev/null +++ b/include/engine/script/scripted_object.h @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSCRIPTEDOBJECT__ +#define __NSCRIPTEDOBJECT__ + + + #include "script/script_vm.h" + #include "container/nlist.h" + + +namespace GS { + namespace NML { class Tag; } + namespace Script { + class Unit; + +/* + @short Scripted object base class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class ScriptedObject +{ + List unit_list; + +protected: + + sVM vm; + +public: + + /// Unit factory. +virtual Unit *NewUnit() const = 0; + + IVM *GetVM() const { return vm; } + + Unit *AddUnit(Unit *); + bool RemoveUnit(Unit *); + void RemoveAllUnit(); + + Unit *GetUnit(const char *script_path, const char *script_class) const; + const List &GetUnitList() const { return unit_list; } + +/*! + @name Serialization. + @{ +*/ + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; +/// @} + + ScriptedObject(IVM *v) : vm(v) {} +virtual ~ScriptedObject(); +}; + + } // Script +} // GS + + +#endif // __NSCRIPTEDOBJECT__ diff --git a/include/engine/ui/ui.h b/include/engine/ui/ui.h new file mode 100644 index 0000000..8fffc24 --- /dev/null +++ b/include/engine/ui/ui.h @@ -0,0 +1,169 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUI_SCENE__ +#define __NUI_SCENE__ + + + #include "ui/ui_item.h" + #include "ui/ui_cursor.h" + #include "ui/ui_message.h" + #include "ui/ui_event_handler.h" + #include "ui/ui_window_skin.h" + #include "ui/ui_scene_event_interface.h" + #include "scene3d/scene_io_flag.h" + #include "motion/scene_motion_container.h" + #include "core/tool_mode.h" + #include "core/clock.h" + #include "core/ace.h" + #include "color/color.h" + + +namespace GS { + namespace GPU { class TriangleBatch; } + namespace Render { class RasterFont; } + namespace S2D { + struct Group; + struct Camera; + class Window; + class Widget; + +/*! + @short Scene 2D + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Scene : public SharedObject, public ACE::Unit +{ + uint current_item_uid; + +protected: + + SharedList item_list; + Item *lock; + + Matrix3 screen_to_ui, ui_to_screen; + + SharedPtr default_camera, current_camera; + + Widget *RecurseWidgetBelowCursor(Window *, Widget *, int x, int y); + void ProcessCursorEnterLeaveWidget(Cursor *, Window *, Widget *); + + /// Execute an ACE command. + bool ExecCommand(ACE::Command *, float dt); + + Core::sClock clock; + +public: + + String name; + + void SetClock(Core::Clock * = 0); + +/*! + @name Script system. + @{ +*/ + Script::sVM vm; + + AutoPtr scene_event; + AutoPtr scripted_object; + + void SetAsScriptGlobalScene(Script::IVM * = 0); +/*! + @} + @name Item list. + @{ +*/ + const SharedList &GetItemList() const { return item_list; } + + /// Get item 2d from name. + Item *ItemFromName(const char *name, Item *parent = 0) const; + /// Get item 2d from unique identifier. + Item *ItemFromUid(uint) const; + + void SetupItemComponents(Item *); + + void AddItem(Item *, bool setup_components); + bool RemoveItem(Item *); + + void DeleteAllItems(); +/*! + @} + @name Motion system. + @{ +*/ + Core::SceneMotionContainer motion; + + /*! + @short Start a motion on the scene items. + @note Request an animation source group if you need control on the + started animation sources. + */ + void SetMotion(const char *name, Automation::SourceGroup ** = 0, float blend = Units::Sec(0.1), Automation::Player::AddSourceMode = Automation::Player::SourceSet, float weight = 1); +/// @} + + Camera *GetDefaultCamera() const { return default_camera; } + + Camera *GetCurrentCamera() const { return current_camera; } + void SetCurrentCamera(Camera *camera = 0); + + /// Lock all UI events to a specific item. + void Lock(Item *i) { lock = i; } + void Unlock() { lock = 0; } + + void UpdateCursor(Cursor *); + + /// Call event handler. + bool CallEventHandler(Cursor *, EventCode, EventTable *); + void CallEventHandler(Cursor *, Widget *, EventCode, bool can_propagate = true); + + void DrawProfilerText(Renderer &, Render::RasterFont *font[2], float &x, float &y); + + sWindowSkin window_skin; + + Matrix3 offset_matrix; ///< Global post-projection offset matrix. + Color global_fade_color; + + /// Normalized screen coordinates to scene coordinates in pixels. + const Matrix3 &GetScreenToUIMatrix() const { return screen_to_ui; } + /// Scene coordinates in pixels to normalized screen coordinates. + const Matrix3 &GetUIToScreenMatrix() const { return ui_to_screen; } + + float GetGlobalFadeEffect() const; + void SetGlobalFadeEffect(float opacity = 1); + + /// Evaluate scene. + void Update(); + + void SetRenderMatrices(Renderer &); + + void Render(Renderer &, GPU::TriangleBatch * = 0); + void RenderGlobalFade(Renderer &); + void RenderSetup(Core::ResourceFactories *); + + void Setup(); + void Reset(); + void Clear(); + + bool IsItemToBeSaved(Item *, const Group *, uint save_flag) const; + NML::Tag *LinkInfoAsMetaTag(Item *, const Group *, uint flag) const; + + bool FromMetaFileStoreGroup(const char *, Group ** = 0, uint = SceneIOAll, ToolMode = NoTool, int load_level = 0); + bool FromMetaTagStoreGroup(const NML::Tag &, Group **group = 0, uint = SceneIOAll, ToolMode = NoTool, int load_level = 0); + bool FromMetaTag(const NML::Tag &tag, ToolMode tool = NoTool) { return FromMetaTagStoreGroup(tag, 0, SceneIOAll, tool); } + + NML::Tag *AsMetaTag(const Group *, uint = SceneIOAll, ToolMode = NoTool) const; + NML::Tag *AsMetaTag() const { return AsMetaTag(0); } + + Scene(Script::IVM * = 0); +virtual ~Scene(); +}; + + } // S2D +} // GS + + +#endif // __NUI_SCENE__ diff --git a/include/engine/ui/ui_ace_manager.h b/include/engine/ui/ui_ace_manager.h new file mode 100644 index 0000000..9fad7eb --- /dev/null +++ b/include/engine/ui/ui_ace_manager.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __UIACEMANAGER__ +#define __UIACEMANAGER__ + + +namespace GS { + namespace ACE { class Manager; } + namespace S2D { + +enum +{ + ACE_toalpha = 0, + ACE_toposition, + ACE_toscale, + ACE_toangle, + ACE_show, + ACE_hide, + + ACE_globalfade +}; + +struct ACEManager +{ +static ACE::Manager *Get(); +}; + + } // S2D +} // GS + + +#endif // __UIACEMANAGER__ diff --git a/include/engine/ui/ui_camera.h b/include/engine/ui/ui_camera.h new file mode 100644 index 0000000..1a34ebd --- /dev/null +++ b/include/engine/ui/ui_camera.h @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCAMERA2D__ +#define __NCAMERA2D__ + + + #include "ui/ui_item.h" + + +namespace GS { + namespace S2D { + +/*! + @short Scene 2d camera. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct Camera : public Item +{ + Vector2 resolution; ///< Camera virtual resolution. + +virtual void RenderSetup(Core::ResourceFactories *) {} +virtual void Render(Renderer &, GPU::TriangleBatch * = 0) {} +}; + + } // S2D +} // GS + + +#endif // __NCAMERA2D__ diff --git a/include/engine/ui/ui_cursor.h b/include/engine/ui/ui_cursor.h new file mode 100644 index 0000000..819380c --- /dev/null +++ b/include/engine/ui/ui_cursor.h @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUI_CURSOR__ +#define __NUI_CURSOR__ + + + #include "ui/ui_item.h" + #include "ui/widget.h" + + +namespace GS { + namespace S2D { + +// Scene 2D cursor. +struct Cursor +{ + int id; + +struct State +{ + float x, y; + bool down; + + SharedPtr item; + SharedPtr widget; + + void Reset() + { + x = y = 0; + down = false; + } + + State() { Reset(); } +}; + + State current_state, + previous_state, + down_state; +}; + + } +} + + +#endif // __NUI_CURSOR__ diff --git a/include/engine/ui/ui_event_handler.h b/include/engine/ui/ui_event_handler.h new file mode 100644 index 0000000..393025b --- /dev/null +++ b/include/engine/ui/ui_event_handler.h @@ -0,0 +1,84 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUIEVENTHANDLER__ +#define __NUIEVENTHANDLER__ + + + #include "script/script_vm.h" + #include "script/script_object.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace S2D { + +enum EventCode +{ + Event_None = 0, + + Event_CursorDown, + Event_CursorHit, + Event_CursorUp, + + Event_CursorEnter, + Event_CursorLeave, + Event_CursorMove, +}; + +/// 2D event handler. +class EventHandler +{ + friend class EventTable; + +protected: + + EventCode code; + AutoPtr handler, context; + +public: + + EventCode GetCode() const { return code; } + Script::Object *GetHandler() { return handler; } + Script::Object *GetContext() { return context; } + + EventHandler(EventCode c = Event_None) : code(c) {} +}; + +/*! + @short UI event table. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class EventTable +{ + bool enabled; + AutoList handler_list; + +public: + + void Reset() { handler_list.Clear(); } + + /// Returns true if the table has any handler set. + bool HasHandler() const { return handler_list.GetCount() > 0; } + + EventHandler *GetHandler(EventCode) const; + EventHandler *SetHandler(EventCode, Script::Object *handler, Script::Object *context = 0); + void DeleteHandler(EventCode); + + bool HasHandler(EventCode code) const { return asbool(GetHandler(code)); } + bool HasHandlerContext(EventCode) const; + + void Enable(bool v) { enabled = v; } + bool IsEnabled() const { return enabled; } + + EventTable() : enabled(true) {} +}; + + } // S2D +} // GS + + +#endif // __NUIEVENTHANDLER__ diff --git a/include/engine/ui/ui_group.h b/include/engine/ui/ui_group.h new file mode 100644 index 0000000..7a0f975 --- /dev/null +++ b/include/engine/ui/ui_group.h @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUI_GROUP__ +#define __NUI_GROUP__ + + + #include "container/nlist.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace S2D { + class Item; + +/*! + @short UI Group. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct Group +{ + String name; + List item_list; + + bool IsMember(const Item *) const; +}; + + } // S2D +} // GS + + +#endif // __NUI_GROUP__ diff --git a/include/engine/ui/ui_item.h b/include/engine/ui/ui_item.h new file mode 100644 index 0000000..e040208 --- /dev/null +++ b/include/engine/ui/ui_item.h @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUIITEM__ +#define __NUIITEM__ + + + #include "automation/automation_player.h" + #include "ui/ui_item_event_interface.h" + #include "script/scripted_object.h" + #include "math/matrix3.h" + #include "geometry/rect.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + #include "memory/nshared_ptr.h" + #include "memory/bit_field.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace GPU { class TriangleBatch; } + namespace Core { struct ResourceFactories; } + namespace Render { class Renderer; } + + namespace S2D { + class EventTable; + + using Render::Renderer; + +/*! + @short UI Item. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Item : public SharedObject +{ + friend class Scene; + +public: + +enum Type +{ + Type_None = 0, + Type_Camera, + Type_Sprite, + Type_Window +}; + +enum Flag +{ + Flag_ItemActive = (1 << 0) +}; + +protected: + + uint uid; + Type type; + + Item *parent; + + Vector2 position, pivot, size, scale; + float zorder, angle; + + Matrix3 local_matrix, matrix, imatrix; + + List children; ///< Children list. + +public: + + String name; + + BitField item_flags; + + uint GetUid() const { return uid; } + Type GetItemType() const { return type; } + +virtual EventTable *GetEventTable() const { return 0; } + + Item *GetParent() const { return parent; } + void SetParent(Item * = 0); + + bool Inherits(const Item *) const; + + List &GetChildren() { return children; } + + void ComputeMatrix(); + + const Matrix3 &GetLocalMatrix() { return local_matrix; } + const Matrix3 &GetMatrix() { return matrix; } + const Matrix3 &GetInverseMatrix() { return imatrix; } + + /// Snapshot a transformation to this sprite position, rotation and scale. + void SnapshotTransformation(const Matrix3 &); + + float GetZOrder() const { return zorder; } + void SetZOrder(float z) { zorder = z; } + Vector2 GetPosition() const { return position; } + void SetPosition(float x, float y) { position.Set(x, y); } + Vector2 GetPivot() const { return pivot; } + void SetPivot(float x, float y) { pivot.Set(x, y); } + Vector2 GetScale() const { return scale; } + void SetScale(float x, float y) { scale.Set(x, y); } + Vector2 GetSize() const { return size; } +virtual void SetSize(float x, float y) { size.Set(Types::Max (1, x), Types::Max (1, y)); } + + float GetRotation() const { return angle; } + void SetRotation(float a) { angle = a; } + + /// Rectangle in local space. +virtual iRect GetRect() const; + /// Rectangle in screen space. +virtual iRect GetScreenRect() const; + + iRect LocalToScreen(const iRect &) const; + iRect ScreenToLocal(const iRect &) const; + Vector2 LocalToScreen(const Vector2 &) const; + Vector2 ScreenToLocal(const Vector2 &) const; + +virtual void RenderSetup(Core::ResourceFactories * = 0) = 0; +virtual void Render(Renderer &, GPU::TriangleBatch * = 0) = 0; + + AutoPtr item_event; + AutoPtr scripted_object; + AutoPtr automation_player; + + void Reset(); + void Setup(); + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag() const; + + Item(); +virtual ~Item(); +}; + + } // S2D +} // GS + + +#endif // __NUIITEM__ diff --git a/include/engine/ui/ui_item_automated_property_provider.h b/include/engine/ui/ui_item_automated_property_provider.h new file mode 100644 index 0000000..09814aa --- /dev/null +++ b/include/engine/ui/ui_item_automated_property_provider.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUIITEMAUTOMATEDPROPERTYPROVIDER__ +#define __NUIITEMAUTOMATEDPROPERTYPROVIDER__ + + + #include "automation/automated_property_provider.h" + + +namespace GS { + namespace S2D { + class Item; + namespace Automation { + +/*! + @short Item automated property provider. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct ItemPropertyProvider : public GS::Automation::IPropertyProvider +{ + S2D::Item *item; + +virtual bool GetProperty(Core::MotionChannel::Type, float &); +virtual bool SetProperty(Core::MotionChannel::Type, float); +virtual Quaternion GetRotation() const; +virtual bool SetRotation(const Quaternion &); + + ItemPropertyProvider(S2D::Item *i) : item(i) {} +}; + + } // Automation + } // S2D +} // GS + + +#endif // __NITEMAUTOMATEDPROPERTYPROVIDER__ diff --git a/include/engine/ui/ui_item_event_interface.h b/include/engine/ui/ui_item_event_interface.h new file mode 100644 index 0000000..9e8a55f --- /dev/null +++ b/include/engine/ui/ui_item_event_interface.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __IUIITEMEVENT__ +#define __IUIITEMEVENT__ + + +namespace GS { + namespace S2D { + class Item; + +/*! + @short Item event interface. + Implement this class if you wish to process item events. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct IItemEvent +{ +virtual void OnSetup(Item *) {} +virtual void OnSetupDone(Item *) {} +virtual void OnReset(Item *) {} + +virtual void OnActivate(Item *, bool) {} + +virtual void OnPhysicStep(Item *, bool /*step_taken*/) {} + +virtual void OnUpdate(Item *) {} +virtual void OnDelete(Item *) {} + +virtual void OnRenderDone(Item *) {} +virtual void OnRenderUser(Item *) {} + +// virtual void OnCollision(Item *, Item * /*with*/, const nCollisionPair &) {} + +virtual ~IItemEvent() {} +}; + + } // S2D +} // GS + + +#endif // __IUIITEMEVENT__ diff --git a/include/engine/ui/ui_item_script_event.h b/include/engine/ui/ui_item_script_event.h new file mode 100644 index 0000000..050d8cb --- /dev/null +++ b/include/engine/ui/ui_item_script_event.h @@ -0,0 +1,44 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUIITEMSCRIPTEVENT__ +#define __NUIITEMSCRIPTEVENT__ + + + #include "ui/ui_item_event_interface.h" + + +namespace GS { + namespace S2D { + +/*! + @short Item script event. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ItemScriptEvent : public IItemEvent +{ +virtual void OnSetup(Item *); +virtual void OnSetupDone(Item *); +virtual void OnReset(Item *); + +virtual void OnActivate(Item *, bool activate); + +virtual void OnPhysicStep(Item *, bool step_taken); + +virtual void OnUpdate(Item *); +virtual void OnDelete(Item *); + +virtual void OnRenderDone(Item *); +virtual void OnRenderUser(Item *); + +// virtual void OnCollision(Item *, Item *with, const nCollisionPair &); +}; + + } +} + + +#endif // __NUIITEMSCRIPTEVENT__ diff --git a/include/engine/ui/ui_item_script_unit.h b/include/engine/ui/ui_item_script_unit.h new file mode 100644 index 0000000..f55db84 --- /dev/null +++ b/include/engine/ui/ui_item_script_unit.h @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __UIITEMSCRIPTUNIT__ +#define __UIITEMSCRIPTUNIT__ + + + #include "script/script_unit.h" + #include "script/script_object.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace S2D { + +/*! + @short UI item script unit. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct ItemScriptUnit : public Script::Unit +{ + AutoPtr + update_callback, + trigger_callback, + activation_callback, + physic_callback, + physic_sleep_callback, + collision_callback, + collisionex_callback, + render_user_callback; + + bool Open(); + void Close(); + + ItemScriptUnit(Script::IVM *); + ~ItemScriptUnit(); +}; + + } // S2D +} // GS + + +#endif // __UIITEMSCRIPTUNIT__ diff --git a/include/engine/ui/ui_item_scripted_object.h b/include/engine/ui/ui_item_scripted_object.h new file mode 100644 index 0000000..5a6a76f --- /dev/null +++ b/include/engine/ui/ui_item_scripted_object.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __UIITEMSCRIPTEDOBJECT__ +#define __UIITEMSCRIPTEDOBJECT__ + + + #include "script/scripted_object.h" + + +namespace GS { + namespace S2D { + class Item; + +/*! + @short Managed item scripted object. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class ItemScriptedObject : public Script::ScriptedObject +{ + Item *item; + +public: + +virtual Script::Unit *NewUnit() const; + + ItemScriptedObject(Item *i, Script::IVM *vm = 0) : Script::ScriptedObject(vm), item(i) {} +}; + + } // S2D +} // GS + + +#endif // __UIITEMSCRIPTEDOBJECT__ diff --git a/include/engine/ui/ui_message.h b/include/engine/ui/ui_message.h new file mode 100644 index 0000000..4a75900 --- /dev/null +++ b/include/engine/ui/ui_message.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUI_MESSAGE__ +#define __NUI_MESSAGE__ + + + #include "messaging/messaging.h" + + +namespace GS { + namespace S2D { + class Scene; + +/* + @short UI message enum. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +enum Message +{ + UIMsg_None = 0, ///< No message. + + UIMsg_AddingItem, + UIMsg_ItemAdded, + UIMsg_DeletingItem, + UIMsg_ItemDeleted, + + UIMsg_Deleting, + UIMsg_Deleted, + UIMsg_Loading, + UIMsg_Loaded, + + UIMsg_SpriteLinkChanging, + UIMsg_SpriteLinkChanged, + + UIMsg_LastMessage +}; + +/* + @short UI message return value. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +enum ReturnValue +{ + UIReturn_Ok = 0 +}; + +/// UI listener. +struct Listener +{ +virtual ReturnValue ProcessMessage(Message, const Scene *, const void *) = 0; +}; + +extern Messaging::Broadcaster g_ui_messenger; + + } // S2D +} // GS + + +#endif // __NUI_MESSAGE__ diff --git a/include/engine/ui/ui_scene_event_interface.h b/include/engine/ui/ui_scene_event_interface.h new file mode 100644 index 0000000..7484780 --- /dev/null +++ b/include/engine/ui/ui_scene_event_interface.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __UISCENEEVENTINTERFACE__ +#define __UISCENEEVENTINTERFACE__ + + +namespace GS { + namespace S2D { + + class Scene; + +/*! + @short UI scene event interface. + + Implement this class if you wish to process script events from C++. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct ISceneEvent +{ +virtual void OnSetup(Scene *) {} +virtual void OnReset(Scene *) {} +virtual void OnUpdate(Scene *) {} +virtual void OnDelete(Scene *) {} + +virtual ~ISceneEvent() {} +}; + + } +} + + +#endif // __UISCENEEVENTINTERFACE__ diff --git a/include/engine/ui/ui_scene_script_event.h b/include/engine/ui/ui_scene_script_event.h new file mode 100644 index 0000000..3f71612 --- /dev/null +++ b/include/engine/ui/ui_scene_script_event.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __UISCENESCRIPTEVENT__ +#define __UISCENESCRIPTEVENT__ + + + #include "ui/ui_scene_event_interface.h" + + +namespace GS { + namespace S2D { + + class Scene; + struct ISceneEvent; + +/*! + @short UI scene event interface. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct SceneScriptEvent : public ISceneEvent +{ +virtual void OnSetup(Scene *); +virtual void OnReset(Scene *); +virtual void OnUpdate(Scene *); +virtual void OnDelete(Scene *); +}; + + } +} + + +#endif // __UISCENESCRIPTEVENT__ diff --git a/include/engine/ui/ui_scene_scripted_object.h b/include/engine/ui/ui_scene_scripted_object.h new file mode 100644 index 0000000..abfc0bf --- /dev/null +++ b/include/engine/ui/ui_scene_scripted_object.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUISCENESCRIPTEDOBJECT__ +#define __NUISCENESCRIPTEDOBJECT__ + + + #include "script/scripted_object.h" + + +namespace GS { + namespace S2D { + class Scene; + +/*! + @short UI scene scripted object. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class SceneScriptedObject : public Script::ScriptedObject +{ + Scene *scene; + +public: + +virtual Script::Unit *NewUnit() const; + + SceneScriptedObject(Script::IVM *vm, Scene *s) : Script::ScriptedObject(vm), scene(s) {} +}; + + } // S2D +} // GS + + +#endif // __NUISCENESCRIPTEDOBJECT__ diff --git a/include/engine/ui/ui_script_unit.h b/include/engine/ui/ui_script_unit.h new file mode 100644 index 0000000..df2bfef --- /dev/null +++ b/include/engine/ui/ui_script_unit.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __UISCENESCRIPTUNIT__ +#define __UISCENESCRIPTUNIT__ + + + #include "script/script_unit.h" + #include "script/script_object.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace S2D { + +/*! + @short UI scene script unit. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct SceneUnit : public Script::Unit +{ + AutoPtr frame_callback; + + bool Open(); + void Close(); + + SceneUnit(Script::IVM *); + ~SceneUnit(); +}; + + } // S2D +} // GS + + +#endif // __UISCENESCRIPTUNIT__ diff --git a/include/engine/ui/ui_sprite.h b/include/engine/ui/ui_sprite.h new file mode 100644 index 0000000..07f381d --- /dev/null +++ b/include/engine/ui/ui_sprite.h @@ -0,0 +1,80 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSPRITE__ +#define __NSPRITE__ + + + #include "ui/ui_event_handler.h" + #include "ui/ui_item.h" + #include "core/ace.h" + #include "core/render_data.h" + #include "core/resource_factories.h" + + +namespace GS { + namespace S2D { + +/* + @short Sprite class. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Sprite : public Item, public ACE::Unit +{ +protected: + + AutoPtr event_table; + +public: + +struct RenderData +{ + Render::sTexture texture; +}; + +enum +{ + FlagFlipU = (1 << 2), + FlagFlipV = (1 << 3), + + FlagBlendOpaque = (1 << 4), + FlagBlendAdditive = (1 << 5), + + FlagNonSensitive = (1 << 6), + FlagResolutionInvariant = (1 << 7), + FlagTransformUV = (1 << 8), + + FlagSnapToPixel = (1 << 9) +}; + + BitField sprite_flags; + + String texture; + + Vector2 uv_origin; + Matrix3 uv_matrix; + float opacity; + +virtual EventTable *GetEventTable() const { return event_table; } + + bool ExecCommand(ACE::Command *, float dt); + +virtual void Render(Render::Renderer &, GPU::TriangleBatch * = 0); +virtual void RenderSetup(Core::ResourceFactories * = 0); + + AutoPtr render_data; + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag() const; + + Sprite(); +}; + + } // S2D +} // GS + + +#endif // __NSPRITE__ diff --git a/include/engine/ui/ui_window.h b/include/engine/ui/ui_window.h new file mode 100644 index 0000000..30bd98b --- /dev/null +++ b/include/engine/ui/ui_window.h @@ -0,0 +1,87 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NWINDOW__ +#define __NWINDOW__ + + + #include "ui/widget.h" + #include "ui/ui_sprite.h" + #include "ui/ui_window_skin.h" + + +namespace GS { + struct RenderResourceFactory; + + namespace S2D { + +/*! + @short Window class. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Window : public Sprite +{ +public: + +enum +{ + FlagNoDecoration = (1 << 0), + FlagNoTitleBar = (1 << 1), + + // Non-serializable + FlagCacheDirty = (1 << 2), + FlagRenderDirty = (1 << 3) +}; + +protected: + + sWindowSkin skin; + sPicture cache; + + sWidget title_widget; + sWidget base_widget; + + BitField window_flags; + +public: + + Picture *GetCache() const { return cache; } + + void Invalidate(); + + void SetSkin(WindowSkin *); + void ComposeSkin(); + void Compose(); + + void SetSize(float w, float h); + + sPicture background_picture; + Color background_color; + + Widget *GetWidget(uint id); + + Widget *GetTitleWidget() const; + void SetTitleWidget(Widget *); + Widget *GetBaseWidget() const; + void SetBaseWidget(Widget *); + + iRect GetRect() const; + iRect GetClientRect() const; + +virtual void RenderSetup(Core::ResourceFactories * = 0); +virtual void Render(Renderer &, GPU::TriangleBatch * = 0); + +virtual bool FromMetaTag(NML::Tag &); +virtual NML::Tag *AsMetaTag() const; + + Window(); +}; + + } // S2D +} // GS + + +#endif // __NWINDOW__ diff --git a/include/engine/ui/ui_window_skin.h b/include/engine/ui/ui_window_skin.h new file mode 100644 index 0000000..b2e005e --- /dev/null +++ b/include/engine/ui/ui_window_skin.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __WINDOWSKIN__ +#define __WINDOWSKIN__ + + + #include "font/font_cache.h" + #include "picture/pict.h" + + +namespace GS { + namespace S2D { + +/// UI Window skin. +struct WindowSkin : public SharedObject +{ + sPicture top, left, right, bottom, top_left, top_right, bottom_left, bottom_right; + uint color; + + sFontEx title_font; + + int title_top, + title_bottom, + title_size, + title_color; +}; + +typedef SharedPtr sWindowSkin; + + } //S2D +} // GS + + +#endif // __WINDOWSKIN__ diff --git a/include/engine/ui/widget.h b/include/engine/ui/widget.h new file mode 100644 index 0000000..e578f1d --- /dev/null +++ b/include/engine/ui/widget.h @@ -0,0 +1,128 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NWIDGET__ +#define __NWIDGET__ + + + #include "ui/ui_event_handler.h" + #include "geometry/rect.h" + #include "math/vector.h" + #include "memory/nshared_ptr.h" + #include "memory/nweak_ptr.h" + + +namespace GS { + class Picture; + + namespace S2D { + class Widget; + + typedef SharedPtr sWidget; + +/// Widget type. +enum WidgetType +{ + WidgetTypeBase = 0, + WidgetTypeSizer, + WidgetTypeVSizer, + WidgetTypeHSizer, + WidgetTypeContainer, + WidgetTypeSpacer, + WidgetTypeText, + WidgetTypeCanvas, + WidgetTypeDrawable, + WidgetTypeBitmap, + WidgetTypeCheck +}; + +/*! + @short Base widget. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Widget : public SharedObject +{ +public: + +enum Align +{ + AlignNone = 0, + AlignLeft, + AlignTop, + AlignMiddle, + AlignRight, + AlignBottom, + AlignGrow +}; + +protected: + + WidgetType type; + Widget *parent; + + AutoPtr event_table; + + int object_id; + iRect rect; + + Align h_align, v_align; + + bool hidden; ///< Hidden. + bool dirty; ///< Dirty flag. + + Vector4 border_size; ///< Border size in pixel (x->top, y->bottom, z->left, w->right). + + SharedList children; + + Vector2 format; ///< Formatting size. + + /// Setup and align output rectangle. + iRect FormatOutputRect(const iRect &rect, const iRect &out_rect); + +public: + + int GetId() const { return object_id; } + WidgetType GetType() const { return type; } + + void SetHidden(bool h = true); + bool IsHidden() const { return hidden; } + bool IsDirty() const { return dirty; } + + void Validate() { dirty = false; } +virtual void Invalidate(); + +virtual void Refresh() = 0; +virtual void Compose(Picture &output, const iRect &clip_rect) = 0; + + EventTable *GetEventTable() const { return event_table; } + + void SetParent(Widget *w); + Widget *GetParent() const { return parent; } + + Widget *GetChild(int id); + + const SharedList &GetChildren() const { return children; } + + /// Return widget rect in parent window client space. + iRect GetRect() const; + + void SetBorderSize(float top = 2, float bottom = 2, float left = 2, float right = 2); + void SetHAlign(Align = AlignMiddle); + void SetVAlign(Align = AlignMiddle); + void SetFormattingSize(const Vector2 &); + + /// Get widget formatting size ratio. + Vector2 GetFormat() const; + + Widget(int id = -1); +virtual ~Widget(); +}; + + } // S2D +} // GS + + +#endif // __NWIDGET__ diff --git a/include/engine/ui/widget_bitmap.h b/include/engine/ui/widget_bitmap.h new file mode 100644 index 0000000..066192f --- /dev/null +++ b/include/engine/ui/widget_bitmap.h @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUI_WIDGET_BITMAP__ +#define __NUI_WIDGET_BITMAP__ + + + #include "ui/widget_drawable.h" + + +namespace GS { + namespace S2D { + +/// Bitmap widget. +struct BitmapWidget : public DrawableWidget +{ + void SetPicture(Picture *); + + BitmapWidget(int id = -1, Picture *bitmap = 0); +}; + + } // S2D +} // GS + + +#endif // __NUI_WIDGET_BITMAP__ diff --git a/include/engine/ui/widget_canvas.h b/include/engine/ui/widget_canvas.h new file mode 100644 index 0000000..682c0ca --- /dev/null +++ b/include/engine/ui/widget_canvas.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUIWIDGETCANVAS__ +#define __NUIWIDGETCANVAS__ + + + #include "ui/widget_drawable.h" + + +namespace GS { + namespace S2D { + +/*! + @short Canvas widget. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct CanvasWidget : public DrawableWidget +{ + /// Allocate canvas dimensions. + bool Allocate(uint width, uint height); + + Picture *Lock() { return picture; } + void Unlock() { dirty = true; } + + CanvasWidget(int id = -1, uint width = 8, uint height = 8); +}; + + } // S2D +} // GS + + +#endif // __NUIWIDGETCANVAS__ diff --git a/include/engine/ui/widget_check.h b/include/engine/ui/widget_check.h new file mode 100644 index 0000000..7a921cf --- /dev/null +++ b/include/engine/ui/widget_check.h @@ -0,0 +1,66 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUIWIDGETCHECK__ +#define __NUIWIDGETCHECK__ + + + #include "ui/widget_bitmap.h" + #include "ui/widget_text.h" + + +namespace GS { + namespace S2D { + +/*! + @short Check widget. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class CheckWidget : public Widget +{ +protected: + + BitmapWidget check_bitmap; + TextWidget label; + + bool state; + int marging; + +public: + + TextWidget &GetLabel() { return label; } + + int GetMarging() const { return marging; } + void SetMarging(int m) + { + if (marging == m) + return; + Widget::Invalidate(); + marging = m; + } + + bool GetState() const { return state; } + void SetState(bool state); + +virtual void Refresh(); +virtual void Compose(Picture &, const iRect &out_rect); +virtual void Invalidate(); + + CheckWidget(int id = -1, const char *label = 0, FontEx *font = 0, int size = 16, bool b_state = true) : + Widget(id), check_bitmap(-1, 0), label(-1, label, font, size) + { + type = WidgetTypeCheck; + + marging = 4; + SetState(b_state); + } +}; + + } // S2D +} // GS + + +#endif // __NUIWIDGETCHECK__ diff --git a/include/engine/ui/widget_drawable.h b/include/engine/ui/widget_drawable.h new file mode 100644 index 0000000..ea67d22 --- /dev/null +++ b/include/engine/ui/widget_drawable.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NWIDGETDRAWABLE__ +#define __NWIDGETDRAWABLE__ + + + #include "ui/widget.h" + #include "picture/pict.h" + + +namespace GS { + namespace S2D { + +/*! + @short Drawable widget. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class DrawableWidget : public Widget +{ +protected: + + sPicture picture; + +public: + + Picture *GetPicture() const { return picture; } + +virtual void Refresh() {} +virtual void Compose(Picture &output, const iRect &clip_rect); + +protected: + + DrawableWidget(int id = -1); +virtual ~DrawableWidget() {} +}; + + } // S2D +} // GS + + +#endif // __NWIDGETDRAWABLE__ diff --git a/include/engine/ui/widget_sizer.h b/include/engine/ui/widget_sizer.h new file mode 100644 index 0000000..12118d6 --- /dev/null +++ b/include/engine/ui/widget_sizer.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NWIDGETSIZER__ +#define __NWIDGETSIZER__ + + + #include "ui/widget.h" + + +namespace GS { + namespace S2D { + +/*! + @short Sizer widget. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct SizerWidget : public Widget +{ +virtual void Invalidate(); + + Widget *Add(Widget *widget); + bool Remove(Widget *widget) { return children.Remove(widget); } + + SizerWidget(int id = -1) : Widget(id) { type = WidgetTypeSizer; } +}; + +struct HSizerWidget : public SizerWidget +{ +virtual void Refresh(); +virtual void Compose(Picture &output, const iRect &out_rect); + + void SetColumnSize(int size); + + HSizerWidget(int id = -1) : SizerWidget(id) { type = WidgetTypeHSizer; } +}; + +struct VSizerWidget : public SizerWidget +{ +virtual void Refresh(); +virtual void Compose(Picture &output, const iRect &out_rect); + + VSizerWidget(int id = -1) : SizerWidget(id) { type = WidgetTypeVSizer; } +}; + + } // S2D +} // GS + + +#endif // __NWIDGETSIZER__ diff --git a/include/engine/ui/widget_spacer.h b/include/engine/ui/widget_spacer.h new file mode 100644 index 0000000..c8afe3c --- /dev/null +++ b/include/engine/ui/widget_spacer.h @@ -0,0 +1,43 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUI_WIDGET_SPACER__ +#define __NUI_WIDGET_SPACER__ + + + #include "ui/widget.h" + + +namespace GS { + namespace S2D { + +/*! + @short Spacer widget. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct SpacerWidget : public Widget +{ + void Invalidate() { dirty = true; } + +virtual void Refresh() {} +virtual void Compose(Picture &, const iRect &out_rect) + { + dirty = false; + rect = out_rect; + } + + SpacerWidget(int id = -1) : Widget(id) + { + type = WidgetTypeSpacer; + format.Set(0.5, 0.5); + } +}; + + } // S2D +} // GS + + +#endif // __NUI_WIDGET_SPACER__ diff --git a/include/engine/ui/widget_staticcontainer.h b/include/engine/ui/widget_staticcontainer.h new file mode 100644 index 0000000..b025c9a --- /dev/null +++ b/include/engine/ui/widget_staticcontainer.h @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUI_WIDGET_CONTAINER__ +#define __NUI_WIDGET_CONTAINER__ + + + #include "ui/widget.h" + + +namespace GS { + namespace S2D { + +// +struct ContainerCell +{ + iRect cell_rect; ///< Cell rect in parent coordinate frame. + sWidget widget; ///< Cell widget. +}; + +/*! + @short Container widget. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class ContainerWidget : public Widget +{ +protected: + + List cell_list; + +public: + + void Invalidate(); + +virtual void Refresh(); +virtual void Compose(Picture &, const iRect &out_rect); + + ContainerCell *GetCell(const Widget *) const; + + Widget *Add(Widget *, const iRect &cell_rect); + bool Remove(Widget *); + + ContainerWidget(int id = -1) : Widget(id) { type = WidgetTypeContainer; } + ~ContainerWidget(); +}; + + } // S2D +} // GS + + +#endif // __NWIDGETCONTAINER__ diff --git a/include/engine/ui/widget_text.h b/include/engine/ui/widget_text.h new file mode 100644 index 0000000..2a4fc41 --- /dev/null +++ b/include/engine/ui/widget_text.h @@ -0,0 +1,95 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NUIWIDGETTEXT__ +#define __NUIWIDGETTEXT__ + + + #include "ui/widget.h" + #include "font/font_renderer.h" + + +namespace GS { + namespace S2D { + +/*! + @short Text widget. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class TextWidget : public Widget +{ +protected: + + TextState state; ///< Widget text state. + String text; ///< Widget text. + +public: + + const char *GetText() const { return text.c_str(); } + void SetText(const char *); + + /// Set text block formatting rule. + void SetTextFormat(TextState::Format f) + { + if (state.format != f) + { + state.format = f; + Invalidate(); + } + } + /// Get text formatting rule. + TextState::Format GetTextFormat() const { return state.format; } + + /// Get text alignment rule. + TextState::Alignment GetTextAlignment() const { return state.alignment; } + /// Set text alignment rule. + void SetTextAlignment(TextState::Alignment align) + { + if (state.alignment != align) + { + state.alignment = align; + Invalidate(); + } + } + + void SetFont(FontEx *); + void SetFontSize(int size); + void SetFontColor(float r, float g, float b, float a = 1.0); + + /// Set column formatting width in character. + void SetColumnWidth(int w) + { + state.column_width = w; + Invalidate(); + } + + /// Set font tracking. + void SetTextTracking(float tracking_offset = 0) + { + state.SetTracking(tracking_offset); + dirty = true; + } + /// Set font heading. + void SetTextHeading(float heading_offset = 0) + { + state.SetLeading(heading_offset); + dirty = true; + } + + void SetTextState(const TextState &); + void GetTextState(TextState &) const; + +virtual void Refresh(); +virtual void Compose(Picture &output, const iRect &clip_rect); + + TextWidget(int id = -1, const char * = "Text", FontEx * = 0, int size = 16); +}; + + } // S2D +} // GS + + +#endif // __NUIWIDGETTEXT__ diff --git a/include/framework/ascii/ascii_encoder.h b/include/framework/ascii/ascii_encoder.h new file mode 100644 index 0000000..c9880bc --- /dev/null +++ b/include/framework/ascii/ascii_encoder.h @@ -0,0 +1,82 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NASCIIENC__ +#define __NASCIIENC__ + + + #include "ntypes.h" + + +/*! + @short ASCII encoding. + + This class currently provide two commonly used encoding method: + yEnc and UUEncode. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +namespace nAsciiEncoder +{ + /*! + @short Perform UUEncoding. + + @param source Input binary stream. + @param len Input binary stream length. + @param uuenc Output buffer. + @param max Output buffer length. + @return The number of bytes written to the output buffer. + + @note If yenc is NULL the function can be used to check the size + of the encoded stream prior to allocating an output buffer. + */ + uint UUEncode(const uchar *source, size_t len, uchar *uuenc = 0, size_t max = 0); + + /*! + @short Perform UUDecoding. + + @param source UUEncoded byte stream. + @param len UUEncoded byte stream length. + @param bin Output buffer. + @param max Output buffer length. + @return The number of bytes written to the output buffer. + + @note If bin is NULL the function can be used to check the size + of the decoded stream prior to allocating an output buffer. + */ + uint UUDecode(const uchar *source, size_t len, uchar *bin = 0, size_t max = 0); + /*! + @short Perform yEncoding. + + @param source Input binary stream. + @param len Input binary stream length. + @param yenc Output buffer. + @param max Output buffer length. + @param line_len Number of character to output before a line-feed character is sent. + @return The number of bytes written to the output buffer. + + @note If yenc is NULL the function can be used to check the size + of the encoded stream prior to allocating an output buffer. + */ + uint yEncode(const uchar *source, size_t len, uchar *yenc = 0, size_t max = 0, uint line_len = 64); + + /*! + @short Perform yDecoding. + + @param source yEncoded byte stream. + @param len yEncoded byte stream length. + @param bin Output buffer. + @param max Output buffer length. + @return The number of bytes written to the output buffer. + + @note If bin is NULL the function can be used to check the size + of the decoded stream prior to allocating an output buffer. + */ + uint yDecode(const uchar *source, size_t len, uchar *bin = 0, size_t max = 0); +}; + + +#endif // __NASCIIENC__ diff --git a/include/framework/ascii/parser.h b/include/framework/ascii/parser.h new file mode 100644 index 0000000..725eb00 --- /dev/null +++ b/include/framework/ascii/parser.h @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NASCII_PARSER__ +#define __NASCII_PARSER__ + + +/*! + @short ASCII parsing tools. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +namespace GS { + namespace AsciiParser { + + /// Return true is the provided character is uppercase. +bool IsUpperCase(const char s); + /// Return whether a constant is float or int. +bool IsConstantFloat(const char *s, const char *e); + /// Find a character inside an ASCII block. +const char *Find(const char *s, const char *e, char f); + /// Run to end of string. +const char *RunToEOS(const char *s, const char *e); + /// Run to end of line marker. +const char *RunToEOL(const char *s, const char *e); + /// Skip end of line marker. +const char *SkipEOL(const char *s, const char *e); + /*! + @short Run to the end of a group started with character 'op' closed with character 'cl'. + @note This function automatically skips nested group of the same kind. + */ +const char *RunToEOG(const char *s, const char *e, char op, char cl); + /// Run to the end of a C comment block (/*...*/). +const char *RunToEOC(const char *s, const char *e); + /// Run to the end of a C expression. +const char *RunToEOE(const char *s, const char *e); + /// Skip non-{space/tab/comments} string. +const char *SkipEntry(const char *s, const char *e, bool skip_minus = false); + /// Skip spaces. +const char *SkipSpace(const char *s, const char *e); + /// Go to the next entry. +const char *NextEntry(const char *s, const char *e, bool skip_minus = false); + + } +} + + +#endif // __NASCII_PARSER__ diff --git a/include/framework/audio/audio_io.h b/include/framework/audio/audio_io.h new file mode 100644 index 0000000..6b0782f --- /dev/null +++ b/include/framework/audio/audio_io.h @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __AUDIOIO__ +#define __AUDIOIO__ + + + #include "audio/stream_interface.h" + #include "audio/stream_factory.h" + #include "audio/sample_interface.h" + #include "audio/sample_factory.h" + #include "memory/singleton.h" + #include "container/nlist.h" + + +namespace GS { + +/* + @short Audio factory. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class AudioIO : public Singleton +{ + AutoList stream_factories; + AutoList sample_factories; + +public: + + /// Register a stream codec. + void RegisterStreamFactory(IAudioStreamFactory *); + /// Register a sample codec. + void RegisterSampleFactory(ISampleFactory *); + + /// Open stream. + IAudioStream *OpenStream(const char *path, const char *format = 0); + /// Load a sample. + ISample *LoadSample(const char *path, const char *format = 0); +}; + +} // GS + + +#endif // __AUDIOIO__ + diff --git a/include/framework/audio/sample_factory.h b/include/framework/audio/sample_factory.h new file mode 100644 index 0000000..6e718cf --- /dev/null +++ b/include/framework/audio/sample_factory.h @@ -0,0 +1,32 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ISAMPLEFACTORY__ +#define __ISAMPLEFACTORY__ + + +namespace GS { + struct ISample; + +/* + @short Sample I/O codec interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct ISampleFactory +{ + /// Get the codec name. +virtual const char *GetName() = 0; + /// Load a sample. +virtual ISample *Load(const char *path) = 0; + +virtual ~ISampleFactory() {} +}; + +} // GS + + +#endif // __ISAMPLEFACTORY__ + diff --git a/include/framework/audio/sample_format.h b/include/framework/audio/sample_format.h new file mode 100644 index 0000000..1b691b4 --- /dev/null +++ b/include/framework/audio/sample_format.h @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSAMPLEFORMAT__ +#define __NSAMPLEFORMAT__ + + + #include "ntypes.h" + + +namespace GS { + +/*! + @short Sample format. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct SampleFormat +{ +enum Format +{ + Format_PCM = 0, +#if __PLATFORM_NINTENDO_WII__ + Format_Wii_ADPCM +#endif +}; + + Format format; + uint channels; + + uint frequency; + uchar resolution; + + /// Get the PCM data memory footprint a given number of samples in this format. + uint GetPCMDataSize(uint sample_count) const + { return (sample_count * channels * resolution) / 8; } + + SampleFormat(Format _format = Format_PCM, uint _channels = 2, uint _frequency = 48000, uchar _bit_per_sample = 16) : format(_format), channels(_channels), frequency(_frequency), resolution(_bit_per_sample) {} +}; + +} // GS + + +#endif // __NSAMPLEFORMAT__ diff --git a/include/framework/audio/sample_interface.h b/include/framework/audio/sample_interface.h new file mode 100644 index 0000000..0f9541e --- /dev/null +++ b/include/framework/audio/sample_interface.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ISAMPLE__ +#define __ISAMPLE__ + + + #include "audio/sample_format.h" + #include "time/ntime.h" + + +namespace GS { + +/*! + @short Sample base interface. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct ISample +{ + /// Return the format identifier (eg. "WAV"). +virtual const char *GetFormat() = 0; + + /// Get sample format. +virtual bool GetSampleFormat(SampleFormat &) const = 0; + /// Get sample duration. +virtual Time GetDuration() const = 0; + +virtual ~ISample() {} +}; + +} // GS + + +#endif // __ISAMPLE__ diff --git a/include/framework/audio/sample_stream_factory.h b/include/framework/audio/sample_stream_factory.h new file mode 100644 index 0000000..18643ab --- /dev/null +++ b/include/framework/audio/sample_stream_factory.h @@ -0,0 +1,34 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SAMPLESTREAMFACTORY__ +#define __SAMPLESTREAMFACTORY__ + + + #include "audio/sample_interface.h" + #include "audio/sample_factory.h" + + +namespace GS { + struct ISample; + +/*! + @short Sample stream factory + This codec can decode any supported audio stream to a WAV sample. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct SampleStreamFactory : public ISampleFactory +{ + /// Get the codec name. +virtual const char *GetName() { return "Stream"; } + /// Load a sample. +virtual ISample *Load(const char *path); +}; + +} // GS + + +#endif // __SAMPLESTREAMFACTORY__ diff --git a/include/framework/audio/sample_wav.h b/include/framework/audio/sample_wav.h new file mode 100644 index 0000000..03213c8 --- /dev/null +++ b/include/framework/audio/sample_wav.h @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SAMPLEWAV__ +#define __SAMPLEWAV__ + + + #include "audio/sample_interface.h" + #include "time/ntime.h" + + +namespace GS { + +/*! + @short WAV sample. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class SampleWav : public ISample +{ + friend struct SampleWavFactory; + +protected: + + SampleFormat format; + + uint sample_count; + Array pcm_data; + +public: + + /// Return the sample count. + uint GetSampleCount() const { return sample_count; } + /// Return the PCM data. + void *GetPCMData() const { return pcm_data.c_ptr(); } + /// Return the PCM data size. + uint GetPCMDataSize() const; + + /// Set PCM data, the data array content will be transfered to the sample. + void Set(Array &data, uint sample_count, const SampleFormat &); + /// Allocate PCM samples for a given format. + char *AllocAs(uint sample_count, const SampleFormat &); + + /// Return the sample format identifier (eg. "WAV"). +virtual const char *GetFormat() { return "WAV"; } + + /// Get the sample format. +virtual bool GetSampleFormat(SampleFormat &) const; + /// Get sample duration. +virtual Time GetDuration() const; + + SampleWav() : sample_count(0) {} +}; + +} // GS + + +#endif // __SAMPLEWAV__ diff --git a/include/framework/audio/sample_wav_factory.h b/include/framework/audio/sample_wav_factory.h new file mode 100644 index 0000000..b55268c --- /dev/null +++ b/include/framework/audio/sample_wav_factory.h @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SAMPLEWAVCODEC__ +#define __SAMPLEWAVCODEC__ + + + #include "audio/sample_factory.h" + + +namespace GS { + struct ISample; + +/// Sample WAV codec +struct SampleWavFactory : public ISampleFactory +{ + /// Get the codec name. +virtual const char *GetName() { return "WAV"; } + /// Load a sample. +virtual ISample *Load(const char *path); +}; + +} // GS + + +#endif // __SAMPLEWAVCODEC__ diff --git a/include/framework/audio/stream_factory.h b/include/framework/audio/stream_factory.h new file mode 100644 index 0000000..11f335c --- /dev/null +++ b/include/framework/audio/stream_factory.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ISTREAMFACTORY__ +#define __ISTREAMFACTORY__ + + +namespace GS { + struct IAudioStream; + +/* + @short Stream factory interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct IAudioStreamFactory +{ + /// Get factory name. +virtual const char *GetName() = 0; + /// Open a stream. +virtual IAudioStream *Open(const char *path) = 0; + +virtual ~IAudioStreamFactory() {} +}; + +} // GS + + +#endif // __ISTREAMFACTORY__ diff --git a/include/framework/audio/stream_interface.h b/include/framework/audio/stream_interface.h new file mode 100644 index 0000000..69afb66 --- /dev/null +++ b/include/framework/audio/stream_interface.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __AUDIOSTREAMINTERFACE__ +#define __AUDIOSTREAMINTERFACE__ + + + #include "audio/sample_format.h" + + +namespace GS { + +/* + @short Audio stream interface. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct IAudioStream +{ + SampleFormat format; + + /// Return the stream data format (eg. "OGG"). +virtual const char *GetFormat() = 0; + +virtual bool Seek(int t_ms = 0) = 0; +virtual bool IsEOF() const = 0; + +virtual size_t GetPCM(void *) = 0; +virtual size_t GetPCMBufferSize() const = 0; + +virtual bool Open(const char *uri) = 0; +virtual void Close() = 0; + +virtual ~IAudioStream() {} +}; + +} // GS + + +#endif // __AUDIOSTREAMINTERFACE__ diff --git a/include/framework/bih/bih.h b/include/framework/bih/bih.h new file mode 100644 index 0000000..24a525c --- /dev/null +++ b/include/framework/bih/bih.h @@ -0,0 +1,140 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NBIH__ +#define __NBIH__ + + + #include "geometry/bounding_box.h" + #include "container/narray.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace BIH { + +// Bounding interval hierarchy node. +struct Node +{ + char axis; ///< @TODO: Packed bitfield! + void *p; ///< Pointer to child nodes or index array. + + union + { + uint count; ///< Index count in leaf. + float split[2]; ///< Split planes. + }; + + Node() : axis(3), p(0) {} + ~Node(); +}; + +struct StackEntry +{ + Node *node; + float tmin, tmax; +}; + +// +struct Trace +{ + StackEntry stack[65]; + uint stack_pos; + + bool want_closest; + + bool has_i; ///< Do we have an intersection. + float i_t; ///< Distance to intersection from ray's origin. + Vector4 s; ///< Ray origin. + Vector4 d; ///< Ray direction. + + uint node_visited; ///< Number of nodes visited. + + Trace(bool closest = true) : want_closest(closest), has_i(false) {} +}; + +/*! + @short Bounding interval hierarchy. + + This is a fully generic bounding interval hierarchy implementation. + In order to use this structure on a custom set of data you need to derive + from this class and provide the implementation for the TraceLeaf method. + + In order to build the structure you simply provide a list of volumes to the + build() methods. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Tree +{ +protected: + + /// Minimum leaf volume count. + uint min_leaf_vcount; + + MinMax minmax; ///< Hierarchy bounding box. + AutoPtr root; ///< Hierarchy root node. + + Array sarray; ///< Index array. + + uint node_count; + uint leaf_count; + uint depth; +/*! + @name Trace functions. + @{ +*/ + /// Trace a leaf. +virtual void TraceLeaf(Node *leaf, float tmin, float tmax, Trace &trace, void *parm = 0) = 0; + /// Trace a node. + void TraceNode(Node *node, float tmin, float tmax, Trace &trace); +/// @} + +/*! + @name Intersection functions. + @{ +*/ + /// Intersect a node. + uint IntersectNode(Node *node, MinMax &sub_mm, uint *index_array, uint max_index); +/// @} + +/*! + @name Build functions. + @{ +*/ + /// Create a leaf. + void MakeNodeLeaf(Node *node, uint count, uint *sarray, MinMax *varray); + /// Perform a node split. + void DoNodeSplit(MinMax &minmax, uint count, uint *sarray, MinMax *varray, uint &pivot, Node *node, uint &split_axis); + /// Split an index list of volumes. + bool Split(MinMax &minmax, uint count, uint *sarray, MinMax *varray, Node *node, uint depth); + + /// Build hierarchy from a set of input volumes. +virtual bool Build(uint volume_count, MinMax *varray); +/// @} + +public: + + /// Intersect tree with an axis aligned bounding box. + uint Intersect(MinMax &minmax, uint *index_array, uint max_index); + /* + @short Raytrace hierarchy. + @note Ray direction must be normalized. + */ +virtual void Raytrace(Trace &trace, const Vector4 &s, const Vector4 &d, float l = -1.f, void *parm = 0); + + /// Delete hierarchy. +virtual void Free(); + + Tree(); +virtual ~Tree(); +}; + + } // BIH +} // GS + + +#endif // __NBIH__ diff --git a/include/framework/color/color.h b/include/framework/color/color.h new file mode 100644 index 0000000..b24c8e0 --- /dev/null +++ b/include/framework/color/color.h @@ -0,0 +1,106 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCOLOR__ +#define __NCOLOR__ + + + #include "math/vector.h" + + +namespace GS { + +/*! + @short The base color object. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Color : public Vector4 +{ + bool operator == (const Vector4 &b) const { return Math::TestEqual(x, b.x) && Math::TestEqual(y, b.y) && Math::TestEqual(z, b.z) && Math::TestEqual(w, b.w); } + bool operator != (const Vector4 &b) const { return !Math::TestEqual(x, b.x) || !Math::TestEqual(y, b.y) || !Math::TestEqual(z, b.z) || !Math::TestEqual(w, b.w); } + + /// Standard C++ operators. + void operator += (const Color &b) { x += b.x; y += b.y; z += b.z; w += b.w; }; + void operator += (const float k) { x += k; y += k; z += k; w += k; }; + void operator -= (const Color &b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; }; + void operator -= (const float k) { x -= k; y -= k; z -= k; w -= k; }; + void operator *= (const Color &b) { x *= b.x; y *= b.y; z *= b.z; w *= b.w; }; + void operator *= (const float k) { x *= k; y *= k; z *= k; w *= k; }; + void operator /= (const Color &b) { x /= b.x; y /= b.y; z /= b.z; w /= b.w; }; + void operator /= (const float k) { float k_ = 1.0f / k; x *= k_; y *= k_; z *= k_; w *= k_; }; + + Color operator + (const Color &b) const { return Color(x + b.x, y + b.y, z + b.z, w + b.w); } + Color operator + (const float v) const { return Color(x + v, y + v, z + v, w + v); } + Color operator - (const Color &b) const { return Color(x - b.x, y - b.y, z - b.z, w - b.w); } + Color operator - (const float v) const { return Color(x - v, y - v, z - v, w - v); } + Color operator * (const Color &b) const { return Color(x * b.x, y * b.y, z * b.z, w * b.w); } + Color operator * (const float v) const { return Color(x * v, y * v, z * v, w * v); } + Color operator / (const Color &b) const { return Color(x / b.x, y / b.y, z / b.z, w / b.w); } + Color operator / (const float v) const { return Color(x / v, y / v, z / v, w / v); } + + void operator = (const Vector4 &v) { x = v.x; y = v.y; z = v.z; w = v.w; } + + /*! + @short Return a grayscale value representing this color. + + The grayscale value is computed accounting for the human eye color intensity perception. + @see FastGray(). + */ +inline float Grayscale() const + { return 0.3f * x + 0.59f * y + 0.11f * z; } + /*! + @short Return a grayscale value representing this color. + + @note This function is not optically accurate. + @see Grayscale(). + */ +inline float Fastgray() const + { return (x + y + z) / 3.f; } + + /// Return the color object as an RGBA value. + uint AsInteger() const; + /// Load the color object from an RGBA value. + void FromInteger(uint value); + +/*! + @name Static color objects. + @{ +*/ +static Color White; +static Color Grey; +static Color Black; +static Color Red; +static Color Green; +static Color Blue; +static Color Yellow; +static Color Purple; +/// @} + + /// Scale color not alpha. + Color ScaleChroma(float k) const + { return Color(x * k, y * k, z * k, w); } + + /// Return a color object from a vector object. +static Color FromVector(Vector4 &v) + { return Color(v.x, v.y, v.z, v.w); } + +static uint ARGBtoRGBA(uint argb) + { return ((argb & 0xff) << 24) + (((argb >> 8) & 0xff) << 16) + (((argb >> 16) & 0xff) << 8) + ((argb >> 24) & 0xff); } + + Color(const Vector4 &v) + { *this = v; } + Color(uint rgba32) + { FromInteger(rgba32); } + + Color(float r, float g, float b, float a = 1) : Vector4(r, g, b, a) {} + Color() {} +}; + +} // GS + + +#endif // __NCOLOR__ + diff --git a/include/framework/data/nvariant.h b/include/framework/data/nvariant.h new file mode 100644 index 0000000..7157889 --- /dev/null +++ b/include/framework/data/nvariant.h @@ -0,0 +1,136 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NVARIANT__ +#define __NVARIANT__ + + + #include "nstring/nstring.h" + + +namespace GS { + +/*! + @short Base property. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Variant +{ +public: + +enum Type +{ + VariantNone = 0, + VariantFloat, + VariantBool, + VariantInteger, + VariantString, + VariantBinary +}; + +protected: + + void Reset(); + +public: + +/*! + @name Property value. + @{ +*/ + Type type; + + union + { + char *d_value; + bool b_value; + float f_value; + int i_value; + uint u_value; + }; + + size_t d_size; /// Binary data size. + String s_value; +/// @} + + String id; ///< Variant id. + + bool operator < (const Variant &b) const; + bool operator > (const Variant &b) const; + bool operator == (const Variant &b) const; + bool operator != (const Variant &b) const; + + Variant &operator = (bool v); + Variant &operator = (int v); + Variant &operator = (uint v); + Variant &operator = (const char *v); + Variant &operator = (float v); + + Variant &operator = (const Variant &v); + + /// Get property type. + Type GetType() const { return type; } + /// Free current property value. + void Free(); + + /// Get string value. + bool Get(const char * &v) const; + /// Get bool value. + bool Get(bool &v) const; + /// Get integer value. + bool Get(int &v) const; + /// Get unsigned value. + bool Get(uint &v) const; + /// Get float value. + bool Get(float &v) const; + + /// Set binary data. + bool SetBinary(const void *data, size_t size); + /// Get binary data. + bool GetBinary(void *&data, size_t &size) const; + + /// Direct access to the binary buffer. + void *GetBinaryBuffer() const { return GetType() == VariantBinary ? (void *)d_value : 0; } + /// Binary buffer size. + size_t GetBinarySize() const { return GetType() == VariantBinary ? d_size : 0; } + + /// Get children array. + bool Get(List &a); + + Variant(const char *v) + { Reset(); *this = v; } + Variant(bool v) + { Reset(); *this = v; } + Variant(int v) + { Reset(); *this = v; } + Variant(uint v) + { Reset(); *this = v; } + Variant(float v) + { Reset(); *this = v; } + Variant(void *d, size_t l) + { Reset(); SetBinary(d, l); } + + Variant(const char *i, const char *v) + { Reset(); id = i; *this = v; } + Variant(const char *i, bool v) + { Reset(); id = i; *this = v; } + Variant(const char *i, int v) + { Reset(); id = i; *this = v; } + Variant(const char *i, uint v) + { Reset(); id = i; *this = v; } + Variant(const char *i, float v) + { Reset(); id = i; *this = v; } + + Variant() + { Reset(); } + ~Variant(); +}; + +} + + +#endif // __NVARIANT__ + diff --git a/include/framework/data/registry.h b/include/framework/data/registry.h new file mode 100644 index 0000000..7988ee6 --- /dev/null +++ b/include/framework/data/registry.h @@ -0,0 +1,65 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NREGISTRY__ +#define __NREGISTRY__ + + + #include "metafile/nml.h" + #include "messaging/messaging.h" + + +namespace GS { + +enum RegistryMessage +{ + RegistryMsg_None = 0, ///< No message. + RegistryMsg_StartKeyChangeBatch, + RegistryMsg_KeyChange, + RegistryMsg_EndKeyChangeBatch +}; + +enum RegistryRValue +{ + RegistryReturn_Ok = 0 +}; + +// +struct RegistryKeyChange +{ + String key; + RegistryKeyChange(const char *k) { key = String(k).TrimChar(';'); } +}; + +struct Registry; + +/// Registry listener. +struct RegistryListener +{ +virtual RegistryRValue ProcessMessage(RegistryMessage message, const Registry *from, const void *parm) = 0; +virtual ~RegistryListener() {} +}; + +/* + @short Registry. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Registry : public Messaging::Broadcaster , public NML::File +{ + NML::Tag *CreateKey(const char *path, const Variant *value = 0, bool recursive = true); + NML::Tag *CreateKey(const char *path, const Variant &value, bool recursive = true); + bool DeleteKey(const char *path); + + /// Get the float value of a given key. + float GetReal(const char *path, float default_value = 0) const; + /// Get the boolean value of a given key. + bool GetBool(const char *path, bool default_value = false) const; +}; + +} // GS + + +#endif // __NREGISTRY__ diff --git a/include/framework/font/font_cache.h b/include/framework/font/font_cache.h new file mode 100644 index 0000000..f914274 --- /dev/null +++ b/include/framework/font/font_cache.h @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __FONTCACHE__ +#define __FONTCACHE__ + + + #include "font/font_factory.h" + #include "font/font_extended.h" + #include "memory/nauto_ptr.h" + #include "memory/nweak_ptr.h" + #include "container/nlist.h" + + +namespace GS { + +/// Extended font alias. +struct FontAlias +{ + String alias; + sFontEx font; +}; + +/* + @short Font cache. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class FontCache : public SharedObject +{ + AutoList font_aliases; + AutoPtr font_factory; + +public: + + FontEx *GetFont(const char *) const; + FontAlias *GetAlias(const char *) const; + FontEx *GetAliasedFont(const char *) const; + + FontEx *LoadFont(const char *, const char *alias = 0); + + void DeleteAlias(const char *); + void DeleteAllFont(); + + FontCache(IFontFactory *factory) : font_factory(factory) {} + ~FontCache(); +}; + +typedef SharedPtr sFontCache; + +} // GS + + +#endif // __FONTCACHE__ diff --git a/include/framework/font/font_extended.h b/include/framework/font/font_extended.h new file mode 100644 index 0000000..9e15052 --- /dev/null +++ b/include/framework/font/font_extended.h @@ -0,0 +1,70 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __FONTEXTENDED__ +#define __FONTEXTENDED__ + + + #include "font/font_interface.h" + #include "memory/nauto_ptr.h" + #include "memory/nweak_ptr.h" + + +namespace GS { + +/*! + @short Extended font to help normalization. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class FontEx : public IFont +{ + sIFont font; + WeakPtr current_glyph_font; + + int pixel_size; + +public: + + WeakPtr fallback; ///< Fall-back font when a glyph is not found in the current font. + + float size_multiplier, ///< Offsets to ease TTF normalization. + tracking_offset, + leading_offset; + + /// Return the font name. + const char *GetName() const { return font->GetName(); } + /// Return the bounding rect for a given string. + iRect GetTextBoundRect(const char *text) const { return font->GetTextBoundRect(text); } + + /// Set font size in pixels. + bool SetPixelSize(int); + /// Get font height in pixels. + int GetHeight() const; + /// Get font current glyph advance. + int GetAdvance() const; + + /// Return true if the font supports kerning. + bool HasKerning() const; + /// Return the kerning for a glyph pair. + int GetKerning(uint previous_glyph, uint glyph) const; + + /// Load the glyph corresponding to a UTF-32 codepoint. + bool LoadGlyph(uint codepoint, bool for_render); + /// Render currently loaded glyph to a picture. + bool RenderCurrentGlyph(Picture &picture, const iPoint &position, const iRect &clip, const Color &color); + + /// Set a fallback font to query in case a glyph cannot be found in this font. + void SetFallback(IFont *f) { fallback = f; } + + FontEx(IFont *f) : font(f), size_multiplier(1), tracking_offset(1), leading_offset(1) {} +}; + +typedef SharedPtr sFontEx; + +} // GS + + +#endif // __FONTEXTENDED__ diff --git a/include/framework/font/font_factory.h b/include/framework/font/font_factory.h new file mode 100644 index 0000000..e4ed836 --- /dev/null +++ b/include/framework/font/font_factory.h @@ -0,0 +1,26 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __FONTFACTORY__ +#define __FONTFACTORY__ + + +namespace GS { + struct IFont; + +/// Font factory. +struct IFontFactory +{ + /// Load a font. +virtual IFont *LoadFont(const char *) = 0; + +virtual ~IFontFactory() {} +}; + +} // GS + + +#endif // __FONTFACTORY__ diff --git a/include/framework/font/font_interface.h b/include/framework/font/font_interface.h new file mode 100644 index 0000000..601cec4 --- /dev/null +++ b/include/framework/font/font_interface.h @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __FONTINTERFACE__ +#define __FONTINTERFACE__ + + + #include "color/color.h" + #include "geometry/rect.h" + #include "memory/nshared_ptr.h" + #include "nstring/nstring.h" + + +namespace GS { + class Picture; + +/*! + @short Font interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct IFont : public SharedObject +{ + /// Return the font name. +virtual const char *GetName() const = 0; + + /// Return the bounding rect for a given string. +virtual iRect GetTextBoundRect(const char *) const = 0; + + /// Set font size in pixels. +virtual bool SetPixelSize(int) = 0; + /// Get font height in pixels. +virtual int GetHeight() const = 0; + /// Get font current glyph advance. +virtual int GetAdvance() const = 0; + + /// Return true if the font supports kerning. +virtual bool HasKerning() const = 0; + /// Return the kerning for a glyph codepoint. +virtual int GetKerning(uint previous_codepoint, uint codepoint) const = 0; + + /// Load the glyph corresponding to a UTF-32 codepoint. +virtual bool LoadGlyph(uint codepoint, bool for_render) = 0; + /// Render currently loaded glyph to a picture. +virtual bool RenderCurrentGlyph(Picture &picture, const iPoint &position, const iRect &clip, const Color &color = Color::White) = 0; + + /// Set a fallback font to query in case a glyph cannot be found in this font. +virtual void SetFallback(IFont *) {} + +virtual ~IFont() {} +}; + +typedef SharedPtr sIFont; + +} // GS + + +#endif // __FONTINTERFACE__ diff --git a/include/framework/font/font_renderer.h b/include/framework/font/font_renderer.h new file mode 100644 index 0000000..b8ec6d5 --- /dev/null +++ b/include/framework/font/font_renderer.h @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __FONTRENDERER__ +#define __FONTRENDERER__ + + + #include "font/font_extended.h" + #include "font/font_cache.h" + #include "math/vector.h" + + +namespace GS { + class Picture; + struct SubString; + +/// Text widget state structure. +class TextState +{ + int size; + float tracking, ///< Text tracking (horizontal offset between two characters). + leading; ///< Text heading (vertical offset between lines). + +public: + +enum Format +{ + Line = 0, + Paragraph, + Column +}; + +enum Alignment +{ + Left = 0, + Right, + Center, + Justify +}; + + sFontEx font; + Color color; + + Format format; ///< Text format. + Alignment alignment; ///< Text alignment. + int column_width; ///< Text column width. + + int GetSize() const { return font.IsValid() ? (int)(size * font->size_multiplier) : size; } + float GetTracking() const { return font.IsValid() ? tracking + font->tracking_offset : tracking; } + float GetLeading() const { return font.IsValid() ? leading + font->leading_offset : leading; } + + void SetSize(int s) { size = s; } + void SetTracking(float t) { tracking = t; } + void SetLeading(float l) { leading = l; } + + TextState() + { + size = 16; + color = Color::Black; + + format = Line; + alignment = Left; + + column_width = 80; + tracking = 0; + leading = 0; + } +}; + +/* + @short Font renderer. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class FontRenderer +{ +public: + +enum CommandCode +{ + CommandNone = 0, + CommandColor, + CommandFont, + CommandSize, + + CommandParseError +}; + +static float default_text_tracking; +static float default_text_heading; + +/// Renderer command. +struct Command +{ + CommandCode code; + Vector4 vector; + sIFont font; +}; + +protected: + + /// Check current string for a command. +static const char *CheckCommand(const char *string, Command &command); + /// Get the next sub-string from the current text buffer. +static const char *FetchSubString(const char *string, SubString &sstr, TextState &state, int max_width, int max_character); + /// Draw a substring to a picture. +static void DrawSubString(SubString &sub_string, Picture &output, TextState &state, const iRect &out_rect, const iRect &clip_rect, int justification); + +public: + + /// Format a string using a text state, return the required output rectangle. +static iRect Format(const char *text, const TextState &in_state, const iRect &out_rect); + /// Compose a string using a text state. +static iRect Compose(Picture &output, const char *text, const TextState &state, const iRect &out_rect, const iRect &clip_rect); +}; + +} // GS + + +#endif // __FONTRENDERER__ diff --git a/include/framework/geometry/bounding_box.h b/include/framework/geometry/bounding_box.h new file mode 100644 index 0000000..585717c --- /dev/null +++ b/include/framework/geometry/bounding_box.h @@ -0,0 +1,184 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NBOUNDINGBOX__ +#define __NBOUNDINGBOX__ + + + #include "math/matrix3.h" + + +namespace GS { + +/*! + @short AABB. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class MinMax +{ +protected: + +enum +{ + ClipNone = 0, + ClipRight = 1, + ClipLeft = 2, + ClipTop = 4, + ClipBottom = 8, + ClipFront = 16, + ClipBack = 32 +}; + + /// Internal use. + uint cc_oc(const Vector4 &min, const Vector4 &max, const Vector4 &p) const + { + uint oc = ClipNone; + if (p.x > max.x) oc |= ClipRight; + else if (p.x < min.x) oc |= ClipLeft; + if (p.y > max.y) oc |= ClipTop; + else if (p.y < min.y) oc |= ClipBottom; + if (p.z > max.z) oc |= ClipBack; + else if (p.z < min.z) oc |= ClipFront; + return oc; + } + + /// Internal use. + uint ss_oc(const Vector4 &p) const + { + uint oc = ClipNone; + oc |= p.x > 0 ? ClipRight : ClipLeft; + oc |= p.y > 0 ? ClipTop : ClipBottom; + oc |= p.z > 0 ? ClipBack : ClipFront; + return oc; + } + +public: + + Vector4 mn, mx; + + /// Return the start of the interval on a given axis. + float GetMin(uint axis) const + { return mn[axis]; } + /// Return the end of the interval on a given axis. + float GetMax(uint axis) const + { return mx[axis]; } + /// Return whether the MinMax object overlap with another one. + bool TestAxisOverlap(const MinMax &b, uint axis) const + { return (b.mn[axis] > mx[axis]) || (b.mx[axis] < mn[axis]) ? false : true; } + + /// Intersect ray with this minmax. + bool IntersectRay(const Vector4 &o, const Vector4 &d, float &tmin, float &tmax); + + /// Returns whether a line intersect with the MinMax. + bool ClassifyLine(const Vector4 &p, const Vector4 &d, Vector4 &i, Vector4 *n = 0) const; + /// Returns whether a segment intersect with the MinMax. + bool ClassifySegment(const Vector4 &p0, const Vector4 &p1, Vector4 &i, Vector4 *n = 0) const; + + /// Return whether two MinMax overlap at a given time. + bool TestOverlap(const MinMax &b) const + { + if (mx.x < b.mn.x) return false; + if (mx.y < b.mn.y) return false; + if (mx.z < b.mn.z) return false; + if (b.mx.x < mn.x) return false; + if (b.mx.y < mn.y) return false; + if (b.mx.z < mn.z) return false; + return true; + } + + /// Test position. +inline bool IsInside(const Vector4 &p) const + { return (p.x < mn.x) || (p.y < mn.y) || (p.z < mn.z) || (p.x > mx.x) || (p.y > mx.y) || (p.z > mx.z) ? false : true; } + + /// Grow the min~max boundaries to include another min~max structure. + void Grow(const MinMax &b) + { + mn = Vector4::Minimum(b.mn, mn); + mx = Vector4::Maximum(b.mx, mx); + } + + /// Grow the min~max boundaries to include a vector. + void Grow(const Vector4 &p) + { + mn = Vector4::Minimum(p, mn); + mx = Vector4::Maximum(p, mx); + } + + /// Get the min-max area. + float GetArea() const + { return (mx.x - mn.x) * (mx.y - mn.y) * (mx.z - mn.z); } + /// Get the min-max center. + Vector4 GetCenter() const + { return (mn + mx) * 0.5f; } + + /// Set min-max. + void Set(const Vector4 &min, const Vector4 &max) + { mn = min; mx = max; } + /// Set from position and size. + void SetFromPositionSize(const Vector4 &p, const Vector4 &s) + { + mn = p - s * 0.5f; + mx = p + s * 0.5f; + } + + void Reset() + { mn.Set(); mx.Set(); } + +/*! + @name Serialization + @{ +*/ + bool FromMetaTag(NML::Tag &tag); + NML::Tag *AsMetaTag(); +/// @} + + MinMax() : mn(0, 0, 0), mx(0, 0, 0) {} + MinMax(const Vector4 &min, const Vector4 &max) : mn(min), mx(max) {} +}; + +/*! + @short Oriented bounding box. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct OBB +{ + Vector4 bb_position; + Vector4 bb_scale; + Matrix3 bb_rotation; + + /// Compute the min/max of the OBB. + void ComputeMinMax(MinMax &minmax); + + /*! + @short Transform OBB. + @warning Scaling is not supported. + */ + void Transform(const Matrix4 &mtx); + + /// OBB from min~max. +static OBB FromMinMax(const MinMax &minmax) + { return OBB((minmax.mn + minmax.mx) * 0.5f, minmax.mx - minmax.mn); } + + bool FromMetaTag(NML::Tag &tag); + NML::Tag *AsMetaTag(); + + OBB(const MinMax &minmax) + { *this = FromMinMax(minmax); } + OBB(const Vector4 &p, const Vector4 &s, const Matrix3 *m = 0) + { + bb_position = p; + bb_scale = s; + if (m) + bb_rotation = *m; + } + OBB() {} +}; + +} // GS + + +#endif // __NBOUNDINGBOX__ + diff --git a/include/framework/geometry/curve.h b/include/framework/geometry/curve.h new file mode 100644 index 0000000..9411c94 --- /dev/null +++ b/include/framework/geometry/curve.h @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCURVE__ +#define __NCURVE__ + + + #include "math/nmath.h" + #include "metafile/nml.h" + #include "reflection/nenum_string.h" + #include "container/narray_list.h" + #include "time/ntime_range.h" + #include "time/ntime.h" + + +namespace GS { + +static const float DefaultCurveOptimizationThreshold = 0.05f; + +/* + @short Curve control point. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct CurvePoint +{ + NPLACEMENT_NEW(Curve) + +/// Curve control point shape. +enum Shape +{ + Shape_None = 0, + Shape_Linear, + Shape_TCB, + Shape_Hermite, + Shape_Bezier, + Shape_Bezier2, + Shape_Step +}; + + Shape shape; + + Time t; + float v, + tension, continuity, bias, + param[4]; //< TCB parameters. + + CurvePoint(const Time &time, float value, Shape shp = Shape_Linear) : t(time), v(value), shape(shp) + { + tension = 0; + continuity = 0; + bias = 0; + + param[0] = param[1] = param[2] = param[3] = 0; + } + CurvePoint() : t(0), v(0), shape(Shape_Linear) + { + tension = 0; + continuity = 0; + bias = 0; + + param[0] = param[1] = param[2] = param[3] = 0; + } +}; + +/*! + @short Curve object. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Curve +{ +public: + + NPLACEMENT_NEW(Curve) + +enum LoopMode +{ + Reset = 0, ///< Returns 0. + Constant, ///< Returns first/last knot value. + Repeat, ///< Warp evaluation time to a value inside curve range and evaluate. + Oscillate, ///< Ping-pong style evaluation. + OffsetAndRepeat ///< Same as repeat but the whole curve is offset with the last knot value. +}; + +static Reflection::Enum::Dict loop_mode_dict[]; + +protected: + + ArrayList points; ///< Curve knots. + + uint Optimize(uint point_count, const CurvePoint *src, CurvePoint *dst, float threshold); + +public: + + /// Evaluate curve at a given time. + void Evaluate(Time t, float *value, LoopMode loop_mode = Constant, Time loop_start = Time::Inf, Time loop_end = Time::Inf) const; + + /// Evaluate incoming tangent to the curve. + float Incoming(const CurvePoint *kf0, const CurvePoint *kf1, const CurvePoint *kf2) const; + /// Evaluate outgoing tangent to the curve. + float Outgoing(const CurvePoint *kf0, const CurvePoint *kf1, const CurvePoint *kfp) const; + + /*! + @short Update a control point. + @note The time epsilon is considered on both side of the control + points time. If no point to update is found a new point is + inserted. + */ + void Update(const CurvePoint &, const Time &t_epsilon); + /// Insert a control point. + void Insert(const CurvePoint &); + /// Append a control point to the control point list. + void Append(const CurvePoint &); + + /// Delete a curve control point from the channel. + void Delete(CurvePoint *); + + /// Get curve time range, very fast. + TimeRange GetTimeRange() const; + /// Get curve value range, requires a full parsing of the knot list. + Range GetValueRange() const; + + /// Get curve range length in time. + Time GetDuration() const { return GetTimeRange().valueRange(); } + + /// Optimize curve removing the less influential knots. + uint Optimize(float threshold = DefaultCurveOptimizationThreshold); + + /// Return the curve control points as an array. + ArrayList &GetPoints() { return points; } + /// Return the number of control point in curve. + uint GetPointCount() const { return points.GetCount(); } + + /// Sort curve point array by time. + void Sort(); + /*! + @short Set a control point content. + + @Note This function does modify the internal ordering of the curve + keys in order to keep them time ordered. + Please use the Sort() function to make sure the curve can + still be correctly evaluated after a key time modification. + */ + void SetPoint(uint index, const CurvePoint &content) const; + + /// Allocate a set of control points. + bool AllocatePoint(uint n); + + /*! + @short Return the closest point on curve to a given time position. + The default behavior is to return the first point whose time is + greater than the query time. + */ + int GetPointIndex(const Time &time, bool t_greater_than = true) const; + + void Clear(); + +virtual size_t MemoryFootPrint() const { return size_t(points.GetCount()) * sizeof(CurvePoint) + sizeof(Curve); } + + bool FromMetaTag(NML::Tag &); + NML::Tag *AsMetaTag() const; + +virtual ~Curve(); +}; + +} // GS + + +#endif // __NCURVE__ diff --git a/include/framework/geometry/frustum.h b/include/framework/geometry/frustum.h new file mode 100644 index 0000000..7f42af8 --- /dev/null +++ b/include/framework/geometry/frustum.h @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NFRUSTRUM__ +#define __NFRUSTRUM__ + + + #include "geometry/plane.h" + + +class nMatrix4; + +namespace GS { + + struct Shape; + class MinMax; + +/*! + @short Frustum. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Frustum +{ +public: + +enum Visibility +{ + Outside = 0, + Inside, + Clipped +}; + +enum VolumePlane +{ + Top = 0, + Bottom, + Left, + Right, + Near, + Far +}; + +protected: + + Vector4 vtx[8]; ///< Frustum vertices. + Plane plane[6]; ///< Frustum planes. + +public: + +inline const Vector4 *GetVertices() const { return vtx; } + + /// Compute perspective frustum volume planes. + void SetPerspective(float fov, float near, float far, const Matrix4 *m = 0, float h_ar = 1, float v_ar = 1); + /// Compute orthographic frustum volume planes. + void SetOrthographic(float width, float height, float near, float far, const Matrix4 *m = 0, float h_ar = 1, float v_ar = 1); + + /// Return the visibility flag of a vector set against this frustum. + Visibility ClassifySet(uint count, const Vector4 * const GSRESTRICT set, const float offset = 0) const; + /// Return the visibility flag of a frustum against this frustum. + Visibility ClassifyFrustrum(const Frustum &frustum) const; + /// Return the visibility flag of a sphere against this frustum. + Visibility ClassifySphere(const Vector4 &p, float r) const; + /// Return the visibility flag of a minmax against this frustum. + Visibility ClassifyMinMax(const MinMax &mm, const Matrix4 *m = 0) const; + + /// Return the visibility flag of a shape against this frustum. + Visibility ClassifyShape(const Shape &s, const Matrix4 *m = 0) const; +}; + +} // GS + + +#endif // __NFRUSTRUM__ diff --git a/include/framework/geometry/geometric_tools.h b/include/framework/geometry/geometric_tools.h new file mode 100644 index 0000000..2fc22a3 --- /dev/null +++ b/include/framework/geometry/geometric_tools.h @@ -0,0 +1,103 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOMETRICTOOLS__ +#define __NGEOMETRICTOOLS__ + + + #include "math/vector.h" + + +namespace GS { + namespace Geometric { + +/// Compute 2d triangle area. +float TriArea2D(float x0, float y0, float x1, float y1, float x2, float y2); + +/*! + @short Test intersection between a ray and a plane. + + @param a Origin of the ray. + @param v Direction of the ray. + @param n Normal of the plane. + @param p A point on the plane. + + @param t Output, the parametric 't' value of the point of + intersection. + + @return False if the ray is embedded in or coplanar to the plane. + True otherwise. +*/ +bool LineIntersectPlane(const Vector4 &a, const Vector4 &v, const Vector4 &n, const Vector4 &p, float &t); + +/*! + @short Compute barycentric coordinates. +*/ +void Barycentric(const Vector4 &a, const Vector4 &b, const Vector4 &c, const Vector4 &p, float &u, float &v, float &w); + +/*! + @short Test intersection between a ray and a plane. + + @param a Origin of the ray. + @param v Normalized direction of the ray. + @param c Center of the sphere. + @param r Radius of the sphere. + + @param t Output, the parametric 't' value of the points of + intersection. t[0] is the closest point of + intersection to the origin of the ray. + + @return False if no intersection. +*/ +bool LineIntersectSphere(const Vector4 &a, const Vector4 &v, const Vector4 &c, float r, float t[2]); + +/*! + @short Determine the closest points between two lines. + + @param a First point on first line. + @param b Second point on first line. + @param u First point on second line. + @param v Second point on second line. + + @param t Output, the parametric 't' values of the closest + points on each line. t[0] belongs to (a;b), t[1] + belongs to (u;v). + + @return False if both lines are parallel. +*/ +bool LineClosestPointToLine(const Vector4 &a, const Vector4 &b, const Vector4 &u, const Vector4 &v, float t[2]); + + +/*! + @short Determine the closest point to a line from a position in space. + + @param a First point on line. + @param b Second point on line. + @param u Location. + @param i Output the closest point on line to u. + + @return t Parametric position of i on the [a;b] segment. + If t < 0 or t > 1 then i lies outside the [a;b] segment. +*/ +float LineClosestPoint(const Vector4 &a, const Vector4 &b, const Vector4 &u, Vector4 *p = 0); + +/*! + @short Determine the closest point to a segment from a position in space. + + @param a First point on segment. + @param b Second point on segment. + @param u Location. + @param i Output the closest point on segment to u. + + @return t Parametric position of i on the [a;b] segment. +*/ +float SegmentClosestPoint(const Vector4 &a, const Vector4 &b, const Vector4 &u, Vector4 *p = 0); + + } // Geometric +} // GS + + +#endif // __NGEOMETRICTOOLS__ diff --git a/include/framework/geometry/plane.h b/include/framework/geometry/plane.h new file mode 100644 index 0000000..ae08767 --- /dev/null +++ b/include/framework/geometry/plane.h @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPLANE__ +#define __NPLANE__ + + + #include "math/vector.h" + + +namespace GS { + +/*! + @short Plane. + ax + by + cz + d = 0 + @author Emmanuel Julien (ejulien@nworks.fr) +*/ + +class Plane +{ + float d; ///< Distance to origin. + Vector4 p, n; ///< Point in plane and normal. + +public: + + /// Return plane normal. +inline const Vector4 &GetNormal() const + { return n; } + + /*! + @short Return point distance to plane. + + Distance is signed, positive when the point is in front of the plane, + negative otherwise. + */ +inline float DistanceToPlane(const Vector4 &p) const + { return p.Dot(n) + d; } + + /// Set plane from point/normal and an optional transformation matrix. + void Set(const Vector4 *_p, const Vector4 &_n, const Matrix4 * = 0); + /// Set plane three vectors and an optional transformation matrix. + void Set(const Vector4 _p[3], const Matrix4 * = 0); + + Plane(); + Plane(const Vector4 &_p, const Vector4 &_n, const Matrix4 *_m = 0) + { Set(&_p, _n, _m); } +}; + +} // GS + + +#endif // __NPLANE__ diff --git a/include/framework/geometry/rect.h b/include/framework/geometry/rect.h new file mode 100644 index 0000000..2506b3c --- /dev/null +++ b/include/framework/geometry/rect.h @@ -0,0 +1,112 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRECT__ +#define __NRECT__ + + + #include "ntypes.h" + + +namespace GS { + namespace NML { + class File; + class Tag; + } + +/*! + @short Point. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +template struct Point +{ + T x, y; + + T operator [] (size_t n) const { return *(&x + n); } + + void Set(T _x, T _y) + { x = _x; y = _y; } + + Point(T ux, T uy) : x(ux), y(uy) {} + Point() : x(0), y(0) {} +}; + +typedef Point iPoint; +typedef Point fPoint; + +/*! + @short Rectangle. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +template struct Rect +{ + T sx, sy, ex, ey; + + void SetWidth(T w) { ex = sx + w; } + void SetHeight(T h) { ey = sy + h; } + T GetWidth() const { return ex - sx; } + T GetHeight() const { return ey - sy; } + + Rect operator * (T v) const + { return Rect (sx * v, sy * v, ex * v, ey * v); } + Rect operator / (T v) const + { return Rect (sx / v, sy / v, ex / v, ey / v); } + + bool Inside(T x, T y) const + { return (x > sx) && (y > sy) && (x < ex) && (y < ey); } + + bool FitsInside(const Rect &b) const + { return (GetWidth() <= b.GetWidth()) && (GetHeight() <= b.GetHeight()); } + + bool Intersect(const Rect &b) const + { return ((ex < b.sx) || (ey < b.sy) || (sx > b.ex) || (sy > b.ey)) ? false : true; } + + Rect Intersection(const Rect &b) const + { + T _sx = Types::Max(sx, b.sx), _sy = Types::Max(sy, b.sy), + _ex = Types::Min(ex, b.ex), _ey = Types::Min(ey, b.ey); + + T n_sx = Types::Min(_sx, _ex), n_sy = Types::Min(_sy, _ey), + n_ex = Types::Max(_sx, _ex), n_ey = Types::Max(_sy, _ey); + + return Rect (_sx = n_sx, _sy = n_sy, _ex = n_ex, _ey = n_ey); + } + + Rect Grow(T border) const + { return Rect (sx - border, sy - border, ex + border, ey + border); } + + void Set(T usx, T usy, T uex, T uey) + { sx = usx; sy = usy; ex = uex; ey = uey; } + void Set(T ux = 0, T uy = 0) + { sx = ux; sy = uy; ex = ux; ey = uy; } + + Rect Offset(T x, T y) const + { return Rect (sx + x, sy + y, ex + x, ey + y); } + + Rect AsFloat() const + { return Rect (float(sx), float(sy), float(ex), float(ey)); } + Rect AsInt() const + { return Rect (int(sx), int(sy), int(ex), int(ey)); } + + NML::Tag *AsMetaTag(const char *id) const; + bool FromMetaTag(NML::Tag &); + +static Rect FromWidthHeight(T sx, T sy, T w, T h) + { return Rect (sx, sy, sx + w, sy + h); } + + Rect(const Rect &b) : sx(b.sx), sy(b.sy), ex(b.ex), ey(b.ey) {} + Rect(T usx, T usy, T uex, T uey) : sx(usx), sy(usy), ex(uex), ey(uey) {} + Rect(T usx, T usy) : sx(usx), ex(usx), sy(usy), ey(usy) {} + Rect() : sx(0), sy(0), ex(0), ey(0) {} +}; + +typedef Rect iRect; +typedef Rect fRect; + +} // GS + + +#endif // __NRECT__ diff --git a/include/framework/geometry/sat.h b/include/framework/geometry/sat.h new file mode 100644 index 0000000..65751ed --- /dev/null +++ b/include/framework/geometry/sat.h @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSAT__ +#define __NSAT__ + + + #include + + +namespace GS { + namespace SAT { + +/// SAT overlap test results. +enum Overlap +{ + Outside = 0, + Inside, // B inside A + Clipped +}; + +/// Helper function to test overlap on a given axis. +Overlap TestOverlap(const Vector4 &axis, int ca, const Vector4 *a, int cb, const Vector4 *b) +{ + // A interval. + float a_mn = FLT_MAX, a_mx = -FLT_MAX; + for (int n = 0; n < ca; ++n) + { + float d = axis.Dot(a[n]); + if (d < a_mn) a_mn = d; + if (d > a_mx) a_mx = d; + } + + // B interval. + float b_mn = FLT_MAX, b_mx = -FLT_MAX; + for (int n = 0; n < cb; ++n) + { + float d = axis.Dot(b[n]); + if (d < b_mn) b_mn = d; + if (d > b_mx) b_mx = d; + } + + // Test overlap. + if ((a_mx < b_mn) || (a_mn > b_mx)) + return Outside; + if ((b_mn > a_mn) && (b_mx < a_mx)) + return Inside; + + return Clipped; +} + + } // SAT +} // GS + + +#endif // __NSAT__ diff --git a/include/framework/math/matrix3.h b/include/framework/math/matrix3.h new file mode 100644 index 0000000..f4cccca --- /dev/null +++ b/include/framework/math/matrix3.h @@ -0,0 +1,225 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMATRIX3__ +#define __NMATRIX3__ + + + #include "math/vector.h" + + +namespace GS { + struct Quaternion; + class Matrix4; + +/*! + @short 3x3 Matrix. + This matrix class is column major. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Matrix3 +{ +static Matrix3 static_identity; + +public: + + NPLACEMENT_NEW(Matrix) + + /// The matrix values. + float m[3][3]; + + bool operator == (const Matrix3 &b) const + { + for (uint i = 0; i < 3; i++) + for (uint j = 0; j < 3; j++) + if (!Math::TestEqual(m[i][j], b.m[i][j])) + return false; + return true; + } + + bool operator != (const Matrix3 &b) const + { + for (uint i = 0; i < 3; i++) + for (uint j = 0; j < 3; j++) + if (!Math::TestEqual(m[i][j], b.m[i][j])) + return true; + return false; + } + + Matrix3 operator + (const Matrix3 &b) const + { + Matrix3 r; + for (uint j = 0; j < 3; j++) + for (uint i = 0; i < 3; i++) + r.m[i][j] = m[i][j] + b.m[i][j]; + return r; + } + + void operator += (const Matrix3 &b) + { *this = *this + b; } + + void operator *= (const float k) + { + for (uint j = 0; j < 3; j++) + for (uint i = 0; i < 3; i++) + m[i][j] *= k; + } + void operator /= (const float k) + { + for (uint j = 0; j < 3; j++) + for (uint i = 0; i < 3; i++) + m[i][j] /= k; + } + + Matrix3 operator - (const Matrix3 &b) const + { + Matrix3 r; + for (uint j = 0; j < 3; j++) + for (uint i = 0; i < 3; i++) + r.m[i][j] = m[i][j] - b.m[i][j]; + return r; + } + void operator -= (const Matrix3 &b) + { *this = *this - b; } + + Vector4 operator * (const Vector4 &v) const + { + Vector4 o; + o.x = v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2]; + o.y = v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2]; + o.z = v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2]; + o.w = 1; + return o; + } + Matrix3 operator * (const Matrix3 &b) const + { + #define __M33M33(__I, __J) m[__I][0] * b.m[0][__J] + m[__I][1] * b.m[1][__J] + m[__I][2] * b.m[2][__J] + return Matrix3 ( + __M33M33(0, 0), __M33M33(1, 0), __M33M33(2, 0), + __M33M33(0, 1), __M33M33(1, 1), __M33M33(2, 1), + __M33M33(0, 2), __M33M33(1, 2), __M33M33(2, 2) + ); + } + Matrix3 operator * (const float v) const + { + Matrix3 r; + for (uint j = 0; j < 3; j++) + for (uint i = 0; i < 3; i++) + r.m[i][j] = m[i][j] * v; + return r; + } + void operator *= (const Matrix3 &b) + { *this = (*this) * b; } + Matrix3 operator / (const float v) const + { + Matrix3 r; + for (uint j = 0; j < 3; j++) + for (uint i = 0; i < 3; i++) + r.m[i][j] = m[i][j] / v; + return r; + } + + /// Apply to a set of vector objects. + void Apply(Vector4 *o, const Vector4 *v, uint n = 1) const; + + /// Compute the determinant of the matrix. + float Det() const + { + return ((m[1][1] * m[2][2]) - (m[1][2] * m[2][1])) * m[0][0] + + ((m[1][2] * m[2][0]) - (m[1][0] * m[2][2])) * m[0][1] + + ((m[1][0] * m[2][1]) - (m[1][1] * m[2][0])) * m[0][2]; + } + + /// Compute inverse matrix. + bool Inverse(Matrix3 &i) const; + + /// Return the transposed matrix. +inline Matrix3 Transposed() const + { + return Matrix3 + ( + m[0][0], m[0][1], m[0][2], + m[1][0], m[1][1], m[1][2], + m[2][0], m[2][1], m[2][2] + ); + } + + /// Return the nth row. +inline Vector4 GetRow(uint n) const { return Vector4(m[0][n], m[1][n], m[2][n]); } + /// Return the nth column. +inline Vector4 GetColumn(uint n) const { return Vector4(m[n][0], m[n][1], m[n][2]); } + /// Set the nth row. + void SetRow(uint n, const Vector4 &row); + /// Set the nth column. + void SetColumn(uint n, const Vector4 &col); + + /// Set matrix values. + void Set ( + float m00, float m10, float m20, + float m01, float m11, float m21, + float m02, float m12, float m22 + ); + /// Set matrix values. + void Set(const Vector4 &u, const Vector4 &v, const Vector4 &w); + + /// Return this matrix after normalization. + Matrix3 Normalized() const; + /// Normalize as orthonormal base. + Matrix3 AsOrthonormalBase() const; + /// Return an Euler orientation equivalent to this matrix. + Vector4 AsEuler(Math::rOrder rorder = Math::rOrder_Default) const; + + /// Vector matrix. +static Matrix3 VectorMatrix(const Vector4 &v); + /// Identity matrix. +static Matrix3 &IdentityMatrix() { return static_identity; } + /// Translation matrix. +static Matrix3 TranslationMatrix(const Vector2 &t); +static Matrix3 TranslationMatrix(const Vector4 &t); + /// Scale matrix. +static Matrix3 ScaleMatrix(const Vector2 &s); +static Matrix3 ScaleMatrix(const Vector4 &s); + /// Cross product matrix. +static Matrix3 CrossProductMatrix(const Vector4 &v); + + /// Rotation matrix around X axis. +static Matrix3 RotationMatrixXAxis(float a); + /// Rotation matrix around Y axis. +static Matrix3 RotationMatrixYAxis(float a); + /// Rotation matrix around Z axis. +static Matrix3 RotationMatrixZAxis(float a); + /*! + @short From Orthonormal basis. + + Transform an orthogonal basis formed by one or two vectors to a + rotation matrix. + @note Left-handed base, eg: u = {1,0,0}, v = {0,1,0}, w = {0,0,1}. + */ +static Matrix3 FromOrthonormalBasis(const Vector4 &w, const Vector4 *v = 0); + /// From Euler triplet. +static Matrix3 FromEuler(float x = 0, float y = 0, float z = 0, Math::rOrder rorder = Math::rOrder_Default); + /// From Euler vector. +static Matrix3 FromEuler(const Vector4 &euler, Math::rOrder rorder = Math::rOrder_Default); + /// From matrix4. +static Matrix3 FromMatrix4(const Matrix4 &mtx); + + NML::Tag *AsMetaTag(const char *) const; + bool FromMetaTag(NML::Tag &); + + Matrix3( + float m00 = 1, float m10 = 0, float m20 = 0, + float m01 = 0, float m11 = 1, float m21 = 0, + float m02 = 0, float m12 = 0, float m22 = 1 + ) + { Set(m00, m10, m20, m01, m11, m21, m02, m12, m22); } + Matrix3(const Vector4 &u, const Vector4 &v, const Vector4 &w) + { Set(u, v, w); } +}; + +} // GS + + +#endif // __NMATRIX3__ diff --git a/include/framework/math/matrix4.h b/include/framework/math/matrix4.h new file mode 100644 index 0000000..2ba0e2a --- /dev/null +++ b/include/framework/math/matrix4.h @@ -0,0 +1,239 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMATRIX4__ +#define __NMATRIX4__ + + + #include "math/vector.h" + + +namespace GS { + class Matrix3; + +/*! + @short 4x4 Matrix. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Matrix4 +{ +static Matrix4 static_identity; + +public: + + NPLACEMENT_NEW(Matrix) + + /// The matrix values. + float m[4][4]; + + bool operator == (const Matrix4 &b) const + { + for (uint i = 0; i < 4; i++) + for (uint j = 0; j < 4; j++) + if (!Math::TestEqual(m[i][j], b.m[i][j])) + return false; + return true; + } + + bool operator != (const Matrix4 &b) const + { + for (uint i = 0; i < 4; i++) + for (uint j = 0; j < 4; j++) + if (!Math::TestEqual(m[i][j], b.m[i][j])) + return true; + return false; + } + +inline Matrix4 operator * (const Matrix4 &b) const + { + #define __M44M44(__I, __J) m[__I][0] * b.m[0][__J] + m[__I][1] * b.m[1][__J] + m[__I][2] * b.m[2][__J] + m[__I][3] * b.m[3][__J] + return Matrix4( + __M44M44(0, 0), __M44M44(1, 0), __M44M44(2, 0), __M44M44(3, 0), + __M44M44(0, 1), __M44M44(1, 1), __M44M44(2, 1), __M44M44(3, 1), + __M44M44(0, 2), __M44M44(1, 2), __M44M44(2, 2), __M44M44(3, 2), + __M44M44(0, 3), __M44M44(1, 3), __M44M44(2, 3), __M44M44(3, 3) + ); + } +const Matrix4 operator * (float v) const + { + Matrix4 r; + for (uint j = 0; j < 4; ++j) + for (uint i = 0; i < 4; ++i) + r.m[i][j] = m[i][j] * v; + return r; + } + +const Matrix4 operator + (const Matrix4 &b) const + { + Matrix4 r; + for (uint j = 0; j < 4; j++) + for (uint i = 0; i < 4; i++) + r.m[i][j] = m[i][j] + b.m[i][j]; + return r; + } + + /// Return the nth row. +inline Vector4 GetRow(uint n, bool w_to_one = true) const + { return Vector4(m[0][n], m[1][n], m[2][n], w_to_one ? 1 : m[3][n]); } + /// Return the nth column. +inline Vector4 GetColumn(uint n, bool w_to_one = true) const + { return Vector4(m[n][0], m[n][1], m[n][2], w_to_one ? 1 : m[n][3]); } + /// Set the nth row. +inline void SetRow(uint n, const Vector4 &r, bool w_to_one = true) + { m[0][n] = r.x; m[1][n] = r.y; m[2][n] = r.z; m[3][n] = w_to_one ? 1 : r.w; } + /// Set the nth column. +inline void SetColumn(uint n, const Vector4 &c, bool w_to_one = true) + { m[n][0] = c.x; m[n][1] = c.y; m[n][2] = c.z; m[n][3] = w_to_one ? 1 : c.w; } + + bool Inverse(Matrix4 &out) const; + /*! + @short Return the inverse matrix using a fast approximation. + @warning This function works only for standard 3d transformation + matrices. + */ + Matrix4 InversedFast() const; + /// Transpose matrix. + Matrix4 Transposed() const + { + return Matrix4( + m[0][0], m[0][1], m[0][2], m[0][3], + m[1][0], m[1][1], m[1][2], m[1][3], + m[2][0], m[2][1], m[2][2], m[2][3], + m[3][0], m[3][1], m[3][2], m[3][3] + ); + } + /// Normalize matrix. + Matrix4 AsOrthonormalBase() const; + + /// Interpolate between two 4x4 transformation matrices. +static Matrix4 LerpAsOrthonormalBase(const Matrix4 &a, const Matrix4 &b, float k, bool fast = false); + + /// Decompose a transformation matrix into a position vector, a scale vector and a 3x3 rotation matrix. + void Decompose(Vector4 *position, Vector4 *scale = 0, Matrix3 *rotation = 0) const; + /// Decompose a transformation matrix into a position vector, a scale vector and a rotation vector. + void Decompose(Vector4 *position, Vector4 *scale, Vector4 *rotation, Math::rOrder order = Math::rOrder_Default) const; + + /// Apply to vector array. +inline void Apply(Vector4 *o, const Vector4 *i, uint n = 1) const + { + for (uint c = 0; c < n; c++) + { + o[c].x = i[c].x * m[0][0] + i[c].y * m[0][1] + i[c].z * m[0][2] + i[c].w * m[0][3]; + o[c].y = i[c].x * m[1][0] + i[c].y * m[1][1] + i[c].z * m[1][2] + i[c].w * m[1][3]; + o[c].z = i[c].x * m[2][0] + i[c].y * m[2][1] + i[c].z * m[2][2] + i[c].w * m[2][3]; + o[c].w = i[c].x * m[3][0] + i[c].y * m[3][1] + i[c].z * m[3][2] + i[c].w * m[3][3]; + } + } + /// Apply upper-left 3x3 sub-matrix to vector array. +inline void ApplyRotation(Vector4 *o, const Vector4 *i, uint n = 1) const + { + for (uint c = 0; c < n; c++) + { + o[c].x = i[c].x * m[0][0] + i[c].y * m[0][1] + i[c].z * m[0][2]; + o[c].y = i[c].x * m[1][0] + i[c].y * m[1][1] + i[c].z * m[1][2]; + o[c].z = i[c].x * m[2][0] + i[c].y * m[2][1] + i[c].z * m[2][2]; + o[c].w = 1.f; + } + } + + /// Set values. + void Set ( + float m00, float m10, float m20, float m30, + float m01, float m11, float m21, float m31, + float m02, float m12, float m22, float m32, + float m03, float m13, float m23, float m33 + ) + { + m[0][0] = m00; m[1][0] = m10; m[2][0] = m20; m[3][0] = m30; + m[0][1] = m01; m[1][1] = m11; m[2][1] = m21; m[3][1] = m31; + m[0][2] = m02; m[1][2] = m12; m[2][2] = m22; m[3][2] = m32; + m[0][3] = m03; m[1][3] = m13; m[2][3] = m23; m[3][3] = m33; + } + + /// Identity matrix. +static const Matrix4 &IdentityMatrix() + { return static_identity; } + + /// Translation matrix. +static Matrix4 TranslationMatrix(const Vector4 &t); + /// Scale matrix. +static Matrix4 ScaleMatrix(const Vector4 &s); + /// From matrix3. +static Matrix4 FromMatrix3(const Matrix3 &mtx); + /// Position/scale/rotation/offset matrix. +static Matrix4 TransformationMatrix(const Vector4 &p, const Vector4 &r, const Vector4 &s, const Vector4 *o = 0); + /// Position/scale/rotation/offset matrix. +static Matrix4 TransformationMatrix(const Vector4 &p, const Matrix3 &r, const Vector4 &s, const Vector4 *o = 0); + + NML::Tag *AsMetaTag(const char *id) const; + bool FromMetaTag(NML::Tag &); + + Matrix4( + float m00, float m10, float m20, float m30, + float m01, float m11, float m21, float m31, + float m02, float m12, float m22, float m32, + float m03, float m13, float m23, float m33 + ) + { + m[0][0] = m00; m[1][0] = m10; m[2][0] = m20; m[3][0] = m30; + m[0][1] = m01; m[1][1] = m11; m[2][1] = m21; m[3][1] = m31; + m[0][2] = m02; m[1][2] = m12; m[2][2] = m22; m[3][2] = m32; + m[0][3] = m03; m[1][3] = m13; m[2][3] = m23; m[3][3] = m33; + } + Matrix4() {} +}; + + +/* + @short 4x4 matrix with inverse. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Matrix4WithInverse +{ +protected: + + NPLACEMENT_NEW(Matrix) + + Matrix4 matrix, + imatrix; + + /// Commit a matrix change. + void Commit(); + +public: + + /// Return the matrix inverse. + const Matrix4 &Get() const; + /// Return the matrix inverse. + const Matrix4 &GetInverse() const; + + /// Set matrix. + void Set(const Matrix4 &m); + + /// Return the nth row. + Vector4 GetRow(uint n, bool w_1 = true) const; + /// Return the nth column. + Vector4 GetColumn(uint n, bool w_1 = true) const; + /// Set the nth row. + void SetRow(uint n, const Vector4 &row, bool w_1 = true); + /// Set the nth column. + void SetColumn(uint n, const Vector4 &col, bool w_1 = true); + + bool FromMetaTag(NML::Tag &tag); + NML::Tag *AsMetaTag(const char *id) const; + + Matrix4WithInverse() + { + matrix = Matrix4::IdentityMatrix(); + imatrix = Matrix4::IdentityMatrix(); + } +}; + +} // GS + + +#endif // __NMATRIX4__ + diff --git a/include/framework/math/quaternion.h b/include/framework/math/quaternion.h new file mode 100644 index 0000000..1b8907c --- /dev/null +++ b/include/framework/math/quaternion.h @@ -0,0 +1,107 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NQUATERNION__ +#define __NQUATERNION__ + + + #include "math/nmath.h" + + +namespace GS { + struct Vector4; + class Matrix3; + + namespace NML { + class File; + class Tag; + } + +/*! + @short Quaternion. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Quaternion +{ + float x, y, z, w; + + void operator += (const Quaternion &b) { x += b.x; y += b.y; z += b.z; w += b.w; }; + void operator += (float k) { x += k; y += k; z += k; w += k; }; + void operator -= (const Quaternion &b) { x -= b.x; y -= b.y; z -= b.z; w -= b.w; }; + void operator -= (float k) { x -= k; y -= k; z -= k; w -= k; }; + void operator *= (const Quaternion &b) + { + Quaternion t = *this; + w = t.w * b.w - (t.x * b.x + t.y * b.y + t.z * b.z); + x = t.w * b.x + b.w * t.x + t.y * b.z - t.z * b.y; + y = t.w * b.y + b.w * t.y + t.z * b.x - t.x * b.z; + z = t.w * b.z + b.w * t.z + t.x * b.y - t.y * b.x; + }; + void operator *= (float k) { x *= k; y *= k; z *= k; w *= k; }; + void operator /= (float k) { k = 1.f / k; x *= k; y *= k; z *= k; w *= k; }; + + Quaternion operator + (const Quaternion &b) const + { return Quaternion(x + b.x, y + b.y, z + b.z, w + b.w); } + Quaternion operator + (float v) const + { return Quaternion(x + v, y + v, z + v, w + v); } + Quaternion operator - (const Quaternion &b) const + { return Quaternion(x - b.x, y - b.y, z - b.z, w - b.w); } + Quaternion operator - (float v) const + { return Quaternion(x - v, y - v, z - v, w - v); } + Quaternion operator * (const Quaternion &b) const + { + return Quaternion ( + w * b.x + b.w * x + y * b.z - z * b.y, + w * b.y + b.w * y + z * b.x - x * b.z, + w * b.z + b.w * z + x * b.y - y * b.x, + w * b.w - (x * b.x + y * b.y + z * b.z) + ); + } + Quaternion operator * (float v) const + { return Quaternion(x * v, y * v, z * v, w * v); } + Quaternion operator / (float v) const + { v = 1.f / v; return Quaternion(x * v, y * v, z * v, w * v); } + + /// Dot product. + float Dot(const Quaternion &b) const + { return x * b.x + y * b.y + z * b.z + w * b.w; } + + /// Normalize quaternion. + Quaternion Normalize() const; + /// Inverse quaternion. + Quaternion Inverse() const; + /// To rotation matrix. + Matrix3 AsMatrix3() const; + + /// Distance to quaternion. +static float Distance(const Quaternion &a, const Quaternion &b); + /// Slerp. +static Quaternion Slerp(float t, const Quaternion &a, const Quaternion &b); + + /// From Euler angle. +static Quaternion FromEuler(float x, float y, float z, Math::rOrder rorder = Math::rOrder_Default); + /// Get an orientation from a 'look at' vector (look_at = to - from). +static Quaternion LookAt(const Vector4 &at); + /// From matrix3. +static Quaternion FromMatrix3(const Matrix3 &m); + /// From axis-angle. +static Quaternion FromAxisAngle(float angle, float x, float y, float z); + + /// Set quaternion values. + void Set(float _x = 0, float _y = 0, float _z = 0, float _w = 1.f) + { x = _x; y = _y; z = _z; w = _w; } + + NML::Tag *AsMetaTag(const char *id) const; + bool FromMetaTag(NML::Tag &tag); + + Quaternion(float _x = 0, float _y = 0, float _z = 0, float _w = 1.f) + { Set(_x, _y, _z, _w); } +}; + +} // GS + + +#endif // __NQUATERNION__ diff --git a/include/framework/math/vector.h b/include/framework/math/vector.h new file mode 100644 index 0000000..ca97d85 --- /dev/null +++ b/include/framework/math/vector.h @@ -0,0 +1,301 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NVECTOR__ +#define __NVECTOR__ + + + #include "math/nmath.h" + #include "alloc/ialloc.h" + + +namespace GS { + class Matrix3; + class Matrix4; + + namespace NML { + class File; + class Tag; + } + +/*! + @short Vector 2d template class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template struct tVector2 +{ + NPLACEMENT_NEW(Vector) + + T x, y; + +inline bool operator == (const tVector2 &b) const { return (x == b.x) && (y == b.y); } +inline bool operator != (const tVector2 &b) const { return (x != b.x) || (y != b.y); } + +inline void operator += (const tVector2 &b) { x += b.x; y += b.y; } +inline void operator += (const float k) { x += k; y += k; } +inline void operator -= (const tVector2 &b) { x -= b.x; y -= b.y; } +inline void operator -= (const float k) { x -= k; y -= k; } +inline void operator *= (const tVector2 &b) { x *= b.x; y *= b.y; } +inline void operator *= (const float k) { x *= k; y *= k; } +inline void operator /= (const tVector2 &b) { x /= b.x; y /= b.y; } +inline void operator /= (const float k) { x /= k; y /= k; } + +inline tVector2 operator + (const tVector2 &b) const { return tVector2 (x + b.x, y + b.y); } +inline tVector2 operator + (const T v) const { return tVector2 (x + v, y + v); } +inline tVector2 operator - (const tVector2 &b) const { return tVector2 (x - b.x, y - b.y); } +inline tVector2 operator - (const T v) const { return tVector2 (x - v, y - v); } +inline tVector2 operator * (const tVector2 &b) const { return tVector2 (x * b.x, y * b.y); } +inline tVector2 operator * (const T v) const { return tVector2 (x * v, y * v); } +inline tVector2 operator / (const tVector2 &b) const { return tVector2 (x / b.x, y / b.y); } +inline tVector2 operator / (const T v) const { return tVector2 (x / v, y / v); } + + tVector2 operator * (const Matrix3 &m) const; + + /// Squared vector length. +inline float Len2() const { return (float)(x * x + y * y); } + /// Vector length. +inline float Len() const { return Math::Sqrt((float)(x * x + y * y)); } + + /// Normalize this vector. +inline void Normalize() { float l = Len(); if (l) { float k = 1.f / l; x *= k; y *= k; } } + /// Normalize vector. +inline tVector2 Normalized() const + { + float k = 1.f / Len(); + return tVector2 (x * k, y * k); + } + + /// Reversed vector. +inline tVector2 Reversed() const + { return tVector2 (-x, -y); } + + /// Vector squared distance. +static float Dist2(const tVector2 &a, const tVector2 &b) + { return ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y)); } + /// Vector distance. +static float Dist(const tVector2 &a, const tVector2 &b) + { return Math::Sqrt((float)((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y))); } + + /// Set vector 2D components. +inline void Set(const T a, const T b) { x = a; y = b; } + + tVector2 (T a, T b) { Set(a, b); } + tVector2 () { Set(0, 0); } +}; + +typedef tVector2 Vector2; + +/*! + @short 4-Component vector + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Vector4 +{ + NPLACEMENT_NEW(Vector) + + float x, y, z, w; + +inline bool operator == (const Vector4 &b) const { return Math::TestEqual(x, b.x) && Math::TestEqual(y, b.y) && Math::TestEqual(z, b.z); } +inline bool operator != (const Vector4 &b) const { return !Math::TestEqual(x, b.x) || !Math::TestEqual(y, b.y) || !Math::TestEqual(z, b.z); } + +inline void operator += (const Vector4 &b) { x += b.x; y += b.y; z += b.z; }; +inline void operator += (const float k) { x += k; y += k; z += k; }; +inline void operator -= (const Vector4 &b) { x -= b.x; y -= b.y; z -= b.z; }; +inline void operator -= (const float k) { x -= k; y -= k; z -= k; }; +inline void operator *= (const Vector4 &b) { x *= b.x; y *= b.y; z *= b.z; }; +inline void operator *= (const float k) { x *= k; y *= k; z *= k; }; +inline void operator /= (const Vector4 &b) { x /= b.x; y /= b.y; z /= b.z; }; +inline void operator /= (const float k) { float k_ = k ? 1 / k : 0; x *= k_; y *= k_; z *= k_; }; + +inline Vector4 operator + (const Vector4 &b) const { return Vector4(x + b.x, y + b.y, z + b.z); } +inline Vector4 operator + (const float v) const { return Vector4(x + v, y + v, z + v); } +inline Vector4 operator - (const Vector4 &b) const { return Vector4(x - b.x, y - b.y, z - b.z); } +inline Vector4 operator - (const float v) const { return Vector4(x - v, y - v, z - v); } +inline Vector4 operator * (const Vector4 &b) const { return Vector4(x * b.x, y * b.y, z * b.z); } +inline Vector4 operator * (const float v) const { return Vector4(x * v, y * v, z * v); } +inline Vector4 operator / (const Vector4 &b) const { return Vector4(x / b.x, y / b.y, z / b.z); } +inline Vector4 operator / (const float v) const { float i = v ? 1 / v : 0; return Vector4(x * i, y * i, z * i); } + +inline float operator [] (size_t n) const { return (&x)[n]; } +inline float &operator [] (size_t n) { return (&x)[n]; } + +inline Vector4 SafeDivided(const Vector4 &b) const + { return Vector4(b.x ? x / b.x : 0, b.y ? y / b.y : 0, b.z ? z / b.z : 0); } + + /// Set vector components. +inline void Set(float x_, float y_, float z_, float w_) + { x = x_; y = y_; z = z_; w = w_; } +inline void Set(float x_ = 0.f, float y_ = 0.f, float z_ = 0.f) // Used to provide script overload. + { x = x_; y = y_; z = z_; w = 1.0f; } +inline void Set(Vector4 &v) + { x = v.x; y = v.y; z = v.z; w = v.w; } + + /// Dot product. +inline float Dot(const Vector4 &b) const + { return x * b.x + y * b.y + z * b.z; } + /// Cross product. +inline Vector4 Cross(const Vector4 &b) const + { return Vector4(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); } + + void operator *= (const Matrix4 &); + Vector4 operator * (const Matrix4 &) const; + void operator *= (const Matrix3 &); + Vector4 operator * (const Matrix3 &) const; + + /// Reverse this vector. +inline void Reverse() { x = -x; y = -y; z = -z; } + /// Inverse vector. +inline void Inverse() { x = x ? 1.f / x : 0; y = y ? 1.f / y : 0; z = z ? 1.f / z : 0; } + + /// Normalize this vector. +inline void Normalize() { float l = Len(); if (l) { float k = 1.f / l; x *= k; y *= k; z *= k; } } + /// Normalize vector. +inline Vector4 Normalized() const + { + float l = Len(); + float k = l ? 1.f / l : 1.f; + return Vector4(x * k, y * k, z * k); + } + + /// Clamp vector components to [min;max]. + Vector4 Clamped(float min, float max) const; + /// Clamp vector components to [min;max]. + Vector4 Clamped(const Vector4 &min, const Vector4 &max) const; + /// Clamp vector magnitude to [min;max]. + Vector4 ClampedMagnitude(float min, float max) const; + + /// Return the opposite vector to this vector. +inline Vector4 Reversed() const + { return Vector4(-x, -y, -z); } + /// Return the inverse vector to this vector. +inline Vector4 Inversed() const + { return Vector4(1.f / x, 1.f / y, 1.f / z); } + /// Absolute vector. + Vector4 Abs() const; + /// Sign vector. +inline Vector4 Sign() const + { return Vector4(x < 0.f ? -1.f : 1.f, y < 0.f ? -1.f : 1.f, z < 0.f ? -1.f : 1.f); } + + /// Maximum of two vectors. +static Vector4 Maximum(const Vector4 &a, const Vector4 &b) + { return Vector4(a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y, a.z > b.z ? a.z : b.z); } + /// Minimum of two vectors. +static Vector4 Minimum(const Vector4 &a, const Vector4 &b) + { return Vector4(a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y, a.z < b.z ? a.z : b.z); } + + /*! + @short Reflect vector. + @note Vector must be normalized. + */ +inline Vector4 Reflected(const Vector4 &n) const + { + Vector4 rv = Reversed(); + return n * (2.f * rv.Dot(n)) - rv; + } + /*! + @short Refract vector. + @note Vector must be normalized. + */ +inline Vector4 Refracted(const Vector4 &n, float kin = 1, float kout = 1) const + { + const float k = kin / kout; + return (*this) * k + n * (k - 1.f); + } + + /// Squared vector length. +inline float Len2() const { return (float)(x * x + y * y + z * z); } + /// Vector length. +inline float Len() const { return Math::Sqrt((float)(x * x + y * y + z * z)); } + /// Hash vector. + int Hash() const; + + Vector4 Floor() const; + Vector4 Ceil() const; + + /*! + @short Return a random vector. + @note w component is not randomized but set to 1. + */ +static Vector4 Random(float min = -1, float max = 1); + /// Vector squared distance. +static float Dist2(const Vector4 &a, const Vector4 &b) + { return ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y) + (b.z - a.z) * (b.z - a.z)); } + /// Vector distance. +static float Dist(const Vector4 &a, const Vector4 &b) + { return Math::Sqrt((float)((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y) + (b.z - a.z) * (b.z - a.z))); } + /*! + @short Vector base to Euler. + @note base convention u = {0,0,1}, v = {1,0,0}, second axis is optional. + */ +static void BaseToEuler(Vector4 &euler, Vector4 &u, Vector4 *v = NULL); + + /*! + @short Return a vector which is facing a given direction. + + Returns a copy of this vector if it is already facing the given + direction or the opposite of this vector otherwise. + */ + Vector4 FaceForward(Vector4 &dir); + + NML::Tag *AsMetaTag(const char *id, bool full_dump = false) const; + bool FromMetaTag(NML::Tag &tag); + + Vector4(float a, float b, float c, float d = 1) : x(a), y(b), z(c), w(d) {} + Vector4(const tVector2 &v2) : x(v2.x), y(v2.y), z(1), w(1) {} + Vector4(const tVector2 &v2) : x(float(v2.x)), y(float(v2.y)), z(1), w(1) {} + Vector4() {} +}; + +} // GS + + +#define Vec3Set(v, a, b, c) { (v).x = a; (v).y = b; (v).z = c; } + +#define Vec3Len2(v) ((v).x * (v).x + (v).y * (v).y + (v).z * (v).z) +#define Vec3Len(v) Math::Sqrt((float)Vec3Len2(v)) + +#define Vec3Add(r, a, b) { (r).x = (a).x + (b).x; (r).y = (a).y + (b).y; (r).z = (a).z + (b).z; } +#define Vec3AddConst(r, a, k) { (r).x = (a).x + k; (r).y = (a).y + k; (r).z = (a).z + k; } +#define Vec3Sub(r, a, b) { (r).x = (a).x - (b).x; (r).y = (a).y - (b).y; (r).z = (a).z - (b).z; } +#define Vec3SubConst(r, a, k) { (r).x = (a).x - k; (r).y = (a).y - k; (r).z = (a).z - k; } +#define Vec3Mul(r, a, b) { (r).x = (a).x * (b).x; (r).y = (a).y * (b).y; (r).z = (a).z * (b).z; } +#define Vec3MulConst(r, a, k) { float _k = k; (r).x = (a).x * _k; (r).y = (a).y * _k; (r).z = (a).z * _k; } +#define Vec3Div(r, a, b) { (r).x = (a).x / (b).x; (r).y = (a).y / (b).y; (r).z = (a).z / (b).z; } +#define Vec3DivConst(r, a, k) { float ik = 1.f / k; (r).x = (a).x * ik; (r).y = (a).y * ik; (r).z = (a).z * ik; } + +#define Vec3Inc(r, a) { (r).x += (a).x; (r).y += (a).y; (r).z += (a).z; } +#define Vec3IncConst(r, k) { (r).x += k; (r).y += k; (r).z += k; } +#define Vec3Dec(r, a) { (r).x -= (a).x; (r).y -= (a).y; (r).z -= (a).z; } +#define Vec3DecConst(r, k) { (r).x -= k; (r).y -= k; (r).z -= k; } +#define Vec3Scale(r, a) { (r).x *= (a).x; (r).y *= (a).y; (r).z *= (a).z; } +#define Vec3ScaleConst(r, k) { float _k = k; (r).x *= _k; (r).y *= _k; (r).z *= _k; } +#define Vec3Shrink(r, a) { (r).x /= (a).x; (r).y /= (a).y; (r).z /= (a).z; } +#define Vec3ShrinkConst(r, k) { float ik = 1.f / k; (r).x *= ik; (r).y *= ik; (r).z *= ik; } + +#define Vec3Dot(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z) +#define Vec3Cross(r, a, b) {\ + (r).x = (a).y * (b).z - (a).z * (b).y;\ + (r).y = (a).z * (b).x - (a).x * (b).z;\ + (r).z = (a).x * (b).y - (a).y * (b).x;\ +} + +#define Vec3Clamp(v, a, b) {\ + if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\ + if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\ + if ((v).x < a) (v).x = a; else if ((v).x > b) (v).x = b;\ +} +#define Vec3ClampMag(v, m) {\ + const float m2 = (m) * (m);\ + const float l2 = Vec3Len2(v);\ + if (l2 > m2)\ + {\ + const float k = Math::Sqrt((float)(m2 / l2));\ + Vec3ScaleConst(v, k);\ + }\ +} + + +#endif // __NVECTOR__ diff --git a/include/framework/math/vector_nml.h b/include/framework/math/vector_nml.h new file mode 100644 index 0000000..f7d1b94 --- /dev/null +++ b/include/framework/math/vector_nml.h @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NVECTORNML__ +#define __NVECTORNML__ + + + #include "metafile/nml.h" + #include "math/vector.h" + + +namespace GS { + +//------------------------------------------------------------------------------ +template NML::Tag *tVectorAsMetaTag(const tVector2 &v, const char *id) +{ + NML::Tag *root = id ? new NML::Tag(id) : new NML::Tag("Vector2"); + + if (root) + { + root->AddChild("X", v.x); + root->AddChild("Y", v.y); + } + return root; +} +template bool tVectorFromMetaTag(tVector2 &v, NML::Tag &tag) +{ + NML::Tag *t; + List ::Iterator i(tag.GetTags().GetRoot()); + + if ((t = i.ObjectPtr()) == NULL) + return false; + v.x = t->GetReal(); + ++i; + + if ((t = i.ObjectPtr()) == NULL) + return false; + v.y = t->GetReal(); + + return true; +} +//------------------------------------------------------------------------------ + +} // GS + + +#endif // __NVECTORNML__ diff --git a/include/framework/metafile/nml.h b/include/framework/metafile/nml.h new file mode 100644 index 0000000..3535c93 --- /dev/null +++ b/include/framework/metafile/nml.h @@ -0,0 +1,224 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMETALANG__ +#define __NMETALANG__ + + + #include "data/nvariant.h" + #include "container/nlist.h" + + +namespace GS { + namespace IO { class Handle; } + + namespace NML { + class Tag; + class File; + +static const int version = 1; + +/// Metatag. +class Tag +{ + friend struct Parser; + friend class File; + +protected: + + /// Locate a tag through its path. +static Tag *GetTagEx(const List &tag, const char *path, const File *root = 0, bool verbose = false); + + List tags; + + Variant value; + +public: + + NPLACEMENT_NEW(Metatag) + + String name; + + /// Get this tag parent by exploring a given tag hierarchy. + Tag *GetParent(Tag *) const; + + /// Get value. + Variant &GetValue() { return value; } + const Variant &GetValue() const { return value; } + + /// Remove a child tag from this tag. + bool RemoveTag(Tag *t) { return tags.Remove(t); } + /// Delete all child tags. + uint DeleteChildren(const char *filter = 0); + /// Get child count. + uint GetChildCount() const { return tags.GetCount(); } + /// Return the tag children list. + const List &GetTags() const { return tags; } + + /// Add child to tag. + Tag *AddChild(Tag *); + Tag *AddChild(const char *); + Tag *AddChild(const char *, bool); + Tag *AddChild(const char *, int); + Tag *AddChild(const char *, uint); + Tag *AddChild(const char *, float); + Tag *AddChild(const char *, const char *); + Tag *AddChild(const char *, void *, size_t); + + /// Return tag child. + Tag *GetTag(const char *path, const File * = 0, bool verbose = false) const; + /// Return the tag at a given path only if it matches the required type. + Tag *GetTypedTag(const char *path, Variant::Type, const File * = 0, bool verbose = false) const; + + bool GetBool() const { bool v; if (value.Get(v)) return v; return false; } + int GetInteger() const { return value.i_value; } + uint GetUnsigned() const { return value.u_value; } + const char *GetString() const { return value.s_value; } + float GetReal() const { return value.f_value; } + + void SetBool(bool v) { value = v; } + void SetInteger(int v) { value = v; } + void SetUnsigned(uint v) { value = v; } + void SetString(const char *v) { value = v; } + void SetReal(float v) { value = v; } + + Variant::Type GetType() const { return value.GetType(); } + + /// Clone a tag and optionally recurse and clone its children. + bool Clone(const Tag &src, bool recursive = true); + /// Clone this tag and optionally recurse and clone its children. + Tag *Clone(bool recursive = true) const; + + /// Free the tag data, set its type to nVariant::VariantNone. + void Free(); + + Tag() {} + Tag(const char *n) : name(n) {} + Tag(const char *n, bool v) : name(n), value(v) {} + Tag(const char *n, int v) : name(n), value(v) {} + Tag(const char *n, uint v) : name(n), value(v) {} + Tag(const char *n, float v) : name(n), value(v) {} + Tag(const char *n, const char *v) : name(n), value(v) {} + Tag(const char *n, void *data, size_t size) : name(n), value(data, size) {} + + ~Tag(); +}; + +/*! + @short Meta file. + + A metafile contain the whole database in memory. + This class is not meant to be used with heavy databases. + + Tags can be accessed using tag paths. A tag path is formatted as follow: + "root:node:...:tag;". + + @note The closing hyphen is not required but warnings will be sent to the + log if you don't use it. The node delimiter ':' can be repeated any + number of time between nodes with no effect (eg: ":::node1::node2:;"). + By definition a file is a node tag and cannot have a value. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class File +{ + friend struct Parser; + +public: + +enum Binary +{ + Binary_UU = 0, ///< UUEncoded. + Binary_yEnc ///< yEncoded. +}; + +protected: + + List tags; + Binary binary_method; ///< Binary encoding method. + +public: + + String name; + + /// Get the file ASCII binary encoding method. + Binary GetBinaryMethod() const { return binary_method; } + + const List &GetTags() const { return tags; } + + uint GetRootCount() const { return tags.GetCount(); } + + void Clear() { ListDeleteAllPtr(Tag *, tags); } + bool isEmpty() const { return asbool(GetRootCount() == 0); } + + /// Add a root tag to the file. + Tag *AddRoot(Tag *); + Tag *AddRoot(const char *); + Tag *AddRoot(const char *, bool); + Tag *AddRoot(const char *, int); + Tag *AddRoot(const char *, float); + Tag *AddRoot(const char *, const char *); + Tag *AddRoot(const char *, void *, size_t); + + /// Unlink a root tag from file. + bool UnlinkRoot(Tag *); + + /// Return the tag at a given path. + Tag *GetTag(const char *path, bool verbose = false) const + { return Tag::GetTagEx(tags, path, this, verbose); } + + /// Return the tag at a given path only if it match the required type. + Tag *GetTypedTag(const char *path, Variant::Type, bool verbose = false) const; + + bool GetBool(const char *path, bool _default = false, bool verbose = false) const; + int GetInteger(const char *path, int _default = -1, bool verbose = false) const; + float GetReal(const char *path, float _default = -1.f, bool verbose = false) const; + const char *GetString(const char *path, const char *_default = 0, bool verbose = false) const; + + /// Duplicate the structure of a source file into this file. + void Import(const File &, bool clear_before_import = true); + /// Clone a file and all its tags. + File *Clone() const; + + void Free(); + + File() : binary_method(Binary_yEnc) {} + ~File(); +}; + +/*! + @short Meta file parser. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Parser +{ +static const char *ParseTagPreprocessorDirective(Tag &tag, const char *s, const char *e); + +static bool IsMetafile(const char *); + +static bool SaveBinaryTag(IO::Handle &, const Tag &, File::Binary = File::Binary_yEnc); +static bool SaveTag(IO::Handle &, const Tag &, File::Binary = File::Binary_yEnc, uint idt = 0); + +static bool ParseTag(Tag &, const char *s, const char *e, const char **r = 0); + +static bool LoadFromMemory(const char *, size_t, File &); +static File *Load(const char *, bool verbose = true); +static bool Load(const char *, File &, bool verbose = true); + +static bool Save(IO::Handle &, const File &); +static bool Save(const char *, const File &); +static bool SaveBinary(IO::Handle &, const File &); +static bool SaveBinary(const char *, const File &); +}; + +#define NMLTagForeach(__I__, __T__) ListForeachPtr(GS::NML::Tag *, __I__, (__T__).GetTags()) +#define NMLFileForeach(__I__, __F__) ListForeachPtr(GS::NML::Tag *, __I__, (__F__).GetTags()) + + } // NML +} // GS + + +#endif // __NMETALANG__ diff --git a/include/framework/metafile/nml_object.h b/include/framework/metafile/nml_object.h new file mode 100644 index 0000000..d3ab093 --- /dev/null +++ b/include/framework/metafile/nml_object.h @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMETAOBJECT__ +#define __NMETAOBJECT__ + + + #include "metafile/nml.h" + #include "reflection/c_refl.h" + + +/*! + @short Serialization helper. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +namespace GS { + namespace NML { + +template bool LoadFromFile(T &object, File &file) +{ + return file.isEmpty() ? false : object.FromMetaTag(*file.GetTags()[0]); +} +template bool LoadFromFile(T &object, const char *path, bool verbose = true) +{ + File file; + file.name = path; + if (!Parser::Load(path, file, verbose)) + return false; + return LoadFromFile(object, file); +} + +template bool SaveToFile(T &object, File &file) +{ + file.Clear(); + return file.AddRoot(object.AsMetaTag()) ? true : false; +} +template bool SaveToFile(T &object, const char *path) +{ + File file; + file.name = path; + if (!SaveToFile(object, file)) + return false; + + return Parser::Save(path, file); +} + +bool GenericObjectFromMetaTag(Tag &, void *obj, Reflection::Property *obj_prop); +Tag *GenericObjectToMetaTag(Tag *, const void *obj, Reflection::Property *obj_prop); + +bool GenericObjectFromMetaFile(const char *, void *obj, Reflection::Property *obj_prop, const char *root_name = 0); +bool GenericObjectToMetaFile(const char *, const void *obj, Reflection::Property *obj_prop, const char *root_name = 0); + + } // NML +} // GS + + +#endif // __NMETAOBJECT__ diff --git a/include/framework/metafile/nml_string.h b/include/framework/metafile/nml_string.h new file mode 100644 index 0000000..13953ff --- /dev/null +++ b/include/framework/metafile/nml_string.h @@ -0,0 +1,28 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMETAFILE_TO_STRING__ +#define __NMETAFILE_TO_STRING__ + + +namespace GS { + class String; + + namespace NML { + class Tag; + class File; + +bool TagToString(const Tag &, String &); +bool TagFromString(const String &, Tag &); + +bool FileToString(const File &, String &); +bool FileFromString(const String &, File &); + + } // NML +} // GS + + +#endif // __NMETAFILE_TO_STRING__ diff --git a/include/framework/picture/pict.h b/include/framework/picture/pict.h new file mode 100644 index 0000000..8f26102 --- /dev/null +++ b/include/framework/picture/pict.h @@ -0,0 +1,341 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPICTURE__ +#define __NPICTURE__ + + + #include "geometry/rect.h" + #include "picture/pict_color_format.h" + #include "memory/bit_field.h" + #include "memory/nshared_ptr.h" + + +namespace GS { + struct Color; + struct Vector4; + class Gradient; + +/*! + @short The base image class. + + When used with PictureTools, this class provides high-quality sub-pixel + bitmap manipulations from shrinking/enlargement to blit/resize. + + Importing/exporting from common image formats can be done through the + GS::PictureIO class. + + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Picture : public SharedObject +{ +public: + + NPLACEMENT_NEW(Picture) + +enum BlendMode +{ + BlendReplace = 0, + BlendCompose, + BlendComposeFast, + BlendAdd, + BlendMultiply, + BlendMultiply2x, + BlendAlphaAdd, + BlendAlphaMultiply, + BlendAlphaMultiply2x, + RgbToAlpha +}; + +protected: + + uchar *data; ///< Internal pointer to the picture's data. + + uint hash, ///< Raster data hash value. + width, ///< Object's width. + height; ///< Object's height. + + PixelFormat pxformat; ///< Pixel format. + + /// Zeroify the class but do not free anything. + void Zeroify(); + + /*! + @short Internal free. + @note Free raster data only. + */ + void FreeData(); + +enum +{ + PictureIsStub = (1 << 1) +}; + + BitField protected_flag; + +public: + +enum +{ + HasForeignData = (1 << 1) +}; + + BitField pic_flag; + String name; + +/*! + @name Blit functions. + @{ +*/ + /// Blit. +static bool Blit(const Picture &src, Picture &dst, const Rect *src_rect = 0, const Rect *dst_rect = 0, BlendMode op = BlendReplace); + /// Blit using a mask. +static bool BlitMask(const Picture &src, Picture &dst, Picture &mask, const Rect *src_rect = 0, const Rect *dst_rect = 0); + /*! + @short Scaled blit. + + This function is designed to be used in high quality compositing + and perform a bilinear filtered sub-pixel blit. + + @note When a rectangle is omitted the whole picture is used. + */ +static bool ScaleBlit(Picture &src, Picture &dst, Rect *src_rect = 0, Rect *dst_rect = 0); + +/*! + @} + @name Cropping/framing functions. + @{ +*/ + /*! + @short Reframe picture. + + All offsets may be negative. + Fill color can be specified and defaults to black. + + @note Reframe(-2, -2, 2, 2) to display a 2 pixel-wide frame around + the picture. + */ + bool Reframe(int offset_sx, int offset_sy, int offset_ex, int offset_ey, const Color *fill = 0); + /// Crop picture to specified dimension. + bool Crop(uint target_width, uint target_height) + { return (target_width <= width) && (target_height <= height) ? Reframe(0, 0, target_width - width, target_height - height) : false; } + +/*! + @} + @name Rescaling functions. + @{ +*/ + /*! + @short Downscale a picture using area-summing filtering. + @note 0 can be used on width or height to resize the picture + proportionally. + */ + bool Downscale(uint width, uint height); + /*! + @short Resize a picture using bilinear filtering. + @note 0 can be used on width or height to resize the picture + proportionally. + */ + bool Resize(uint width, uint height); + /// Flip picture. + bool Flip(bool flip_h, bool flip_v); + +/*! + @} + @name Color conversion functions. + @{ +*/ +protected: + + bool RealToIntegerConversion(const PixelFormat &); + bool IntegerToIntegerConversion(const PixelFormat &); + bool Fast8888Conversion(const PixelFormat &); + +public: + + bool Swizzle(uchar r = 0, uchar g = 1, uchar b = 2, uchar a = 3); + + /// Convert YUV buffers to RGB buffer. +static void YUV422toRGB32(uchar * const yuv_plane[3], uchar *rgb32, int width, int height, int dst_pitch = 0, int dst_height = 0); + + /// Alpha blend two 32bit RGBA values together. +static uint ColorBlend(uint u, uint v, float opacity); + +static void AlphaCompositePixel(uchar *data, uchar r, uchar g, uchar b, uchar a); +static uchar AlphaCompositeAlpha(uchar a, uchar b); +static uchar AlphaCompositeColor(uchar u, uchar v, uchar a, uchar b, uchar k); + + bool ToGrayscale(); + void Negative(bool r = true, bool g = true, bool b = true, bool a = false); + + void UnpackYCbCr(uchar *y, uchar *cb, uchar *cr); + void PackYCbCr(uchar *y, uchar *cb, uchar *cr); + +/*! + @} + @name Sampling functions. + @{ +*/ + void Sample(float u, float v, Color &out, uint _w = 0, uint _h = 0) const; + void Sample(float u, float v, uint &out, uint _w = 0, uint _h = 0) const; + void SampleRGBA(float u, float v, Color &out, uint _w = 0, uint _h = 0) const; + + uint SampleInteger(float u, float v, uint _w = 0, uint _h = 0) const; + Color SampleColor(float u, float v, uint _w = 0, uint _h = 0) const; + Color SampleRGBAColor(float u, float v, uint _w = 0, uint _h = 0) const; +/*! + @} + @name Drawing functions. + @note Most of these functions are for now extremely slow! + @{ +*/ +protected: + + /// Low-level draw line. + void LowLevelDrawLine(bool hq, float sx, float sy, float ex, float ey, float r, float g, float b, float a = 1, const Rect *clip_rect = 0); + +public: + + /// Fill picture with a given color. + bool Fill(float r, float g, float b, float a = 1, const Rect *clip_rect = 0, bool lock_alpha = false); + + /// Draw a gradient. + void DrawGradient(const Gradient &gradient, const Rect *clip_rect = 0); + /*! + @short Apply a convolution kernel to the picture. + @note Do not use in time critical code as this function is slow + and uses a temporary copy of the picture. + */ + bool ApplyConvolution(uint kernel_width, uint kernel_height, const int *weights, int weight = 256, int pass = 1, const Rect *clip_rect = 0); + + void DrawPlot(float x, float y, float r, float g, float b, float a = 1, const Rect *clip_rect = 0); + void DrawPlotHQ(float x, float y, float r, float g, float b, float a = 1, const Rect *clip_rect = 0); + + void DrawLine(float sx, float sy, float ex, float ey, float r, float g, float b, float a = 1, const Rect *clip_rect = 0); + void DrawLineHQ(float sx, float sy, float ex, float ey, float r, float g, float b, float a = 1, const Rect *clip_rect = 0); + + void DrawPolygon(uint point_count, Point *point, float r, float g, float b, float a = 1, const Rect *clip_rect = 0); +/// @} + + bool ComputeHash(); + int GetHash() const; + + bool Compare(const Picture &picture) const; + + /// Clone the picture via assignment operator. + void operator = (Picture &picture) { Clone(picture); } + + /// Convert the picture to another pixel formats. + bool Convert(const PixelFormatDescription &); + /// Set the picture format without performing any data conversion. + bool SetFormat(const PixelFormatDescription &); + + /*! + @short Set the picture dimensions but do not perform any allocation. + + This function is used by the 3d engine built on the picture object. + It should not have any practical usage in standard usage. + */ + void Stub(uint w, uint h); + /// Is stub. +inline bool IsStub() const { return protected_flag.IsSet(PictureIsStub); } + + /*! + @short Return image dimensions as a nfRect. + @note sx and sy are 0. Only ex and ey are relevant. + */ +inline iRect GetRect() const { return iRect(0, 0, width, height); } + /*! + @short Return image dimensions as a rectangle. + @note sx and sy are 0. Only ex and ey are relevant. + */ +inline void GetRect(iRect &rect) const { rect.Set(0, 0, width, height); } + + /// Test is the picture has an alpha component. + bool HasAlpha() const; + +inline uchar *GetData() const { return data; } + uchar *GetDataOffset(uint offset_x, uint offset_y) const { return data + (offset_x + offset_y * GetWidth()) * (pxformat.GetBpp() / 8); } + +inline uint GetWidth() const { return width; } +inline uint GetHeight() const { return height; } + +inline uchar GetBpp() const { return pxformat.GetBpp(); } +inline uint GetPitch() const { return (width * (pxformat.GetBpp() / 8)); } + +inline bool isValid() const { return (width && height && data); } + + /// Return the pixel format descriptor of the picture. +inline const PixelFormat &GetPixelFormat() const { return pxformat; } + + void Clone(const Picture &, bool clone_data = true); + +/* + @name Memory allocator. + @{ +*/ +virtual uchar *AllocMemory(size_t); +virtual void FreeMemory(uchar *); +/// @} + + /*! + @short Set the picture object raster data source. + + @note Ownership of the data buffer can be passed to this object. + */ +virtual void SetData(void *data, uint w, uint h, const PixelFormatDescription & = PixelFormat::RGBA8, bool take_ownership = false); + /*! + @short Allocate internal buffers overriding object settings. + + @note Ownership of the data buffer is passed to this object. + @note If the internals already match the new settings this + function returns without doing anything unless user data is + passed. + @note If you provide the picture raster data buffer, you must make + sure that the pointer you pass to this function as user_data + is at least large enough to hold the complete picture in + memory. + @see SetData(). + */ +virtual bool AllocAs(uint w, uint h, const PixelFormatDescription & = PixelFormat::RGBA8); + /*! + @short Free all object's data. + + @note If you used the SetData() function the passed buffer will + not be freed by this object. You are responsible for + cleaning memory in such case. + */ +virtual void Free() + { + FreeData(); + Zeroify(); + } + + Picture(const Picture &p) + { + Zeroify(); + Clone(p); + } + Picture(void *data, uint w, uint h, const PixelFormatDescription &f = PixelFormat::RGBA8, bool take_ownership = false) + { + Zeroify(); + SetData(data, w, h, f, take_ownership); + } + Picture(uint w, uint h, const PixelFormatDescription &f = PixelFormat::RGBA8) + { + Zeroify(); + AllocAs(w, h, f); + } + Picture() { Zeroify(); } +virtual ~Picture(); +}; + +typedef SharedPtr sPicture; + +} // GS + + +#endif // __NPICTURE__ diff --git a/include/framework/picture/pict_color_format.h b/include/framework/picture/pict_color_format.h new file mode 100644 index 0000000..c066613 --- /dev/null +++ b/include/framework/picture/pict_color_format.h @@ -0,0 +1,147 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCOLORFORMAT__ +#define __NCOLORFORMAT__ + + + #include "nstring/nstring.h" + + +namespace GS { + +/// The color space for a pixel format. +enum PixelColorSpace +{ + PixelColorSpace_NULL = 0, + PixelColorSpace_RGB ///< Standard RGB space. +}; + +/// Pixel format descriptor. +struct PixelFormatDescription +{ + PixelColorSpace space; + /*! + When working with integer values these are actual bit masks. + However when working with real values they are byte sized offsets + in the pixel packet to access a given component. + */ + uint amask, rmask, gmask, bmask; + uchar bpp; + bool real; +}; + +/*! + @short Structure holding a picture pixel format. + @note This structure only works with continuous bit masks. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct PixelFormat +{ + // Predefined pixel formats. +static PixelFormatDescription NONE; +static PixelFormatDescription BGRA8; +static PixelFormatDescription RGBA8; +static PixelFormatDescription ARGB8; +static PixelFormatDescription BGR8; +static PixelFormatDescription RGB8; +static PixelFormatDescription RGB555; +static PixelFormatDescription RGB565; +static PixelFormatDescription RGBA4444; +static PixelFormatDescription RGBF; +static PixelFormatDescription RGBAF; +static PixelFormatDescription YUYV; + + PixelFormatDescription desc; + + uchar ashift, rshift, bshift, gshift; + uchar acount, rcount, bcount, gcount; + + /// Get format name (only use for cosmetic purposes! This is not a reliable naming convention). + String GetName() const; + + /// Internal function to parse a bit mask. + void LoadMask(uint mask, uchar &shift, uchar &count) + { + shift = Memory::GetShiftCount(mask); + count = Memory::GetBitCount(mask); + } + + /// Compare a format descriptor to this format. + bool operator == (const PixelFormatDescription &fmt) const + { + if ( (fmt.space != desc.space) || (fmt.bpp != desc.bpp) || + (fmt.amask != desc.amask) || (fmt.rmask != desc.rmask) || + (fmt.gmask != desc.gmask) || (fmt.bmask != desc.bmask) || + (fmt.real != desc.real) ) + return false; + return true; + } + /// Compare a format descriptor to this format. + bool operator != (const PixelFormatDescription &fmt) const + { return !(*this == fmt); } + + /// Return the format bpp. + uchar GetBpp() const { return desc.bpp; } + + /// Is format using real or integer numbers. + bool IsReal() const { return desc.real; } + + /// Set the the pixel format from user provided data. + void Set + ( + PixelColorSpace space = PixelColorSpace_RGB, + uint amask = 0xff000000, + uint rmask = 0x00ff0000, + uint gmask = 0x0000ff00, + uint bmask = 0x000000ff, + uchar bpp = 32, + bool real = false + ) + { + desc.amask = amask; + desc.rmask = rmask; + desc.gmask = gmask; + desc.bmask = bmask; + desc.bpp = bpp; + desc.space = space; + LoadMask(amask, ashift, acount); + LoadMask(rmask, rshift, rcount); + LoadMask(gmask, gshift, gcount); + LoadMask(bmask, bshift, bcount); + desc.real = real; + } + /// Set the the pixel format from a descriptor. + void Set(const PixelFormatDescription &fmt) + { Set(fmt.space, fmt.amask, fmt.rmask, fmt.gmask, fmt.bmask, fmt.bpp, fmt.real); } + + /// Return a reference to the format descriptor. + const PixelFormatDescription &GetDesc() const { return desc; } + + /// Format a color for this color format. + uint Format(float r, float g, float b, float a = 1) const; + + /// Constructor. + PixelFormat + ( + PixelColorSpace space = PixelColorSpace_RGB, + uint amask = 0xff000000, + uint rmask = 0x00ff0000, + uint gmask = 0x0000ff00, + uint bmask = 0x000000ff, + uchar bpp = 32, + bool real = false + ) + { Set(space, amask, rmask, gmask, bmask, bpp, real); } + /// Constructor via a format descriptor. + PixelFormat(const PixelFormatDescription &desc) + { Set(desc); } +}; + +} // GS + + +#endif // __NCOLORFORMAT__ diff --git a/include/framework/picture/pict_gradient.h b/include/framework/picture/pict_gradient.h new file mode 100644 index 0000000..da406a0 --- /dev/null +++ b/include/framework/picture/pict_gradient.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCOLORGRADIENT__ +#define __NCOLORGRADIENT__ + + + #include "ntypes.h" + #include "picture/pict.h" + #include "color/color.h" + + +namespace GS { + +/* + @short Color gradient. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Gradient +{ + uint control_point_count; + + Picture::BlendMode op; + +public: + + float k[8]; ///< Gradient coefficient. + Color color[8]; ///< Gradient color. + +inline uint GetControlPointCount() const { return control_point_count; } +inline Picture::BlendMode GetOperator() const { return op; } + +inline void SetOperator(Picture::BlendMode _op) { op = _op; } +inline void Reset() { control_point_count = 0; } + + bool FromMetaTag(NML::Tag *); + + Gradient() + { + control_point_count = 0; + op = Picture::BlendMultiply; + } +}; + +} // GS + + +#endif // __NCOLORGRADIENT__ diff --git a/include/framework/picture/pict_io.h b/include/framework/picture/pict_io.h new file mode 100644 index 0000000..ccf54ce --- /dev/null +++ b/include/framework/picture/pict_io.h @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NPICTUREIO__ +#define __NPICTUREIO__ + + + #include "picture/pict_io_codec.h" + #include "memory/singleton.h" + #include "container/nlist.h" + + +namespace GS { + +/* + @short Picture I/O class. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class PictureIO : public Singleton +{ + AutoList codec_list; + +public: + + /*! + @short Generic load function. + This function try to load a given resource using all registered + codec. This is a convenience function and is not designed to be + fast. If you know the file format you are working with then please + directly use the appropriate codec. + */ + bool Load(Picture &, const char *uri); + /// Save a picture through a given codec. + bool Save(const Picture &, const char *uri, const char *codec_name); + + /// Return a codec from its ID or the file extension it supports. + PictureCodec *Codec(const char *codec_name); + + /// Register an I/O codec inside the manager. + bool RegisterCodec(PictureCodec *, bool verbose = false); + + /// Delete all registered codec. + void DeleteCodecs() { codec_list.Clear(); } + + /// Load a BMP resource via the core codec. + bool BmpLoad(Picture &, IO::Handle &); + /*! + @short Load a TARGA (TGA) resource via the core codec. + @note Supported color format are BGRA8/BGR8/RGB24/RGB555 + both RLE and RAW. + */ + bool TgaLoad(Picture &, IO::Handle &); + /*! + @short Save a picture to TARGA (TGA) via the core codec. + @note Supported color format are BGRA8/BGR8/RGB24/RGB555. + */ + bool TgaSave(const Picture &, const char *uri); +}; + +} // GS + + +#endif // __NPICTUREIO__ + diff --git a/include/framework/picture/pict_io_codec.h b/include/framework/picture/pict_io_codec.h new file mode 100644 index 0000000..8035576 --- /dev/null +++ b/include/framework/picture/pict_io_codec.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NPICTUREIOCODEC__ +#define __NPICTUREIOCODEC__ + + + #include "filesystem/io_handle.h" + #include "nstring/nstring.h" + + +namespace GS { + class Picture; + +/* + @short Picture I/O codec. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct PictureCodec +{ +enum +{ + NoCaps = 0, + + CanRead = (1 << 0), ///< Codec can read data. + CanWrite = (1 << 1), ///< Codec can write data. + WriteRaw = (1 << 2), ///< Codec supports raw output. + WriteLossy = (1 << 3), ///< Codec supports lossy compression. + WriteLossless = (1 << 4), ///< Codec supports lossless compression. + AlphaChannel = (1 << 5), ///< Codec supports alpha channel. + RealData = (1 << 6) ///< Codec works on real data. +}; + +virtual bool Load(IO::Handle &, Picture &) = 0; +virtual bool Save(IO::Handle &, const Picture &) { return false; } + +virtual const char *GetName() const = 0; +virtual const char *GetDesc() const = 0; + +virtual uint GetCaps() const = 0; + +virtual ~PictureCodec() {} +}; + +} // GS + + +#endif // __NPICTUREIOCODEC__ diff --git a/include/framework/picture/pict_tools.h b/include/framework/picture/pict_tools.h new file mode 100644 index 0000000..1ddf06b --- /dev/null +++ b/include/framework/picture/pict_tools.h @@ -0,0 +1,22 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __PICT_TOOLS__ +#define __PICT_TOOLS__ + + +namespace GS { + class Picture; + namespace PictureTools { + +/// Compare two pictures. +bool Compare(const Picture &, const Picture &, float threshold = 0.f); + + } // PictureTools +} // GS + + +#endif // __PICT_TOOLS__ \ No newline at end of file diff --git a/include/framework/plugin/plugin_manager.h b/include/framework/plugin/plugin_manager.h new file mode 100644 index 0000000..40e7f81 --- /dev/null +++ b/include/framework/plugin/plugin_manager.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __PLUGIN_MANAGER__ +#define __PLUGIN_MANAGER__ + + + #include "shared/shared_library.h" + #include "plugin/shared_systems.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + #include "platform.h" + + +namespace GS { + +static const int PluginLoadOk = 0; +static const int PluginLoadError = 1; + +static const int PluginMissingClass = 2; +static const int PluginClassError = 3; +static const int PluginMissingVersion = 4; +static const int PluginVersionError = 5; +static const int PluginInterfaceError = 6; + +/*! + @short Plugin manager + @author Emmanuel Julien (ejulien@owloh.com) +*/ +template class PluginManager +{ + typedef void SetSharedSystems(SharedSystems &); + typedef T *Factory(); + typedef const char *GetPluginClass(); + typedef uint GetPluginVersion(); + +public: + + struct Plugin + { + String path; + AutoPtr shared_lib; + }; + +private: + + AutoList plugins; + +public: + + /// Return a new instance to concrete interface the plugin implements. + T *CreatePluginInterface(Plugin *p) + { + Factory *p_factory = p ? (Factory *)p->shared_lib->GetFunctionPointer("createPluginInterface") : 0; + return p_factory ? p_factory() : 0; + } + + /* + @short Load a plugin. + + The plugin is dynamically loaded from the specified path and its + class and version are checked for compatibility with the host + interface class and version. + + A return code can be passed to get more information on failure. + */ + Plugin *LoadPlugin(const char *path, int *code = 0) + { + AutoPtr p(new Plugin); + if (p.IsNull()) + return 0; + + if (code) + *code = PluginLoadOk; + + #define Error(V) { if (code) *code = V; return 0; } + + p->shared_lib = Platform::Get().LoadSharedLibrary(path); + if (p->shared_lib.IsNull()) + Error(PluginLoadError); + + GetPluginClass *get_plugin_class = (GetPluginClass *)p->shared_lib->GetFunctionPointer("getPluginClass"); + GetPluginVersion *get_plugin_version = (GetPluginVersion *)p->shared_lib->GetFunctionPointer("getPluginVersion"); + SetSharedSystems *set_shared_systems = (SetSharedSystems *)p->shared_lib->GetFunctionPointer("setSharedSystems"); + + if (!get_plugin_class) + Error(PluginMissingClass); + if (!get_plugin_version) + Error(PluginMissingVersion); + if (!set_shared_systems) + Error(PluginInterfaceError); + if (String(T::GetPluginClass()) != get_plugin_class()) + Error(PluginClassError); + if (T::GetPluginVersion() != get_plugin_version()) + Error(PluginVersionError); + + // Set the shared platform pointer. + SharedSystems shared; + set_shared_systems(shared); + + p->path = path; + plugins.Add(p); + + return p.Detach(); + } +}; + +} // GS + + +#endif // __PLUGIN_MANAGER__ diff --git a/include/framework/plugin/shared_systems.h b/include/framework/plugin/shared_systems.h new file mode 100644 index 0000000..920b075 --- /dev/null +++ b/include/framework/plugin/shared_systems.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SHARED_SYSTEMS__ +#define __SHARED_SYSTEMS__ + + +namespace GS { + class Platform; + class AudioIO; + class PictureIO; + class LogSystem; + +class SharedSystems +{ + Platform *platform; + LogSystem *log_system; + PictureIO *picture_io; + AudioIO *audio_io; + +public: + + /// Call from the master module responsible for instantiating plugins. + void Get(); + /// Call from a dynamically module to share the master module systems. + void Set(); + + SharedSystems() : platform(0), log_system(0), picture_io(0), audio_io(0) { Get(); } +}; + +} // GS + + +#endif // __SHARED_SYSTEMS__ diff --git a/include/framework/shape/shape.h b/include/framework/shape/shape.h new file mode 100644 index 0000000..f4cae52 --- /dev/null +++ b/include/framework/shape/shape.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSHAPE__ +#define __NSHAPE__ + + + #include "math/vector.h" + + +namespace GS { + +/*! + @short Shape base class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Shape +{ + /// Get shape center. +virtual Vector4 &GetCenter() const = 0; + /// Get distance to support point on a given direction. +virtual float GetSupportDistance(const Vector4 &) const = 0; +}; + +} // GS + + +#endif // __NSHAPE__ diff --git a/include/framework/shape/shape_box.h b/include/framework/shape/shape_box.h new file mode 100644 index 0000000..68c8603 --- /dev/null +++ b/include/framework/shape/shape_box.h @@ -0,0 +1,47 @@ +/* + + nEngine + Emmanuel Julien 2000-2010 + All Rights Reserved + + http://www.gamestart3d.com + Please refer to the included license.txt for license informations. + +*/ + + +#ifndef __NSHAPEBOX__ +#define __NSHAPEBOX__ + + + #include "shape/shape.h" + + +/*! + @short Box shape class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct nBoxShape : public nShape +{ + Vector4 center; + Vector4 half_d; + +virtual Vector4 &GetCenter() const + { return center; } +virtual float GetSupportDistance(const Vector4 &d) const + { return d.Abs().Dot(half_d); } + + nSphereShape(const Vector4 &c, const Vector4 &d) + { + center = c; + half_d = d; + } + nSphereShape() + { + center.Set(0, 0, 0); + half_d.Set(0, 0, 0); + } +}; + + +#endif // __NSHAPEBOX__ diff --git a/include/framework/shape/shape_convex.h b/include/framework/shape/shape_convex.h new file mode 100644 index 0000000..0bf777a --- /dev/null +++ b/include/framework/shape/shape_convex.h @@ -0,0 +1,59 @@ +/* + + nEngine + Emmanuel Julien 2000-2010 + All Rights Reserved + + http://www.gamestart3d.com + Please refer to the included license.txt for license informations. + +*/ + + +#ifndef __NSHAPECONVEX__ +#define __NSHAPECONVEX__ + + + #include "shape/shape.h" + #include "container/narray.h" + + +/*! + @short Convex shape class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct nConvexShape : public nShape +{ + Vector4 center; + nArray vtx; + +virtual Vector4 &GetCenter() const + { return center; } +virtual float GetSupportDistance(const Vector4 &d) const + { + if (!vtx.GetCount()) + return 0; + + float d = vtx[0].Dot(d); + for (uint n = 1; n < vtx.GetCount(); ++n) + { + float _d = vtx[n].Dot(d); + if (_d > d) + d = _d; + } + return d; + } + + nConvexShape(const Vector4 &c, const nArray &v) + { + center = c; + vtx.Clone(v); + } + nConvexShape() + { + center.Set(0, 0, 0); + } +}; + + +#endif // __NSHAPECONVEX__ diff --git a/include/framework/shape/shape_sphere.h b/include/framework/shape/shape_sphere.h new file mode 100644 index 0000000..e60c737 --- /dev/null +++ b/include/framework/shape/shape_sphere.h @@ -0,0 +1,47 @@ +/* + + nEngine + Emmanuel Julien 2000-2010 + All Rights Reserved + + http://www.gamestart3d.com + Please refer to the included license.txt for license informations. + +*/ + + +#ifndef __NSHAPESPHERE__ +#define __NSHAPESPHERE__ + + + #include "shape/shape.h" + + +/*! + @short Sphere shape class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct nSphereShape : public nShape +{ + Vector4 center; + float radius; + +virtual Vector4 &GetCenter() const + { return center; } +virtual float GetSupportDistance(const Vector4 &) const + { return radius; } + + nSphereShape(const Vector4 &c, float r) + { + center = c; + radius = r; + } + nSphereShape() + { + center.Set(0, 0, 0); + radius = 0; + } +}; + + +#endif // __NSHAPESPHERE__ diff --git a/include/framework/sort/sort.h b/include/framework/sort/sort.h new file mode 100644 index 0000000..f7bbe08 --- /dev/null +++ b/include/framework/sort/sort.h @@ -0,0 +1,111 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSORT__ +#define __NSORT__ + + + #include "ntypes.h" + #include "container/narray.h" + + +namespace GS { + +/*! + Sort class. + + Can sort floating point numbers using QuickSort. + Can also sort integer numbers using Radix sort (byte-sort). + + Use T to specify the type of value to sort and O to track a user value in + the sorted array (for example an index into the unsorted array). + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template struct Sort +{ + //---------------------------------------------------------------------- + struct Entry + { + T v; + O o; + }; + //---------------------------------------------------------------------- + +protected: + +static void inline SwapEntries(Entry &a, Entry &b) + { Entry t = a; a = b; b = t; } + +static void RecurseQuickSort(Entry *entries, int left, int right) + { + if (left >= right) + return; + + int pivot = (left + right) >> 1; + SwapEntries(entries[left], entries[pivot]); + + int ls = left; + for (int cr = left + 1; cr <= right; ++cr) + if (entries[cr].v < entries[left].v) + SwapEntries(entries[cr], entries[++ls]); + + SwapEntries(entries[left], entries[ls]); + RecurseQuickSort(entries, left, ls - 1); + RecurseQuickSort(entries, ls + 1, right); + } + +public: + + /// Quicksort n entries in-place. +static void QuickSort(int n, Entry *entries) + { + RecurseQuickSort(entries, 0, n - 1); + } + + /// Byte-sort sort n entries from in to out. +static Array *ByteSort(uint n, Array *a, Array *b) + { + if (!a || !b) + return 0; + + uint radix[257]; + + for (size_t pass = 0; pass < sizeof(T); ++pass) + { + // clear radix buffer + for (uint i = 0; i < 257; ++i) + radix[i] = 0; + + // count radix + for (uint i = 0; i < n; ++i) + ++radix[uint((*a)[i].v & 255) + 1]; + + // convert count to index + for (uint i = 0; i < 256; ++i) + radix[i + 1] += radix[i]; + + // insert values + for (uint i = 0; i < n; i++) + { + const uint p = radix[uint((*a)[i].v & 255)]++; + (*b)[p].v = (*a)[i].v >> 8; // transfer & shift radix + (*b)[p].o = (*a)[i].o; + } + + // swap arrays + Array *tmp = b; b = a; a = tmp; + } + return a; + } + //---------------------------------------------------------------------- +}; + +} // GS + + +#endif + diff --git a/include/framework/timing/benchmark.h b/include/framework/timing/benchmark.h new file mode 100644 index 0000000..e103a36 --- /dev/null +++ b/include/framework/timing/benchmark.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NBENCHMARK__ +#define __NBENCHMARK__ + + + #include "time/ntime.h" + #include "container/smart_median_average.h" + + +namespace GS { + +/*! + @short Benchmark. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class Benchmark +{ + SmartMedianAverage avg; + Time r_clock, t_clock; + +public: + + void Start(); + void Stop(); + + float GetMs() const; + void Reset(); + + Benchmark(bool start = false); +}; + +/// Scoped benchmark. +struct ScopedBenchmark +{ + Benchmark &bench; + + ScopedBenchmark(Benchmark &b) : bench(b) + { bench.Start(); } + ~ScopedBenchmark() + { bench.Stop(); } +}; + +} // GS + + +#endif // __NBENCHMARK__ diff --git a/include/framework/timing/loop_benchmark.h b/include/framework/timing/loop_benchmark.h new file mode 100644 index 0000000..b4d9d04 --- /dev/null +++ b/include/framework/timing/loop_benchmark.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NLOOPBENCHMARK__ +#define __NLOOPBENCHMARK__ + + + #include "time/ntime.h" + + +namespace GS { + +/*! + @short Loop benchmark tool. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class LoopBenchmark +{ + uint loop_count; + Time r_time, t_time; + + float ms; + +public: + + void MarkLoop(); + + float GetMs() const; + float GetFps() const; + + void Reset(); + + LoopBenchmark() : loop_count(0), ms(0) {} +}; + +} // GS + + +#endif // __NLOOPBENCHMARK__ diff --git a/include/framework/timing/profiler.h b/include/framework/timing/profiler.h new file mode 100644 index 0000000..ddb44d6 --- /dev/null +++ b/include/framework/timing/profiler.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NPROFILER__ +#define __NPROFILER__ + + + #include "timing/benchmark.h" + + +namespace GS { + +/*! + @short Profiler. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct Profiler +{ + // System is owned by the profiler. + struct System + { + String label; + Benchmark profile; + + AutoList sub_systems; + + void Reset() + { + profile.Reset(); + ListForeachPtr(System *, s, sub_systems) + s->Reset(); + } + }; + + AutoList root_systems; + + /*! + @short Declare a system. + The system can be declared as a sub-system of another system. + */ + System *DeclareSystem(const char *label, System *subsystem_of = 0) + { + System *sys = new System; + if (sys == 0) + return 0; + + sys->label = label; + + if (subsystem_of) + subsystem_of->sub_systems.Add(sys); + else + root_systems.Add(sys); + + return sys; + } + + /// Reset all system in the profiler. +virtual void ResetProfiles() + { + ListForeachPtr(System *, s, root_systems) + s->Reset(); + } +}; + +#if __ENGINE_RETAIL__ + #define ScopedSystemProfile(_System) ; +#else + #define ScopedSystemProfile(_System) ScopedBenchmark _scoped_profile(_System->profile); +#endif + +} // GS + + +#endif // __NPROFILER__ diff --git a/include/modules/archive/archive.h b/include/modules/archive/archive.h new file mode 100644 index 0000000..2ab9e9d --- /dev/null +++ b/include/modules/archive/archive.h @@ -0,0 +1,163 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NARCHIVE__ +#define __NARCHIVE__ + + + #include "nstring/nstring.h" + #include "container/nlist.h" + #include "memory/nauto_ptr.h" + #include "filesystem/io_handle.h" + + +namespace GS { + namespace Threading { class Mutex; } + +/// Archive index entry. +struct ArchiveEntry +{ + // Do not change this enumeration order! +enum Method +{ + MethodRaw = 0, + MethodZLibCompress +}; + + String path; ///< Entry path. + + char method; ///< Compression method. + size_t offset; ///< Data offset in archive. + size_t length; ///< Original length. + size_t compressed_length; ///< Compressed length. +}; + +/*! + @short Archive index. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class ArchiveIndex +{ + friend class Archive; + +protected: + + AutoList index; + +public: + /// Find an entry in the index file. + ArchiveEntry *FindEntry(const char *alias) const; + + /// Load archive index. + bool Load(const char *uri); + /// Save archive index. + bool Save(const char *uri); +}; + +/*! + @short Archive storage. + + A pretty straightforward solid archive file format. + Supports per-file compression algorithm selection. + + @author Emmanuel Julien +*/ +class Archive +{ +public: + +enum Revision +{ + Legacy = 0, + EnhancedLegacy +}; + +protected: + + AutoPtr access_mutex; + + bool verbose; + bool append_mode; ///< Archive open in append mode. + + ArchiveIndex index; ///< Archive index table. + + AutoPtr handle; + + Revision revision; + size_t offset_padding, ///< File offset padding. + size_padding; ///< File size padding. + +public: + + /*! + @short Set file offset padding. + + Padding archive content is necessary on some platforms that do not + support seeking or reading an arbitrary amount of bytes inside a + file. This is often the case with the DVD unit of console systems. + */ + void SetOffsetPadding(size_t padding = 0) + { offset_padding = padding; } + /*! + @short Set file size padding. + @see SetOffsetPadding(). + */ + void SetSizePadding(size_t padding = 0) + { size_padding = padding; } + + /// Return internal index object. + const List &GetIndex() const + { return index.index; } + + /// Set the verbose mode. + void SetVerbose(bool v = true) + { verbose = v; } + + /// Load current archive index file. + bool LoadIndex(const char *path); + /// Save current archive index file. + bool SaveIndex(const char *path); + + /*! + @short Open archive. + + @note If no index is provided one will automatically be created + upon archive opening. Although this a fast process it + requires that the archive be opened on a stream-able + file system and that the whole archive be seeked through. + */ + bool OpenRead(const char *uri, const char *index_uri = 0); + /// Create a new archive. + bool CreateNew(const char *); + /// Close archive. + void Close(); + + /// Check if a file exists in archive. + ArchiveEntry *Exists(const char *path) const + { return index.FindEntry(path); } + + /*! + @short Load a file from the archive. + + @note The output buffer is expected to old enough room to store + the decompressed data. + @see Exists(). + */ + bool FileRead(const char *, void *); + + /// Write a memory block to the archive. + ArchiveEntry *MemoryBlockWrite(const char *, const void *, size_t, int compression_level = 6); + /// Write a file to the archive. + ArchiveEntry *FileWrite(const char *path, const char *alias = 0, int compression_level = 6); + + Archive(); + ~Archive(); +}; + +} // GS + + +#endif // __NARCHIVE__ diff --git a/include/modules/audio_stream_ogg/audio_stream_ogg.h b/include/modules/audio_stream_ogg/audio_stream_ogg.h new file mode 100644 index 0000000..1db6984 --- /dev/null +++ b/include/modules/audio_stream_ogg/audio_stream_ogg.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __AUDIOOGGSTREAM__ +#define __AUDIOOGGSTREAM__ + + + #include "filesystem/io_handle.h" + #define STB_VORBIS_HEADER_ONLY + #include "stb_vorbis.c" + #undef STB_VORBIS_HEADER_ONLY + #include "audio/stream_interface.h" + #include "memory/ring_buffer.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + +/* + @short OGG audio stream. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class AudioStreamOGG : public IAudioStream +{ +protected: + + AutoPtr h; + Array buffer; + size_t byte_left; + + size_t RefillBuffer(); + void ConsumeBuffer(size_t); + + int seek_correction, consumed, err; + + stb_vorbis_info vorbis_info; + stb_vorbis *vf; + +public: + + /// Return the stream data format (eg. "OGG"). + const char *GetFormat() { return "OGG"; } + + bool Seek(int t_ms = 0); + bool IsEOF() const; + + size_t GetPCM(void *); + size_t GetPCMBufferSize() const; + + bool Open(const char *uri); + void Close(); + + AudioStreamOGG(); + ~AudioStreamOGG(); +}; + +} // GS + + +#endif // __AUDIOOGGSTREAM__ diff --git a/include/modules/audio_stream_ogg/audio_stream_ogg_factory.h b/include/modules/audio_stream_ogg/audio_stream_ogg_factory.h new file mode 100644 index 0000000..16e3334 --- /dev/null +++ b/include/modules/audio_stream_ogg/audio_stream_ogg_factory.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __OGGSTREAMFACTORY__ +#define __OGGSTREAMFACTORY__ + + + #include "audio/stream_factory.h" + + +namespace GS { + +/* + @short OGG stream factory. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct OGGStreamFactory : public IAudioStreamFactory +{ + /// Get factory name. +virtual const char *GetName() { return "OGG"; } + /// Open a stream. +virtual IAudioStream *Open(const char *path); +}; + +} // GS + + +#endif // __OGGSTREAMFACTORY__ diff --git a/include/modules/debug_enet/network_debugger.h b/include/modules/debug_enet/network_debugger.h new file mode 100644 index 0000000..af4c9bf --- /dev/null +++ b/include/modules/debug_enet/network_debugger.h @@ -0,0 +1,68 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SCRIPT_NETWORK_DEBUGGER__ +#define __SCRIPT_NETWORK_DEBUGGER__ + + + #include "async/async_call_queue.h" + #include "script/script_vm_debug_profile_base.h" + + +namespace GS { + namespace Script { + class NetworkDebuggerThread; + +/*! + @short Networked debugger VM event handler. + This event handler spawns and communicates with a network controller thread. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class NetworkDebugger : public IDebuggerProfiler +{ + NetworkDebuggerThread *thread; + + bool start_signal; + +public: + + ASync::CallQueue async; + + String GetPeerAddress(); + + bool IsConnected() const; + void Stop(); + + void BroadcastNetworkCommand(const String &); + bool GetStartSignal() const { return start_signal; } + + // Network debugger interface. +virtual void OnNetworkReady(const String &, int) {} +virtual void OnControllerConnected() {} +virtual void OnControllerDisconnected() {} +virtual void OnControllerPacketReceived(const Array &); + + // Debugger interface implementation. + void OnSuspendExecution(const char *source, int line); + bool OnUpdateSuspendedExecution(); + + // VM interface implementation. + void OnFatalError(const char *reason); + void OnCompilerError(const char *error, const char *source, int line); + void OnRuntimeException(const char *error); + + NetworkDebugger(IVM *vm, IDebugger *dbg, const char *address, int port); + ~NetworkDebugger(); +}; + + } // Script +} // GS + + +#endif // __SCRIPT_NETWORK_DEBUGGER__ + + + diff --git a/include/modules/debug_enet/network_debugger_thread.h b/include/modules/debug_enet/network_debugger_thread.h new file mode 100644 index 0000000..90d362c --- /dev/null +++ b/include/modules/debug_enet/network_debugger_thread.h @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NETWORK_DEBUGGER_THREAD__ +#define __NETWORK_DEBUGGER_THREAD__ + + + #include "network_enet/enet_network.h" + #include "async/async_call_queue.h" + #include "thread/thread.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace Script { + +class NetworkDebugger; + +/*! + @short Debugger network controller. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class NetworkDebuggerThread : public Threading::Thread, public Network::Enet +{ +protected: + + String address; + int port; + + NetworkDebugger &ctl; + +private: + +static const int StateStopped = 0; +static const int StateWaitingController = 1; +static const int StateControllerConnected = 2; +static const int StateStop = 3; + + Threading::Atomic32 connected, state; + + void *ctl_peer; + +virtual void OnPeerConnection(void *); +virtual void OnPacketReceived(void *, const void *, size_t); +virtual void OnConnectionClosed(void *); + +virtual bool OpenServer(const char *address = "127.0.0.1", int port = 999); +virtual bool OpenClient(const char *address = "127.0.0.1", int port = 999) { return false; } + +virtual void Execute(); + +public: + + String GetControllerAddress(); + + bool IsConnected() const { return asbool(connected.Get()); } + void DisconnectController(); + + void SendToController(const String &); + + void Stop(); + + ASync::CallQueue async; + + NetworkDebuggerThread(NetworkDebugger &h, const char *address, int port); + ~NetworkDebuggerThread(); +}; + + } // Script +} // GS + + +#endif // __NETWORK_DEBUGGER_THREAD__ diff --git a/include/modules/font_freetype/ft2_font.h b/include/modules/font_freetype/ft2_font.h new file mode 100644 index 0000000..9e58bc2 --- /dev/null +++ b/include/modules/font_freetype/ft2_font.h @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __FT2FONT__ +#define __NTEXTFONT__ + + + #include + #include FT_FREETYPE_H + + #include "font/font_interface.h" + #include "geometry/rect.h" + #include "nstring/nstring.h" + + +namespace GS { + +/// Freetype 2 font. +class Freetype2Font : public IFont +{ + friend class Freetype2FontFactory; + + String name; + Array buffer; + + bool has_kerning; + FT_Face face; + +public: + + /// Return the font name. +virtual const char *GetName() const { return name; } + + /// Return the bounding rect for a given string. +virtual iRect GetTextBoundRect(const char *) const; + + /// Set font size in pixels. +virtual bool SetPixelSize(int); + /// Get font height in pixels. +virtual int GetHeight() const; + /// Get font current glyph advance. +virtual int GetAdvance() const; + + /// Return true if the font supports kerning. +virtual bool HasKerning() const; + /// Return the kerning for a codepoint pair. +virtual int GetKerning(uint previous_codepoint, uint codepoint) const; + + /// Load the glyph corresponding to a UTF-32 codepoint. +virtual bool LoadGlyph(uint codepoint, bool for_render); + /// Render currently loaded glyph to a picture. +virtual bool RenderCurrentGlyph(Picture &picture, const iPoint &position, const iRect &clip, const Color &color = Color::White); + + Freetype2Font() : face(0) {} + ~Freetype2Font(); +}; + +} // GS + + +#endif // __NTEXTFONT__ diff --git a/include/modules/font_freetype/ft2_font_factory.h b/include/modules/font_freetype/ft2_font_factory.h new file mode 100644 index 0000000..aba046e --- /dev/null +++ b/include/modules/font_freetype/ft2_font_factory.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __FT2FONTFACTORY__ +#define __FT2FONTFACTORY__ + + + #include "ft2build.h" + #include FT_FREETYPE_H + #include "font/font_factory.h" + + +namespace GS { + struct IFont; + +/// Font factory. +class Freetype2FontFactory : public IFontFactory +{ + FT_Library ft2; + +public: + + /// Load a font. +virtual IFont *LoadFont(const char *); + + Freetype2FontFactory(); +virtual ~Freetype2FontFactory(); +}; + +} // GS + + +#endif // __FT2FONTFACTORY__ diff --git a/include/modules/http_curl/http_curl.h b/include/modules/http_curl/http_curl.h new file mode 100644 index 0000000..015403d --- /dev/null +++ b/include/modules/http_curl/http_curl.h @@ -0,0 +1,48 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __HTTPCURL__ +#define __HTTPCURL__ + + + #include "http/http_interface.h" + #include "async/async_call_queue.h" + + +namespace GS { + namespace HTTP { + class CurlThread; + +/*! + @short CURL based HTTP helper. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class Curl : public IHTTP +{ + CurlThread *curl_thread; + + int u_ticket_id; + int GetTicketId(); + +public: + + ASync::CallQueue event_queue; + + /// Post an asynchronous HTTP request. +virtual int Post(const char *url, const char *post); + + /// Process pending event dispatch in the caller thread. +virtual void Update(); + + Curl(); + ~Curl(); +}; + + } // Http +} // GS + + +#endif // __HTTPCURL__ diff --git a/include/modules/import_fbx/import_fbx.h b/include/modules/import_fbx/import_fbx.h new file mode 100644 index 0000000..1db1133 --- /dev/null +++ b/include/modules/import_fbx/import_fbx.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __FBXIMPORT__ +#define __FBXIMPORT__ + + + #define FBXSDK_NEW_API + #include "fbxsdk.h" + + #include "import/import_interface.h" + #include "automation/automated_property_provider.h" + #include "core/resource_factory_event_interface.h" + #include "container/nlist.h" + + +namespace GS { + + namespace Core { + class Motion; + class Geometry; + struct Material; + } + namespace S3D { + class MItem; + struct MObject; + +/// Exported node cache. +struct ExportedNode +{ + FbxNode *node; + MItem *item; + + ExportedNode(FbxNode *n, MItem *i) : node(n), item(i) {} +}; + +/*! + @short Autodesk FBX Importer. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class FBXImporter : public IImport +{ + int current_node_index; + + String input_path; + Scene *scene; + const Config *config; + + FbxManager *sdk_manager; + FbxScene *fbx_scene; + + List geometry_list; + List node_list; + + /// Save material. + String SaveMaterial(const Core::Material &, const char *); + + /// Get the item corresponding to a node, if it has been exported already. + bool GetNodeItem(FbxNode *, MItem **); + + /// Export motion channels. + void ExportMotionChannel(FbxNode *, FbxAnimCurve *, Core::Motion *, Core::MotionChannel::Type); + /// Bake transformation. + void BakeTransformation(FbxNode *, MItem *, Core::Motion *); + /// Export motions. + void ExportMotions(FbxNode *, MItem *); + /// Export mesh layer. + void ExportMeshLayer(FbxMesh *, Core::Geometry *, int layer_index = 0); + /// Export skin. + bool ExportDeformers(FbxMesh *, FbxNode *, Core::Geometry &, MObject *); + /// Export vertex color. + void ExportMeshVertexColor(FbxMesh *, Core::Geometry *); + /// Export tangent frame. + void ExportMeshTangentFrame(FbxMesh *, Core::Geometry *); + /// Export a geometry (topology and normals). + String ExportGeometry(FbxMesh *, FbxNode *, MObject *); + + /// Export a file-based texture. + String ExportFileTexture(FbxFileTexture *); + /// Export a layered texture. + String ExportLayeredTexture(FbxLayeredTexture *); + /// Export a material. + String ExportMaterial(FbxSurfaceMaterial *, FbxMesh *, bool use_skin); + + /// Export a camera. + MItem *ExportCamera(FbxNodeAttribute *, FbxNode * = 0); + /// Export a mesh. + MObject *ExportObject(FbxNodeAttribute *, FbxNode * = 0); + /// Export a light. + MItem *ExportLight(FbxNodeAttribute *, FbxNode * = 0); + /// Dispatch the node to the correct exporter. + MItem *ExportNode(FbxNode *pNode); + + /// Create and import an FBX file to a native FBX scene. + FbxScene *LoadNativeScene(const char *fbx_path); + +public: + + /// Return the geometries created during import. + const List &GeometryList() const { return geometry_list; } + + /// Test importer on a file. +virtual bool TestImport(const char *uri); + /// Import scene from file. +virtual bool ImportScene(Scene *, const char *uri, const Config &, Group ** = 0); + + FBXImporter(); + ~FBXImporter(); +}; + + } // S3D +} // GS + + +#endif // __FBXIMPORT__ diff --git a/include/modules/import_obj/import_obj.h b/include/modules/import_obj/import_obj.h new file mode 100644 index 0000000..74136a2 --- /dev/null +++ b/include/modules/import_obj/import_obj.h @@ -0,0 +1,46 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NOBJ_IMPORT__ +#define __NOBJ_IMPORT__ + + + #include "import/import_interface.h" + + +struct ObjMtl; + +namespace GS { + namespace Core { class Geometry; } + namespace S3D { + +/* + @short OBJ importer. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class OBJImporter : public IImport +{ + const Config *config; + + /// Load a material library from file. + bool LoadMaterialLibrary(List &, const char *uri); + +public: + + /// Import geometry. + Core::Geometry *ImportGeometry(const char *uri, IResourceFactoryEvent * = 0); + + /// Test importer on a file. +virtual bool TestImport(const char *uri); + /// Import as scene from obj groups. +virtual bool ImportScene(Scene *, const char *uri, const Config &, Group ** = 0); +}; + + } // S3D +} // GS + + +#endif // __NOBJ_IMPORT__ diff --git a/include/modules/io_archive/io_archive.h b/include/modules/io_archive/io_archive.h new file mode 100644 index 0000000..a921046 --- /dev/null +++ b/include/modules/io_archive/io_archive.h @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOARCHIVE__ +#define __NIOARCHIVE__ + + + #include "archive/archive.h" + #include "container/narray.h" + + +namespace GS { + namespace IO { + +// +struct ArchiveHandle : public Handle +{ + size_t cursor; + Array data; + + ArchiveHandle(Base *io) : Handle(io), cursor(0) {} +}; + +/*! + @short I/O Archive + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Archive : public Base +{ + GS::Archive archive; + bool connected; + +public: + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual bool Delete(const char *); + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t); + +virtual bool MkDir(const char *) { return false; } + + bool IsConnected() const { return connected; } + + Archive(const char *uri, const char *index_uri = 0); +}; + + } // IO +} // GS + + +#endif // __NIOARCHIVE__ diff --git a/include/modules/io_net/io_net_client.h b/include/modules/io_net/io_net_client.h new file mode 100644 index 0000000..e90dbe4 --- /dev/null +++ b/include/modules/io_net/io_net_client.h @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIONETCLIENT__ +#define __NIONETCLIENT__ + + + #include "io_net/io_net_client_worker_thread.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace IO { + +// +class NetHandle : public Handle +{ + friend class Net; + + int remote_id; + +public: + + NetHandle(Base *io, int id) : Handle(io), remote_id(id) {} + ~NetHandle(); +}; + +/*! + @short Networked I/O client. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Net : public Base +{ + NetWorkerThread worker; + + bool QueueTask(NetWorkerBaseTask &); + +public: + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual String Hash(const char *uri); +virtual bool Delete(const char *) { return false; } + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t) { return 0; } + +virtual bool MkDir(const char *) { return false; } + + //--------------------------------------------------------------------- + bool IsConnected() const; + + bool Connect(const char *ip, int port); + void Disconnect(); + //--------------------------------------------------------------------- + + ~Net() { Disconnect(); } +}; + + } // IO +} // GS + + +#endif // __NIONETCLIENT__ diff --git a/include/modules/io_net/io_net_client_worker_thread.h b/include/modules/io_net/io_net_client_worker_thread.h new file mode 100644 index 0000000..3777613 --- /dev/null +++ b/include/modules/io_net/io_net_client_worker_thread.h @@ -0,0 +1,131 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIONETCLIENTWORKERTHREAD__ +#define __NIONETCLIENTWORKERTHREAD__ + + + #include "network_enet/enet_network.h" + #include "filesystem/io_handle.h" + #include "container/narray.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + #include "thread/thread.h" + #include "thread/mutex.h" + + +namespace GS { + namespace IO { + +//----------------------------------------------------------------------------- +struct NetWorkerBaseTask +{ +enum TaskType +{ TypeOpen = 0, TypeClose, TypeSeek, TypeTell, TypeRead, TypeHash }; + + TaskType type; + + // [EJ] a full memory barrier is required when accessing these two variables + Threading::Atomic32 processed; + Threading::Atomic32 success; +}; +struct NetWorkerOpenTask : public NetWorkerBaseTask +{ + String path; + Mode mode; + NetWorkerOpenTask(const char *p, Mode m) : path(p), mode(m) { type = TypeOpen; } + int handle; +}; +struct NetWorkerCloseTask : public NetWorkerBaseTask +{ + int handle; + NetWorkerCloseTask(int h) : handle(h) { type = TypeClose; } +}; +struct NetWorkerSeekTask : public NetWorkerBaseTask +{ + int handle; + ptrdiff_t offset; + Base::SeekRef seek_ref; + NetWorkerSeekTask(int h, ptrdiff_t o, Base::SeekRef ref) : handle(h), offset(o), seek_ref(ref) { type = TypeSeek; } + size_t pos; +}; +struct NetWorkerTellTask : public NetWorkerBaseTask +{ + int handle; + NetWorkerTellTask(int h) : handle(h) { type = TypeTell; } + size_t pos; +}; +struct NetWorkerReadTask : public NetWorkerBaseTask +{ + int handle; + void *data; + size_t size; + NetWorkerReadTask(int h, void *p, size_t s) : handle(h), data(p), size(s) { type = TypeRead; } + size_t read_size; +}; +struct NetWorkerHashTask : public NetWorkerBaseTask +{ + String path; + NetWorkerHashTask(const char *p) : path(p) { type = TypeHash; } + String hash; +}; +//----------------------------------------------------------------------------- + +/* + @short I/O Network worker thread. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class NetWorkerThread : public Threading::Thread, public Network::Enet +{ + String ip; + int port; + + void *server_peer; + int handshaking; + + Array response; + bool WaitServerResponse(); + void ClearServerResponse(); + + void ProcessIOPacket(const void *, size_t); + +virtual void OnPeerConnection(void *peer); +virtual void OnPacketReceived(void *peer, const void *, size_t); +virtual void OnConnectionClosed(void *peer); + +virtual void Execute(); + + Threading::Mutex task_mutex; + List task_queue; + + bool ProcessOpenTask(NetWorkerOpenTask &); + bool ProcessCloseTask(NetWorkerCloseTask &); + bool ProcessSeekTask(NetWorkerSeekTask &); + bool ProcessTellTask(NetWorkerTellTask &); + bool ProcessReadTask(NetWorkerReadTask &); + bool ProcessHashTask(NetWorkerHashTask &); + void ProcessTask(NetWorkerBaseTask &); + + Threading::Atomic32 running; + +public: + + bool IsConnected() const { return asbool(server_peer); } + + bool QueueTask(NetWorkerBaseTask &); + bool CancelTask(NetWorkerBaseTask &); + + bool Start(const char *ip, int port); + void Stop(); + + NetWorkerThread(); +}; + + } // IO +} // GS + + +#endif // __NIONETCLIENTWORKERTHREAD__ diff --git a/include/modules/io_net/io_net_server.h b/include/modules/io_net/io_net_server.h new file mode 100644 index 0000000..a2ab34d --- /dev/null +++ b/include/modules/io_net/io_net_server.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIONETSERVER__ +#define __NIONETSERVER__ + + + #include "network_enet/enet_network.h" + #include "filesystem/io_handle.h" + #include "memory/nauto_ptr.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + #include "time/ntime.h" + + +namespace GS { + namespace NML { class File; } + namespace IO { + +// +template struct Measure +{ + Time time; + T value; +}; + +/*! + @short Networked I/O server. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class NetServer : public Network::Enet +{ + SharedPtr basefs; // Support IO system. + + Measure bandwidth_measure; + int bandwidth; + +// Client handle info +struct ClientHandleInfo +{ + int id; + String name; + + AutoPtr handle; + + ClientHandleInfo() : id(0) {} +}; + +// Connected peer +struct Client +{ + void *peer; + int handshake_step; + + AutoList handles; + + Client(void *p) : peer(p), handshake_step(0) {} +}; + + AutoList clients; + + bool ProcessOpenCommand(Client &, StringList &); + bool ProcessReadCommand(Client &, StringList &); + bool ProcessSeekCommand(Client &, StringList &); + bool ProcessTellCommand(Client &, StringList &); + bool ProcessCloseCommand(Client &, StringList &); + bool ProcessHashCommand(Client &, StringList &); + bool ProcessClientRequest(Client &, const String &); + + int GetClientOpenHandleCount(const Client &) const; + int GetClientFreeHandleIndex(const Client &) const; + Handle *GetClientHandle(const Client &, int handle_id) const; + Client *GetClient(void *peer); + +public: + +struct Statistics +{ + bool connected; + + int sent_data; // in bytes + int bandwidth; // in bytes + + int packet_loss; // in % + + struct Handle + { + String name; + }; + + Array handles; + + Statistics() : connected(false), sent_data(0), bandwidth(0), packet_loss(0) {} +}; + + void GetStatistics(Statistics &); + + const AutoList &GetClients() const { return clients; } + +virtual void OnPeerConnection(void *peer); +virtual void OnPacketReceived(void *peer, const void *, size_t); +virtual void OnConnectionClosed(void *peer); + + bool Start(const char *ip, int port); + void Stop(); + + NetServer(Base *); + ~NetServer(); +}; + + } // IONet +} // GS + + +#endif // __NIONETSERVER__ diff --git a/include/modules/io_net/io_net_server_thread.h b/include/modules/io_net/io_net_server_thread.h new file mode 100644 index 0000000..2ff2169 --- /dev/null +++ b/include/modules/io_net/io_net_server_thread.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIONETSERVERTHREAD__ +#define __NIONETSERVERTHREAD__ + + + #include "io_net/io_net_server.h" + #include "thread/mutex.h" + #include "thread/thread.h" + #include "thread/atomic_value.h" + #include "filesystem/io_base.h" + #include "memory/nshared_ptr.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace IO { + +// +class NetServerThread : public Threading::Thread +{ + String ip; + int port; + + SharedPtr basefs; + Threading::Atomic32 state; + + Threading::Mutex server_mutex; + AutoPtr server; + +public: + + void GetStatistics(NetServer::Statistics &); + + void Execute(); + bool Start(const char *ip, int port); + void Stop(); + + NetServerThread(Base *fs) : basefs(fs) {} + ~NetServerThread(); +}; + + } // IO +} // GS + + +#endif // __NIONETSERVERTHREAD__ \ No newline at end of file diff --git a/include/modules/io_zip/io_zip.h b/include/modules/io_zip/io_zip.h new file mode 100644 index 0000000..cf76418 --- /dev/null +++ b/include/modules/io_zip/io_zip.h @@ -0,0 +1,74 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOZIP__ +#define __NIOZIP__ + + + #include + #include "filesystem/io_handle.h" + #include "filesystem/io_memory.h" + #include "container/nmap.h" + #include "nstring/nstring.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace IO { + +// +class ZipHandle : public Handle +{ + friend class Zip; + + AutoPtr h; + Pair *p; + +public: + + ZipHandle(Base *io) : Handle(io), p(0) {} +}; + +/*! + @short Zip-based I/O. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Zip : public Base +{ + void *zfile; + String password; + + Map refc_map; + SharedPtr memfs; // Support IO system. + +public: + + bool SetArchive(const char *uri, const char *password = 0); + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual bool Delete(const char *); + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t); + +virtual bool MkDir(const char *) { return false; } + + Zip(const char *uri, const char *password = 0); + ~Zip(); +}; + + } // IO +} // GS + + +#endif // __NIOZIP__ diff --git a/include/modules/nav_detour/navmesh.h b/include/modules/nav_detour/navmesh.h new file mode 100644 index 0000000..e08da57 --- /dev/null +++ b/include/modules/nav_detour/navmesh.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NAVMESH__ +#define __NAVMESH__ + + +namespace GS { + namespace Core { class Geometry; } + namespace Nav { + +class Mesh +{ +public: + + /// Agent configuration. +struct AgentConfig +{ + float height, + radius, + max_climb; +}; + /// Build configuration. +struct BuildConfig +{ + AgentConfig agent; +}; + + /// Build navigation mesh from configuration. + bool Build(const Core::Geometry *, const BuildConfig &); +}; + + } // Nav +} // GS + + +#endif // __NAVMESH__ diff --git a/include/modules/nav_detour/navpath.h b/include/modules/nav_detour/navpath.h new file mode 100644 index 0000000..2ce7c85 --- /dev/null +++ b/include/modules/nav_detour/navpath.h @@ -0,0 +1,13 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __PATHFINDING_PATH__ +#define __PATHFINDING_PATH__ + + + + +#endif // __PATHFINDING_PATH__ diff --git a/include/modules/network_enet/enet_network.h b/include/modules/network_enet/enet_network.h new file mode 100644 index 0000000..ec5f6ee --- /dev/null +++ b/include/modules/network_enet/enet_network.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ENETNETWORK__ +#define __ENETNETWORK__ + + + #include + #include "network/network_interface.h" + + +namespace GS { + namespace Network { + +/* + @short Enet network. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Enet : public INetwork +{ +protected: + + ENetHost *host; + +public: + +virtual void GetStatistics(Statistics &); +virtual int GetPeerPacketLossRatio(void *peer); + +/*! + @name Communication interface. + @{ +*/ +virtual void UpdateHost(); + +virtual bool Send(void *peer, const void *data, size_t size); +virtual bool Broadcast(const void *data, size_t size); +/// @} + + bool IsOpen() const { return asbool(host); } + +virtual bool GetHostAddress(String &address); +virtual bool GetPeerAddress(void *peer, String &address); +virtual void SetPeerTimeout(void *peer, Timeout = TimeoutDefault); + +virtual bool OpenServer(const char *address = "127.0.0.1", int port = 999); +virtual bool OpenClient(const char *address = "127.0.0.1", int port = 999); +virtual void Disconnect(void *peer); + + void Close(); + + Enet(); + ~Enet(); +}; + + } // Network +} // GS + + +#endif // __ENETNETWORK__ diff --git a/include/modules/physic_bullet/bullet_character_controller.h b/include/modules/physic_bullet/bullet_character_controller.h new file mode 100644 index 0000000..8a50e76 --- /dev/null +++ b/include/modules/physic_bullet/bullet_character_controller.h @@ -0,0 +1,189 @@ +#ifndef CC_PHYSICS_H +#define CC_PHYSICS_H + + + #include "BulletCollision/CollisionDispatch/btGhostObject.h" + #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" + #include "BulletCollision/CollisionShapes/btCapsuleShape.h" + #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + #include "BulletCollision/CollisionDispatch/btCollisionWorld.h" + #include "LinearMath/btDefaultMotionState.h" + #include "BulletDynamics/Character/btCharacterControllerInterface.h" + + +// +class btCustomCharacterController : public btCharacterControllerInterface +{ + btScalar mHalfHeight; + + btPairCachingGhostObject *mGhostObject; + btConvexShape *mConvexShape; + btConvexShape *mStandingConvexShape; + btConvexShape *mDuckingConvexShape; + + btCollisionWorld *mCollisionWorld; + + btVector3 mStepVelocity; + + btScalar mVerticalVelocity; + btScalar mVerticalOffset; + btScalar mFallSpeed; + btScalar mJumpSpeed; + btScalar mMaxJumpHeight; + btScalar mMaxSlopeRadians; + btScalar mMaxSlopeCosine; + btScalar mGravity; + + btScalar mTurnAngle; + + btScalar mStepHeight; + + btScalar mAddedMargin; + + btVector3 mWalkDirection; + btVector3 mNormalizedDirection; + + btVector3 mCurrentPosition; + + btManifoldArray mManifoldArray; + + bool mGroundContact; + btVector3 mGroundNormal; + + bool mTouchingContact; + +bool dbg_step_high; +bool dbg_down_sweep_hit; +void performStep(btScalar dt); +bool SweepAndSlide(btVector3 &from, btVector3 &to, int); + + bool mUseWalkDirection; + btScalar mVelocityTimeInterval; + + int mUpAxis; + + btVector3 mLinearVelocity; + btScalar mMass; + + class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback + { + btCollisionObject *mMe; + + public: + + ClosestNotMeRayResultCallback(btCollisionObject * me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0, 0, 0), btVector3(0, 0, 0)), mMe(me) {} + + btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace) + { + if (rayResult.m_collisionObject == mMe) + return 1.0; + return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); + } + }; + + class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback + { + btCollisionObject *mMe; + const btVector3 mUp; + btScalar mMinSlopeDot; + + public: + + ClosestNotMeConvexResultCallback(btCollisionObject *me, const btVector3 &up, btScalar minSlopeDot) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0, 0, 0), btVector3(0, 0, 0)), mMe(me), mUp(up), mMinSlopeDot(minSlopeDot) {} + + btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) + { + if (convexResult.m_hitCollisionObject == mMe) + return 1.0; + + btVector3 hitNormalWorld; + if (normalInWorldSpace) + hitNormalWorld = convexResult.m_hitNormalLocal; + else + hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal; + + btScalar dotUp = mUp.dot(hitNormalWorld); + if (dotUp < mMinSlopeDot) + return 1.0; + + return btCollisionWorld::ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace); + } + }; + + static btVector3 *getUpAxisDirections() + { + static btVector3 sUpAxisDirection[3] = { btVector3(1, 0, 0), btVector3(0, 1, 0), btVector3(0, 0, 1) }; + return sUpAxisDirection; + } + + static btVector3 getNormalizedVector(const btVector3& v) + { + btVector3 n = v.normalized(); + + if (n.length() < SIMD_EPSILON) + n.setValue(0, 0, 0); + + return n; + } + + bool SweepTest(const btVector3 &, const btVector3 &, btScalar &fraction, btVector3 *normal = 0, btVector3 *hit = 0); + + btVector3 computeReflectionDirection(const btVector3 & direction, const btVector3 & normal); + void setPlayerMode(); + +public: + + btCustomCharacterController(btPairCachingGhostObject *ghostObject, btConvexShape *convexShape, btScalar stepHeight, btCollisionWorld *collisionWorld, int upAxis = 1); + + btVector3 getUpAxisDirection() const { return getUpAxisDirections()[mUpAxis]; } + + void setDuckingConvexShape(btConvexShape * shape); + bool recoverFromPenetration(const btVector3 &step_direction); + void stepUp(btCollisionWorld * collisionWorld); + void setRBForceImpulseBasedOnCollision(); + void updateTargetPositionBasedOnCollision(const btVector3 & hitNormal, btScalar tangentMag = 0, btScalar normalMag = 1); + void stepForwardAndStrafe(btCollisionWorld * collisionWorld, const btVector3 & walkMove); + void stepDown(btCollisionWorld * collisionWorld, btScalar dt); + void setVelocityForTimeInterval(const btVector3 & velocity, btScalar timeInterval); + + void reset() {} + + void warp(const btVector3 & origin); + void preStep(btCollisionWorld * collisionWorld); + void playerStep(btCollisionWorld * collisionWorld, btScalar dt); + + void setFallSpeed(btScalar fallSpeed); + void setJumpSpeed(btScalar jumpSpeed); + void setMaxJumpHeight(btScalar maxJumpHeight); + + bool canJump() const; + void jump(); + + void duck(); + + void stand(); + bool canStand(); + + void setGravity(const btScalar gravity); + btScalar getGravity() const; + + void setMaxSlope(btScalar slopeRadians); + btScalar getMaxSlope() const; + + bool onGround() const; + + void setWalkDirection(const btVector3 & walkDirection); + void setWalkDirection(const btScalar x, const btScalar y, const btScalar z); + void setOrientation(const btQuaternion & orientation); + + btVector3 getWalkDirection() const; + btVector3 getPosition() const; + + void debugDraw(btIDebugDraw * debugDrawer); + + void updateAction(btCollisionWorld * collisionWorld, btScalar dt); +}; + + +#endif // CC_PHYSICS_H diff --git a/include/modules/physic_bullet/bullet_constraint.h b/include/modules/physic_bullet/bullet_constraint.h new file mode 100644 index 0000000..57c628f --- /dev/null +++ b/include/modules/physic_bullet/bullet_constraint.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NBULLET_CONSTRAINT__ +#define __NBULLET_CONSTRAINT__ + + + #include "physic/physic_constraint.h" + + +class btDiscreteDynamicsWorld; +class btTypedConstraint; + +namespace GS { + namespace S3D { + +/* + @short Bullet physic constraint. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class BulletConstraint : public PhysicConstraint +{ + friend class BulletWorld; + + btDiscreteDynamicsWorld *world; + btTypedConstraint *constraint; + +public: + void setLimitHinge(float low, float high, float _softness = 0.9f, float _biasFactor = 0.3f, float _relaxationFactor = 1.0f); + + + void SetPivotA(const Matrix4 &); + void SetPivotB(const Matrix4 &); + + bool SetupConstraint(const PhysicConstraintDesc &); + void DeleteConstraint(); + + void Enable(bool = true); + + BulletConstraint(btDiscreteDynamicsWorld *); +virtual ~BulletConstraint(); +}; + + } // S3D +} // GS + + +#endif // __NBULLET_CONSTRAINT__ diff --git a/include/modules/physic_bullet/bullet_debug.h b/include/modules/physic_bullet/bullet_debug.h new file mode 100644 index 0000000..e679f42 --- /dev/null +++ b/include/modules/physic_bullet/bullet_debug.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NBULLETDEBUG__ +#define __NBULLETDEBUG__ + + + #include "btBulletDynamicsCommon.h" + #include "color/color.h" + #include "math/vector.h" + #include "container/narray.h" + + +namespace GS { + namespace Core { class Camera; } + + namespace Render { + class Renderer; + class RasterFont; + } + namespace S3D { + using Render::Renderer; + using Render::RasterFont; + using Core::Camera; + +/*! + @short Bullet debug interface. +*/ +class BulletDebugDraw : public btIDebugDraw +{ + friend class BulletWorld; + +protected: + + Renderer &renderer; + + Camera *camera; + RasterFont *raster_font; + + int debug_mode; + + Array vtx_cache; + Array col_cache; + uint line_count; + + bool xray_first_pass; + +public: + + float GetXRayAlpha() const; + void SetXRayFirstPass(bool pass); + + void SetDebugMode(int mode) { debug_mode = mode; } + + void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color); + void drawContactPoint(const btVector3 &PointOnB, const btVector3 &normalOnB, btScalar distance, int lifeTime, const btVector3 &color); + void reportErrorWarning(const char *warningString); + void draw3dText(const btVector3 &location, const char *textString); + + void setDebugMode(int mode) { debug_mode = mode; } + int getDebugMode() const { return debug_mode; } + + void Flush(); + + BulletDebugDraw(Renderer &); +}; + + } // S3D +} // GS + + +#endif // __NBULLETDEBUG__ diff --git a/include/modules/physic_bullet/bullet_item.h b/include/modules/physic_bullet/bullet_item.h new file mode 100644 index 0000000..fd6a475 --- /dev/null +++ b/include/modules/physic_bullet/bullet_item.h @@ -0,0 +1,175 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NBULLET_ITEM__ +#define __NBULLET_ITEM__ + + + #include "physic_bullet/bullet_world.h" + #include "physic/physic_item.h" + #include "math/matrix4.h" + #include "container/narray.h" + #include "memory/nauto_ptr.h" + + #include "BulletDynamics/Character/btKinematicCharacterController.h" + + +namespace GS { + namespace S3D { + class BulletPhysicItem; + +// +class BulletMotionState : public btDefaultMotionState +{ + BulletPhysicItem *item; + Matrix4 bullet_matrix, engine_matrix; + +public: + + /// Return the last matrix Bullet sent. + const Matrix4 &GetGraphicMatrix() const { return bullet_matrix; } + void SetEngineMatrix(const Matrix4 &m) { engine_matrix = m; } + + /// Transform to Bullet. +virtual void getWorldTransform(btTransform ¢erOfMassWorldTrans) const; + /// Transform from Bullet. +virtual void setWorldTransform(const btTransform ¢erOfMassWorldTrans); + + BulletMotionState(BulletPhysicItem *); +}; + +/* + @short Bullet physic item. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class BulletPhysicItem : public PhysicItem +{ + friend class BulletWorld; + + btDiscreteDynamicsWorld *btworld; + +struct ShapeData +{ + AutoPtr shape; + + SharedPtr convex; + SharedPtr mesh; +}; + + Array shapes; + + uint collision_mask, self_mask; // cached copies to properly handle activation/deactivation. + +public: + + AutoPtr motion_state; + + AutoPtr compound; + AutoPtr rigid_body; + + AutoPtr vehicle_raycaster; + AutoPtr vehicle; + + AutoPtr ghost_object; + AutoPtr convex_shape; + AutoPtr character_controller; + + Vector4 center; + Vector4 scale; + + bool SetupCharacterController(const PhysicItemDesc &); + bool SetupKinematicDynamicBody(const PhysicItemDesc &, PhysicWorld *); + float SetupCollisionShapes(const PhysicItemDesc &, Array &, PhysicWorld *); + void ForceUpdateMassShapePhysic(const PhysicItemDesc &, PhysicWorld *); + + /// Create a Bullet transformation from a 4x4 matrix. +static void TransformFromMatrix4(const Matrix4 &, btTransform &); + /// Create a 4x4 matrix to a Bullet transformation. +static void TransformToMatrix4(const btTransform &, Matrix4 &); + + /* + @short Return the center of mass offset. + Bullet does not handle offset center of mass directly. + */ + const Vector4 &GetCenter() const { return center; } + + void SetScale(const Vector4 &); + Vector4 GetScale() const; + + //---------------------------------------------------------------------- + void SetSelfMask(uint m); + uint GetSelfMask() const; + void SetCollisionMask(uint m); + uint GetCollisionMask() const; + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + void SetLinearFactor(const Vector4 &); + void SetAngularFactor(const Vector4 &); + + void SetLinearDamping(float = 0.999f); + float GetLinearDamping() const; + void SetAngularDamping(float = 0.99f); + float GetAngularDamping() const; + + void SetGravity(const Vector4 &); + Vector4 GetGravity() const; + void ApplyImpulse(const Vector4 &I, const Vector4 *p = 0); + void ApplyForce(const Vector4 &F, const Vector4 *p = 0); + void ApplyTorque(const Vector4 &T); + + void SetAngularVelocity(const Vector4 &); + Vector4 GetAngularVelocity() const; + void SetLinearVelocity(const Vector4 &); + Vector4 GetLinearVelocity() const; + + Vector4 GetLocalPointVelocity(const Vector4 &) const; + Vector4 GetWorldPointVelocity(const Vector4 &) const; + + Vector4 GetCenterOfMass() const; + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + void GetGraphicMatrix(Matrix4 &); + void SetEngineMatrix(const Matrix4 &); + void GetMatrix(Matrix4 &); + void SetMatrix(const Matrix4 &); + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- +virtual void VehicleSetForce(float F, uint wheel_index); +virtual void VehicleSetBrake(float F, uint wheel_index); +virtual void VehicleSetSteering(float v, uint wheel_index); +virtual void VehicleSetFriction(float f, uint wheel_index); + +virtual Matrix4 VehicleGetWheelMatrix(uint wheel_index); + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- +virtual void CharacterSetRotationMatrix(const Matrix3 &); +virtual void CharacterSetVelocity(const Vector4 &); + //---------------------------------------------------------------------- + +virtual void SetSleeping(bool sleep = false); +virtual bool IsSleeping() const; + +virtual void SetActive(bool active); +virtual bool GetActive() const; + +virtual void ResetBody(); + +virtual bool SetupBody(const PhysicItemDesc &, PhysicWorld *); +virtual void DeleteBody(); + + BulletPhysicItem(btDiscreteDynamicsWorld * = 0); +virtual ~BulletPhysicItem(); +}; + + } // S3D +} // GS + + +#endif // __NBULLET_ITEM__ diff --git a/include/modules/physic_bullet/bullet_world.h b/include/modules/physic_bullet/bullet_world.h new file mode 100644 index 0000000..e20c8d6 --- /dev/null +++ b/include/modules/physic_bullet/bullet_world.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __NBULLETPHYSICWORLD__ +#define __NBULLETPHYSICWORLD__ + + + #include "nstring/nstring.h" + +/* + @short Enable multi-threading support in Bullet Dynamics. + Not working at the moment (need to let the API stabilize a bit first). +*/ +#define __ENABLE_BULLET_MULTITHREAD__ 0 +/* + @short Number of thread used by Bullet. +*/ +#define __BULLET_THREAD_COUNT__ 3 + + + #include "memory/nauto_ptr.h" + #include "memory/nshared_ptr.h" + #include "physic/physic_world.h" + #include "btBulletDynamicsCommon.h" + #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" + +#if __ENABLE_BULLET_MULTITHREAD__ + #include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h" + #include "BulletMultiThreaded/PlatformDefinitions.h" + #if __PLATFORM_WINDOWS__ + #include "BulletMultiThreaded/Win32ThreadSupport.h" + #include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + #elif __PLATFORM_LINUX__ + #include "BulletMultiThreaded/PosixThreadSupport.h" + #include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" + #endif +#endif + +namespace GS { + namespace S3D { + class Scene; + class BulletDebugDraw; + +/// Bullet convex hull. +struct BulletConvex : public SharedObject +{ + String name; + Vector4 center; + AutoPtr convex; +}; + +/// Bullet mesh. +struct BulletMesh : public SharedObject +{ + String name; + String suffix; + Vector4 center; + + Array bt_mat; + Array bt_id_mat; + Array bt_vtx; + Array bt_idx; + + AutoPtr mesh_interface; + AutoPtr mesh; +}; + +/*! + @short Bullet physic world. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class BulletWorld : public PhysicWorld +{ +protected: + + SharedList mesh_cache; + SharedList convex_cache; + + AutoPtr world; + AutoPtr broadphase; + AutoPtr dispatcher; + AutoPtr collision_config; + AutoPtr solver; + AutoPtr pair_callback; +#if __ENABLE_BULLET_MULTITHREAD__ + AutoPtr thread_support_collision; +#endif + + AutoPtr debug_draw; + +public: + + PhysicItem *NewItem(); + PhysicConstraint *NewConstraint(); + + BulletConvex *LoadConvex(const char *); + BulletMesh *LoadMesh(const char *, const char *suffix); + void ClearConvexMeshCache(); + + bool HasDebugger() const; + void CreateDebugger(Renderer * = 0); + + void DrawDebug(Renderer &, Camera *, RasterFont *, bool xray_first_pass); + + /// Raytrace world, the callback object Process() method is called on each hit. + bool Raytrace(const Vector4 &s, const Vector4 &d, PhysicTrace &, int collision_mask = ~0, int shape_mask = ~0, float max_distance = -1.f); + + uint GetCollisionPairCount(); + bool GetCollisionPair(uint, CollisionPair &); + + void Step(const Time &dt); + + bool Create(); + void Delete(); + + BulletWorld(); + ~BulletWorld(); +}; + + } // S3D +} // GS + + +#endif // __NBULLETPHYSICWORLD__ diff --git a/include/modules/pict_io_jpeglib/pict_jpeglib_codec.h b/include/modules/pict_io_jpeglib/pict_jpeglib_codec.h new file mode 100644 index 0000000..6d83721 --- /dev/null +++ b/include/modules/pict_io_jpeglib/pict_jpeglib_codec.h @@ -0,0 +1,34 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __PICTJPEGLIBCODEC__ +#define __PICTJPEGLIBCODEC__ + + + #include "picture/pict_io_codec.h" + + +namespace GS { + +/* + @short IJG jpeglib codec. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct PictureJpeglibCodec : public PictureCodec +{ +virtual bool Load(IO::Handle &, Picture &); +virtual bool Save(IO::Handle &, const Picture &); + +virtual const char *GetName() const { return "IJG"; } +virtual const char *GetDesc() const { return "IJG jpeglib read/write codec"; } + +virtual uint GetCaps() const { return CanRead | CanWrite | WriteLossy | AlphaChannel; } +}; + +} + + +#endif // __PICTJPEGLIBCODEC__ diff --git a/include/modules/pict_io_stb/pict_stb_codec.h b/include/modules/pict_io_stb/pict_stb_codec.h new file mode 100644 index 0000000..61680c8 --- /dev/null +++ b/include/modules/pict_io_stb/pict_stb_codec.h @@ -0,0 +1,34 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __PICTSTBCODEC__ +#define __PICTSTBCODEC__ + + + #include "picture/pict_io_codec.h" + + +namespace GS { + +/* + @short STB (Sean Barrett picture) codec. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct PictureSTBCodec : public PictureCodec +{ + bool Load(IO::Handle &, Picture &); + + const char *GetName() const { return "STB"; } + const char *GetDesc() const { return "STB image (Sean Barrett image library) codec"; } + + uint GetCaps() const { return CanRead; } +}; + +} // GS + + +#endif // __PICTSTBCODEC__ + diff --git a/include/modules/raytracer/raytracer_core.h b/include/modules/raytracer/raytracer_core.h new file mode 100644 index 0000000..3b45ef1 --- /dev/null +++ b/include/modules/raytracer/raytracer_core.h @@ -0,0 +1,296 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __TRACER_CORE__ +#define __TRACER_CORE__ + + + #include "raytracer/raytracer_scene.h" + #include "raytracer/raytracer_spread.h" + #include "core/shader_tree.h" + #include "core/material.h" + #include "picture/pict.h" + + +namespace GS { + struct Color; + + namespace Core { + struct ShaderBlock; + struct ShaderBlockValue; + } + namespace S3D { class Scene; } + namespace Raytrace { + +// +struct Bounce +{ + uint indirect, + reflection, + refraction; +}; + +/// Ray grid (ray density estimation). +struct RayGrid +{ + Vector4 p[4], d[4]; + + RayGrid(const Vector4 &_p, const Vector4 &_d) + { p[0] = _p; d[0] = _d; } +}; + +// +struct Statistics +{ + uint ray_count, + tri_test; + + void Reset() + { + ray_count = 0; + tri_test = 0; + } + + Statistics() + { Reset(); } +}; + +// +struct Configuration +{ + uint trace_shadow_transparency_max_recursion, + trace_reflection_max_recursion, + trace_refraction_max_recursion, + indirect_gi_bounce, + gi_sample, + aa_sample; + + bool trace_shadow, + trace_gi, + trace_aa, + trace_transparency, + trace_reflection, + trace_refraction, + gi_use_ambient, + aa_jitter, + ao_activate, + fresnel_activate; + + float ao_length, + ao_angle; + + bool interlaced, ///< Interlaced render. + interlace_even, ///< Start with even ordered scanline. + interlaced_trace_half_frame; ///< When rendering interlaced, compute half-frames instead of full ones (at a very small cost in quality). + + float aa_threshold; + + uint job_affinity; + + Configuration() + { + trace_shadow_transparency_max_recursion = 32; + trace_reflection_max_recursion = 2; + trace_refraction_max_recursion = 6; + indirect_gi_bounce = 1; + + trace_shadow = true; + trace_reflection = true; + trace_refraction = true; + trace_gi = false; + trace_aa = true; + trace_transparency = true; + + ao_length = 1.0f; + ao_angle = 90.0f; + ao_activate = false; + + fresnel_activate = false; + + gi_use_ambient = false; + gi_sample = 8; + aa_sample = 4; + aa_threshold = 0.0075f; + aa_jitter = false; + + interlaced = false; + interlace_even = true; + interlaced_trace_half_frame = true; + + job_affinity = uint(~0); + } +}; + +class Raytracer; + +// +struct Progress +{ + const Raytracer *instance; + + String description; + uint start_clock; ///< System clock when rendering started. + + float progress; + int w, h; + Color *buffer; + + bool aborted; ///< Rendering aborted. + bool done; ///< Rendering done. +}; + +/// Progress hook. +struct ProgressHook +{ virtual bool RaytracerProgress(const Progress &) = 0; }; + +/*! + @short Raytracer. + + This class can be used as a generic raytracer to render raytraced pictures + of a scene or as a baking tool for the nGeometry class. + Supports, forward raytracing, Monte-Carlo raytracing, photon mapping along + more common material properties, diffuse, specular, reflection, refraction, + etc... + + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Raytracer +{ +public: + +/// Geometry attributes. +enum GeometryAttribute +{ + GeometryNormal = 0, + GeometryVertexColor +}; + +protected: + + bool abort; + + Core::ResourceFactory *gf; + + const S3D::Scene *scene; + + SceneBIH scene_tree, ///< Scene tree. + scene_shadow_tree; ///< Shadow scene tree. + + Array lgt; ///< Light array. + + Statistics statistics; + Configuration configuration; + Spread monte_carlo[32]; ///< Monte-Carlo vector spread. + + Vector2 viewport; ///< Output resolution of the current rendering. + + float render_clock; ///< Reference clock frozen at frame start. + + /// Compute the Fresnel factor + float Fresnel(const Vector4 &v, const Vector4 &np, float eta); + + /// Compute trace result radiance. + void ComputeRadiance(Trace &trace, Color &o, Bounce &bounce); + /// Raytrace. + void Raytrace(const RayGrid &ray, Color &o, Bounce &bounce, Trace *previous_trace = 0); + + /// Evaluate shader block on the CPU. + bool EvaluateShaderBlock(const Trace &trace, const Core::ShaderBlock *block, Core::ShaderBlockValue &out); + + /// Sample material opacity. + float SampleMaterialOpacity(const Trace &trace); + /// Sample material sink. +virtual Vector4 SampleMaterialSink(const Trace &trace, Core::ShaderTree::ShaderSinkType sink); + /// Sample material attribute. + Vector4 SampleMaterialAttribute(const Trace &trace, Core::MaterialChannel channel); + /// Sample geometry attribute. + Vector4 SampleGeometryAttribute(const Trace &trace, GeometryAttribute attr); + + /// Shadow feel. + float ShadowFeel(const Vector4 &s, const Vector4 &d, float l, int r); + +/*! + @name Interlace support. + @{ +*/ + bool interlace_even; ///< Internal interlace parity. + Picture interlace_half_frame; ///< The previous interlace frame. +/// @} + +public: + + ProgressHook *hook; + + /// Get system configuration. + Configuration &GetConfiguration() + { return configuration; } + /// Set system configuration. + void SetConfiguration(const Configuration &config); + + /// Return system statistics object. + const Statistics &GetStatistics() const { return statistics; } + + /// Abort current rendering. + void Abort(); + /// Last render abort flag. + bool Aborted() const { return abort; } + + /*! + @short Start a rendering sequence. + + @note This call is only necessary when rendering an interlaced + sequence. + */ + void StartInterlacedSequence(); + + /// Trace a primary ray across the scene tree, returns resulting HDR color. + void PrimaryRay(const RayGrid &ray, Color &o); + /*! + @short Raytrace scene to a raw raytracing structure. + + Use this function if you need the intersected scene object and its + geometric properties rather than a fully computed evaluation. + */ + void RawPrimaryRay(const Vector4 &s, const Vector4 &d, Trace &t, float l = -1.f) { scene_tree.RaytraceScene(t, s, d, l); } + /*! + @short Perform a full scene raytracing. + + @note The raytracer internally only works with real colors. + The frame is converted by the end of the render to rgb24. + @note The provided picture object will be reallocated to the + render output dimensions and all previous content will be + lost. + */ + bool Render(Picture &, uint width = 640, uint height = 480); + + /// Return the internal scene BIH tree. + SceneBIH &GetBIH() { return scene_tree; } + /// Return the internal scene shadow BIH tree. + SceneBIH &GetShadowBIH() { return scene_shadow_tree; } + + /*! + @short Setup a scene for use by the raytracer. + + @note The raytracer does not mirror any data from the scene + so it will rely on the object remaining valid as long + as it is registered as the current raytracer scene. + @warning Before deleting the referred scene object do not forget + to call SetScene(NULL) in order to release all + references. + */ + bool SetScene(const S3D::Scene *); + + void Free(); + + Raytracer(Core::ResourceFactory * = 0); +virtual ~Raytracer() {} +}; + + } // Raytrace +} // GS + + +#endif // __TRACER_CORE__ diff --git a/include/modules/raytracer/raytracer_job.h b/include/modules/raytracer/raytracer_job.h new file mode 100644 index 0000000..e23f2f8 --- /dev/null +++ b/include/modules/raytracer/raytracer_job.h @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRAYTRACERJOB__ +#define __NRAYTRACERJOB__ + + + #include "raytracer/raytracer_core.h" + #include "async/job.h" + + +namespace GS { + namespace Raytrace { + +// +struct RaytraceJob : public ASync::Job +{ +virtual void Execute(uint); + + Raytracer *core; + Color *hdr; + int pitch; + + int start_height, end_height; + int start_width, end_width; + + Vector4 s; + Vector4 dt_l, pt_l, dt_r, pt_r; + + RaytraceJob() : Job("Raytrace") {} +}; + +// +struct AntialiasJob : public ASync::Job +{ +virtual void Execute(uint); + + Raytracer *core; + Color *hdr; + int pitch; + + int start_height, end_height; + int start_width, end_width; + + Vector4 s; + Vector4 dt_l, pt_l, dt_r, pt_r; + + AntialiasJob() : Job("Antialias") {} +}; + + } // Raytrace +} // GS + + +#endif // __NRAYTRACERJOB__ diff --git a/include/modules/raytracer/raytracer_scene.h b/include/modules/raytracer/raytracer_scene.h new file mode 100644 index 0000000..ea5e35d --- /dev/null +++ b/include/modules/raytracer/raytracer_scene.h @@ -0,0 +1,124 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRAYTRACERSCENE__ +#define __NRAYTRACERSCENE__ + + + #include "core/geometry_tree.h" + #include "bih/bih.h" + + +namespace GS { + + namespace Core { + class Object; + class Geometry; + struct Material; + } + namespace S3D { + class Scene; + struct MLight; + struct MObject; + } + namespace Raytrace { + using Core::IGeometryTree; + +// +struct Trace : public Core::GeometryTrace +{ + Vector4 pi; ///< Intersection point. + Vector4 n; ///< Normal. + + float ir; ///< Current media index of refraction. + float td; ///< Total distance traveled by the ray. + + Core::Object *o; ///< Object intersected. + + Trace(bool closest = true) : Core::GeometryTrace(closest) + { + ir = 1; + td = 0; + m = NULL; + } +}; + +/// +struct Object +{ + Core::Object *o; ///< Object. + Core::sGeometry og, g; ///< Associated geometry. + + AutoPtr tree; + + Object() : o(0) {} +}; + +/// +struct Light +{ + IGeometryTree *g; ///< Shadow cache tree. + uint ip; ///< Shadow cache polygon index. + + S3D::MLight *l; + + Light() : l(0) {} +}; + +/*! + @short Raytracer scene acceleration structure. +*/ +class SceneBIH : BIH::Tree +{ + Array obj; ///< Object array. + + /// Trace leaf content. + void TraceLeaf(BIH::Node *, float tmin, float tmax, BIH::Trace &, void *parm = 0); + + /// Add an object to the scene BIH. + void AddObject(Core::ResourceFactory &, S3D::MObject *, uint &obj_count, MinMax *varray, bool shadow); + +public: + + /*! + @short Translate proxy geometry. + + The raytracer may need to make a hard copy of a geometry for example + to freeze its modifiers before building the acceleration structure. + + This function returns the original geometry from the proxy one as + returned by a primary ray test. + + @note If the geometry is not a proxy, it will be returned as is. + */ + Core::Geometry *TranslateGeometry(Core::Geometry *) const; + +/*! + @group Statistics + @{ +*/ + uint ray_count; ///< Number of ray traced. + + /// Reset internal statistic counters. + void ResetStats(); +/// @} + + /// Build scene tree based on a scene instance. +virtual bool SetScene(Core::ResourceFactory &, const S3D::Scene *, bool shadow = false); + /// Free tree structures. +virtual void Free(); + + /// Raytrace hierarchy. +virtual void RaytraceScene(Trace &, const Vector4 &s, const Vector4 &d, float l = -1.f); + + SceneBIH() { min_leaf_vcount = 3; } +}; + + } // Raytrace +} // GS + + +#endif // __NRAYTRACERSCENE__ diff --git a/include/modules/raytracer/raytracer_spread.h b/include/modules/raytracer/raytracer_spread.h new file mode 100644 index 0000000..260ef8c --- /dev/null +++ b/include/modules/raytracer/raytracer_spread.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRAYTRACER_SPREAD__ +#define __NRAYTRACER_SPREAD__ + + + #include "math/vector.h" + #include "container/narray.h" + + +namespace GS { + namespace Raytrace { + +// +struct Spread +{ + Array spread; + + bool Initialize(uint u_count, uint v_count, float max_spread = Units::Deg(90.f)); + void Free(); +}; + + } // Raytrace +} // GS + + +#endif // __NRAYTRACER_SPREAD__ diff --git a/include/modules/script_squirrel/cobject/cobject.h b/include/modules/script_squirrel/cobject/cobject.h new file mode 100644 index 0000000..0f8786c --- /dev/null +++ b/include/modules/script_squirrel/cobject/cobject.h @@ -0,0 +1,58 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __COBJECT__ +#define __COBJECT__ + + + #include "script/script_engine_types.h" + #include "script_squirrel/squirrel_vm.h" + #include "thread/mutex.h" + + +namespace GS { + namespace Script { + struct EngineVM; + +/*! + @short Weak/shared reference to native C/C++ objects for the Squirrel VM. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class CObject +{ + EngineVM *vm; + +public: + + /// Pop safe user pointer. +static bool Get(HSQUIRRELVM, int stack_index, void **, CObjectType = typetag_Undefined); + /// Get safe user pointer type. +static bool GetType(HSQUIRRELVM, int idx, CObjectType &); + // Get a base object from derived types. +static bool GetBase(HSQUIRRELVM, int idx, void **, CObjectType *derived_types); + /// Push safe user pointer. +static bool Push(HSQUIRRELVM, void *, CObjectType, bool managed = false); + + /// Initialize reference to a native type. + void Initialize(CObjectType, void *, bool managed); + /// Release reference to a native type. + void Release(); + + bool managed; + List ::Item *list_item; // Needs to be cached for fast deletion. + + CObjectType type; + void *native; + + CObject(EngineVM *vm, CObjectType = typetag_Undefined, void *p = 0, bool managed = false); + ~CObject(); +}; + + } // Script +} // GS + + +#endif // __COBJECT__ diff --git a/include/modules/script_squirrel/cobject/cobject_decl.h b/include/modules/script_squirrel/cobject/cobject_decl.h new file mode 100644 index 0000000..08f039e --- /dev/null +++ b/include/modules/script_squirrel/cobject/cobject_decl.h @@ -0,0 +1,20 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __COBJECT_DECL +#define __COBJECT_DECL + + + #include "script_squirrel/cobject/squirrel_bindings_utils.h" + + +namespace GS { class CObject; } + +_DECL_CLASS(CObject); +_DECL_NATIVE_CONSTRUCTION(CObject, GS::CObject); + + +#endif // __COBJECT_DECL diff --git a/include/modules/script_squirrel/cobject/geometry_template_decl.h b/include/modules/script_squirrel/cobject/geometry_template_decl.h new file mode 100644 index 0000000..43a8c4d --- /dev/null +++ b/include/modules/script_squirrel/cobject/geometry_template_decl.h @@ -0,0 +1,20 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __COBJECT_GEOMETRY_TEMPLATE_DECL__ +#define __COBJECT_GEOMETRY_TEMPLATE_DECL__ + + + #include "script_squirrel/cobject/squirrel_bindings_utils.h" + + +class nGeometryTemplate; + +_DECL_CLASS(GeometryTemplate) +_DECL_NATIVE_CONSTRUCTION(GeometryTemplate, nGeometryTemplate) + + +#endif // __COBJECT_GEOMETRY_TEMPLATE_DECL__ diff --git a/include/modules/script_squirrel/cobject/matrix_decl.h b/include/modules/script_squirrel/cobject/matrix_decl.h new file mode 100644 index 0000000..d94c70c --- /dev/null +++ b/include/modules/script_squirrel/cobject/matrix_decl.h @@ -0,0 +1,25 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __COBJECT_MATRIX_DECL__ +#define __COBJECT_MATRIX_DECL__ + + + #include "script_squirrel/cobject/squirrel_bindings_utils.h" + + +namespace GS { + class Matrix3; + class Matrix4; +} + +_DECL_CLASS(Matrix3) +_DECL_NATIVE_CONSTRUCTION(Matrix3, GS::Matrix3) +_DECL_CLASS(Matrix4) +_DECL_NATIVE_CONSTRUCTION(Matrix4, GS::Matrix4) + + +#endif // __COBJECT_MATRIX_DECL__ diff --git a/include/modules/script_squirrel/cobject/quaternion_decl.h b/include/modules/script_squirrel/cobject/quaternion_decl.h new file mode 100644 index 0000000..e4b1932 --- /dev/null +++ b/include/modules/script_squirrel/cobject/quaternion_decl.h @@ -0,0 +1,24 @@ +/* ----------------------------------------------------------------------------- + nEngine - GSFramework + Copyright 2001-2012 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __COBJECT_QUATERNION_DECL__ +#define __COBJECT_QUATERNION_DECL__ + + + #include "script_squirrel/cobject/squirrel_bindings_utils.h" + +#ifndef _T +#define _T +#endif + +struct nQuaternion; + + +_DECL_CLASS(Quaternion) +_DECL_NATIVE_CONSTRUCTION(Quaternion, nQuaternion) + + +#endif // __COBJECT_QUATERNION_DECL__ diff --git a/include/modules/script_squirrel/cobject/squirrel_bindings_utils.h b/include/modules/script_squirrel/cobject/squirrel_bindings_utils.h new file mode 100644 index 0000000..5d021f8 --- /dev/null +++ b/include/modules/script_squirrel/cobject/squirrel_bindings_utils.h @@ -0,0 +1,239 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __CU_BINDING_UTILS__ +#define __CU_BINDING_UTILS__ + + + #include "squirrel.h" + #include "script_squirrel/cobject/squirrel_object.h" + + +namespace GS { + namespace Script { + class CObject; + } +} + +struct ScriptClassMemberDecl +{ + const SQChar *name; + SQFUNCTION func; + int params; + const SQChar *typemask; +}; + +struct SquirrelClassDecl +{ + const SQChar *name; + const SQChar *base; + const ScriptClassMemberDecl *members; +}; + +struct ScriptConstantDecl +{ + const SQChar *name; + SQObjectType type; + + union value + { + value(int v = 0) { i = v; } + value(float v) { f = v; } + value(const SQChar *v) { s = v; } + + float f; + int i; + const SQChar *s; + } val; +}; + +struct ScriptNamespaceDecl +{ + const SQChar *name; + const ScriptClassMemberDecl *members; + const ScriptConstantDecl *constants; + const ScriptClassMemberDecl *delegate; +}; + +//------------------------------------------------------------------------------ +#define case_ItemDerived \ +case typetag_Camera: \ +case typetag_Object: \ +case typetag_Light: \ +case typetag_Trigger: \ +case typetag_Item: +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +#define _GetCObject(_CPP_CLASS, _TYPETAG, _VAR, _IDX) \ + _CPP_CLASS *_VAR = NULL; \ + { \ + _GetParamAt(GS::Script::CObject, CObject, _IDX) \ + if (self->type != _TYPETAG) \ + return sa.ThrowError("Invalid type"); \ + if (!self->native) \ + return sa.ThrowError("Object is null"); \ + _VAR = (_CPP_CLASS *)self->native; \ + } + +#define _GetSelfNonNull \ + _GetSelf(GS::Script::CObject, CObject); \ + if (!self->native) \ + return sa.ThrowError("Object is null"); +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +#define _BEGIN_CLASS(classname)\ + SQInteger __##classname##__SCypeof(HSQUIRRELVM v)\ + {\ + sq_pushstring(v,_SC(#classname),-1);\ + return 1;\ + }\ + struct ScriptClassMemberDecl __##classname##_members[] = {\ + {_SC("_SCypeof"),__##classname##__SCypeof,1,NULL}, + +#define _BEGIN_NAMESPACE(xnamespace) struct ScriptClassMemberDecl __##xnamespace##_members[] = { +#define _BEGIN_NAMESPACE_CONSTANTS(xnamespace) {NULL,NULL,NULL,NULL}}; \ + struct ScriptConstantDecl __##xnamespace##_constants[] = { + +#define _BEGIN_DELEGATE(xnamespace) struct ScriptClassMemberDecl __##xnamespace##_delegate[] = { +#define _DELEGATE(xnamespace) __##xnamespace##_delegate +#define _END_DELEGATE(classname) {NULL,NULL,NULL,NULL}}; + +#define _CONSTANT(name,type,val) {_SC(#name),type,val}, +#define _CONSTANT_IMPL(name,type) {_SC(#name),type,name}, + +#define _MEMBER_FUNCTION(classname,name,nparams,typemask) \ + {_SC(#name),__##classname##_##name,nparams,typemask}, + +#define _END_NAMESPACE(classname,delegate) {NULL,OT_NULL,0}}; \ +struct ScriptNamespaceDecl __##classname##_decl = { \ + _SC(#classname), __##classname##_members,__##classname##_constants,delegate }; + +#define _END_CLASS(classname) {NULL,NULL,NULL,NULL}}; \ +struct SquirrelClassDecl __##classname##_decl = { \ + _SC(#classname), NULL, __##classname##_members }; + +#define _END_CLASS_INHERITANCE(classname,base) {NULL,NULL,NULL,NULL}}; \ +struct SquirrelClassDecl __##classname##_decl = { \ + _SC(#classname), _SC(#base), __##classname##_members }; + +#define _MEMBER_FUNCTION_IMPL(classname,name) \ + SQInteger __##classname##_##name(HSQUIRRELVM v) \ +{ \ + StackHandler sa(v); +#define _END_IMPL } + +#define _INIT_STATIC_NAMESPACE(vm,classname) CreateStaticNamespace(vm,&__##classname##_decl); +#define _INIT_CLASS(vm,classname)CreateClass(vm,&__##classname##_decl); + +#define _DECL_STATIC_NAMESPACE(xnamespace) extern struct ScriptNamespaceDecl __##xnamespace##_decl; +#define _DECL_CLASS(classname) extern struct SquirrelClassDecl __##classname##_decl; + +#define _GetSelf(cppclass,scriptclass) \ + cppclass *self = NULL; \ + if (SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)&__##scriptclass##_decl))) \ + return sq_throwerror(v,_SC("Invalid instance type"));\ + if (!self)\ + return sa.ThrowError("Internal failure"); + +#define _GetParamAt(cppclass,scriptclass,idx) \ + cppclass *self = NULL; \ + if (SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&self,(SQUserPointer)&__##scriptclass##_decl))) \ + return sq_throwerror(v,_SC("Invalid instance type")); \ + if (!self) \ + return sa.ThrowError("Internal failure"); + +#define _CHECK_INST_PARAM_RAW(pname,idx,cppclass,scriptclass) \ + cppclass *pname = NULL; \ + if (SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&pname,(SQUserPointer)&__##scriptclass##_decl))) pname = NULL; + +//------------------------------------------------------------------------------ +#define _GetTypedParam(pname,idx,cppclass,scriptclass) \ + cppclass *pname = NULL; \ + if (SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&pname,(SQUserPointer)&__##scriptclass##_decl))) \ + return sq_throwerror(v,_SC("Invalid instance type")); + +#define _CHECK_INST_PARAM_COBJECT(__PARAM__, __IDX__, __CPPCLASS__) \ + __CPPCLASS__ *__PARAM__ = NULL; \ + { \ + _GetTypedParam(c_object, __IDX__, GS::CObject, CObject) \ + if (!c_object->c_object) \ + return sq_throwerror(v, "C Object is null"); \ + __PARAM__ = (__CPPCLASS__ *)c_object->c_object; \ + } + +#define _CHECK_INST_PARAM_BREAK(pname,idx,cppclass,scriptclass) \ + cppclass *pname = NULL; \ + if (SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&pname,(SQUserPointer)&__##scriptclass##_decl))) \ + break; +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +#define _CLASS_SCAG(classname) ((SQUserPointer)&__##classname##_decl) +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +#define _DECL_NATIVE_CONSTRUCTION(classname,cppclass)\ +bool push_##classname(HSQUIRRELVM v, const cppclass &quat);\ +SquirrelObject new_##classname(HSQUIRRELVM v, const cppclass &quat); +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +#define _IMPL_NATIVE_CONSTRUCTION(classname, cppclass)\ +static SQInteger classname##_release_hook(SQUserPointer p, SQInteger size)\ +{\ + if (p)\ + {\ + cppclass *pv = (cppclass *)p;\ + delete pv;\ + }\ + return 0;\ +}\ +bool push_##classname(HSQUIRRELVM vm, const cppclass &quat)\ +{\ + cppclass *newquat = new cppclass;\ + *newquat = quat;\ + if (!CreateNativeClassInstance(vm,#classname,newquat,classname##_release_hook))\ + {\ + delete newquat;\ + return false;\ + }\ + return true;\ +}\ +::SquirrelObject new_##classname(HSQUIRRELVM vm, const cppclass &quat)\ +{\ + ::SquirrelObject ret(vm);\ + if (push_##classname(vm, quat))\ + {\ + ret.AttachToStackObject(-1);\ + sq_pop(vm, 1);\ + }\ + return ret;\ +}\ +int construct_##classname(HSQUIRRELVM vm, cppclass *p)\ +{\ + sq_setinstanceup(vm, 1, p);\ + sq_setreleasehook(vm, 1, classname##_release_hook);\ + return 1;\ +} +//------------------------------------------------------------------------------ + +bool CreateStaticClass(HSQUIRRELVM v, SquirrelClassDecl *cd); +bool CreateStaticNamespace(HSQUIRRELVM v, ScriptNamespaceDecl *sn); +bool CreateClass(HSQUIRRELVM v, SquirrelClassDecl *cd); +bool InitScriptClasses(HSQUIRRELVM v); +bool CreateNativeClassInstance(HSQUIRRELVM v, const SQChar *classname, SQUserPointer ud, SQRELEASEHOOK hook); +int refcounted_release_hook(SQUserPointer p, int size); +int construct_RefCounted(void *p); + +//------------------------------------------------------------------------------ +#define _SA_RETURN_OBJECT(__EXP__) { ::SquirrelObject o = __EXP__; return sa.Return(o); } +#define _ReturnCObject(__OBJECT__, __TYPE__) { GS::Script::CObject::Push(v, __OBJECT__, __TYPE__); return 1; } +//------------------------------------------------------------------------------ + + +#endif // __CU_BINDING_UTILS__ diff --git a/include/modules/script_squirrel/cobject/squirrel_object.h b/include/modules/script_squirrel/cobject/squirrel_object.h new file mode 100644 index 0000000..56bc3ed --- /dev/null +++ b/include/modules/script_squirrel/cobject/squirrel_object.h @@ -0,0 +1,187 @@ +#ifndef _SQUIRREL_OBJECT_H_ +#define _SQUIRREL_OBJECT_H_ + +class SquirrelObject +{ +// friend class SquirrelVM; +public: + SquirrelObject(HSQUIRRELVM vm); + virtual ~SquirrelObject(); + SquirrelObject(const SquirrelObject &o); + SquirrelObject(HSQOBJECT &o); + SquirrelObject & operator =(const SquirrelObject &o); + SquirrelObject & operator =(int n); + void Append(const SquirrelObject &o); + void AttachToStackObject(int idx); + SquirrelObject Clone(); + bool SetValue(const SquirrelObject &key,const SquirrelObject &val); + + bool SetValue(SQInteger key,const SquirrelObject &val); + bool SetValue(int key,bool b); + bool SetValue(int key,int n); + bool SetValue(int key,float f); + bool SetValue(int key,const SQChar *s); + + bool SetValue(const SQChar *key,const SquirrelObject &val); + bool SetValue(const SQChar *key,bool b); + bool SetValue(const SQChar *key,int n); + bool SetValue(const SQChar *key,float f); + bool SetValue(const SQChar *key,const SQChar *s); + + bool SetInstanceUP(SQUserPointer up); + bool IsNull() const; + bool IsNumeric() const; + int Len() const; + bool SetDelegate(SquirrelObject &obj); + SquirrelObject GetDelegate(); + const SQChar* ToString(); + bool ToBool(); + SQInteger ToInteger(); + SQFloat ToFloat(); + SQUserPointer GetInstanceUP(SQUserPointer tag) const; + SquirrelObject GetValue(const SQChar *key) const; + bool Exists(const SQChar *key) const; + float GetFloat(const SQChar *key) const; + int GetInt(const SQChar *key) const; + const SQChar *GetString(const SQChar *key) const; + bool GetBool(const SQChar *key) const; + SquirrelObject GetValue(int key) const; + float GetFloat(int key) const; + int GetInt(int key) const; + const SQChar *GetString(int key) const; + bool GetBool(int key) const; + SquirrelObject GetAttributes(const SQChar *key = 0); + SQObjectType GetType(); + HSQOBJECT &GetObject(){return _o;} + bool BeginIteration(); + bool Next(SquirrelObject &key,SquirrelObject &value); + void EndIteration(); +private: + bool GetSlot(const SQChar *name) const; + bool GetSlot(int key) const; + HSQOBJECT _o; + HSQUIRRELVM vm; +}; + +struct StackHandler { + StackHandler(HSQUIRRELVM v) { + _top = sq_gettop(v); + this->v = v; + } + SQFloat GetFloat(int idx) { + SQFloat x = 0.0f; + if(idx > 0 && idx <= _top) { + sq_getfloat(v,idx,&x); + } + return x; + } + SQInteger GetInt(int idx) { + SQInteger x = 0; + if(idx > 0 && idx <= _top) { + sq_getinteger(v,idx,&x); + } + return x; + } + HSQOBJECT GetObject(int idx) { + HSQOBJECT x; + if(idx > 0 && idx <= _top) { + sq_resetobject(&x); + sq_getstackobj(v,idx,&x); + } + return x; + } + const SQChar *GetString(int idx) + { + const SQChar *x = 0; + if(idx > 0 && idx <= _top) { + sq_getstring(v,idx,&x); + } + return x; + } + SQUserPointer GetUserPointer(int idx) + { + SQUserPointer x = 0; + if(idx > 0 && idx <= _top) { + sq_getuserpointer(v,idx,&x); + } + return x; + } + SQUserPointer GetInstanceUp(int idx,SQUserPointer tag) + { + SQUserPointer self; + if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&self,tag))) + return 0; + return self; + } + SQUserPointer GetUserdata(int idx,SQUserPointer tag) + { + SQUserPointer otag; + SQUserPointer up; + if(idx > 0 && idx <= _top) { + if(SQ_SUCCEEDED(sq_getuserdata(v,idx,&up,&otag))) { + if(tag == otag) + return up; + } + } + return 0; + } + bool GetBool(int idx) + { + SQBool ret; + if(idx > 0 && idx <= _top) { + if(SQ_SUCCEEDED(sq_getbool(v,idx,&ret))) + return ret ? true : false; + } + return false; + } + int GetType(int idx) + { + if(idx > 0 && idx <= _top) { + return sq_gettype(v,idx); + } + return -1; + } + + SQInteger GetParamCount() { + return _top; + } + int Return(const SQChar *s) + { + sq_pushstring(v,s,-1); + return 1; + } + int Return(float f) + { + sq_pushfloat(v,f); + return 1; + } + int Return(int i) + { + sq_pushinteger(v,i); + return 1; + } + int Return(unsigned int i) + { + sq_pushinteger(v,i); + return 1; + } + int Return(bool b) + { + sq_pushbool(v,b); + return 1; + } + int Return(SquirrelObject &o) + { + sq_pushobject(v,o.GetObject()); + return 1; + } + int Return() { return 0; } + SQInteger ThrowError(const SQChar *error) { + return sq_throwerror(v,error); + } +private: + SQInteger _top; + HSQUIRRELVM v; +}; + +#endif //_SQUIRREL_OBJECT_H_ diff --git a/include/modules/script_squirrel/cobject/uc_binding.h b/include/modules/script_squirrel/cobject/uc_binding.h new file mode 100644 index 0000000..920b311 --- /dev/null +++ b/include/modules/script_squirrel/cobject/uc_binding.h @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +------------------------------------------------------------------------------*/ + + +#ifndef __UC_BINDING__ +#define __UC_BINDING__ + + + #include "squirrel.h" + + + /// Register fast OO Squirrel binding. +void RegisterUCBinding(HSQUIRRELVM vm); + + +#endif // __UC_BINDING__ diff --git a/include/modules/script_squirrel/cobject/uv_decl.h b/include/modules/script_squirrel/cobject/uv_decl.h new file mode 100644 index 0000000..b4590ce --- /dev/null +++ b/include/modules/script_squirrel/cobject/uv_decl.h @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __COBJECT_UV_DECL__ +#define __COBJECT_UV_DECL__ + + + #include "script_squirrel/cobject/squirrel_bindings_utils.h" + #include "math/vector.h" + + +_DECL_CLASS(UV) +_DECL_NATIVE_CONSTRUCTION(UV, GS::Vector2) + + +#endif // __COBJECT_UV_DECL__ diff --git a/include/modules/script_squirrel/cobject/vector_decl.h b/include/modules/script_squirrel/cobject/vector_decl.h new file mode 100644 index 0000000..c406cb7 --- /dev/null +++ b/include/modules/script_squirrel/cobject/vector_decl.h @@ -0,0 +1,20 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __COBJECT_VECTOR_DECL__ +#define __COBJECT_VECTOR_DECL__ + + + #include "script_squirrel/cobject/squirrel_bindings_utils.h" + + +namespace GS { struct Vector4; } + +_DECL_CLASS(Vector) +_DECL_NATIVE_CONSTRUCTION(Vector, GS::Vector4) + + +#endif // __COBJECT_VECTOR_DECL__ diff --git a/include/modules/script_squirrel/engine_vm.h b/include/modules/script_squirrel/engine_vm.h new file mode 100644 index 0000000..cb4b61e --- /dev/null +++ b/include/modules/script_squirrel/engine_vm.h @@ -0,0 +1,41 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NENGINEVM__ +#define __NENGINEVM__ + + + #include "script_squirrel/squirrel_vm.h" + + +namespace GS { + namespace Script { + class CObject; + +/* + @short Squirrel based virtual machine. +*/ +struct EngineVM : public SquirrelVM +{ + List cobjects; + + /// Release all native references. + void ReleaseAllNativeReferences(); + + /// Push a variant onto the Squirrel stack. +virtual bool PushVariant(const Variant &); + /// Invalidate all references to a user object. +virtual int InvalidateNativeReference(void *); + +virtual bool Open(); +virtual void Close(); +}; + + } // Script +} // GS + + +#endif // __NENGINEVM__ diff --git a/include/modules/script_squirrel/engine_vm_debugger.h b/include/modules/script_squirrel/engine_vm_debugger.h new file mode 100644 index 0000000..9715d56 --- /dev/null +++ b/include/modules/script_squirrel/engine_vm_debugger.h @@ -0,0 +1,31 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ENGINE_VM_DEBUGGER__ +#define __ENGINE_VM_DEBUGGER__ + + + #include "script_squirrel/squirrel_debugger.h" + + +namespace GS { + namespace Script { + struct EngineVM; + +/* + @short Editor Squirrel debugger interface. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct EngineDebugger : public SquirrelDebugger +{ + EngineDebugger(EngineVM &); +}; + + } // Script +} // GS + + +#endif // __ENGINE_VM_DEBUGGER__ diff --git a/include/modules/script_squirrel/engine_vm_profiler.h b/include/modules/script_squirrel/engine_vm_profiler.h new file mode 100644 index 0000000..08c70ab --- /dev/null +++ b/include/modules/script_squirrel/engine_vm_profiler.h @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __MONITOR_SCRIPT_PROFILER__ +#define __MONITOR_SCRIPT_PROFILER__ + + + #include "script/script_profiler.h" + #include "script/script_vm.h" + #include "squirrel.h" + + +namespace GS { + namespace Script { + +/* + @short Engine VM profiler interface. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct EngineProfiler : public Profiler +{ + /// Get function profile. + FunctionProfile *GetFunctionProfile(const char *source, const char *function, int line, FunctionProfile *profile) { return 0; } + /// Update profiler. + void Update(int type, FunctionProfile *profile) {} +}; + + } // Script +} // GS + + +#endif // __MONITOR_SCRIPT_PROFILER__ diff --git a/include/modules/script_squirrel/legacy/binding_helpers.h b/include/modules/script_squirrel/legacy/binding_helpers.h new file mode 100644 index 0000000..41b5db2 --- /dev/null +++ b/include/modules/script_squirrel/legacy/binding_helpers.h @@ -0,0 +1,201 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NBINDING_HELPERS__ +#define __NBINDING_HELPERS__ + + + #include "script_squirrel/cobject/uc_binding.h" + #include "script_squirrel/cobject/cobject.h" + #include "script_squirrel/cobject/vector_decl.h" + #include "math/vector.h" + #include "log/log.h" + + +namespace GS { + class MinMax; + struct Color; + struct Vector4; + +template struct Rect; + + namespace Script { + +/// Register a native closure in the vm. +void sq_register(HSQUIRRELVM v, SQFUNCTION f, const char *fname, const SQChar *mask); +/// Create a new class instance on the vm stack. +bool CreateClassInstance(HSQUIRRELVM vm, const char *class_name, bool call = false); + +void PushColor(HSQUIRRELVM vm, const Color &c); +void PushVector2(HSQUIRRELVM vm, const Vector2 &v); +void GetVector2(HSQUIRRELVM vm, SQInteger idx, Vector2 &v); +void PushVector(HSQUIRRELVM vm, const Vector4 &v, bool push_w = false); + +void GetVector(HSQUIRRELVM vm, SQInteger idx, Vector4 &v, bool get_w = false); +void GetUV(HSQUIRRELVM vm, SQInteger idx, Vector2 &uv); + +void PushMinMax(HSQUIRRELVM vm, const MinMax &v); +void GetMinMax(HSQUIRRELVM vm, SQInteger idx, MinMax &v); + +void PushRect(HSQUIRRELVM vm, const Rect &r); +void GetRect(HSQUIRRELVM vm, SQInteger idx, Rect &r); +void PushRect(HSQUIRRELVM vm, const Rect &r); +void GetRect(HSQUIRRELVM vm, SQInteger idx, Rect &r); + +#define GetTableKey(_KEY_, _TYPE_GET_, _IDX_, _TO_)\ +{\ + sq_pushstring(vm, _KEY_, -1);\ + sq_get(vm, (_IDX_) - 1);\ + _TYPE_GET_(vm, -1, &_TO_);\ + sq_pop(vm, 1);\ +} +#define SetTableKey(_KEY_, _TYPE_PUSH_, _IDX_, _V_)\ +{\ + sq_pushstring(vm, _KEY_, -1);\ + _TYPE_PUSH_(vm, _V_);\ + sq_set(vm, (_IDX_) - 2);\ +} + +//------------------------------------------------------------------------------ +#define __SQ_INVALIDATENATIVEREF(__PTR__) ((SquirrelVM *)sq_getforeignptr(vm))->InvalidateNativeReference(__PTR__); +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +#define __SQ_GETSTART(__ARGCOUNT__) \ + int __sq_stackpos = -(__ARGCOUNT__), __sq_argcount = __ARGCOUNT__; +#define __SQ_GETUPDATESTACK \ + __sq_stackpos++; +#define __SQ_GETEND \ + sq_pop(vm, __sq_argcount); +/* + sq_pop(vm, __sq_argcount);\ + if (sq_gettop(vm) != 1)\ + return sq_throwerror(vm, "Internal binding error, stack configuration is invalid"); +*/ + +#define __SQ_STACKPOS __sq_stackpos + +#define __SQ_GETSAFEPTR(__VARNAME__, __TYPE__, __TAG__) \ + __TYPE__ *__VARNAME__; if (!GS::Script::CObject::Get(vm, __sq_stackpos, (void **)&__VARNAME__, __TAG__)) return -1; if (!__VARNAME__) return sq_throwerror(vm, "Object is null"); __SQ_GETUPDATESTACK +#define __SQ_GETSAFEPTRALLOWNULL(__VARNAME__, __TYPE__, __TAG__) \ + __TYPE__ *__VARNAME__; if (!GS::Script::CObject::Get(vm, __sq_stackpos, (void **)&__VARNAME__, __TAG__)) return -1; __SQ_GETUPDATESTACK + +#define __SQ_GETCOBJECTBASE(__VARNAME__, __TYPE__, __TAGS__) \ + __TYPE__ *__VARNAME__; if (!GS::Script::CObject::GetBase(vm, __sq_stackpos, (void **)&__VARNAME__, __TAGS__)) return -1; if (!__VARNAME__) return sq_throwerror(vm, "Object is null"); __SQ_GETUPDATESTACK +#define __SQ_GETCOBJECTBASEALLOWNULL(__VARNAME__, __TYPE__, __TAGS__) \ + __TYPE__ *__VARNAME__; if (!GS::Script::CObject::GetBase(vm, __sq_stackpos, (void **)&__VARNAME__, __TAGS__)) return -1; __SQ_GETUPDATESTACK + +#define __SQ_GETOBJECT(__VARNAME__) \ + HSQOBJECT __VARNAME__; sq_getstackobj(vm, __sq_stackpos, &__VARNAME__); __SQ_GETUPDATESTACK + +#define __SQ_GETINT(__VARNAME__) \ + SQInteger __VARNAME__; sq_getinteger(vm, __sq_stackpos, &__VARNAME__); __SQ_GETUPDATESTACK +#define __SQ_GETFLOAT(__VARNAME__) \ + SQFloat __VARNAME__; sq_getfloat(vm, __sq_stackpos, &__VARNAME__); __SQ_GETUPDATESTACK +#define __SQ_GETBOOL(__VARNAME__) \ + SQBool __VARNAME__; sq_getbool(vm, __sq_stackpos, &__VARNAME__); __SQ_GETUPDATESTACK +#define __SQ_GETSTRING(__VARNAME__) \ + const SQChar *__VARNAME__; sq_getstring(vm, __sq_stackpos, &__VARNAME__); __SQ_GETUPDATESTACK + +#define __SQ_GETCOLOR(__VARNAME__) \ + GS::Color __VARNAME__; GetVector(vm, __sq_stackpos, __VARNAME__); __SQ_GETUPDATESTACK +#define __SQ_GETVECTOR2(__VARNAME__) \ + GS::Vector2 __VARNAME__; GetVector2(vm, __sq_stackpos, __VARNAME__); __SQ_GETUPDATESTACK +#define __SQ_GETVECTORTO(__VECTOR__, __CONDITION__) \ + if (__CONDITION__) GetVector(vm, __sq_stackpos, __VECTOR__); __SQ_GETUPDATESTACK +#define __SQ_GETVECTORTOALWAYS(__VECTOR__) \ + GetVector(vm, __sq_stackpos, __VECTOR__); __SQ_GETUPDATESTACK +#define __SQ_GETUVTO(__UV__) \ + GetUV(vm, __sq_stackpos, __UV__); __SQ_GETUPDATESTACK + +#define __SQ_GETRECT(__VARNAME__) \ + GS::Rect __VARNAME__; GetRect(vm, __sq_stackpos, __VARNAME__); __SQ_GETUPDATESTACK +#define __SQ_GETFRECT(__VARNAME__) \ + GS::Rect __VARNAME__; GetRect(vm, __sq_stackpos, __VARNAME__); __SQ_GETUPDATESTACK +#define __SQ_GETRECTTO(__RECT__) \ + GetRect(vm, __sq_stackpos, __RECT__); __SQ_GETUPDATESTACK + +#define __SQ_GETSINGLE(__G) \ + __SQ_GETSTART(1) __G __SQ_GETEND + +#define __SQ_RETURNSAFEPTR(Val, Tag) { GS::Script::CObject::Push(vm, Val, Tag); return 1; } +#define __SQ_RETURNMANAGEDSAFEPTR(Val, Tag) { GS::Script::CObject::Push(vm, Val, Tag, true); return 1; } + +#define __SQ_RETURNMINMAX(Val) { PushMinMax(vm, Val); return 1; } +#define __SQ_RETURNRECT(Val) { PushRect(vm, Val); return 1; } + +#define __SQ_RETURNCOLOR(Val) { PushColor(vm, Val); return 1; } +#define __SQ_RETURNVECTOR2(Val) { PushVector2(vm, Val); return 1; } +#define __SQ_RETURNVECTORW(Val) { PushVector(vm, Val, true); return 1; } + +#define __SQ_RETURNMINMAX(Val) { PushMinMax(vm, Val); return 1; } + +//------------------------------------------------------------------------------ +// Wrap old accessors to the much faster OO ones. +#ifndef _T +#define _T +#endif + +#define __SQ_GETMATRIX3(__VARNAME__) \ + GS::Matrix3 __VARNAME__;\ + { HSQUIRRELVM v = vm;\ + _GetTypedParam(__mtx, __sq_stackpos, GS::Matrix3, Matrix3);\ + __VARNAME__ = *__mtx;\ + __SQ_GETUPDATESTACK } +#define __SQ_GETMATRIX4(__VARNAME__) \ + GS::Matrix4 __VARNAME__;\ + { HSQUIRRELVM v = vm;\ + _GetTypedParam(__mtx, __sq_stackpos, GS::Matrix4, Matrix4);\ + __VARNAME__ = *__mtx;\ + __SQ_GETUPDATESTACK } + +#define __SQ_RETURNMATRIX3(__V__) \ + { StackHandler sa(vm);\ + _SA_RETURN_OBJECT(new_Matrix3(vm, __V__)) } +#define __SQ_RETURNMATRIX4(__V__) \ + { StackHandler sa(vm);\ + _SA_RETURN_OBJECT(new_Matrix4(vm, __V__)) } + +#define __SQ_GETVECTORW(__VARNAME__) \ + GS::Vector4 __VARNAME__;\ + { HSQUIRRELVM v = vm;\ + _GetTypedParam(__vec, __sq_stackpos, GS::Vector4, Vector);\ + __VARNAME__ = *__vec;\ + __SQ_GETUPDATESTACK } +#define __SQ_GETVECTOR(__VARNAME__) \ + __SQ_GETVECTORW(__VARNAME__) \ + __VARNAME__.w = 1; + +#define __SQ_RETURNVECTOR(Val) \ + { StackHandler sa(vm);\ + _SA_RETURN_OBJECT(new_Vector(vm, Val)) } +//------------------------------------------------------------------------------ + +#define __SQ_RETURNINT(Val) { sq_pushinteger(vm, Val); return 1; } +#define __SQ_RETURNFLOAT(Val) { sq_pushfloat(vm, Val); return 1; } +#define __SQ_RETURNBOOL(Val) { sq_pushbool(vm, Val ? SQTrue : SQFalse); return 1; } +#define __SQ_RETURNNULL { sq_pushnull(vm); return 1; } +#define __SQ_RETURNSTRING(Val) { sq_pushstring(vm, Val, -1); return 1; } +#define __SQ_RETURNOBJECT(Val) { sq_pushobject(vm, Val); return 1; } + +#define __SQ_RETURN return 0; + +#define __SQ_GETSINGLESAFEPTR(Name, Type, Tag) \ + __SQ_GETSTART(1) \ + __SQ_GETSAFEPTR(Name, Type, Tag) \ + __SQ_GETEND + +#define __SQ_GETSINGLESAFEPTRALLOWNULL(Name, Type, Tag) \ + __SQ_GETSTART(1) \ + __SQ_GETSAFEPTRALLOWNULL(Name, Type, Tag) \ + __SQ_GETEND +//------------------------------------------------------------------------------ + + } // Script +} // GS + + +#endif // __NBINDING_HELPERS__ diff --git a/include/modules/script_squirrel/legacy/squirrel_binding.h b/include/modules/script_squirrel/legacy/squirrel_binding.h new file mode 100644 index 0000000..0c9f968 --- /dev/null +++ b/include/modules/script_squirrel/legacy/squirrel_binding.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMANAGER_SCRIPT_BINDING__ +#define __NMANAGER_SCRIPT_BINDING__ + + + /// Squirrel API compatible version. +#define __SQUIRREL_API_VERSION_COMPATIBILITY__ 1 + /// Current Squirrel API version. +#define __SQUIRREL_API_VERSION__ 2 + +typedef struct SQVM* HSQUIRRELVM; + + +void RegisterAIBinding(HSQUIRRELVM); +void RegisterAnimationBinding(HSQUIRRELVM); +void RegisterCameraBinding(HSQUIRRELVM); +void RegisterClockBinding(HSQUIRRELVM); +void RegisterCollisionBinding(HSQUIRRELVM); +void RegisterEmitterBinding(HSQUIRRELVM); +void RegisterGeometryBinding(HSQUIRRELVM); +void RegisterFontBinding(HSQUIRRELVM); +void RegisterGroupBinding(HSQUIRRELVM); +void RegisterHashBinding(HSQUIRRELVM); +void RegisterHTTPBinding(HSQUIRRELVM); +void RegisterWebSocketBinding(HSQUIRRELVM); +void RegisterInstanceBinding(HSQUIRRELVM); +void RegisterIOBinding(HSQUIRRELVM); +void RegisterItemBinding(HSQUIRRELVM); +void RegisterLightBinding(HSQUIRRELVM); +void RegisterProfilerBinding(HSQUIRRELVM); +void RegisterMaterialBinding(HSQUIRRELVM); +void RegisterMatrixBinding(HSQUIRRELVM); +void RegisterMixerBinding(HSQUIRRELVM); +void RegisterMotionBinding(HSQUIRRELVM); +void RegisterNMLBinding(HSQUIRRELVM); +void RegisterObjectBinding(HSQUIRRELVM); +void RegisterPhysicBinding(HSQUIRRELVM); +void RegisterPictureBinding(HSQUIRRELVM); +void RegisterProjectBinding(HSQUIRRELVM); +void RegisterRaytracerBinding(HSQUIRRELVM); +void RegisterRendererBinding(HSQUIRRELVM); +void RegisterResourceFactoryBinding(HSQUIRRELVM); +void RegisterSceneBinding(HSQUIRRELVM); +void RegisterSoundBinding(HSQUIRRELVM); +void RegisterSystemBinding(HSQUIRRELVM); +void RegisterTextureBinding(HSQUIRRELVM); +void RegisterTriggerBinding(HSQUIRRELVM); +void RegisterUIBinding(HSQUIRRELVM); +void RegisterPlatformBinding(HSQUIRRELVM); +void RegisterMaterialShaderBinding(HSQUIRRELVM); + +void RegisterAllSquirrelBinding(HSQUIRRELVM); + + +#define GetVMObject(__VM__) ((GS::Script::SquirrelVM *)sq_getforeignptr(__VM__)) + + +#endif // __NMANAGER_SCRIPT_BINDING__ diff --git a/include/modules/script_squirrel/legacy/ws_manager.h b/include/modules/script_squirrel/legacy/ws_manager.h new file mode 100644 index 0000000..3399bf0 --- /dev/null +++ b/include/modules/script_squirrel/legacy/ws_manager.h @@ -0,0 +1,118 @@ +#ifndef WS_MANAGER_H +#define WS_MANAGER_H + +// Must be defined before including any Windows headers +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0601 // Windows 7 or later +#endif + +// Winsock and Bluetooth headers +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Link required libraries +#pragma comment(lib, "ws2_32.lib") +#pragma comment(lib, "Bthprops.lib") + +#ifndef BT_PORT_ANY +#define BT_PORT_ANY ((ULONG)-1) +#endif + +#ifndef BTH_ADDR_NULL +#define BTH_ADDR_NULL ((BTH_ADDR)0) +#endif + +class WebSocketManager { +public: + struct CallbackEvent { + enum Type { CONNECT, DISCONNECT, MESSAGE }; + Type type; + std::string data; + SOCKET client_socket; + }; + + struct ClientConnection { + SOCKET socket; + std::thread receive_thread; + std::atomic active; + + ClientConnection(SOCKET s) : socket(s), active(true) {} + }; + +private: + SOCKET m_listen_socket; + std::vector m_connections; + mutable std::mutex m_connections_mutex; + std::thread m_accept_thread; + std::atomic m_running; + bool m_initialized; + std::chrono::steady_clock::time_point m_start_time; + uint16_t m_port; + + // Squirrel VM and callbacks + HSQUIRRELVM m_vm; + HSQOBJECT m_on_connect_callback; + HSQOBJECT m_on_disconnect_callback; + HSQOBJECT m_on_message_callback; + bool m_has_on_connect; + bool m_has_on_disconnect; + bool m_has_on_message; + + // Event queue - car la VM Squirrel n'est pas thread-safe + // Les callbacks doivent être appelés depuis le thread principal + std::queue m_event_queue; + mutable std::mutex m_queue_mutex; + + void InternalOnConnect(SOCKET client_socket); + void InternalOnDisconnect(SOCKET client_socket); + void InternalOnMessage(SOCKET client_socket, const std::string& message); + + void InitializeServer(); + void AcceptLoop(); + void ReceiveLoop(ClientConnection* connection); + bool SendToClient(SOCKET client_socket, const std::string& message); + +public: + WebSocketManager(HSQUIRRELVM vm); + ~WebSocketManager(); + + // Server control + bool Start(uint16_t port); + void Stop(); + bool IsRunning() const { return m_running; } + + // Messaging + void Broadcast(const std::string& message); + + // Statistics + int GetConnectionCount() const; + float GetUptime() const; + uint16_t GetPort() const { return m_port; } + + // Squirrel callbacks + void SetOnConnectCallback(HSQOBJECT callback); + void SetOnDisconnectCallback(HSQOBJECT callback); + void SetOnMessageCallback(HSQOBJECT callback); + + // Process events - DOIT être appelé depuis le thread principal ! + // C'est ici que les callbacks Squirrel sont réellement invoqués + void ProcessEvents(); +}; + +#endif // WS_MANAGER_H \ No newline at end of file diff --git a/include/modules/script_squirrel/mmf.h b/include/modules/script_squirrel/mmf.h new file mode 100644 index 0000000..d1cf9e0 --- /dev/null +++ b/include/modules/script_squirrel/mmf.h @@ -0,0 +1,44 @@ +/* + +Tau [Physic engine] + + Emmanuel Julien 2004~2005. + http://xbarr.ninomojo.com + mailto:ejulien@nengine.fr +------------------------------------------ + +*/ + + +#ifndef __MMF_SYSTEM__ +#define __MMF_SYSTEM__ + + + +#include +#include + + +/** +*/ +class CMMF +{ +public: + CMMF(LPCTSTR MMFName, int size, LPCTSTR mutexName); + ~CMMF(); + void Read(void* pData, bool read = true); + void Write(void* pData); + LPVOID GetMMF() { return m_pSharedData; } + +protected: + LPVOID m_pSharedData; + +private: + CMMF() {} + int m_nSize; + HANDLE m_hFileMapping; + HANDLE m_hMutex; +}; + + +#endif // __MMF_SYSTEM__ diff --git a/include/modules/script_squirrel/squirrel_analyzer.h b/include/modules/script_squirrel/squirrel_analyzer.h new file mode 100644 index 0000000..34d6640 --- /dev/null +++ b/include/modules/script_squirrel/squirrel_analyzer.h @@ -0,0 +1,104 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSQUIRRELANALYZER__ +#define __NSQUIRRELANALYZER__ + + + #include "memory/nshared_ptr.h" + #include "memory/nweak_ptr.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace SquirrelAnalyzer { + +struct Offset +{ + int line, column; + + Offset(int l = 0, int c = 0) : line(l), column(c) {} +}; + +struct Symbol : public SharedObject +{ +enum Type +{ + TypeNone, + TypeVariable, + TypeFunction, + TypeClass +}; + + String name; + Type type; + + Offset offset; + + Symbol() : type(TypeNone) {} +}; + +struct Variable : public Symbol +{ +enum VarType +{ + VarNone, + VarLocal, + VarGlobal, + VarMember, + VarEnum +}; + + VarType var_type; + + Variable() : var_type(VarNone) { type = TypeVariable; } +}; + +struct Function : public Symbol +{ + SharedList symbols; + String prototype; + + Function() { type = TypeFunction; } +}; + +struct Class : public Symbol +{ + String extends; + SharedList symbols; + + Class() { type = TypeClass; } +}; + +struct Source +{ + String name; + SharedList symbols; +}; + +struct SourceSymbol +{ + SharedPtr source; + SharedPtr symbol; +}; + +struct Program +{ + AutoList sources; + bool FindSymbol(const char *name, AutoList &symbols); +}; + +void DumpProgram(const Program &); + + /// Analyze a source, store result in program object. +Source *Analyze(const char *nut, Program &, bool replace = true); + + } // SquirrelAnalyser +} // GS + + +#endif // __NSQUIRRELANALYZER__ diff --git a/include/modules/script_squirrel/squirrel_debugger.h b/include/modules/script_squirrel/squirrel_debugger.h new file mode 100644 index 0000000..acb2d24 --- /dev/null +++ b/include/modules/script_squirrel/squirrel_debugger.h @@ -0,0 +1,63 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SQUIRREL_DEBUGGER__ +#define __SQUIRREL_DEBUGGER__ + + + #include "script/script_debugger.h" + #include "squirrel.h" + + +namespace GS { + namespace Script { + class SquirrelVM; + +/* + @short Squirrel debugger interface. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class SquirrelDebugger : public IDebugger +{ +protected: + + HSQUIRRELVM vm; + + /// Insert a variable in the variable tree. + DebuggerVariable *InsertVariable(const char *name, AutoList &tree, int level); + +public: + +/*! + @name Interface. + @{ +*/ + /// Format variable parameter. +virtual String FormatParameter(DebuggerVariable *variable); + /// Format safe ptr parameter. +virtual String FormatUserObjectParameter(CObjectType type); + /// Convert a debugger variable to a meta string. +virtual void VariableToMetatagString(DebuggerVariable *, String &); + + /// Get call stack depth. +virtual int GetCallstackDepth(); + /// Get current script execution call frame index. +virtual int GetStackFrameIndex(); + + /// Refresh stack locals list. +virtual void RefreshStackFrameLocalsCache(); + /// Get source/line info for the current debug stack frame. +virtual void GetStackFrameSource(const char *&, int &); +/// @} + + SquirrelDebugger(SquirrelVM &); +}; + + } // Script +} // GS + + +#endif // __SQUIRREL_DEBUGGER__ diff --git a/include/modules/script_squirrel/squirrel_vm.h b/include/modules/script_squirrel/squirrel_vm.h new file mode 100644 index 0000000..caf54f5 --- /dev/null +++ b/include/modules/script_squirrel/squirrel_vm.h @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSQUIRRELVM__ +#define __NSQUIRRELVM__ + + + #include "squirrel.h" + #include "script/script_vm.h" + #include "script/script_object.h" + + +namespace GS { + namespace Script { + class SquirrelVM; + +// +struct SquirrelObject : public Object +{ + HSQOBJECT object; + SquirrelObject(SquirrelVM &, HSQOBJECT); + ~SquirrelObject(); +}; + +/* + @short Squirrel based virtual machine. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class SquirrelVM : public IVM +{ +protected: + + HSQUIRRELVM vm; + + int call_arg_count; + +public: + + /// Get VM name. + const char *GetName() const { return "Squirrel"; } + + /// Get VM call stack. + void GetCallStack(AutoList &); + +/*! + @name Squirrel specific API. + @{ +*/ + HSQUIRRELVM VM() const { return vm; } + + /// Set event hook table. +virtual void SetDebugInterface(IDebug *, bool enable_step_hook = false); + + /// Dump VM call stack. +static void DumpCallStack(HSQUIRRELVM, const char *desc, String *msg = 0); + + /// Push null value onto the stack. +virtual bool PushNull(); + /// Push property onto the stack. +virtual bool PushVariant(const Variant &); + /// Get Squirrel value from stack. +virtual bool GetVariantFromStack(int stack_index, Variant &); + /// Get a reference to a stack object. + Object *GetObjectFromStack(int stack_index); +/// @} + + /// Get a reference to a VM object. +virtual Object *GetObjectFromName(const char *name, const Object *context = 0); + + /// Setup a function call in the VM. +virtual bool SetupFunctionCall(const char *func, const Object *function_object = 0, const Object *search_context = 0); + /// Set function call context. +virtual bool SetFunctionCallContext(const Variant &); + /// Push function call null argument. +virtual bool PushNullArgument(); + /// Push function call argument. +virtual bool PushArgument(const Variant &); + /// Execute a function call in the VM. +virtual bool DoFunctionCall(Variant *return_value = 0); + + /// Invalidate all references to a user object. +virtual int InvalidateNativeReference(void *) { return 0; } + + /// Compile a script. +virtual bool Compile(const char *source, uint size, const Object *context = 0, const char *sourcename = 0); + + /// Create a table object. +virtual Object *CreateTable(); + /// Set a VM variable. +virtual bool Set(const char *name, const Variant &, const Object *context = 0); + /// Get a VM variable. +virtual bool Get(const char *name, Variant &, const Object *context = 0); + + /// Create a script array. +virtual Object *CreateArray(); + /// Append a VM variable to an array. +virtual bool Append(const Variant &, const Object *context = 0); + + /// Is the VM open. +virtual bool IsOpen() const { return asbool(vm); } + +virtual bool Open(); +virtual void Close(); + + SquirrelVM(); +virtual ~SquirrelVM(); +}; + + } // Script +} // GS + + +#endif // __NSQUIRRELVM__ diff --git a/include/modules/tools/geometry_merge.h b/include/modules/tools/geometry_merge.h new file mode 100644 index 0000000..4597283 --- /dev/null +++ b/include/modules/tools/geometry_merge.h @@ -0,0 +1,24 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NGEOMETRYMERGETOOL__ +#define __NGEOMETRYMERGETOOL__ + + +namespace GS { + class Matrix4; + + namespace Core { + class Geometry; + +/// Merge two geometries together. +Geometry *MergeGeometry(Geometry *, Geometry *, const Matrix4 * = 0, const Matrix4 * = 0); + + } // Core +} // GS + + +#endif // __NGEOMETRYMERGETOOL__ diff --git a/include/modules/tools/resource_explorer.h b/include/modules/tools/resource_explorer.h new file mode 100644 index 0000000..9042c70 --- /dev/null +++ b/include/modules/tools/resource_explorer.h @@ -0,0 +1,93 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __RESOURCEEXPLORER__ +#define __RESOURCEEXPLORER__ + + + #include "nstring/nstring.h" + #include "container/nlist.h" + #include "memory/nauto_ptr.h" + #include "metafile/nml.h" + + +namespace GS { + namespace Resource { + +//------------------------------------------------------------------------------ +struct DependencyRule +{ + const char *path; + const char *type; +}; + +struct ExplorerRule +{ + const char *type, *root; + DependencyRule *rules; +}; +//------------------------------------------------------------------------------ + +// +struct Explorer +{ +struct Dependency +{ + bool missing; + +virtual const char *GetName() const = 0; +virtual void SetName(const char *) = 0; + + Dependency() : missing(true) {} +virtual ~Dependency() {} +}; +struct DependencyTag : public Dependency +{ + NML::Tag *tag; + +virtual const char *GetName() const; +virtual void SetName(const char *); + + DependencyTag(NML::Tag *t) : tag(t) {} +}; +struct Resource +{ + String name, type; + AutoPtr file; + AutoList dependencies; + + const Dependency *FindDependency(const char *) const; + bool HasMissingDependencies() const; + + Resource(const char *n, const char *t) : name(n), type(t) {} +}; + +private: + + String project_path, core_path; + bool recursive; + + AutoList resources; + + void ExploreResourceRuleTags(const StringList &, uint pos, NML::Tag *, Resource *, int depth); + bool ExploreResourceRule(ExplorerRule &, Resource *, int depth); + +public: + + void Clear(); + + const AutoList &GetResources() const { return resources; } + const Resource *FindResource(const char *) const; + + // Explore dependencies for a given resource. + Resource *ExploreResource(const char *name, const char *base_path, const char *core_path, int max_depth = 128); +}; + + } // Resource +} // GS + + +#endif // __RESOURCEEXPLORER__ diff --git a/include/modules/tools/scene_merge_object_list.h b/include/modules/tools/scene_merge_object_list.h new file mode 100644 index 0000000..2e57b68 --- /dev/null +++ b/include/modules/tools/scene_merge_object_list.h @@ -0,0 +1,30 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __MERGEOBJECTLIST__ +#define __MERGEOBJECTLIST__ + + + #include "scene3d/mitem.h" + #include "core/geometry.h" + + +namespace GS { + namespace Core { struct ResourceFactory; } + namespace S3D { + class Scene; + +struct SceneMergeObjectList +{ +virtual bool OnProgress(int current, int total) { return true; } + bool Merge(Scene *, const SharedList &, Core::ResourceFactory &, sMItem &out_i, Core::sGeometry &out_g); +}; + + } // S3D +} // GS + + +#endif // __MERGEOBJECTLIST__ diff --git a/include/modules/viewer_base/viewer_base.h b/include/modules/viewer_base/viewer_base.h new file mode 100644 index 0000000..66b8490 --- /dev/null +++ b/include/modules/viewer_base/viewer_base.h @@ -0,0 +1,222 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __VIEWERBASE__ +#define __VIEWERBASE__ + + + #include "viewer_base/viewer_base_vmhook.h" + #include "gpu/gpu_triangle_batch.h" + #include "project/project.h" + #include "scene3d/scene.h" + #include "ui/ui.h" + #include "core/mixer.h" + #include "core/renderer.h" + #include "core/resource_factories.h" + #include "core/graphic_resource_factory.h" + #include "core/render_resource_factory.h" + #include "core/mixer_resource_factory.h" + #include "debug_enet/network_debugger.h" + #include "io_net/io_net_client.h" + #include "timing/loop_benchmark.h" + #include "container/nstack.h" + + +namespace GS { + +/* + @short Engine viewer base class. + + Derive from this class and implement the pure virtual functions to create + a platform specific viewer. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class ViewerBase +{ + String GetBaseCommandLineParm() const; + +public: + +enum SessionType +{ + SessionScene = 0, + SessionProject +}; + +enum SessionSource +{ + SessionSourceFilesystem = 0, + SessionSourceArchive, + SessionSourceArchiveBootstrap +}; + +enum State +{ + ViewerSetup = 0, + ViewerClose, + + WaitRemoteSetup, + WaitRemoteController, + + SessionSetup, + SessionRunning, + SessionClose, +}; + + State state; + +protected: + + bool paused; + bool missing_resource; + + LoopBenchmark fps; + + AutoPtr gpu_batch; + +virtual bool OpenVideo() = 0; +virtual bool OpenAudio() = 0; + + bool LoadSessionData(); + + List define_list; + StringList include_list; + + /// Platform specific update. +virtual bool PlatformUpdate() = 0; + + /// Called when a command line parameter is unknown to the base command line parser. +virtual bool OnUnknownCommandLineParam(Stack &_arg, int &n) { return false; } + /// Print additional usage. +virtual void PrintAdditionalUsage() {} + +virtual bool OpenScriptVM(); + void SetVMGlobals(); + + bool OpenSession(); +virtual void ExecuteSession(); + bool CheckRuntimeError(); + void CloseSession(); + + void ExecuteMonitor(); + +virtual Script::NetworkDebugger *CreateVMDebugInterface(); + +public: + + void PrintHeader(); + void PrintUsage(); + +enum MessageType +{ + MessageNormal = 0, + MessageWarning, + MessageError +}; + + /// Platform specific display message to the user. +virtual void DisplayUserMessage(MessageType, const char *) = 0; + + /// Instantiate the renderer object. +virtual bool CreateRenderer() = 0; + /// Instantiate the mixer object. +virtual bool CreateMixer() = 0; + + bool SetupSessionSource(); + + NML::File config_file; + + SessionSource session_source; + SessionType session_type; + + String s_render, s_mixer; + String mixer_output; + String session_source_path; + String input_path; + String config_path; + String raytrace_path; + + String bootstrap_script; + + int raytrace_width, + raytrace_height, + raytrace_aa; + + int time_start, + time_live; + + int frame_count; + + bool ignore_esc, + ignore_bootstrap, + ignore_missing_resource; + + bool enable_profiler, + memory_profiler, + enable_pause, + display_fps; + + bool active_debug; + //--------------------------------------------------------------------- + bool remote; + int remote_port; + + SharedPtr remote_fs; + + NML::File remote_project, + remote_scene; + //--------------------------------------------------------------------- + + bool tool_mode; + + bool safe_mode; + bool fullscreen; + int width, height; + float aspect_ratio; + + Script::sVM script_vm; + Script::NetworkDebugger *script_debugger; + + Core::sResourceFactories factories; + + AutoPtr renderer; + AutoPtr mixer; + + AutoPtr project; + AutoPtr scene_2d; + AutoPtr scene_3d; + + Render::RasterFont *profiler_font[2], *fps_font; + +/*! + @name Viewer API + @{ +*/ + /// Application has been sent to background. + void Suspend(); + /// Application returned to foreground. + void Resume(); + + bool ParseCommandLine(Stack &_arg); + bool LoadViewerConfig(const char *path); + + bool LocateAndParseBootstrap(Stack &_arg); + void SetupVersion(const char *); + +virtual bool OpenViewer(); +virtual State Execute(); +virtual void CloseViewer(); +/// @} + + ViewerBase(); +virtual ~ViewerBase() { CloseViewer(); } +}; + +} // GS + + +#endif // __VIEWERBASE__ diff --git a/include/modules/viewer_base/viewer_base_debugger.h b/include/modules/viewer_base/viewer_base_debugger.h new file mode 100644 index 0000000..59dd722 --- /dev/null +++ b/include/modules/viewer_base/viewer_base_debugger.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __VIEWERBASEMONITOREVENTHANDLER__ +#define __VIEWERBASEMONITOREVENTHANDLER__ + + + #include "debug_enet/network_debugger.h" + + +namespace GS { + class ViewerBase; + namespace Script { + +/*! + @short Viewer base debugger VM event handler. + This event handler augments the network debugger to include the viewer + protocol commands. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct ViewerBaseDebugger : public NetworkDebugger +{ + ViewerBase &viewer; + + // Viewer base debugger interface. +virtual void SetViewerStatus(const char *); +virtual IO::Base *WrapRemoteFileSystem(IO::Base *remote_fs); + + // Network debugger interface. + void OnControllerPacketReceived(const Array &); + + ViewerBaseDebugger(ViewerBase &, IDebugger *, const char *address, int port); +}; + + } // Script +} // GS + + +#endif // __VIEWERBASEMONITOREVENTHANDLER__ diff --git a/include/modules/viewer_base/viewer_base_vmhook.h b/include/modules/viewer_base/viewer_base_vmhook.h new file mode 100644 index 0000000..0dd9138 --- /dev/null +++ b/include/modules/viewer_base/viewer_base_vmhook.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMSVIEW_VMHOOK__ +#define __NMSVIEW_VMHOOK__ + + + #include "script/script_vm.h" + + +namespace GS { + class ViewerBase; + + namespace Script { + +// +class ViewerEventHookTable : public IVM::IDebug +{ + ViewerBase *viewer; + +public: + + /// Handle a runtime debug step. +virtual void OnStep(char type, const char *source, int line, const char *funcname); + /// Handle a VM kill event. +virtual void Kill(const char *reason); + /// Handle a compiler error. +virtual void OnCompilerError(const char *error, const char *source, int line); + /// Handle a runtime error. +virtual void OnRuntimeException(const char *error); + + ViewerEventHookTable(ViewerBase *v) : viewer(v) {} +}; + + } // Script +} // GS + + +#endif // __NMSVIEW_VMHOOK__ diff --git a/include/opencv2/calib3d.hpp b/include/opencv2/calib3d.hpp new file mode 100644 index 0000000..66ffe2c --- /dev/null +++ b/include/opencv2/calib3d.hpp @@ -0,0 +1,1873 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CALIB3D_HPP__ +#define __OPENCV_CALIB3D_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/features2d.hpp" +#include "opencv2/core/affine.hpp" + +/** + @defgroup calib3d Camera Calibration and 3D Reconstruction + +The functions in this section use a so-called pinhole camera model. In this model, a scene view is +formed by projecting 3D points into the image plane using a perspective transformation. + +\f[s \; m' = A [R|t] M'\f] + +or + +\f[s \vecthree{u}{v}{1} = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1} +\begin{bmatrix} +r_{11} & r_{12} & r_{13} & t_1 \\ +r_{21} & r_{22} & r_{23} & t_2 \\ +r_{31} & r_{32} & r_{33} & t_3 +\end{bmatrix} +\begin{bmatrix} +X \\ +Y \\ +Z \\ +1 +\end{bmatrix}\f] + +where: + +- \f$(X, Y, Z)\f$ are the coordinates of a 3D point in the world coordinate space +- \f$(u, v)\f$ are the coordinates of the projection point in pixels +- \f$A\f$ is a camera matrix, or a matrix of intrinsic parameters +- \f$(cx, cy)\f$ is a principal point that is usually at the image center +- \f$fx, fy\f$ are the focal lengths expressed in pixel units. + +Thus, if an image from the camera is scaled by a factor, all of these parameters should be scaled +(multiplied/divided, respectively) by the same factor. The matrix of intrinsic parameters does not +depend on the scene viewed. So, once estimated, it can be re-used as long as the focal length is +fixed (in case of zoom lens). The joint rotation-translation matrix \f$[R|t]\f$ is called a matrix of +extrinsic parameters. It is used to describe the camera motion around a static scene, or vice versa, +rigid motion of an object in front of a still camera. That is, \f$[R|t]\f$ translates coordinates of a +point \f$(X, Y, Z)\f$ to a coordinate system, fixed with respect to the camera. The transformation above +is equivalent to the following (when \f$z \ne 0\f$ ): + +\f[\begin{array}{l} +\vecthree{x}{y}{z} = R \vecthree{X}{Y}{Z} + t \\ +x' = x/z \\ +y' = y/z \\ +u = f_x*x' + c_x \\ +v = f_y*y' + c_y +\end{array}\f] + +Real lenses usually have some distortion, mostly radial distortion and slight tangential distortion. +So, the above model is extended as: + +\f[\begin{array}{l} \vecthree{x}{y}{z} = R \vecthree{X}{Y}{Z} + t \\ x' = x/z \\ y' = y/z \\ x'' = x' \frac{1 + k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} + 2 p_1 x' y' + p_2(r^2 + 2 x'^2) + s_1 r^2 + s_2 r^4 \\ y'' = y' \frac{1 + k_1 r^2 + k_2 r^4 + k_3 r^6}{1 + k_4 r^2 + k_5 r^4 + k_6 r^6} + p_1 (r^2 + 2 y'^2) + 2 p_2 x' y' + s_1 r^2 + s_2 r^4 \\ \text{where} \quad r^2 = x'^2 + y'^2 \\ u = f_x*x'' + c_x \\ v = f_y*y'' + c_y \end{array}\f] + +\f$k_1\f$, \f$k_2\f$, \f$k_3\f$, \f$k_4\f$, \f$k_5\f$, and \f$k_6\f$ are radial distortion coefficients. \f$p_1\f$ and \f$p_2\f$ are +tangential distortion coefficients. \f$s_1\f$, \f$s_2\f$, \f$s_3\f$, and \f$s_4\f$, are the thin prism distortion +coefficients. Higher-order coefficients are not considered in OpenCV. In the functions below the +coefficients are passed or returned as + +\f[(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f] + +vector. That is, if the vector contains four elements, it means that \f$k_3=0\f$ . The distortion +coefficients do not depend on the scene viewed. Thus, they also belong to the intrinsic camera +parameters. And they remain the same regardless of the captured image resolution. If, for example, a +camera has been calibrated on images of 320 x 240 resolution, absolutely the same distortion +coefficients can be used for 640 x 480 images from the same camera while \f$f_x\f$, \f$f_y\f$, \f$c_x\f$, and +\f$c_y\f$ need to be scaled appropriately. + +The functions below use the above model to do the following: + +- Project 3D points to the image plane given intrinsic and extrinsic parameters. +- Compute extrinsic parameters given intrinsic parameters, a few 3D points, and their +projections. +- Estimate intrinsic and extrinsic camera parameters from several views of a known calibration +pattern (every view is described by several 3D-2D point correspondences). +- Estimate the relative position and orientation of the stereo camera "heads" and compute the +*rectification* transformation that makes the camera optical axes parallel. + +@note + - A calibration sample for 3 cameras in horizontal position can be found at + opencv_source_code/samples/cpp/3calibration.cpp + - A calibration sample based on a sequence of images can be found at + opencv_source_code/samples/cpp/calibration.cpp + - A calibration sample in order to do 3D reconstruction can be found at + opencv_source_code/samples/cpp/build3dmodel.cpp + - A calibration sample of an artificially generated camera and chessboard patterns can be + found at opencv_source_code/samples/cpp/calibration_artificial.cpp + - A calibration example on stereo calibration can be found at + opencv_source_code/samples/cpp/stereo_calib.cpp + - A calibration example on stereo matching can be found at + opencv_source_code/samples/cpp/stereo_match.cpp + - (Python) A camera calibration sample can be found at + opencv_source_code/samples/python2/calibrate.py + + @{ + @defgroup calib3d_fisheye Fisheye camera model + + Definitions: Let P be a point in 3D of coordinates X in the world reference frame (stored in the + matrix X) The coordinate vector of P in the camera reference frame is: + + \f[Xc = R X + T\f] + + where R is the rotation matrix corresponding to the rotation vector om: R = rodrigues(om); call x, y + and z the 3 coordinates of Xc: + + \f[x = Xc_1 \\ y = Xc_2 \\ z = Xc_3\f] + + The pinehole projection coordinates of P is [a; b] where + + \f[a = x / z \ and \ b = y / z \\ r^2 = a^2 + b^2 \\ \theta = atan(r)\f] + + Fisheye distortion: + + \f[\theta_d = \theta (1 + k_1 \theta^2 + k_2 \theta^4 + k_3 \theta^6 + k_4 \theta^8)\f] + + The distorted point coordinates are [x'; y'] where + + \f[x' = (\theta_d / r) x \\ y' = (\theta_d / r) y \f] + + Finally, conversion into pixel coordinates: The final pixel coordinates vector [u; v] where: + + \f[u = f_x (x' + \alpha y') + c_x \\ + v = f_y yy + c_y\f] + + @defgroup calib3d_c C API + + @} + */ + +namespace cv +{ + +//! @addtogroup calib3d +//! @{ + +//! type of the robust estimation algorithm +enum { LMEDS = 4, //!< least-median algorithm + RANSAC = 8, //!< RANSAC algorithm + RHO = 16 //!< RHO algorithm + }; + +enum { SOLVEPNP_ITERATIVE = 0, + SOLVEPNP_EPNP = 1, // F.Moreno-Noguer, V.Lepetit and P.Fua "EPnP: Efficient Perspective-n-Point Camera Pose Estimation" + SOLVEPNP_P3P = 2, // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang; "Complete Solution Classification for the Perspective-Three-Point Problem" + SOLVEPNP_DLS = 3, // Joel A. Hesch and Stergios I. Roumeliotis. "A Direct Least-Squares (DLS) Method for PnP" + SOLVEPNP_UPNP = 4 // A.Penate-Sanchez, J.Andrade-Cetto, F.Moreno-Noguer. "Exhaustive Linearization for Robust Camera Pose and Focal Length Estimation" + +}; + +enum { CALIB_CB_ADAPTIVE_THRESH = 1, + CALIB_CB_NORMALIZE_IMAGE = 2, + CALIB_CB_FILTER_QUADS = 4, + CALIB_CB_FAST_CHECK = 8 + }; + +enum { CALIB_CB_SYMMETRIC_GRID = 1, + CALIB_CB_ASYMMETRIC_GRID = 2, + CALIB_CB_CLUSTERING = 4 + }; + +enum { CALIB_USE_INTRINSIC_GUESS = 0x00001, + CALIB_FIX_ASPECT_RATIO = 0x00002, + CALIB_FIX_PRINCIPAL_POINT = 0x00004, + CALIB_ZERO_TANGENT_DIST = 0x00008, + CALIB_FIX_FOCAL_LENGTH = 0x00010, + CALIB_FIX_K1 = 0x00020, + CALIB_FIX_K2 = 0x00040, + CALIB_FIX_K3 = 0x00080, + CALIB_FIX_K4 = 0x00800, + CALIB_FIX_K5 = 0x01000, + CALIB_FIX_K6 = 0x02000, + CALIB_RATIONAL_MODEL = 0x04000, + CALIB_THIN_PRISM_MODEL = 0x08000, + CALIB_FIX_S1_S2_S3_S4 = 0x10000, + // only for stereo + CALIB_FIX_INTRINSIC = 0x00100, + CALIB_SAME_FOCAL_LENGTH = 0x00200, + // for stereo rectification + CALIB_ZERO_DISPARITY = 0x00400 + }; + +//! the algorithm for finding fundamental matrix +enum { FM_7POINT = 1, //!< 7-point algorithm + FM_8POINT = 2, //!< 8-point algorithm + FM_LMEDS = 4, //!< least-median algorithm + FM_RANSAC = 8 //!< RANSAC algorithm + }; + + + +/** @brief Converts a rotation matrix to a rotation vector or vice versa. + +@param src Input rotation vector (3x1 or 1x3) or rotation matrix (3x3). +@param dst Output rotation matrix (3x3) or rotation vector (3x1 or 1x3), respectively. +@param jacobian Optional output Jacobian matrix, 3x9 or 9x3, which is a matrix of partial +derivatives of the output array components with respect to the input array components. + +\f[\begin{array}{l} \theta \leftarrow norm(r) \\ r \leftarrow r/ \theta \\ R = \cos{\theta} I + (1- \cos{\theta} ) r r^T + \sin{\theta} \vecthreethree{0}{-r_z}{r_y}{r_z}{0}{-r_x}{-r_y}{r_x}{0} \end{array}\f] + +Inverse transformation can be also done easily, since + +\f[\sin ( \theta ) \vecthreethree{0}{-r_z}{r_y}{r_z}{0}{-r_x}{-r_y}{r_x}{0} = \frac{R - R^T}{2}\f] + +A rotation vector is a convenient and most compact representation of a rotation matrix (since any +rotation matrix has just 3 degrees of freedom). The representation is used in the global 3D geometry +optimization procedures like calibrateCamera, stereoCalibrate, or solvePnP . + */ +CV_EXPORTS_W void Rodrigues( InputArray src, OutputArray dst, OutputArray jacobian = noArray() ); + +/** @brief Finds a perspective transformation between two planes. + +@param srcPoints Coordinates of the points in the original plane, a matrix of the type CV_32FC2 +or vector\ . +@param dstPoints Coordinates of the points in the target plane, a matrix of the type CV_32FC2 or +a vector\ . +@param method Method used to computed a homography matrix. The following methods are possible: +- **0** - a regular method using all the points +- **RANSAC** - RANSAC-based robust method +- **LMEDS** - Least-Median robust method +- **RHO** - PROSAC-based robust method +@param ransacReprojThreshold Maximum allowed reprojection error to treat a point pair as an inlier +(used in the RANSAC and RHO methods only). That is, if +\f[\| \texttt{dstPoints} _i - \texttt{convertPointsHomogeneous} ( \texttt{H} * \texttt{srcPoints} _i) \| > \texttt{ransacReprojThreshold}\f] +then the point \f$i\f$ is considered an outlier. If srcPoints and dstPoints are measured in pixels, +it usually makes sense to set this parameter somewhere in the range of 1 to 10. +@param mask Optional output mask set by a robust method ( RANSAC or LMEDS ). Note that the input +mask values are ignored. +@param maxIters The maximum number of RANSAC iterations, 2000 is the maximum it can be. +@param confidence Confidence level, between 0 and 1. + +The functions find and return the perspective transformation \f$H\f$ between the source and the +destination planes: + +\f[s_i \vecthree{x'_i}{y'_i}{1} \sim H \vecthree{x_i}{y_i}{1}\f] + +so that the back-projection error + +\f[\sum _i \left ( x'_i- \frac{h_{11} x_i + h_{12} y_i + h_{13}}{h_{31} x_i + h_{32} y_i + h_{33}} \right )^2+ \left ( y'_i- \frac{h_{21} x_i + h_{22} y_i + h_{23}}{h_{31} x_i + h_{32} y_i + h_{33}} \right )^2\f] + +is minimized. If the parameter method is set to the default value 0, the function uses all the point +pairs to compute an initial homography estimate with a simple least-squares scheme. + +However, if not all of the point pairs ( \f$srcPoints_i\f$, \f$dstPoints_i\f$ ) fit the rigid perspective +transformation (that is, there are some outliers), this initial estimate will be poor. In this case, +you can use one of the three robust methods. The methods RANSAC, LMeDS and RHO try many different +random subsets of the corresponding point pairs (of four pairs each), estimate the homography matrix +using this subset and a simple least-square algorithm, and then compute the quality/goodness of the +computed homography (which is the number of inliers for RANSAC or the median re-projection error for +LMeDs). The best subset is then used to produce the initial estimate of the homography matrix and +the mask of inliers/outliers. + +Regardless of the method, robust or not, the computed homography matrix is refined further (using +inliers only in case of a robust method) with the Levenberg-Marquardt method to reduce the +re-projection error even more. + +The methods RANSAC and RHO can handle practically any ratio of outliers but need a threshold to +distinguish inliers from outliers. The method LMeDS does not need any threshold but it works +correctly only when there are more than 50% of inliers. Finally, if there are no outliers and the +noise is rather small, use the default method (method=0). + +The function is used to find initial intrinsic and extrinsic matrices. Homography matrix is +determined up to a scale. Thus, it is normalized so that \f$h_{33}=1\f$. Note that whenever an H matrix +cannot be estimated, an empty one will be returned. + +@sa + getAffineTransform, getPerspectiveTransform, estimateRigidTransform, warpPerspective, + perspectiveTransform + +@note + - A example on calculating a homography for image matching can be found at + opencv_source_code/samples/cpp/video_homography.cpp + + */ +CV_EXPORTS_W Mat findHomography( InputArray srcPoints, InputArray dstPoints, + int method = 0, double ransacReprojThreshold = 3, + OutputArray mask=noArray(), const int maxIters = 2000, + const double confidence = 0.995); + +/** @overload */ +CV_EXPORTS Mat findHomography( InputArray srcPoints, InputArray dstPoints, + OutputArray mask, int method = 0, double ransacReprojThreshold = 3 ); + +/** @brief Computes an RQ decomposition of 3x3 matrices. + +@param src 3x3 input matrix. +@param mtxR Output 3x3 upper-triangular matrix. +@param mtxQ Output 3x3 orthogonal matrix. +@param Qx Optional output 3x3 rotation matrix around x-axis. +@param Qy Optional output 3x3 rotation matrix around y-axis. +@param Qz Optional output 3x3 rotation matrix around z-axis. + +The function computes a RQ decomposition using the given rotations. This function is used in +decomposeProjectionMatrix to decompose the left 3x3 submatrix of a projection matrix into a camera +and a rotation matrix. + +It optionally returns three rotation matrices, one for each axis, and the three Euler angles in +degrees (as the return value) that could be used in OpenGL. Note, there is always more than one +sequence of rotations about the three principle axes that results in the same orientation of an +object, eg. see @cite Slabaugh . Returned tree rotation matrices and corresponding three Euler angules +are only one of the possible solutions. + */ +CV_EXPORTS_W Vec3d RQDecomp3x3( InputArray src, OutputArray mtxR, OutputArray mtxQ, + OutputArray Qx = noArray(), + OutputArray Qy = noArray(), + OutputArray Qz = noArray()); + +/** @brief Decomposes a projection matrix into a rotation matrix and a camera matrix. + +@param projMatrix 3x4 input projection matrix P. +@param cameraMatrix Output 3x3 camera matrix K. +@param rotMatrix Output 3x3 external rotation matrix R. +@param transVect Output 4x1 translation vector T. +@param rotMatrixX Optional 3x3 rotation matrix around x-axis. +@param rotMatrixY Optional 3x3 rotation matrix around y-axis. +@param rotMatrixZ Optional 3x3 rotation matrix around z-axis. +@param eulerAngles Optional three-element vector containing three Euler angles of rotation in +degrees. + +The function computes a decomposition of a projection matrix into a calibration and a rotation +matrix and the position of a camera. + +It optionally returns three rotation matrices, one for each axis, and three Euler angles that could +be used in OpenGL. Note, there is always more than one sequence of rotations about the three +principle axes that results in the same orientation of an object, eg. see @cite Slabaugh . Returned +tree rotation matrices and corresponding three Euler angules are only one of the possible solutions. + +The function is based on RQDecomp3x3 . + */ +CV_EXPORTS_W void decomposeProjectionMatrix( InputArray projMatrix, OutputArray cameraMatrix, + OutputArray rotMatrix, OutputArray transVect, + OutputArray rotMatrixX = noArray(), + OutputArray rotMatrixY = noArray(), + OutputArray rotMatrixZ = noArray(), + OutputArray eulerAngles =noArray() ); + +/** @brief Computes partial derivatives of the matrix product for each multiplied matrix. + +@param A First multiplied matrix. +@param B Second multiplied matrix. +@param dABdA First output derivative matrix d(A\*B)/dA of size +\f$\texttt{A.rows*B.cols} \times {A.rows*A.cols}\f$ . +@param dABdB Second output derivative matrix d(A\*B)/dB of size +\f$\texttt{A.rows*B.cols} \times {B.rows*B.cols}\f$ . + +The function computes partial derivatives of the elements of the matrix product \f$A*B\f$ with regard to +the elements of each of the two input matrices. The function is used to compute the Jacobian +matrices in stereoCalibrate but can also be used in any other similar optimization function. + */ +CV_EXPORTS_W void matMulDeriv( InputArray A, InputArray B, OutputArray dABdA, OutputArray dABdB ); + +/** @brief Combines two rotation-and-shift transformations. + +@param rvec1 First rotation vector. +@param tvec1 First translation vector. +@param rvec2 Second rotation vector. +@param tvec2 Second translation vector. +@param rvec3 Output rotation vector of the superposition. +@param tvec3 Output translation vector of the superposition. +@param dr3dr1 +@param dr3dt1 +@param dr3dr2 +@param dr3dt2 +@param dt3dr1 +@param dt3dt1 +@param dt3dr2 +@param dt3dt2 Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and +tvec2, respectively. + +The functions compute: + +\f[\begin{array}{l} \texttt{rvec3} = \mathrm{rodrigues} ^{-1} \left ( \mathrm{rodrigues} ( \texttt{rvec2} ) \cdot \mathrm{rodrigues} ( \texttt{rvec1} ) \right ) \\ \texttt{tvec3} = \mathrm{rodrigues} ( \texttt{rvec2} ) \cdot \texttt{tvec1} + \texttt{tvec2} \end{array} ,\f] + +where \f$\mathrm{rodrigues}\f$ denotes a rotation vector to a rotation matrix transformation, and +\f$\mathrm{rodrigues}^{-1}\f$ denotes the inverse transformation. See Rodrigues for details. + +Also, the functions can compute the derivatives of the output vectors with regards to the input +vectors (see matMulDeriv ). The functions are used inside stereoCalibrate but can also be used in +your own code where Levenberg-Marquardt or another gradient-based solver is used to optimize a +function that contains a matrix multiplication. + */ +CV_EXPORTS_W void composeRT( InputArray rvec1, InputArray tvec1, + InputArray rvec2, InputArray tvec2, + OutputArray rvec3, OutputArray tvec3, + OutputArray dr3dr1 = noArray(), OutputArray dr3dt1 = noArray(), + OutputArray dr3dr2 = noArray(), OutputArray dr3dt2 = noArray(), + OutputArray dt3dr1 = noArray(), OutputArray dt3dt1 = noArray(), + OutputArray dt3dr2 = noArray(), OutputArray dt3dt2 = noArray() ); + +/** @brief Projects 3D points to an image plane. + +@param objectPoints Array of object points, 3xN/Nx3 1-channel or 1xN/Nx1 3-channel (or +vector\ ), where N is the number of points in the view. +@param rvec Rotation vector. See Rodrigues for details. +@param tvec Translation vector. +@param cameraMatrix Camera matrix \f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$ . +@param distCoeffs Input vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements. If +the vector is NULL/empty, the zero distortion coefficients are assumed. +@param imagePoints Output array of image points, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel, or +vector\ . +@param jacobian Optional output 2Nx(10+\) jacobian matrix of derivatives of image +points with respect to components of the rotation vector, translation vector, focal lengths, +coordinates of the principal point and the distortion coefficients. In the old interface different +components of the jacobian are returned via different output parameters. +@param aspectRatio Optional "fixed aspect ratio" parameter. If the parameter is not 0, the +function assumes that the aspect ratio (*fx/fy*) is fixed and correspondingly adjusts the jacobian +matrix. + +The function computes projections of 3D points to the image plane given intrinsic and extrinsic +camera parameters. Optionally, the function computes Jacobians - matrices of partial derivatives of +image points coordinates (as functions of all the input parameters) with respect to the particular +parameters, intrinsic and/or extrinsic. The Jacobians are used during the global optimization in +calibrateCamera, solvePnP, and stereoCalibrate . The function itself can also be used to compute a +re-projection error given the current intrinsic and extrinsic parameters. + +@note By setting rvec=tvec=(0,0,0) or by setting cameraMatrix to a 3x3 identity matrix, or by +passing zero distortion coefficients, you can get various useful partial cases of the function. This +means that you can compute the distorted coordinates for a sparse set of points or apply a +perspective transformation (and also compute the derivatives) in the ideal zero-distortion setup. + */ +CV_EXPORTS_W void projectPoints( InputArray objectPoints, + InputArray rvec, InputArray tvec, + InputArray cameraMatrix, InputArray distCoeffs, + OutputArray imagePoints, + OutputArray jacobian = noArray(), + double aspectRatio = 0 ); + +/** @brief Finds an object pose from 3D-2D point correspondences. + +@param objectPoints Array of object points in the object coordinate space, 3xN/Nx3 1-channel or +1xN/Nx1 3-channel, where N is the number of points. vector\ can be also passed here. +@param imagePoints Array of corresponding image points, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel, +where N is the number of points. vector\ can be also passed here. +@param cameraMatrix Input camera matrix \f$A = \vecthreethree{fx}{0}{cx}{0}{fy}{cy}{0}{0}{1}\f$ . +@param distCoeffs Input vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements. If +the vector is NULL/empty, the zero distortion coefficients are assumed. +@param rvec Output rotation vector (see Rodrigues ) that, together with tvec , brings points from +the model coordinate system to the camera coordinate system. +@param tvec Output translation vector. +@param useExtrinsicGuess Parameter used for SOLVEPNP_ITERATIVE. If true (1), the function uses +the provided rvec and tvec values as initial approximations of the rotation and translation +vectors, respectively, and further optimizes them. +@param flags Method for solving a PnP problem: +- **SOLVEPNP_ITERATIVE** Iterative method is based on Levenberg-Marquardt optimization. In +this case the function finds such a pose that minimizes reprojection error, that is the sum +of squared distances between the observed projections imagePoints and the projected (using +projectPoints ) objectPoints . +- **SOLVEPNP_P3P** Method is based on the paper of X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang +"Complete Solution Classification for the Perspective-Three-Point Problem". In this case the +function requires exactly four object and image points. +- **SOLVEPNP_EPNP** Method has been introduced by F.Moreno-Noguer, V.Lepetit and P.Fua in the +paper "EPnP: Efficient Perspective-n-Point Camera Pose Estimation". +- **SOLVEPNP_DLS** Method is based on the paper of Joel A. Hesch and Stergios I. Roumeliotis. +"A Direct Least-Squares (DLS) Method for PnP". +- **SOLVEPNP_UPNP** Method is based on the paper of A.Penate-Sanchez, J.Andrade-Cetto, +F.Moreno-Noguer. "Exhaustive Linearization for Robust Camera Pose and Focal Length +Estimation". In this case the function also estimates the parameters \f$f_x\f$ and \f$f_y\f$ +assuming that both have the same value. Then the cameraMatrix is updated with the estimated +focal length. + +The function estimates the object pose given a set of object points, their corresponding image +projections, as well as the camera matrix and the distortion coefficients. + +@note + - An example of how to use solvePnP for planar augmented reality can be found at + opencv_source_code/samples/python2/plane_ar.py + - If you are using Python: + - Numpy array slices won't work as input because solvePnP requires contiguous + arrays (enforced by the assertion using cv::Mat::checkVector() around line 55 of + modules/calib3d/src/solvepnp.cpp version 2.4.9) + - The P3P algorithm requires image points to be in an array of shape (N,1,2) due + to its calling of cv::undistortPoints (around line 75 of modules/calib3d/src/solvepnp.cpp version 2.4.9) + which requires 2-channel information. + - Thus, given some data D = np.array(...) where D.shape = (N,M), in order to use a subset of + it as, e.g., imagePoints, one must effectively copy it into a new array: imagePoints = + np.ascontiguousarray(D[:,:2]).reshape((N,1,2)) + */ +CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints, + InputArray cameraMatrix, InputArray distCoeffs, + OutputArray rvec, OutputArray tvec, + bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE ); + +/** @brief Finds an object pose from 3D-2D point correspondences using the RANSAC scheme. + +@param objectPoints Array of object points in the object coordinate space, 3xN/Nx3 1-channel or +1xN/Nx1 3-channel, where N is the number of points. vector\ can be also passed here. +@param imagePoints Array of corresponding image points, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel, +where N is the number of points. vector\ can be also passed here. +@param cameraMatrix Input camera matrix \f$A = \vecthreethree{fx}{0}{cx}{0}{fy}{cy}{0}{0}{1}\f$ . +@param distCoeffs Input vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements. If +the vector is NULL/empty, the zero distortion coefficients are assumed. +@param rvec Output rotation vector (see Rodrigues ) that, together with tvec , brings points from +the model coordinate system to the camera coordinate system. +@param tvec Output translation vector. +@param useExtrinsicGuess Parameter used for SOLVEPNP_ITERATIVE. If true (1), the function uses +the provided rvec and tvec values as initial approximations of the rotation and translation +vectors, respectively, and further optimizes them. +@param iterationsCount Number of iterations. +@param reprojectionError Inlier threshold value used by the RANSAC procedure. The parameter value +is the maximum allowed distance between the observed and computed point projections to consider it +an inlier. +@param confidence The probability that the algorithm produces a useful result. +@param inliers Output vector that contains indices of inliers in objectPoints and imagePoints . +@param flags Method for solving a PnP problem (see solvePnP ). + +The function estimates an object pose given a set of object points, their corresponding image +projections, as well as the camera matrix and the distortion coefficients. This function finds such +a pose that minimizes reprojection error, that is, the sum of squared distances between the observed +projections imagePoints and the projected (using projectPoints ) objectPoints. The use of RANSAC +makes the function resistant to outliers. + +@note + - An example of how to use solvePNPRansac for object detection can be found at + opencv_source_code/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/ + */ +CV_EXPORTS_W bool solvePnPRansac( InputArray objectPoints, InputArray imagePoints, + InputArray cameraMatrix, InputArray distCoeffs, + OutputArray rvec, OutputArray tvec, + bool useExtrinsicGuess = false, int iterationsCount = 100, + float reprojectionError = 8.0, double confidence = 0.99, + OutputArray inliers = noArray(), int flags = SOLVEPNP_ITERATIVE ); + +/** @brief Finds an initial camera matrix from 3D-2D point correspondences. + +@param objectPoints Vector of vectors of the calibration pattern points in the calibration pattern +coordinate space. In the old interface all the per-view vectors are concatenated. See +calibrateCamera for details. +@param imagePoints Vector of vectors of the projections of the calibration pattern points. In the +old interface all the per-view vectors are concatenated. +@param imageSize Image size in pixels used to initialize the principal point. +@param aspectRatio If it is zero or negative, both \f$f_x\f$ and \f$f_y\f$ are estimated independently. +Otherwise, \f$f_x = f_y * \texttt{aspectRatio}\f$ . + +The function estimates and returns an initial camera matrix for the camera calibration process. +Currently, the function only supports planar calibration patterns, which are patterns where each +object point has z-coordinate =0. + */ +CV_EXPORTS_W Mat initCameraMatrix2D( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, + Size imageSize, double aspectRatio = 1.0 ); + +/** @brief Finds the positions of internal corners of the chessboard. + +@param image Source chessboard view. It must be an 8-bit grayscale or color image. +@param patternSize Number of inner corners per a chessboard row and column +( patternSize = cvSize(points_per_row,points_per_colum) = cvSize(columns,rows) ). +@param corners Output array of detected corners. +@param flags Various operation flags that can be zero or a combination of the following values: +- **CV_CALIB_CB_ADAPTIVE_THRESH** Use adaptive thresholding to convert the image to black +and white, rather than a fixed threshold level (computed from the average image brightness). +- **CV_CALIB_CB_NORMALIZE_IMAGE** Normalize the image gamma with equalizeHist before +applying fixed or adaptive thresholding. +- **CV_CALIB_CB_FILTER_QUADS** Use additional criteria (like contour area, perimeter, +square-like shape) to filter out false quads extracted at the contour retrieval stage. +- **CALIB_CB_FAST_CHECK** Run a fast check on the image that looks for chessboard corners, +and shortcut the call if none is found. This can drastically speed up the call in the +degenerate condition when no chessboard is observed. + +The function attempts to determine whether the input image is a view of the chessboard pattern and +locate the internal chessboard corners. The function returns a non-zero value if all of the corners +are found and they are placed in a certain order (row by row, left to right in every row). +Otherwise, if the function fails to find all the corners or reorder them, it returns 0. For example, +a regular chessboard has 8 x 8 squares and 7 x 7 internal corners, that is, points where the black +squares touch each other. The detected coordinates are approximate, and to determine their positions +more accurately, the function calls cornerSubPix. You also may use the function cornerSubPix with +different parameters if returned coordinates are not accurate enough. + +Sample usage of detecting and drawing chessboard corners: : +@code + Size patternsize(8,6); //interior number of corners + Mat gray = ....; //source image + vector corners; //this will be filled by the detected corners + + //CALIB_CB_FAST_CHECK saves a lot of time on images + //that do not contain any chessboard corners + bool patternfound = findChessboardCorners(gray, patternsize, corners, + CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + + CALIB_CB_FAST_CHECK); + + if(patternfound) + cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1), + TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1)); + + drawChessboardCorners(img, patternsize, Mat(corners), patternfound); +@endcode +@note The function requires white space (like a square-thick border, the wider the better) around +the board to make the detection more robust in various environments. Otherwise, if there is no +border and the background is dark, the outer black squares cannot be segmented properly and so the +square grouping and ordering algorithm fails. + */ +CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners, + int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE ); + +//! finds subpixel-accurate positions of the chessboard corners +CV_EXPORTS bool find4QuadCornerSubpix( InputArray img, InputOutputArray corners, Size region_size ); + +/** @brief Renders the detected chessboard corners. + +@param image Destination image. It must be an 8-bit color image. +@param patternSize Number of inner corners per a chessboard row and column +(patternSize = cv::Size(points_per_row,points_per_column)). +@param corners Array of detected corners, the output of findChessboardCorners. +@param patternWasFound Parameter indicating whether the complete board was found or not. The +return value of findChessboardCorners should be passed here. + +The function draws individual chessboard corners detected either as red circles if the board was not +found, or as colored corners connected with lines if the board was found. + */ +CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize, + InputArray corners, bool patternWasFound ); + +/** @brief Finds centers in the grid of circles. + +@param image grid view of input circles; it must be an 8-bit grayscale or color image. +@param patternSize number of circles per row and column +( patternSize = Size(points_per_row, points_per_colum) ). +@param centers output array of detected centers. +@param flags various operation flags that can be one of the following values: +- **CALIB_CB_SYMMETRIC_GRID** uses symmetric pattern of circles. +- **CALIB_CB_ASYMMETRIC_GRID** uses asymmetric pattern of circles. +- **CALIB_CB_CLUSTERING** uses a special algorithm for grid detection. It is more robust to +perspective distortions but much more sensitive to background clutter. +@param blobDetector feature detector that finds blobs like dark circles on light background. + +The function attempts to determine whether the input image contains a grid of circles. If it is, the +function locates centers of the circles. The function returns a non-zero value if all of the centers +have been found and they have been placed in a certain order (row by row, left to right in every +row). Otherwise, if the function fails to find all the corners or reorder them, it returns 0. + +Sample usage of detecting and drawing the centers of circles: : +@code + Size patternsize(7,7); //number of centers + Mat gray = ....; //source image + vector centers; //this will be filled by the detected centers + + bool patternfound = findCirclesGrid(gray, patternsize, centers); + + drawChessboardCorners(img, patternsize, Mat(centers), patternfound); +@endcode +@note The function requires white space (like a square-thick border, the wider the better) around +the board to make the detection more robust in various environments. + */ +CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize, + OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID, + const Ptr &blobDetector = SimpleBlobDetector::create()); + +/** @brief Finds the camera intrinsic and extrinsic parameters from several views of a calibration pattern. + +@param objectPoints In the new interface it is a vector of vectors of calibration pattern points in +the calibration pattern coordinate space (e.g. std::vector>). The outer +vector contains as many elements as the number of the pattern views. If the same calibration pattern +is shown in each view and it is fully visible, all the vectors will be the same. Although, it is +possible to use partially occluded patterns, or even different patterns in different views. Then, +the vectors will be different. The points are 3D, but since they are in a pattern coordinate system, +then, if the rig is planar, it may make sense to put the model to a XY coordinate plane so that +Z-coordinate of each input object point is 0. +In the old interface all the vectors of object points from different views are concatenated +together. +@param imagePoints In the new interface it is a vector of vectors of the projections of calibration +pattern points (e.g. std::vector>). imagePoints.size() and +objectPoints.size() and imagePoints[i].size() must be equal to objectPoints[i].size() for each i. +In the old interface all the vectors of object points from different views are concatenated +together. +@param imageSize Size of the image used only to initialize the intrinsic camera matrix. +@param cameraMatrix Output 3x3 floating-point camera matrix +\f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . If CV\_CALIB\_USE\_INTRINSIC\_GUESS +and/or CV_CALIB_FIX_ASPECT_RATIO are specified, some or all of fx, fy, cx, cy must be +initialized before calling the function. +@param distCoeffs Output vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements. +@param rvecs Output vector of rotation vectors (see Rodrigues ) estimated for each pattern view +(e.g. std::vector>). That is, each k-th rotation vector together with the corresponding +k-th translation vector (see the next output parameter description) brings the calibration pattern +from the model coordinate space (in which object points are specified) to the world coordinate +space, that is, a real position of the calibration pattern in the k-th pattern view (k=0.. *M* -1). +@param tvecs Output vector of translation vectors estimated for each pattern view. +@param flags Different flags that may be zero or a combination of the following values: +- **CV_CALIB_USE_INTRINSIC_GUESS** cameraMatrix contains valid initial values of +fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image +center ( imageSize is used), and focal distances are computed in a least-squares fashion. +Note, that if intrinsic parameters are known, there is no need to use this function just to +estimate extrinsic parameters. Use solvePnP instead. +- **CV_CALIB_FIX_PRINCIPAL_POINT** The principal point is not changed during the global +optimization. It stays at the center or at a different location specified when +CV_CALIB_USE_INTRINSIC_GUESS is set too. +- **CV_CALIB_FIX_ASPECT_RATIO** The functions considers only fy as a free parameter. The +ratio fx/fy stays the same as in the input cameraMatrix . When +CV_CALIB_USE_INTRINSIC_GUESS is not set, the actual input values of fx and fy are +ignored, only their ratio is computed and used further. +- **CV_CALIB_ZERO_TANGENT_DIST** Tangential distortion coefficients \f$(p_1, p_2)\f$ are set +to zeros and stay zero. +- **CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6** The corresponding radial distortion +coefficient is not changed during the optimization. If CV_CALIB_USE_INTRINSIC_GUESS is +set, the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0. +- **CV_CALIB_RATIONAL_MODEL** Coefficients k4, k5, and k6 are enabled. To provide the +backward compatibility, this extra flag should be explicitly specified to make the +calibration function use the rational model and return 8 coefficients. If the flag is not +set, the function computes and returns only 5 distortion coefficients. +- **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the +backward compatibility, this extra flag should be explicitly specified to make the +calibration function use the thin prism model and return 12 coefficients. If the flag is not +set, the function computes and returns only 5 distortion coefficients. +- **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during +the optimization. If CV_CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the +supplied distCoeffs matrix is used. Otherwise, it is set to 0. +@param criteria Termination criteria for the iterative optimization algorithm. + +The function estimates the intrinsic camera parameters and extrinsic parameters for each of the +views. The algorithm is based on @cite Zhang2000 and @cite BouguetMCT . The coordinates of 3D object +points and their corresponding 2D projections in each view must be specified. That may be achieved +by using an object with a known geometry and easily detectable feature points. Such an object is +called a calibration rig or calibration pattern, and OpenCV has built-in support for a chessboard as +a calibration rig (see findChessboardCorners ). Currently, initialization of intrinsic parameters +(when CV_CALIB_USE_INTRINSIC_GUESS is not set) is only implemented for planar calibration +patterns (where Z-coordinates of the object points must be all zeros). 3D calibration rigs can also +be used as long as initial cameraMatrix is provided. + +The algorithm performs the following steps: + +- Compute the initial intrinsic parameters (the option only available for planar calibration + patterns) or read them from the input parameters. The distortion coefficients are all set to + zeros initially unless some of CV_CALIB_FIX_K? are specified. + +- Estimate the initial camera pose as if the intrinsic parameters have been already known. This is + done using solvePnP . + +- Run the global Levenberg-Marquardt optimization algorithm to minimize the reprojection error, + that is, the total sum of squared distances between the observed feature points imagePoints and + the projected (using the current estimates for camera parameters and the poses) object points + objectPoints. See projectPoints for details. + +The function returns the final re-projection error. + +@note + If you use a non-square (=non-NxN) grid and findChessboardCorners for calibration, and + calibrateCamera returns bad values (zero distortion coefficients, an image center very far from + (w/2-0.5,h/2-0.5), and/or large differences between \f$f_x\f$ and \f$f_y\f$ (ratios of 10:1 or more)), + then you have probably used patternSize=cvSize(rows,cols) instead of using + patternSize=cvSize(cols,rows) in findChessboardCorners . + +@sa + findChessboardCorners, solvePnP, initCameraMatrix2D, stereoCalibrate, undistort + */ +CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints, Size imageSize, + InputOutputArray cameraMatrix, InputOutputArray distCoeffs, + OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, + int flags = 0, TermCriteria criteria = TermCriteria( + TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) ); + +/** @brief Computes useful camera characteristics from the camera matrix. + +@param cameraMatrix Input camera matrix that can be estimated by calibrateCamera or +stereoCalibrate . +@param imageSize Input image size in pixels. +@param apertureWidth Physical width in mm of the sensor. +@param apertureHeight Physical height in mm of the sensor. +@param fovx Output field of view in degrees along the horizontal sensor axis. +@param fovy Output field of view in degrees along the vertical sensor axis. +@param focalLength Focal length of the lens in mm. +@param principalPoint Principal point in mm. +@param aspectRatio \f$f_y/f_x\f$ + +The function computes various useful camera characteristics from the previously estimated camera +matrix. + +@note + Do keep in mind that the unity measure 'mm' stands for whatever unit of measure one chooses for + the chessboard pitch (it can thus be any value). + */ +CV_EXPORTS_W void calibrationMatrixValues( InputArray cameraMatrix, Size imageSize, + double apertureWidth, double apertureHeight, + CV_OUT double& fovx, CV_OUT double& fovy, + CV_OUT double& focalLength, CV_OUT Point2d& principalPoint, + CV_OUT double& aspectRatio ); + +/** @brief Calibrates the stereo camera. + +@param objectPoints Vector of vectors of the calibration pattern points. +@param imagePoints1 Vector of vectors of the projections of the calibration pattern points, +observed by the first camera. +@param imagePoints2 Vector of vectors of the projections of the calibration pattern points, +observed by the second camera. +@param cameraMatrix1 Input/output first camera matrix: +\f$\vecthreethree{f_x^{(j)}}{0}{c_x^{(j)}}{0}{f_y^{(j)}}{c_y^{(j)}}{0}{0}{1}\f$ , \f$j = 0,\, 1\f$ . If +any of CV_CALIB_USE_INTRINSIC_GUESS , CV_CALIB_FIX_ASPECT_RATIO , +CV_CALIB_FIX_INTRINSIC , or CV_CALIB_FIX_FOCAL_LENGTH are specified, some or all of the +matrix components must be initialized. See the flags description for details. +@param distCoeffs1 Input/output vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 ot 12 elements. The +output vector length depends on the flags. +@param cameraMatrix2 Input/output second camera matrix. The parameter is similar to cameraMatrix1 +@param distCoeffs2 Input/output lens distortion coefficients for the second camera. The parameter +is similar to distCoeffs1 . +@param imageSize Size of the image used only to initialize intrinsic camera matrix. +@param R Output rotation matrix between the 1st and the 2nd camera coordinate systems. +@param T Output translation vector between the coordinate systems of the cameras. +@param E Output essential matrix. +@param F Output fundamental matrix. +@param flags Different flags that may be zero or a combination of the following values: +- **CV_CALIB_FIX_INTRINSIC** Fix cameraMatrix? and distCoeffs? so that only R, T, E , and F +matrices are estimated. +- **CV_CALIB_USE_INTRINSIC_GUESS** Optimize some or all of the intrinsic parameters +according to the specified flags. Initial values are provided by the user. +- **CV_CALIB_FIX_PRINCIPAL_POINT** Fix the principal points during the optimization. +- **CV_CALIB_FIX_FOCAL_LENGTH** Fix \f$f^{(j)}_x\f$ and \f$f^{(j)}_y\f$ . +- **CV_CALIB_FIX_ASPECT_RATIO** Optimize \f$f^{(j)}_y\f$ . Fix the ratio \f$f^{(j)}_x/f^{(j)}_y\f$ +. +- **CV_CALIB_SAME_FOCAL_LENGTH** Enforce \f$f^{(0)}_x=f^{(1)}_x\f$ and \f$f^{(0)}_y=f^{(1)}_y\f$ . +- **CV_CALIB_ZERO_TANGENT_DIST** Set tangential distortion coefficients for each camera to +zeros and fix there. +- **CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6** Do not change the corresponding radial +distortion coefficient during the optimization. If CV_CALIB_USE_INTRINSIC_GUESS is set, +the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to 0. +- **CV_CALIB_RATIONAL_MODEL** Enable coefficients k4, k5, and k6. To provide the backward +compatibility, this extra flag should be explicitly specified to make the calibration +function use the rational model and return 8 coefficients. If the flag is not set, the +function computes and returns only 5 distortion coefficients. +- **CALIB_THIN_PRISM_MODEL** Coefficients s1, s2, s3 and s4 are enabled. To provide the +backward compatibility, this extra flag should be explicitly specified to make the +calibration function use the thin prism model and return 12 coefficients. If the flag is not +set, the function computes and returns only 5 distortion coefficients. +- **CALIB_FIX_S1_S2_S3_S4** The thin prism distortion coefficients are not changed during +the optimization. If CV_CALIB_USE_INTRINSIC_GUESS is set, the coefficient from the +supplied distCoeffs matrix is used. Otherwise, it is set to 0. +@param criteria Termination criteria for the iterative optimization algorithm. + +The function estimates transformation between two cameras making a stereo pair. If you have a stereo +camera where the relative position and orientation of two cameras is fixed, and if you computed +poses of an object relative to the first camera and to the second camera, (R1, T1) and (R2, T2), +respectively (this can be done with solvePnP ), then those poses definitely relate to each other. +This means that, given ( \f$R_1\f$,\f$T_1\f$ ), it should be possible to compute ( \f$R_2\f$,\f$T_2\f$ ). You only +need to know the position and orientation of the second camera relative to the first camera. This is +what the described function does. It computes ( \f$R\f$,\f$T\f$ ) so that: + +\f[R_2=R*R_1 +T_2=R*T_1 + T,\f] + +Optionally, it computes the essential matrix E: + +\f[E= \vecthreethree{0}{-T_2}{T_1}{T_2}{0}{-T_0}{-T_1}{T_0}{0} *R\f] + +where \f$T_i\f$ are components of the translation vector \f$T\f$ : \f$T=[T_0, T_1, T_2]^T\f$ . And the function +can also compute the fundamental matrix F: + +\f[F = cameraMatrix2^{-T} E cameraMatrix1^{-1}\f] + +Besides the stereo-related information, the function can also perform a full calibration of each of +two cameras. However, due to the high dimensionality of the parameter space and noise in the input +data, the function can diverge from the correct solution. If the intrinsic parameters can be +estimated with high accuracy for each of the cameras individually (for example, using +calibrateCamera ), you are recommended to do so and then pass CV_CALIB_FIX_INTRINSIC flag to the +function along with the computed intrinsic parameters. Otherwise, if all the parameters are +estimated at once, it makes sense to restrict some parameters, for example, pass +CV_CALIB_SAME_FOCAL_LENGTH and CV_CALIB_ZERO_TANGENT_DIST flags, which is usually a +reasonable assumption. + +Similarly to calibrateCamera , the function minimizes the total re-projection error for all the +points in all the available views from both cameras. The function returns the final value of the +re-projection error. + */ +CV_EXPORTS_W double stereoCalibrate( InputArrayOfArrays objectPoints, + InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, + InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, + Size imageSize, OutputArray R,OutputArray T, OutputArray E, OutputArray F, + int flags = CALIB_FIX_INTRINSIC, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6) ); + + +/** @brief Computes rectification transforms for each head of a calibrated stereo camera. + +@param cameraMatrix1 First camera matrix. +@param cameraMatrix2 Second camera matrix. +@param distCoeffs1 First camera distortion parameters. +@param distCoeffs2 Second camera distortion parameters. +@param imageSize Size of the image used for stereo calibration. +@param R Rotation matrix between the coordinate systems of the first and the second cameras. +@param T Translation vector between coordinate systems of the cameras. +@param R1 Output 3x3 rectification transform (rotation matrix) for the first camera. +@param R2 Output 3x3 rectification transform (rotation matrix) for the second camera. +@param P1 Output 3x4 projection matrix in the new (rectified) coordinate systems for the first +camera. +@param P2 Output 3x4 projection matrix in the new (rectified) coordinate systems for the second +camera. +@param Q Output \f$4 \times 4\f$ disparity-to-depth mapping matrix (see reprojectImageTo3D ). +@param flags Operation flags that may be zero or CV_CALIB_ZERO_DISPARITY . If the flag is set, +the function makes the principal points of each camera have the same pixel coordinates in the +rectified views. And if the flag is not set, the function may still shift the images in the +horizontal or vertical direction (depending on the orientation of epipolar lines) to maximize the +useful image area. +@param alpha Free scaling parameter. If it is -1 or absent, the function performs the default +scaling. Otherwise, the parameter should be between 0 and 1. alpha=0 means that the rectified +images are zoomed and shifted so that only valid pixels are visible (no black areas after +rectification). alpha=1 means that the rectified image is decimated and shifted so that all the +pixels from the original images from the cameras are retained in the rectified images (no source +image pixels are lost). Obviously, any intermediate value yields an intermediate result between +those two extreme cases. +@param newImageSize New image resolution after rectification. The same size should be passed to +initUndistortRectifyMap (see the stereo_calib.cpp sample in OpenCV samples directory). When (0,0) +is passed (default), it is set to the original imageSize . Setting it to larger value can help you +preserve details in the original image, especially when there is a big radial distortion. +@param validPixROI1 Optional output rectangles inside the rectified images where all the pixels +are valid. If alpha=0 , the ROIs cover the whole images. Otherwise, they are likely to be smaller +(see the picture below). +@param validPixROI2 Optional output rectangles inside the rectified images where all the pixels +are valid. If alpha=0 , the ROIs cover the whole images. Otherwise, they are likely to be smaller +(see the picture below). + +The function computes the rotation matrices for each camera that (virtually) make both camera image +planes the same plane. Consequently, this makes all the epipolar lines parallel and thus simplifies +the dense stereo correspondence problem. The function takes the matrices computed by stereoCalibrate +as input. As output, it provides two rotation matrices and also two projection matrices in the new +coordinates. The function distinguishes the following two cases: + +- **Horizontal stereo**: the first and the second camera views are shifted relative to each other + mainly along the x axis (with possible small vertical shift). In the rectified images, the + corresponding epipolar lines in the left and right cameras are horizontal and have the same + y-coordinate. P1 and P2 look like: + + \f[\texttt{P1} = \begin{bmatrix} f & 0 & cx_1 & 0 \\ 0 & f & cy & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix}\f] + + \f[\texttt{P2} = \begin{bmatrix} f & 0 & cx_2 & T_x*f \\ 0 & f & cy & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} ,\f] + + where \f$T_x\f$ is a horizontal shift between the cameras and \f$cx_1=cx_2\f$ if + CV_CALIB_ZERO_DISPARITY is set. + +- **Vertical stereo**: the first and the second camera views are shifted relative to each other + mainly in vertical direction (and probably a bit in the horizontal direction too). The epipolar + lines in the rectified images are vertical and have the same x-coordinate. P1 and P2 look like: + + \f[\texttt{P1} = \begin{bmatrix} f & 0 & cx & 0 \\ 0 & f & cy_1 & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix}\f] + + \f[\texttt{P2} = \begin{bmatrix} f & 0 & cx & 0 \\ 0 & f & cy_2 & T_y*f \\ 0 & 0 & 1 & 0 \end{bmatrix} ,\f] + + where \f$T_y\f$ is a vertical shift between the cameras and \f$cy_1=cy_2\f$ if CALIB_ZERO_DISPARITY is + set. + +As you can see, the first three columns of P1 and P2 will effectively be the new "rectified" camera +matrices. The matrices, together with R1 and R2 , can then be passed to initUndistortRectifyMap to +initialize the rectification map for each camera. + +See below the screenshot from the stereo_calib.cpp sample. Some red horizontal lines pass through +the corresponding image regions. This means that the images are well rectified, which is what most +stereo correspondence algorithms rely on. The green rectangles are roi1 and roi2 . You see that +their interiors are all valid pixels. + +![image](pics/stereo_undistort.jpg) + */ +CV_EXPORTS_W void stereoRectify( InputArray cameraMatrix1, InputArray distCoeffs1, + InputArray cameraMatrix2, InputArray distCoeffs2, + Size imageSize, InputArray R, InputArray T, + OutputArray R1, OutputArray R2, + OutputArray P1, OutputArray P2, + OutputArray Q, int flags = CALIB_ZERO_DISPARITY, + double alpha = -1, Size newImageSize = Size(), + CV_OUT Rect* validPixROI1 = 0, CV_OUT Rect* validPixROI2 = 0 ); + +/** @brief Computes a rectification transform for an uncalibrated stereo camera. + +@param points1 Array of feature points in the first image. +@param points2 The corresponding points in the second image. The same formats as in +findFundamentalMat are supported. +@param F Input fundamental matrix. It can be computed from the same set of point pairs using +findFundamentalMat . +@param imgSize Size of the image. +@param H1 Output rectification homography matrix for the first image. +@param H2 Output rectification homography matrix for the second image. +@param threshold Optional threshold used to filter out the outliers. If the parameter is greater +than zero, all the point pairs that do not comply with the epipolar geometry (that is, the points +for which \f$|\texttt{points2[i]}^T*\texttt{F}*\texttt{points1[i]}|>\texttt{threshold}\f$ ) are +rejected prior to computing the homographies. Otherwise,all the points are considered inliers. + +The function computes the rectification transformations without knowing intrinsic parameters of the +cameras and their relative position in the space, which explains the suffix "uncalibrated". Another +related difference from stereoRectify is that the function outputs not the rectification +transformations in the object (3D) space, but the planar perspective transformations encoded by the +homography matrices H1 and H2 . The function implements the algorithm @cite Hartley99 . + +@note + While the algorithm does not need to know the intrinsic parameters of the cameras, it heavily + depends on the epipolar geometry. Therefore, if the camera lenses have a significant distortion, + it would be better to correct it before computing the fundamental matrix and calling this + function. For example, distortion coefficients can be estimated for each head of stereo camera + separately by using calibrateCamera . Then, the images can be corrected using undistort , or + just the point coordinates can be corrected with undistortPoints . + */ +CV_EXPORTS_W bool stereoRectifyUncalibrated( InputArray points1, InputArray points2, + InputArray F, Size imgSize, + OutputArray H1, OutputArray H2, + double threshold = 5 ); + +//! computes the rectification transformations for 3-head camera, where all the heads are on the same line. +CV_EXPORTS_W float rectify3Collinear( InputArray cameraMatrix1, InputArray distCoeffs1, + InputArray cameraMatrix2, InputArray distCoeffs2, + InputArray cameraMatrix3, InputArray distCoeffs3, + InputArrayOfArrays imgpt1, InputArrayOfArrays imgpt3, + Size imageSize, InputArray R12, InputArray T12, + InputArray R13, InputArray T13, + OutputArray R1, OutputArray R2, OutputArray R3, + OutputArray P1, OutputArray P2, OutputArray P3, + OutputArray Q, double alpha, Size newImgSize, + CV_OUT Rect* roi1, CV_OUT Rect* roi2, int flags ); + +/** @brief Returns the new camera matrix based on the free scaling parameter. + +@param cameraMatrix Input camera matrix. +@param distCoeffs Input vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements. If +the vector is NULL/empty, the zero distortion coefficients are assumed. +@param imageSize Original image size. +@param alpha Free scaling parameter between 0 (when all the pixels in the undistorted image are +valid) and 1 (when all the source image pixels are retained in the undistorted image). See +stereoRectify for details. +@param newImgSize Image size after rectification. By default,it is set to imageSize . +@param validPixROI Optional output rectangle that outlines all-good-pixels region in the +undistorted image. See roi1, roi2 description in stereoRectify . +@param centerPrincipalPoint Optional flag that indicates whether in the new camera matrix the +principal point should be at the image center or not. By default, the principal point is chosen to +best fit a subset of the source image (determined by alpha) to the corrected image. +@return new_camera_matrix Output new camera matrix. + +The function computes and returns the optimal new camera matrix based on the free scaling parameter. +By varying this parameter, you may retrieve only sensible pixels alpha=0 , keep all the original +image pixels if there is valuable information in the corners alpha=1 , or get something in between. +When alpha\>0 , the undistortion result is likely to have some black pixels corresponding to +"virtual" pixels outside of the captured distorted image. The original camera matrix, distortion +coefficients, the computed new camera matrix, and newImageSize should be passed to +initUndistortRectifyMap to produce the maps for remap . + */ +CV_EXPORTS_W Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs, + Size imageSize, double alpha, Size newImgSize = Size(), + CV_OUT Rect* validPixROI = 0, + bool centerPrincipalPoint = false); + +/** @brief Converts points from Euclidean to homogeneous space. + +@param src Input vector of N-dimensional points. +@param dst Output vector of N+1-dimensional points. + +The function converts points from Euclidean to homogeneous space by appending 1's to the tuple of +point coordinates. That is, each point (x1, x2, ..., xn) is converted to (x1, x2, ..., xn, 1). + */ +CV_EXPORTS_W void convertPointsToHomogeneous( InputArray src, OutputArray dst ); + +/** @brief Converts points from homogeneous to Euclidean space. + +@param src Input vector of N-dimensional points. +@param dst Output vector of N-1-dimensional points. + +The function converts points homogeneous to Euclidean space using perspective projection. That is, +each point (x1, x2, ... x(n-1), xn) is converted to (x1/xn, x2/xn, ..., x(n-1)/xn). When xn=0, the +output point coordinates will be (0,0,0,...). + */ +CV_EXPORTS_W void convertPointsFromHomogeneous( InputArray src, OutputArray dst ); + +/** @brief Converts points to/from homogeneous coordinates. + +@param src Input array or vector of 2D, 3D, or 4D points. +@param dst Output vector of 2D, 3D, or 4D points. + +The function converts 2D or 3D points from/to homogeneous coordinates by calling either +convertPointsToHomogeneous or convertPointsFromHomogeneous. + +@note The function is obsolete. Use one of the previous two functions instead. + */ +CV_EXPORTS void convertPointsHomogeneous( InputArray src, OutputArray dst ); + +/** @brief Calculates a fundamental matrix from the corresponding points in two images. + +@param points1 Array of N points from the first image. The point coordinates should be +floating-point (single or double precision). +@param points2 Array of the second image points of the same size and format as points1 . +@param method Method for computing a fundamental matrix. +- **CV_FM_7POINT** for a 7-point algorithm. \f$N = 7\f$ +- **CV_FM_8POINT** for an 8-point algorithm. \f$N \ge 8\f$ +- **CV_FM_RANSAC** for the RANSAC algorithm. \f$N \ge 8\f$ +- **CV_FM_LMEDS** for the LMedS algorithm. \f$N \ge 8\f$ +@param param1 Parameter used for RANSAC. It is the maximum distance from a point to an epipolar +line in pixels, beyond which the point is considered an outlier and is not used for computing the +final fundamental matrix. It can be set to something like 1-3, depending on the accuracy of the +point localization, image resolution, and the image noise. +@param param2 Parameter used for the RANSAC or LMedS methods only. It specifies a desirable level +of confidence (probability) that the estimated matrix is correct. +@param mask + +The epipolar geometry is described by the following equation: + +\f[[p_2; 1]^T F [p_1; 1] = 0\f] + +where \f$F\f$ is a fundamental matrix, \f$p_1\f$ and \f$p_2\f$ are corresponding points in the first and the +second images, respectively. + +The function calculates the fundamental matrix using one of four methods listed above and returns +the found fundamental matrix. Normally just one matrix is found. But in case of the 7-point +algorithm, the function may return up to 3 solutions ( \f$9 \times 3\f$ matrix that stores all 3 +matrices sequentially). + +The calculated fundamental matrix may be passed further to computeCorrespondEpilines that finds the +epipolar lines corresponding to the specified points. It can also be passed to +stereoRectifyUncalibrated to compute the rectification transformation. : +@code + // Example. Estimation of fundamental matrix using the RANSAC algorithm + int point_count = 100; + vector points1(point_count); + vector points2(point_count); + + // initialize the points here ... + for( int i = 0; i < point_count; i++ ) + { + points1[i] = ...; + points2[i] = ...; + } + + Mat fundamental_matrix = + findFundamentalMat(points1, points2, FM_RANSAC, 3, 0.99); +@endcode + */ +CV_EXPORTS_W Mat findFundamentalMat( InputArray points1, InputArray points2, + int method = FM_RANSAC, + double param1 = 3., double param2 = 0.99, + OutputArray mask = noArray() ); + +/** @overload */ +CV_EXPORTS Mat findFundamentalMat( InputArray points1, InputArray points2, + OutputArray mask, int method = FM_RANSAC, + double param1 = 3., double param2 = 0.99 ); + +/** @brief Calculates an essential matrix from the corresponding points in two images. + +@param points1 Array of N (N \>= 5) 2D points from the first image. The point coordinates should +be floating-point (single or double precision). +@param points2 Array of the second image points of the same size and format as points1 . +@param focal focal length of the camera. Note that this function assumes that points1 and points2 +are feature points from cameras with same focal length and principle point. +@param pp principle point of the camera. +@param method Method for computing a fundamental matrix. +- **RANSAC** for the RANSAC algorithm. +- **MEDS** for the LMedS algorithm. +@param threshold Parameter used for RANSAC. It is the maximum distance from a point to an epipolar +line in pixels, beyond which the point is considered an outlier and is not used for computing the +final fundamental matrix. It can be set to something like 1-3, depending on the accuracy of the +point localization, image resolution, and the image noise. +@param prob Parameter used for the RANSAC or LMedS methods only. It specifies a desirable level of +confidence (probability) that the estimated matrix is correct. +@param mask Output array of N elements, every element of which is set to 0 for outliers and to 1 +for the other points. The array is computed only in the RANSAC and LMedS methods. + +This function estimates essential matrix based on the five-point algorithm solver in @cite Nister03 . +@cite SteweniusCFS is also a related. The epipolar geometry is described by the following equation: + +\f[[p_2; 1]^T K^{-T} E K^{-1} [p_1; 1] = 0 \\\f]\f[K = +\begin{bmatrix} +f & 0 & x_{pp} \\ +0 & f & y_{pp} \\ +0 & 0 & 1 +\end{bmatrix}\f] + +where \f$E\f$ is an essential matrix, \f$p_1\f$ and \f$p_2\f$ are corresponding points in the first and the +second images, respectively. The result of this function may be passed further to +decomposeEssentialMat or recoverPose to recover the relative pose between cameras. + */ +CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2, + double focal = 1.0, Point2d pp = Point2d(0, 0), + int method = RANSAC, double prob = 0.999, + double threshold = 1.0, OutputArray mask = noArray() ); + +/** @brief Decompose an essential matrix to possible rotations and translation. + +@param E The input essential matrix. +@param R1 One possible rotation matrix. +@param R2 Another possible rotation matrix. +@param t One possible translation. + +This function decompose an essential matrix E using svd decomposition @cite HartleyZ00 . Generally 4 +possible poses exists for a given E. They are \f$[R_1, t]\f$, \f$[R_1, -t]\f$, \f$[R_2, t]\f$, \f$[R_2, -t]\f$. By +decomposing E, you can only get the direction of the translation, so the function returns unit t. + */ +CV_EXPORTS_W void decomposeEssentialMat( InputArray E, OutputArray R1, OutputArray R2, OutputArray t ); + +/** @brief Recover relative camera rotation and translation from an estimated essential matrix and the +corresponding points in two images, using cheirality check. Returns the number of inliers which pass +the check. + +@param E The input essential matrix. +@param points1 Array of N 2D points from the first image. The point coordinates should be +floating-point (single or double precision). +@param points2 Array of the second image points of the same size and format as points1 . +@param R Recovered relative rotation. +@param t Recoverd relative translation. +@param focal Focal length of the camera. Note that this function assumes that points1 and points2 +are feature points from cameras with same focal length and principle point. +@param pp Principle point of the camera. +@param mask Input/output mask for inliers in points1 and points2. +: If it is not empty, then it marks inliers in points1 and points2 for then given essential +matrix E. Only these inliers will be used to recover pose. In the output mask only inliers +which pass the cheirality check. +This function decomposes an essential matrix using decomposeEssentialMat and then verifies possible +pose hypotheses by doing cheirality check. The cheirality check basically means that the +triangulated 3D points should have positive depth. Some details can be found in @cite Nister03 . + +This function can be used to process output E and mask from findEssentialMat. In this scenario, +points1 and points2 are the same input for findEssentialMat. : +@code + // Example. Estimation of fundamental matrix using the RANSAC algorithm + int point_count = 100; + vector points1(point_count); + vector points2(point_count); + + // initialize the points here ... + for( int i = 0; i < point_count; i++ ) + { + points1[i] = ...; + points2[i] = ...; + } + + double focal = 1.0; + cv::Point2d pp(0.0, 0.0); + Mat E, R, t, mask; + + E = findEssentialMat(points1, points2, focal, pp, RANSAC, 0.999, 1.0, mask); + recoverPose(E, points1, points2, R, t, focal, pp, mask); +@endcode + */ +CV_EXPORTS_W int recoverPose( InputArray E, InputArray points1, InputArray points2, + OutputArray R, OutputArray t, + double focal = 1.0, Point2d pp = Point2d(0, 0), + InputOutputArray mask = noArray() ); + + +/** @brief For points in an image of a stereo pair, computes the corresponding epilines in the other image. + +@param points Input points. \f$N \times 1\f$ or \f$1 \times N\f$ matrix of type CV_32FC2 or +vector\ . +@param whichImage Index of the image (1 or 2) that contains the points . +@param F Fundamental matrix that can be estimated using findFundamentalMat or stereoRectify . +@param lines Output vector of the epipolar lines corresponding to the points in the other image. +Each line \f$ax + by + c=0\f$ is encoded by 3 numbers \f$(a, b, c)\f$ . + +For every point in one of the two images of a stereo pair, the function finds the equation of the +corresponding epipolar line in the other image. + +From the fundamental matrix definition (see findFundamentalMat ), line \f$l^{(2)}_i\f$ in the second +image for the point \f$p^{(1)}_i\f$ in the first image (when whichImage=1 ) is computed as: + +\f[l^{(2)}_i = F p^{(1)}_i\f] + +And vice versa, when whichImage=2, \f$l^{(1)}_i\f$ is computed from \f$p^{(2)}_i\f$ as: + +\f[l^{(1)}_i = F^T p^{(2)}_i\f] + +Line coefficients are defined up to a scale. They are normalized so that \f$a_i^2+b_i^2=1\f$ . + */ +CV_EXPORTS_W void computeCorrespondEpilines( InputArray points, int whichImage, + InputArray F, OutputArray lines ); + +/** @brief Reconstructs points by triangulation. + +@param projMatr1 3x4 projection matrix of the first camera. +@param projMatr2 3x4 projection matrix of the second camera. +@param projPoints1 2xN array of feature points in the first image. In case of c++ version it can +be also a vector of feature points or two-channel matrix of size 1xN or Nx1. +@param projPoints2 2xN array of corresponding points in the second image. In case of c++ version +it can be also a vector of feature points or two-channel matrix of size 1xN or Nx1. +@param points4D 4xN array of reconstructed points in homogeneous coordinates. + +The function reconstructs 3-dimensional points (in homogeneous coordinates) by using their +observations with a stereo camera. Projections matrices can be obtained from stereoRectify. + +@note + Keep in mind that all input data should be of float type in order for this function to work. + +@sa + reprojectImageTo3D + */ +CV_EXPORTS_W void triangulatePoints( InputArray projMatr1, InputArray projMatr2, + InputArray projPoints1, InputArray projPoints2, + OutputArray points4D ); + +/** @brief Refines coordinates of corresponding points. + +@param F 3x3 fundamental matrix. +@param points1 1xN array containing the first set of points. +@param points2 1xN array containing the second set of points. +@param newPoints1 The optimized points1. +@param newPoints2 The optimized points2. + +The function implements the Optimal Triangulation Method (see Multiple View Geometry for details). +For each given point correspondence points1[i] \<-\> points2[i], and a fundamental matrix F, it +computes the corrected correspondences newPoints1[i] \<-\> newPoints2[i] that minimize the geometric +error \f$d(points1[i], newPoints1[i])^2 + d(points2[i],newPoints2[i])^2\f$ (where \f$d(a,b)\f$ is the +geometric distance between points \f$a\f$ and \f$b\f$ ) subject to the epipolar constraint +\f$newPoints2^T * F * newPoints1 = 0\f$ . + */ +CV_EXPORTS_W void correctMatches( InputArray F, InputArray points1, InputArray points2, + OutputArray newPoints1, OutputArray newPoints2 ); + +/** @brief Filters off small noise blobs (speckles) in the disparity map + +@param img The input 16-bit signed disparity image +@param newVal The disparity value used to paint-off the speckles +@param maxSpeckleSize The maximum speckle size to consider it a speckle. Larger blobs are not +affected by the algorithm +@param maxDiff Maximum difference between neighbor disparity pixels to put them into the same +blob. Note that since StereoBM, StereoSGBM and may be other algorithms return a fixed-point +disparity map, where disparity values are multiplied by 16, this scale factor should be taken into +account when specifying this parameter value. +@param buf The optional temporary buffer to avoid memory allocation within the function. + */ +CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, + int maxSpeckleSize, double maxDiff, + InputOutputArray buf = noArray() ); + +//! computes valid disparity ROI from the valid ROIs of the rectified images (that are returned by cv::stereoRectify()) +CV_EXPORTS_W Rect getValidDisparityROI( Rect roi1, Rect roi2, + int minDisparity, int numberOfDisparities, + int SADWindowSize ); + +//! validates disparity using the left-right check. The matrix "cost" should be computed by the stereo correspondence algorithm +CV_EXPORTS_W void validateDisparity( InputOutputArray disparity, InputArray cost, + int minDisparity, int numberOfDisparities, + int disp12MaxDisp = 1 ); + +/** @brief Reprojects a disparity image to 3D space. + +@param disparity Input single-channel 8-bit unsigned, 16-bit signed, 32-bit signed or 32-bit +floating-point disparity image. +@param _3dImage Output 3-channel floating-point image of the same size as disparity . Each +element of _3dImage(x,y) contains 3D coordinates of the point (x,y) computed from the disparity +map. +@param Q \f$4 \times 4\f$ perspective transformation matrix that can be obtained with stereoRectify. +@param handleMissingValues Indicates, whether the function should handle missing values (i.e. +points where the disparity was not computed). If handleMissingValues=true, then pixels with the +minimal disparity that corresponds to the outliers (see StereoMatcher::compute ) are transformed +to 3D points with a very large Z value (currently set to 10000). +@param ddepth The optional output array depth. If it is -1, the output image will have CV_32F +depth. ddepth can also be set to CV_16S, CV_32S or CV_32F. + +The function transforms a single-channel disparity map to a 3-channel image representing a 3D +surface. That is, for each pixel (x,y) andthe corresponding disparity d=disparity(x,y) , it +computes: + +\f[\begin{array}{l} [X \; Y \; Z \; W]^T = \texttt{Q} *[x \; y \; \texttt{disparity} (x,y) \; 1]^T \\ \texttt{\_3dImage} (x,y) = (X/W, \; Y/W, \; Z/W) \end{array}\f] + +The matrix Q can be an arbitrary \f$4 \times 4\f$ matrix (for example, the one computed by +stereoRectify). To reproject a sparse set of points {(x,y,d),...} to 3D space, use +perspectiveTransform . + */ +CV_EXPORTS_W void reprojectImageTo3D( InputArray disparity, + OutputArray _3dImage, InputArray Q, + bool handleMissingValues = false, + int ddepth = -1 ); + +/** @brief Computes an optimal affine transformation between two 3D point sets. + +@param src First input 3D point set. +@param dst Second input 3D point set. +@param out Output 3D affine transformation matrix \f$3 \times 4\f$ . +@param inliers Output vector indicating which points are inliers. +@param ransacThreshold Maximum reprojection error in the RANSAC algorithm to consider a point as +an inlier. +@param confidence Confidence level, between 0 and 1, for the estimated transformation. Anything +between 0.95 and 0.99 is usually good enough. Values too close to 1 can slow down the estimation +significantly. Values lower than 0.8-0.9 can result in an incorrectly estimated transformation. + +The function estimates an optimal 3D affine transformation between two 3D point sets using the +RANSAC algorithm. + */ +CV_EXPORTS_W int estimateAffine3D(InputArray src, InputArray dst, + OutputArray out, OutputArray inliers, + double ransacThreshold = 3, double confidence = 0.99); + +/** @brief Decompose a homography matrix to rotation(s), translation(s) and plane normal(s). + +@param H The input homography matrix between two images. +@param K The input intrinsic camera calibration matrix. +@param rotations Array of rotation matrices. +@param translations Array of translation matrices. +@param normals Array of plane normal matrices. + +This function extracts relative camera motion between two views observing a planar object from the +homography H induced by the plane. The intrinsic camera matrix K must also be provided. The function +may return up to four mathematical solution sets. At least two of the solutions may further be +invalidated if point correspondences are available by applying positive depth constraint (all points +must be in front of the camera). The decomposition method is described in detail in @cite Malis . + */ +CV_EXPORTS_W int decomposeHomographyMat(InputArray H, + InputArray K, + OutputArrayOfArrays rotations, + OutputArrayOfArrays translations, + OutputArrayOfArrays normals); + +/** @brief The base class for stereo correspondence algorithms. + */ +class CV_EXPORTS_W StereoMatcher : public Algorithm +{ +public: + enum { DISP_SHIFT = 4, + DISP_SCALE = (1 << DISP_SHIFT) + }; + + /** @brief Computes disparity map for the specified stereo pair + + @param left Left 8-bit single-channel image. + @param right Right image of the same size and the same type as the left one. + @param disparity Output disparity map. It has the same size as the input images. Some algorithms, + like StereoBM or StereoSGBM compute 16-bit fixed-point disparity map (where each disparity value + has 4 fractional bits), whereas other algorithms output 32-bit floating-point disparity map. + */ + CV_WRAP virtual void compute( InputArray left, InputArray right, + OutputArray disparity ) = 0; + + CV_WRAP virtual int getMinDisparity() const = 0; + CV_WRAP virtual void setMinDisparity(int minDisparity) = 0; + + CV_WRAP virtual int getNumDisparities() const = 0; + CV_WRAP virtual void setNumDisparities(int numDisparities) = 0; + + CV_WRAP virtual int getBlockSize() const = 0; + CV_WRAP virtual void setBlockSize(int blockSize) = 0; + + CV_WRAP virtual int getSpeckleWindowSize() const = 0; + CV_WRAP virtual void setSpeckleWindowSize(int speckleWindowSize) = 0; + + CV_WRAP virtual int getSpeckleRange() const = 0; + CV_WRAP virtual void setSpeckleRange(int speckleRange) = 0; + + CV_WRAP virtual int getDisp12MaxDiff() const = 0; + CV_WRAP virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0; +}; + + +/** @brief Class for computing stereo correspondence using the block matching algorithm, introduced and +contributed to OpenCV by K. Konolige. + */ +class CV_EXPORTS_W StereoBM : public StereoMatcher +{ +public: + enum { PREFILTER_NORMALIZED_RESPONSE = 0, + PREFILTER_XSOBEL = 1 + }; + + CV_WRAP virtual int getPreFilterType() const = 0; + CV_WRAP virtual void setPreFilterType(int preFilterType) = 0; + + CV_WRAP virtual int getPreFilterSize() const = 0; + CV_WRAP virtual void setPreFilterSize(int preFilterSize) = 0; + + CV_WRAP virtual int getPreFilterCap() const = 0; + CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; + + CV_WRAP virtual int getTextureThreshold() const = 0; + CV_WRAP virtual void setTextureThreshold(int textureThreshold) = 0; + + CV_WRAP virtual int getUniquenessRatio() const = 0; + CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + CV_WRAP virtual int getSmallerBlockSize() const = 0; + CV_WRAP virtual void setSmallerBlockSize(int blockSize) = 0; + + CV_WRAP virtual Rect getROI1() const = 0; + CV_WRAP virtual void setROI1(Rect roi1) = 0; + + CV_WRAP virtual Rect getROI2() const = 0; + CV_WRAP virtual void setROI2(Rect roi2) = 0; + + /** @brief Creates StereoBM object + + @param numDisparities the disparity search range. For each pixel algorithm will find the best + disparity from 0 (default minimum disparity) to numDisparities. The search range can then be + shifted by changing the minimum disparity. + @param blockSize the linear size of the blocks compared by the algorithm. The size should be odd + (as the block is centered at the current pixel). Larger block size implies smoother, though less + accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher + chance for algorithm to find a wrong correspondence. + + The function create StereoBM object. You can then call StereoBM::compute() to compute disparity for + a specific stereo pair. + */ + CV_WRAP static Ptr create(int numDisparities = 0, int blockSize = 21); +}; + +/** @brief The class implements the modified H. Hirschmuller algorithm @cite HH08 that differs from the original +one as follows: + +- By default, the algorithm is single-pass, which means that you consider only 5 directions +instead of 8. Set mode=StereoSGBM::MODE_HH in createStereoSGBM to run the full variant of the +algorithm but beware that it may consume a lot of memory. +- The algorithm matches blocks, not individual pixels. Though, setting blockSize=1 reduces the +blocks to single pixels. +- Mutual information cost function is not implemented. Instead, a simpler Birchfield-Tomasi +sub-pixel metric from @cite BT98 is used. Though, the color images are supported as well. +- Some pre- and post- processing steps from K. Konolige algorithm StereoBM are included, for +example: pre-filtering (StereoBM::PREFILTER_XSOBEL type) and post-filtering (uniqueness +check, quadratic interpolation and speckle filtering). + +@note + - (Python) An example illustrating the use of the StereoSGBM matching algorithm can be found + at opencv_source_code/samples/python2/stereo_match.py + */ +class CV_EXPORTS_W StereoSGBM : public StereoMatcher +{ +public: + enum + { + MODE_SGBM = 0, + MODE_HH = 1 + }; + + CV_WRAP virtual int getPreFilterCap() const = 0; + CV_WRAP virtual void setPreFilterCap(int preFilterCap) = 0; + + CV_WRAP virtual int getUniquenessRatio() const = 0; + CV_WRAP virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + CV_WRAP virtual int getP1() const = 0; + CV_WRAP virtual void setP1(int P1) = 0; + + CV_WRAP virtual int getP2() const = 0; + CV_WRAP virtual void setP2(int P2) = 0; + + CV_WRAP virtual int getMode() const = 0; + CV_WRAP virtual void setMode(int mode) = 0; + + /** @brief Creates StereoSGBM object + + @param minDisparity Minimum possible disparity value. Normally, it is zero but sometimes + rectification algorithms can shift images, so this parameter needs to be adjusted accordingly. + @param numDisparities Maximum disparity minus minimum disparity. The value is always greater than + zero. In the current implementation, this parameter must be divisible by 16. + @param blockSize Matched block size. It must be an odd number \>=1 . Normally, it should be + somewhere in the 3..11 range. + @param P1 The first parameter controlling the disparity smoothness. See below. + @param P2 The second parameter controlling the disparity smoothness. The larger the values are, + the smoother the disparity is. P1 is the penalty on the disparity change by plus or minus 1 + between neighbor pixels. P2 is the penalty on the disparity change by more than 1 between neighbor + pixels. The algorithm requires P2 \> P1 . See stereo_match.cpp sample where some reasonably good + P1 and P2 values are shown (like 8\*number_of_image_channels\*SADWindowSize\*SADWindowSize and + 32\*number_of_image_channels\*SADWindowSize\*SADWindowSize , respectively). + @param disp12MaxDiff Maximum allowed difference (in integer pixel units) in the left-right + disparity check. Set it to a non-positive value to disable the check. + @param preFilterCap Truncation value for the prefiltered image pixels. The algorithm first + computes x-derivative at each pixel and clips its value by [-preFilterCap, preFilterCap] interval. + The result values are passed to the Birchfield-Tomasi pixel cost function. + @param uniquenessRatio Margin in percentage by which the best (minimum) computed cost function + value should "win" the second best value to consider the found match correct. Normally, a value + within the 5-15 range is good enough. + @param speckleWindowSize Maximum size of smooth disparity regions to consider their noise speckles + and invalidate. Set it to 0 to disable speckle filtering. Otherwise, set it somewhere in the + 50-200 range. + @param speckleRange Maximum disparity variation within each connected component. If you do speckle + filtering, set the parameter to a positive value, it will be implicitly multiplied by 16. + Normally, 1 or 2 is good enough. + @param mode Set it to StereoSGBM::MODE_HH to run the full-scale two-pass dynamic programming + algorithm. It will consume O(W\*H\*numDisparities) bytes, which is large for 640x480 stereo and + huge for HD-size pictures. By default, it is set to false . + + The first constructor initializes StereoSGBM with all the default parameters. So, you only have to + set StereoSGBM::numDisparities at minimum. The second constructor enables you to set each parameter + to a custom value. + */ + CV_WRAP static Ptr create(int minDisparity, int numDisparities, int blockSize, + int P1 = 0, int P2 = 0, int disp12MaxDiff = 0, + int preFilterCap = 0, int uniquenessRatio = 0, + int speckleWindowSize = 0, int speckleRange = 0, + int mode = StereoSGBM::MODE_SGBM); +}; + +//! @} calib3d + +/** @brief The methods in this namespace use a so-called fisheye camera model. + @ingroup calib3d_fisheye +*/ +namespace fisheye +{ +//! @addtogroup calib3d_fisheye +//! @{ + + enum{ + CALIB_USE_INTRINSIC_GUESS = 1, + CALIB_RECOMPUTE_EXTRINSIC = 2, + CALIB_CHECK_COND = 4, + CALIB_FIX_SKEW = 8, + CALIB_FIX_K1 = 16, + CALIB_FIX_K2 = 32, + CALIB_FIX_K3 = 64, + CALIB_FIX_K4 = 128, + CALIB_FIX_INTRINSIC = 256 + }; + + /** @brief Projects points using fisheye model + + @param objectPoints Array of object points, 1xN/Nx1 3-channel (or vector\ ), where N is + the number of points in the view. + @param imagePoints Output array of image points, 2xN/Nx2 1-channel or 1xN/Nx1 2-channel, or + vector\. + @param affine + @param K Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param D Input vector of distortion coefficients \f$(k_1, k_2, k_3, k_4)\f$. + @param alpha The skew coefficient. + @param jacobian Optional output 2Nx15 jacobian matrix of derivatives of image points with respect + to components of the focal lengths, coordinates of the principal point, distortion coefficients, + rotation vector, translation vector, and the skew. In the old interface different components of + the jacobian are returned via different output parameters. + + The function computes projections of 3D points to the image plane given intrinsic and extrinsic + camera parameters. Optionally, the function computes Jacobians - matrices of partial derivatives of + image points coordinates (as functions of all the input parameters) with respect to the particular + parameters, intrinsic and/or extrinsic. + */ + CV_EXPORTS void projectPoints(InputArray objectPoints, OutputArray imagePoints, const Affine3d& affine, + InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray()); + + /** @overload */ + CV_EXPORTS_W void projectPoints(InputArray objectPoints, OutputArray imagePoints, InputArray rvec, InputArray tvec, + InputArray K, InputArray D, double alpha = 0, OutputArray jacobian = noArray()); + + /** @brief Distorts 2D points using fisheye model. + + @param undistorted Array of object points, 1xN/Nx1 2-channel (or vector\ ), where N is + the number of points in the view. + @param K Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param D Input vector of distortion coefficients \f$(k_1, k_2, k_3, k_4)\f$. + @param alpha The skew coefficient. + @param distorted Output array of image points, 1xN/Nx1 2-channel, or vector\ . + */ + CV_EXPORTS_W void distortPoints(InputArray undistorted, OutputArray distorted, InputArray K, InputArray D, double alpha = 0); + + /** @brief Undistorts 2D points using fisheye model + + @param distorted Array of object points, 1xN/Nx1 2-channel (or vector\ ), where N is the + number of points in the view. + @param K Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param D Input vector of distortion coefficients \f$(k_1, k_2, k_3, k_4)\f$. + @param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 + 1-channel or 1x1 3-channel + @param P New camera matrix (3x3) or new projection matrix (3x4) + @param undistorted Output array of image points, 1xN/Nx1 2-channel, or vector\ . + */ + CV_EXPORTS_W void undistortPoints(InputArray distorted, OutputArray undistorted, + InputArray K, InputArray D, InputArray R = noArray(), InputArray P = noArray()); + + /** @brief Computes undistortion and rectification maps for image transform by cv::remap(). If D is empty zero + distortion is used, if R or P is empty identity matrixes are used. + + @param K Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param D Input vector of distortion coefficients \f$(k_1, k_2, k_3, k_4)\f$. + @param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 + 1-channel or 1x1 3-channel + @param P New camera matrix (3x3) or new projection matrix (3x4) + @param size Undistorted image size. + @param m1type Type of the first output map that can be CV_32FC1 or CV_16SC2 . See convertMaps() + for details. + @param map1 The first output map. + @param map2 The second output map. + */ + CV_EXPORTS_W void initUndistortRectifyMap(InputArray K, InputArray D, InputArray R, InputArray P, + const cv::Size& size, int m1type, OutputArray map1, OutputArray map2); + + /** @brief Transforms an image to compensate for fisheye lens distortion. + + @param distorted image with fisheye lens distortion. + @param undistorted Output image with compensated fisheye lens distortion. + @param K Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param D Input vector of distortion coefficients \f$(k_1, k_2, k_3, k_4)\f$. + @param Knew Camera matrix of the distorted image. By default, it is the identity matrix but you + may additionally scale and shift the result by using a different matrix. + @param new_size + + The function transforms an image to compensate radial and tangential lens distortion. + + The function is simply a combination of fisheye::initUndistortRectifyMap (with unity R ) and remap + (with bilinear interpolation). See the former function for details of the transformation being + performed. + + See below the results of undistortImage. + - a\) result of undistort of perspective camera model (all possible coefficients (k_1, k_2, k_3, + k_4, k_5, k_6) of distortion were optimized under calibration) + - b\) result of fisheye::undistortImage of fisheye camera model (all possible coefficients (k_1, k_2, + k_3, k_4) of fisheye distortion were optimized under calibration) + - c\) original image was captured with fisheye lens + + Pictures a) and b) almost the same. But if we consider points of image located far from the center + of image, we can notice that on image a) these points are distorted. + + ![image](pics/fisheye_undistorted.jpg) + */ + CV_EXPORTS_W void undistortImage(InputArray distorted, OutputArray undistorted, + InputArray K, InputArray D, InputArray Knew = cv::noArray(), const Size& new_size = Size()); + + /** @brief Estimates new camera matrix for undistortion or rectification. + + @param K Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param image_size + @param D Input vector of distortion coefficients \f$(k_1, k_2, k_3, k_4)\f$. + @param R Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 + 1-channel or 1x1 3-channel + @param P New camera matrix (3x3) or new projection matrix (3x4) + @param balance Sets the new focal length in range between the min focal length and the max focal + length. Balance is in range of [0, 1]. + @param new_size + @param fov_scale Divisor for new focal length. + */ + CV_EXPORTS_W void estimateNewCameraMatrixForUndistortRectify(InputArray K, InputArray D, const Size &image_size, InputArray R, + OutputArray P, double balance = 0.0, const Size& new_size = Size(), double fov_scale = 1.0); + + /** @brief Performs camera calibaration + + @param objectPoints vector of vectors of calibration pattern points in the calibration pattern + coordinate space. + @param imagePoints vector of vectors of the projections of calibration pattern points. + imagePoints.size() and objectPoints.size() and imagePoints[i].size() must be equal to + objectPoints[i].size() for each i. + @param image_size Size of the image used only to initialize the intrinsic camera matrix. + @param K Output 3x3 floating-point camera matrix + \f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . If + fisheye::CALIB_USE_INTRINSIC_GUESS/ is specified, some or all of fx, fy, cx, cy must be + initialized before calling the function. + @param D Output vector of distortion coefficients \f$(k_1, k_2, k_3, k_4)\f$. + @param rvecs Output vector of rotation vectors (see Rodrigues ) estimated for each pattern view. + That is, each k-th rotation vector together with the corresponding k-th translation vector (see + the next output parameter description) brings the calibration pattern from the model coordinate + space (in which object points are specified) to the world coordinate space, that is, a real + position of the calibration pattern in the k-th pattern view (k=0.. *M* -1). + @param tvecs Output vector of translation vectors estimated for each pattern view. + @param flags Different flags that may be zero or a combination of the following values: + - **fisheye::CALIB_USE_INTRINSIC_GUESS** cameraMatrix contains valid initial values of + fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image + center ( imageSize is used), and focal distances are computed in a least-squares fashion. + - **fisheye::CALIB_RECOMPUTE_EXTRINSIC** Extrinsic will be recomputed after each iteration + of intrinsic optimization. + - **fisheye::CALIB_CHECK_COND** The functions will check validity of condition number. + - **fisheye::CALIB_FIX_SKEW** Skew coefficient (alpha) is set to zero and stay zero. + - **fisheye::CALIB_FIX_K1..4** Selected distortion coefficients are set to zeros and stay + zero. + @param criteria Termination criteria for the iterative optimization algorithm. + */ + CV_EXPORTS_W double calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, const Size& image_size, + InputOutputArray K, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags = 0, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); + + /** @brief Stereo rectification for fisheye camera model + + @param K1 First camera matrix. + @param D1 First camera distortion parameters. + @param K2 Second camera matrix. + @param D2 Second camera distortion parameters. + @param imageSize Size of the image used for stereo calibration. + @param R Rotation matrix between the coordinate systems of the first and the second + cameras. + @param tvec Translation vector between coordinate systems of the cameras. + @param R1 Output 3x3 rectification transform (rotation matrix) for the first camera. + @param R2 Output 3x3 rectification transform (rotation matrix) for the second camera. + @param P1 Output 3x4 projection matrix in the new (rectified) coordinate systems for the first + camera. + @param P2 Output 3x4 projection matrix in the new (rectified) coordinate systems for the second + camera. + @param Q Output \f$4 \times 4\f$ disparity-to-depth mapping matrix (see reprojectImageTo3D ). + @param flags Operation flags that may be zero or CV_CALIB_ZERO_DISPARITY . If the flag is set, + the function makes the principal points of each camera have the same pixel coordinates in the + rectified views. And if the flag is not set, the function may still shift the images in the + horizontal or vertical direction (depending on the orientation of epipolar lines) to maximize the + useful image area. + @param newImageSize New image resolution after rectification. The same size should be passed to + initUndistortRectifyMap (see the stereo_calib.cpp sample in OpenCV samples directory). When (0,0) + is passed (default), it is set to the original imageSize . Setting it to larger value can help you + preserve details in the original image, especially when there is a big radial distortion. + @param balance Sets the new focal length in range between the min focal length and the max focal + length. Balance is in range of [0, 1]. + @param fov_scale Divisor for new focal length. + */ + CV_EXPORTS_W void stereoRectify(InputArray K1, InputArray D1, InputArray K2, InputArray D2, const Size &imageSize, InputArray R, InputArray tvec, + OutputArray R1, OutputArray R2, OutputArray P1, OutputArray P2, OutputArray Q, int flags, const Size &newImageSize = Size(), + double balance = 0.0, double fov_scale = 1.0); + + /** @brief Performs stereo calibration + + @param objectPoints Vector of vectors of the calibration pattern points. + @param imagePoints1 Vector of vectors of the projections of the calibration pattern points, + observed by the first camera. + @param imagePoints2 Vector of vectors of the projections of the calibration pattern points, + observed by the second camera. + @param K1 Input/output first camera matrix: + \f$\vecthreethree{f_x^{(j)}}{0}{c_x^{(j)}}{0}{f_y^{(j)}}{c_y^{(j)}}{0}{0}{1}\f$ , \f$j = 0,\, 1\f$ . If + any of fisheye::CALIB_USE_INTRINSIC_GUESS , fisheye::CV_CALIB_FIX_INTRINSIC are specified, + some or all of the matrix components must be initialized. + @param D1 Input/output vector of distortion coefficients \f$(k_1, k_2, k_3, k_4)\f$ of 4 elements. + @param K2 Input/output second camera matrix. The parameter is similar to K1 . + @param D2 Input/output lens distortion coefficients for the second camera. The parameter is + similar to D1 . + @param imageSize Size of the image used only to initialize intrinsic camera matrix. + @param R Output rotation matrix between the 1st and the 2nd camera coordinate systems. + @param T Output translation vector between the coordinate systems of the cameras. + @param flags Different flags that may be zero or a combination of the following values: + - **fisheye::CV_CALIB_FIX_INTRINSIC** Fix K1, K2? and D1, D2? so that only R, T matrices + are estimated. + - **fisheye::CALIB_USE_INTRINSIC_GUESS** K1, K2 contains valid initial values of + fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the image + center (imageSize is used), and focal distances are computed in a least-squares fashion. + - **fisheye::CALIB_RECOMPUTE_EXTRINSIC** Extrinsic will be recomputed after each iteration + of intrinsic optimization. + - **fisheye::CALIB_CHECK_COND** The functions will check validity of condition number. + - **fisheye::CALIB_FIX_SKEW** Skew coefficient (alpha) is set to zero and stay zero. + - **fisheye::CALIB_FIX_K1..4** Selected distortion coefficients are set to zeros and stay + zero. + @param criteria Termination criteria for the iterative optimization algorithm. + */ + CV_EXPORTS_W double stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputOutputArray K1, InputOutputArray D1, InputOutputArray K2, InputOutputArray D2, Size imageSize, + OutputArray R, OutputArray T, int flags = fisheye::CALIB_FIX_INTRINSIC, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)); + +//! @} calib3d_fisheye +} + +} // cv + +#ifndef DISABLE_OPENCV_24_COMPATIBILITY +#include "opencv2/calib3d/calib3d_c.h" +#endif + +#endif diff --git a/include/opencv2/calib3d/calib3d.hpp b/include/opencv2/calib3d/calib3d.hpp new file mode 100644 index 0000000..b3da45e --- /dev/null +++ b/include/opencv2/calib3d/calib3d.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/calib3d.hpp" diff --git a/include/opencv2/calib3d/calib3d_c.h b/include/opencv2/calib3d/calib3d_c.h new file mode 100644 index 0000000..2392692 --- /dev/null +++ b/include/opencv2/calib3d/calib3d_c.h @@ -0,0 +1,422 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CALIB3D_C_H__ +#define __OPENCV_CALIB3D_C_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup calib3d_c + @{ + */ + +/****************************************************************************************\ +* Camera Calibration, Pose Estimation and Stereo * +\****************************************************************************************/ + +typedef struct CvPOSITObject CvPOSITObject; + +/* Allocates and initializes CvPOSITObject structure before doing cvPOSIT */ +CVAPI(CvPOSITObject*) cvCreatePOSITObject( CvPoint3D32f* points, int point_count ); + + +/* Runs POSIT (POSe from ITeration) algorithm for determining 3d position of + an object given its model and projection in a weak-perspective case */ +CVAPI(void) cvPOSIT( CvPOSITObject* posit_object, CvPoint2D32f* image_points, + double focal_length, CvTermCriteria criteria, + float* rotation_matrix, float* translation_vector); + +/* Releases CvPOSITObject structure */ +CVAPI(void) cvReleasePOSITObject( CvPOSITObject** posit_object ); + +/* updates the number of RANSAC iterations */ +CVAPI(int) cvRANSACUpdateNumIters( double p, double err_prob, + int model_points, int max_iters ); + +CVAPI(void) cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst ); + +/* Calculates fundamental matrix given a set of corresponding points */ +#define CV_FM_7POINT 1 +#define CV_FM_8POINT 2 + +#define CV_LMEDS 4 +#define CV_RANSAC 8 + +#define CV_FM_LMEDS_ONLY CV_LMEDS +#define CV_FM_RANSAC_ONLY CV_RANSAC +#define CV_FM_LMEDS CV_LMEDS +#define CV_FM_RANSAC CV_RANSAC + +enum +{ + CV_ITERATIVE = 0, + CV_EPNP = 1, // F.Moreno-Noguer, V.Lepetit and P.Fua "EPnP: Efficient Perspective-n-Point Camera Pose Estimation" + CV_P3P = 2, // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang; "Complete Solution Classification for the Perspective-Three-Point Problem" + CV_DLS = 3 // Joel A. Hesch and Stergios I. Roumeliotis. "A Direct Least-Squares (DLS) Method for PnP" +}; + +CVAPI(int) cvFindFundamentalMat( const CvMat* points1, const CvMat* points2, + CvMat* fundamental_matrix, + int method CV_DEFAULT(CV_FM_RANSAC), + double param1 CV_DEFAULT(3.), double param2 CV_DEFAULT(0.99), + CvMat* status CV_DEFAULT(NULL) ); + +/* For each input point on one of images + computes parameters of the corresponding + epipolar line on the other image */ +CVAPI(void) cvComputeCorrespondEpilines( const CvMat* points, + int which_image, + const CvMat* fundamental_matrix, + CvMat* correspondent_lines ); + +/* Triangulation functions */ + +CVAPI(void) cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2, + CvMat* projPoints1, CvMat* projPoints2, + CvMat* points4D); + +CVAPI(void) cvCorrectMatches(CvMat* F, CvMat* points1, CvMat* points2, + CvMat* new_points1, CvMat* new_points2); + + +/* Computes the optimal new camera matrix according to the free scaling parameter alpha: + alpha=0 - only valid pixels will be retained in the undistorted image + alpha=1 - all the source image pixels will be retained in the undistorted image +*/ +CVAPI(void) cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix, + const CvMat* dist_coeffs, + CvSize image_size, double alpha, + CvMat* new_camera_matrix, + CvSize new_imag_size CV_DEFAULT(cvSize(0,0)), + CvRect* valid_pixel_ROI CV_DEFAULT(0), + int center_principal_point CV_DEFAULT(0)); + +/* Converts rotation vector to rotation matrix or vice versa */ +CVAPI(int) cvRodrigues2( const CvMat* src, CvMat* dst, + CvMat* jacobian CV_DEFAULT(0) ); + +/* Finds perspective transformation between the object plane and image (view) plane */ +CVAPI(int) cvFindHomography( const CvMat* src_points, + const CvMat* dst_points, + CvMat* homography, + int method CV_DEFAULT(0), + double ransacReprojThreshold CV_DEFAULT(3), + CvMat* mask CV_DEFAULT(0), + int maxIters CV_DEFAULT(2000), + double confidence CV_DEFAULT(0.995)); + +/* Computes RQ decomposition for 3x3 matrices */ +CVAPI(void) cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, + CvMat *matrixQx CV_DEFAULT(NULL), + CvMat *matrixQy CV_DEFAULT(NULL), + CvMat *matrixQz CV_DEFAULT(NULL), + CvPoint3D64f *eulerAngles CV_DEFAULT(NULL)); + +/* Computes projection matrix decomposition */ +CVAPI(void) cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr, + CvMat *rotMatr, CvMat *posVect, + CvMat *rotMatrX CV_DEFAULT(NULL), + CvMat *rotMatrY CV_DEFAULT(NULL), + CvMat *rotMatrZ CV_DEFAULT(NULL), + CvPoint3D64f *eulerAngles CV_DEFAULT(NULL)); + +/* Computes d(AB)/dA and d(AB)/dB */ +CVAPI(void) cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB ); + +/* Computes r3 = rodrigues(rodrigues(r2)*rodrigues(r1)), + t3 = rodrigues(r2)*t1 + t2 and the respective derivatives */ +CVAPI(void) cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1, + const CvMat* _rvec2, const CvMat* _tvec2, + CvMat* _rvec3, CvMat* _tvec3, + CvMat* dr3dr1 CV_DEFAULT(0), CvMat* dr3dt1 CV_DEFAULT(0), + CvMat* dr3dr2 CV_DEFAULT(0), CvMat* dr3dt2 CV_DEFAULT(0), + CvMat* dt3dr1 CV_DEFAULT(0), CvMat* dt3dt1 CV_DEFAULT(0), + CvMat* dt3dr2 CV_DEFAULT(0), CvMat* dt3dt2 CV_DEFAULT(0) ); + +/* Projects object points to the view plane using + the specified extrinsic and intrinsic camera parameters */ +CVAPI(void) cvProjectPoints2( const CvMat* object_points, const CvMat* rotation_vector, + const CvMat* translation_vector, const CvMat* camera_matrix, + const CvMat* distortion_coeffs, CvMat* image_points, + CvMat* dpdrot CV_DEFAULT(NULL), CvMat* dpdt CV_DEFAULT(NULL), + CvMat* dpdf CV_DEFAULT(NULL), CvMat* dpdc CV_DEFAULT(NULL), + CvMat* dpddist CV_DEFAULT(NULL), + double aspect_ratio CV_DEFAULT(0)); + +/* Finds extrinsic camera parameters from + a few known corresponding point pairs and intrinsic parameters */ +CVAPI(void) cvFindExtrinsicCameraParams2( const CvMat* object_points, + const CvMat* image_points, + const CvMat* camera_matrix, + const CvMat* distortion_coeffs, + CvMat* rotation_vector, + CvMat* translation_vector, + int use_extrinsic_guess CV_DEFAULT(0) ); + +/* Computes initial estimate of the intrinsic camera parameters + in case of planar calibration target (e.g. chessboard) */ +CVAPI(void) cvInitIntrinsicParams2D( const CvMat* object_points, + const CvMat* image_points, + const CvMat* npoints, CvSize image_size, + CvMat* camera_matrix, + double aspect_ratio CV_DEFAULT(1.) ); + +#define CV_CALIB_CB_ADAPTIVE_THRESH 1 +#define CV_CALIB_CB_NORMALIZE_IMAGE 2 +#define CV_CALIB_CB_FILTER_QUADS 4 +#define CV_CALIB_CB_FAST_CHECK 8 + +// Performs a fast check if a chessboard is in the input image. This is a workaround to +// a problem of cvFindChessboardCorners being slow on images with no chessboard +// - src: input image +// - size: chessboard size +// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called, +// 0 if there is no chessboard, -1 in case of error +CVAPI(int) cvCheckChessboard(IplImage* src, CvSize size); + + /* Detects corners on a chessboard calibration pattern */ +CVAPI(int) cvFindChessboardCorners( const void* image, CvSize pattern_size, + CvPoint2D32f* corners, + int* corner_count CV_DEFAULT(NULL), + int flags CV_DEFAULT(CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE) ); + +/* Draws individual chessboard corners or the whole chessboard detected */ +CVAPI(void) cvDrawChessboardCorners( CvArr* image, CvSize pattern_size, + CvPoint2D32f* corners, + int count, int pattern_was_found ); + +#define CV_CALIB_USE_INTRINSIC_GUESS 1 +#define CV_CALIB_FIX_ASPECT_RATIO 2 +#define CV_CALIB_FIX_PRINCIPAL_POINT 4 +#define CV_CALIB_ZERO_TANGENT_DIST 8 +#define CV_CALIB_FIX_FOCAL_LENGTH 16 +#define CV_CALIB_FIX_K1 32 +#define CV_CALIB_FIX_K2 64 +#define CV_CALIB_FIX_K3 128 +#define CV_CALIB_FIX_K4 2048 +#define CV_CALIB_FIX_K5 4096 +#define CV_CALIB_FIX_K6 8192 +#define CV_CALIB_RATIONAL_MODEL 16384 +#define CV_CALIB_THIN_PRISM_MODEL 32768 +#define CV_CALIB_FIX_S1_S2_S3_S4 65536 + + +/* Finds intrinsic and extrinsic camera parameters + from a few views of known calibration pattern */ +CVAPI(double) cvCalibrateCamera2( const CvMat* object_points, + const CvMat* image_points, + const CvMat* point_counts, + CvSize image_size, + CvMat* camera_matrix, + CvMat* distortion_coeffs, + CvMat* rotation_vectors CV_DEFAULT(NULL), + CvMat* translation_vectors CV_DEFAULT(NULL), + int flags CV_DEFAULT(0), + CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( + CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) ); + +/* Computes various useful characteristics of the camera from the data computed by + cvCalibrateCamera2 */ +CVAPI(void) cvCalibrationMatrixValues( const CvMat *camera_matrix, + CvSize image_size, + double aperture_width CV_DEFAULT(0), + double aperture_height CV_DEFAULT(0), + double *fovx CV_DEFAULT(NULL), + double *fovy CV_DEFAULT(NULL), + double *focal_length CV_DEFAULT(NULL), + CvPoint2D64f *principal_point CV_DEFAULT(NULL), + double *pixel_aspect_ratio CV_DEFAULT(NULL)); + +#define CV_CALIB_FIX_INTRINSIC 256 +#define CV_CALIB_SAME_FOCAL_LENGTH 512 + +/* Computes the transformation from one camera coordinate system to another one + from a few correspondent views of the same calibration target. Optionally, calibrates + both cameras */ +CVAPI(double) cvStereoCalibrate( const CvMat* object_points, const CvMat* image_points1, + const CvMat* image_points2, const CvMat* npoints, + CvMat* camera_matrix1, CvMat* dist_coeffs1, + CvMat* camera_matrix2, CvMat* dist_coeffs2, + CvSize image_size, CvMat* R, CvMat* T, + CvMat* E CV_DEFAULT(0), CvMat* F CV_DEFAULT(0), + int flags CV_DEFAULT(CV_CALIB_FIX_INTRINSIC), + CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria( + CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6)) ); + +#define CV_CALIB_ZERO_DISPARITY 1024 + +/* Computes 3D rotations (+ optional shift) for each camera coordinate system to make both + views parallel (=> to make all the epipolar lines horizontal or vertical) */ +CVAPI(void) cvStereoRectify( const CvMat* camera_matrix1, const CvMat* camera_matrix2, + const CvMat* dist_coeffs1, const CvMat* dist_coeffs2, + CvSize image_size, const CvMat* R, const CvMat* T, + CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2, + CvMat* Q CV_DEFAULT(0), + int flags CV_DEFAULT(CV_CALIB_ZERO_DISPARITY), + double alpha CV_DEFAULT(-1), + CvSize new_image_size CV_DEFAULT(cvSize(0,0)), + CvRect* valid_pix_ROI1 CV_DEFAULT(0), + CvRect* valid_pix_ROI2 CV_DEFAULT(0)); + +/* Computes rectification transformations for uncalibrated pair of images using a set + of point correspondences */ +CVAPI(int) cvStereoRectifyUncalibrated( const CvMat* points1, const CvMat* points2, + const CvMat* F, CvSize img_size, + CvMat* H1, CvMat* H2, + double threshold CV_DEFAULT(5)); + + + +/* stereo correspondence parameters and functions */ + +#define CV_STEREO_BM_NORMALIZED_RESPONSE 0 +#define CV_STEREO_BM_XSOBEL 1 + +/* Block matching algorithm structure */ +typedef struct CvStereoBMState +{ + // pre-filtering (normalization of input images) + int preFilterType; // =CV_STEREO_BM_NORMALIZED_RESPONSE now + int preFilterSize; // averaging window size: ~5x5..21x21 + int preFilterCap; // the output of pre-filtering is clipped by [-preFilterCap,preFilterCap] + + // correspondence using Sum of Absolute Difference (SAD) + int SADWindowSize; // ~5x5..21x21 + int minDisparity; // minimum disparity (can be negative) + int numberOfDisparities; // maximum disparity - minimum disparity (> 0) + + // post-filtering + int textureThreshold; // the disparity is only computed for pixels + // with textured enough neighborhood + int uniquenessRatio; // accept the computed disparity d* only if + // SAD(d) >= SAD(d*)*(1 + uniquenessRatio/100.) + // for any d != d*+/-1 within the search range. + int speckleWindowSize; // disparity variation window + int speckleRange; // acceptable range of variation in window + + int trySmallerWindows; // if 1, the results may be more accurate, + // at the expense of slower processing + CvRect roi1, roi2; + int disp12MaxDiff; + + // temporary buffers + CvMat* preFilteredImg0; + CvMat* preFilteredImg1; + CvMat* slidingSumBuf; + CvMat* cost; + CvMat* disp; +} CvStereoBMState; + +#define CV_STEREO_BM_BASIC 0 +#define CV_STEREO_BM_FISH_EYE 1 +#define CV_STEREO_BM_NARROW 2 + +CVAPI(CvStereoBMState*) cvCreateStereoBMState(int preset CV_DEFAULT(CV_STEREO_BM_BASIC), + int numberOfDisparities CV_DEFAULT(0)); + +CVAPI(void) cvReleaseStereoBMState( CvStereoBMState** state ); + +CVAPI(void) cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right, + CvArr* disparity, CvStereoBMState* state ); + +CVAPI(CvRect) cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity, + int numberOfDisparities, int SADWindowSize ); + +CVAPI(void) cvValidateDisparity( CvArr* disparity, const CvArr* cost, + int minDisparity, int numberOfDisparities, + int disp12MaxDiff CV_DEFAULT(1) ); + +/* Reprojects the computed disparity image to the 3D space using the specified 4x4 matrix */ +CVAPI(void) cvReprojectImageTo3D( const CvArr* disparityImage, + CvArr* _3dImage, const CvMat* Q, + int handleMissingValues CV_DEFAULT(0) ); + +/** @} calib3d_c */ + +#ifdef __cplusplus +} // extern "C" + +////////////////////////////////////////////////////////////////////////////////////////// +class CV_EXPORTS CvLevMarq +{ +public: + CvLevMarq(); + CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria= + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), + bool completeSymmFlag=false ); + ~CvLevMarq(); + void init( int nparams, int nerrs, CvTermCriteria criteria= + cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON), + bool completeSymmFlag=false ); + bool update( const CvMat*& param, CvMat*& J, CvMat*& err ); + bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm ); + + void clear(); + void step(); + enum { DONE=0, STARTED=1, CALC_J=2, CHECK_ERR=3 }; + + cv::Ptr mask; + cv::Ptr prevParam; + cv::Ptr param; + cv::Ptr J; + cv::Ptr err; + cv::Ptr JtJ; + cv::Ptr JtJN; + cv::Ptr JtErr; + cv::Ptr JtJV; + cv::Ptr JtJW; + double prevErrNorm, errNorm; + int lambdaLg10; + CvTermCriteria criteria; + int state; + int iters; + bool completeSymmFlag; +}; + +#endif + +#endif /* __OPENCV_CALIB3D_C_H__ */ diff --git a/include/opencv2/core.hpp b/include/opencv2/core.hpp new file mode 100644 index 0000000..6594476 --- /dev/null +++ b/include/opencv2/core.hpp @@ -0,0 +1,3111 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 2015, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_HPP__ +#define __OPENCV_CORE_HPP__ + +#ifndef __cplusplus +# error core.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/version.hpp" +#include "opencv2/core/base.hpp" +#include "opencv2/core/cvstd.hpp" +#include "opencv2/core/traits.hpp" +#include "opencv2/core/matx.hpp" +#include "opencv2/core/types.hpp" +#include "opencv2/core/mat.hpp" +#include "opencv2/core/persistence.hpp" + +/** +@defgroup core Core functionality +@{ + @defgroup core_basic Basic structures + @defgroup core_c C structures and operations + @{ + @defgroup core_c_glue Connections with C++ + @} + @defgroup core_array Operations on arrays + @defgroup core_xml XML/YAML Persistence + @defgroup core_cluster Clustering + @defgroup core_utils Utility and system functions and macros + @{ + @defgroup core_utils_neon NEON utilities + @} + @defgroup core_opengl OpenGL interoperability + @defgroup core_ipp Intel IPP Asynchronous C/C++ Converters + @defgroup core_optim Optimization Algorithms + @defgroup core_directx DirectX interoperability + @defgroup core_eigen Eigen support + @defgroup core_opencl OpenCL support +@} + */ + +namespace cv { + +//! @addtogroup core_utils +//! @{ + +/*! @brief Class passed to an error. + +This class encapsulates all or almost all necessary +information about the error happened in the program. The exception is +usually constructed and thrown implicitly via CV_Error and CV_Error_ macros. +@see error + */ +class CV_EXPORTS Exception : public std::exception +{ +public: + /*! + Default constructor + */ + Exception(); + /*! + Full constructor. Normally the constuctor is not called explicitly. + Instead, the macros CV_Error(), CV_Error_() and CV_Assert() are used. + */ + Exception(int _code, const String& _err, const String& _func, const String& _file, int _line); + virtual ~Exception() throw(); + + /*! + \return the error description and the context as a text string. + */ + virtual const char *what() const throw(); + void formatMessage(); + + String msg; ///< the formatted error message + + int code; ///< error code @see CVStatus + String err; ///< error description + String func; ///< function name. Available only when the compiler supports getting it + String file; ///< source file name where the error has occured + int line; ///< line number in the source file where the error has occured +}; + +/*! @brief Signals an error and raises the exception. + +By default the function prints information about the error to stderr, +then it either stops if cv::setBreakOnError() had been called before or raises the exception. +It is possible to alternate error processing by using cv::redirectError(). +@param exc the exception raisen. +@deprecated drop this version + */ +CV_EXPORTS void error( const Exception& exc ); + +enum SortFlags { SORT_EVERY_ROW = 0, //!< each matrix row is sorted independently + SORT_EVERY_COLUMN = 1, //!< each matrix column is sorted + //!< independently; this flag and the previous one are + //!< mutually exclusive. + SORT_ASCENDING = 0, //!< each matrix row is sorted in the ascending + //!< order. + SORT_DESCENDING = 16 //!< each matrix row is sorted in the + //!< descending order; this flag and the previous one are also + //!< mutually exclusive. + }; + +//! @} core_utils + +//! @addtogroup core +//! @{ + +//! Covariation flags +enum CovarFlags { + /** The output covariance matrix is calculated as: + \f[\texttt{scale} \cdot [ \texttt{vects} [0]- \texttt{mean} , \texttt{vects} [1]- \texttt{mean} ,...]^T \cdot [ \texttt{vects} [0]- \texttt{mean} , \texttt{vects} [1]- \texttt{mean} ,...],\f] + The covariance matrix will be nsamples x nsamples. Such an unusual covariance matrix is used + for fast PCA of a set of very large vectors (see, for example, the EigenFaces technique for + face recognition). Eigenvalues of this "scrambled" matrix match the eigenvalues of the true + covariance matrix. The "true" eigenvectors can be easily calculated from the eigenvectors of + the "scrambled" covariance matrix. */ + COVAR_SCRAMBLED = 0, + /**The output covariance matrix is calculated as: + \f[\texttt{scale} \cdot [ \texttt{vects} [0]- \texttt{mean} , \texttt{vects} [1]- \texttt{mean} ,...] \cdot [ \texttt{vects} [0]- \texttt{mean} , \texttt{vects} [1]- \texttt{mean} ,...]^T,\f] + covar will be a square matrix of the same size as the total number of elements in each input + vector. One and only one of COVAR_SCRAMBLED and COVAR_NORMAL must be specified.*/ + COVAR_NORMAL = 1, + /** If the flag is specified, the function does not calculate mean from + the input vectors but, instead, uses the passed mean vector. This is useful if mean has been + pre-calculated or known in advance, or if the covariance matrix is calculated by parts. In + this case, mean is not a mean vector of the input sub-set of vectors but rather the mean + vector of the whole set.*/ + COVAR_USE_AVG = 2, + /** If the flag is specified, the covariance matrix is scaled. In the + "normal" mode, scale is 1./nsamples . In the "scrambled" mode, scale is the reciprocal of the + total number of elements in each input vector. By default (if the flag is not specified), the + covariance matrix is not scaled ( scale=1 ).*/ + COVAR_SCALE = 4, + /** If the flag is + specified, all the input vectors are stored as rows of the samples matrix. mean should be a + single-row vector in this case.*/ + COVAR_ROWS = 8, + /** If the flag is + specified, all the input vectors are stored as columns of the samples matrix. mean should be a + single-column vector in this case.*/ + COVAR_COLS = 16 +}; + +//! k-Means flags +enum KmeansFlags { + /** Select random initial centers in each attempt.*/ + KMEANS_RANDOM_CENTERS = 0, + /** Use kmeans++ center initialization by Arthur and Vassilvitskii [Arthur2007].*/ + KMEANS_PP_CENTERS = 2, + /** During the first (and possibly the only) attempt, use the + user-supplied labels instead of computing them from the initial centers. For the second and + further attempts, use the random or semi-random centers. Use one of KMEANS_\*_CENTERS flag + to specify the exact method.*/ + KMEANS_USE_INITIAL_LABELS = 1 +}; + +//! type of line +enum LineTypes { + FILLED = -1, + LINE_4 = 4, //!< 4-connected line + LINE_8 = 8, //!< 8-connected line + LINE_AA = 16 //!< antialiased line +}; + +//! Only a subset of Hershey fonts +//! are supported +enum HersheyFonts { + FONT_HERSHEY_SIMPLEX = 0, //!< normal size sans-serif font + FONT_HERSHEY_PLAIN = 1, //!< small size sans-serif font + FONT_HERSHEY_DUPLEX = 2, //!< normal size sans-serif font (more complex than FONT_HERSHEY_SIMPLEX) + FONT_HERSHEY_COMPLEX = 3, //!< normal size serif font + FONT_HERSHEY_TRIPLEX = 4, //!< normal size serif font (more complex than FONT_HERSHEY_COMPLEX) + FONT_HERSHEY_COMPLEX_SMALL = 5, //!< smaller version of FONT_HERSHEY_COMPLEX + FONT_HERSHEY_SCRIPT_SIMPLEX = 6, //!< hand-writing style font + FONT_HERSHEY_SCRIPT_COMPLEX = 7, //!< more complex variant of FONT_HERSHEY_SCRIPT_SIMPLEX + FONT_ITALIC = 16 //!< flag for italic font +}; + +enum ReduceTypes { REDUCE_SUM = 0, //!< the output is the sum of all rows/columns of the matrix. + REDUCE_AVG = 1, //!< the output is the mean vector of all rows/columns of the matrix. + REDUCE_MAX = 2, //!< the output is the maximum (column/row-wise) of all rows/columns of the matrix. + REDUCE_MIN = 3 //!< the output is the minimum (column/row-wise) of all rows/columns of the matrix. + }; + + +/** @brief Swaps two matrices +*/ +CV_EXPORTS void swap(Mat& a, Mat& b); +/** @overload */ +CV_EXPORTS void swap( UMat& a, UMat& b ); + +//! @} core + +//! @addtogroup core_array +//! @{ + +/** @brief Computes the source location of an extrapolated pixel. + +The function computes and returns the coordinate of a donor pixel corresponding to the specified +extrapolated pixel when using the specified extrapolation border mode. For example, if you use +cv::BORDER_WRAP mode in the horizontal direction, cv::BORDER_REFLECT_101 in the vertical direction and +want to compute value of the "virtual" pixel Point(-5, 100) in a floating-point image img , it +looks like: +@code{.cpp} + float val = img.at(borderInterpolate(100, img.rows, cv::BORDER_REFLECT_101), + borderInterpolate(-5, img.cols, cv::BORDER_WRAP)); +@endcode +Normally, the function is not called directly. It is used inside filtering functions and also in +copyMakeBorder. +@param p 0-based coordinate of the extrapolated pixel along one of the axes, likely \<0 or \>= len +@param len Length of the array along the corresponding axis. +@param borderType Border type, one of the cv::BorderTypes, except for cv::BORDER_TRANSPARENT and +cv::BORDER_ISOLATED . When borderType==cv::BORDER_CONSTANT , the function always returns -1, regardless +of p and len. + +@sa copyMakeBorder +*/ +CV_EXPORTS_W int borderInterpolate(int p, int len, int borderType); + +/** @brief Forms a border around an image. + +The function copies the source image into the middle of the destination image. The areas to the +left, to the right, above and below the copied source image will be filled with extrapolated +pixels. This is not what filtering functions based on it do (they extrapolate pixels on-fly), but +what other more complex functions, including your own, may do to simplify image boundary handling. + +The function supports the mode when src is already in the middle of dst . In this case, the +function does not copy src itself but simply constructs the border, for example: + +@code{.cpp} + // let border be the same in all directions + int border=2; + // constructs a larger image to fit both the image and the border + Mat gray_buf(rgb.rows + border*2, rgb.cols + border*2, rgb.depth()); + // select the middle part of it w/o copying data + Mat gray(gray_canvas, Rect(border, border, rgb.cols, rgb.rows)); + // convert image from RGB to grayscale + cvtColor(rgb, gray, COLOR_RGB2GRAY); + // form a border in-place + copyMakeBorder(gray, gray_buf, border, border, + border, border, BORDER_REPLICATE); + // now do some custom filtering ... + ... +@endcode +@note When the source image is a part (ROI) of a bigger image, the function will try to use the +pixels outside of the ROI to form a border. To disable this feature and always do extrapolation, as +if src was not a ROI, use borderType | BORDER_ISOLATED. + +@param src Source image. +@param dst Destination image of the same type as src and the size Size(src.cols+left+right, +src.rows+top+bottom) . +@param top +@param bottom +@param left +@param right Parameter specifying how many pixels in each direction from the source image rectangle +to extrapolate. For example, top=1, bottom=1, left=1, right=1 mean that 1 pixel-wide border needs +to be built. +@param borderType Border type. See borderInterpolate for details. +@param value Border value if borderType==BORDER_CONSTANT . + +@sa borderInterpolate +*/ +CV_EXPORTS_W void copyMakeBorder(InputArray src, OutputArray dst, + int top, int bottom, int left, int right, + int borderType, const Scalar& value = Scalar() ); + +/** @brief Calculates the per-element sum of two arrays or an array and a scalar. + +The function add calculates: +- Sum of two arrays when both input arrays have the same size and the same number of channels: +\f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1}(I) + \texttt{src2}(I)) \quad \texttt{if mask}(I) \ne0\f] +- Sum of an array and a scalar when src2 is constructed from Scalar or has the same number of +elements as `src1.channels()`: +\f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1}(I) + \texttt{src2} ) \quad \texttt{if mask}(I) \ne0\f] +- Sum of a scalar and an array when src1 is constructed from Scalar or has the same number of +elements as `src2.channels()`: +\f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1} + \texttt{src2}(I) ) \quad \texttt{if mask}(I) \ne0\f] +where `I` is a multi-dimensional index of array elements. In case of multi-channel arrays, each +channel is processed independently. + +The first function in the list above can be replaced with matrix expressions: +@code{.cpp} + dst = src1 + src2; + dst += src1; // equivalent to add(dst, src1, dst); +@endcode +The input arrays and the output array can all have the same or different depths. For example, you +can add a 16-bit unsigned array to a 8-bit signed array and store the sum as a 32-bit +floating-point array. Depth of the output array is determined by the dtype parameter. In the second +and third cases above, as well as in the first case, when src1.depth() == src2.depth(), dtype can +be set to the default -1. In this case, the output array will have the same depth as the input +array, be it src1, src2 or both. +@note Saturation is not applied when the output array has the depth CV_32S. You may even get +result of an incorrect sign in the case of overflow. +@param src1 first input array or a scalar. +@param src2 second input array or a scalar. +@param dst output array that has the same size and number of channels as the input array(s); the +depth is defined by dtype or src1/src2. +@param mask optional operation mask - 8-bit single channel array, that specifies elements of the +output array to be changed. +@param dtype optional depth of the output array (see the discussion below). +@sa subtract, addWeighted, scaleAdd, Mat::convertTo +*/ +CV_EXPORTS_W void add(InputArray src1, InputArray src2, OutputArray dst, + InputArray mask = noArray(), int dtype = -1); + +/** @brief Calculates the per-element difference between two arrays or array and a scalar. + +The function subtract calculates: +- Difference between two arrays, when both input arrays have the same size and the same number of +channels: + \f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1}(I) - \texttt{src2}(I)) \quad \texttt{if mask}(I) \ne0\f] +- Difference between an array and a scalar, when src2 is constructed from Scalar or has the same +number of elements as `src1.channels()`: + \f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1}(I) - \texttt{src2} ) \quad \texttt{if mask}(I) \ne0\f] +- Difference between a scalar and an array, when src1 is constructed from Scalar or has the same +number of elements as `src2.channels()`: + \f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1} - \texttt{src2}(I) ) \quad \texttt{if mask}(I) \ne0\f] +- The reverse difference between a scalar and an array in the case of `SubRS`: + \f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src2} - \texttt{src1}(I) ) \quad \texttt{if mask}(I) \ne0\f] +where I is a multi-dimensional index of array elements. In case of multi-channel arrays, each +channel is processed independently. + +The first function in the list above can be replaced with matrix expressions: +@code{.cpp} + dst = src1 - src2; + dst -= src1; // equivalent to subtract(dst, src1, dst); +@endcode +The input arrays and the output array can all have the same or different depths. For example, you +can subtract to 8-bit unsigned arrays and store the difference in a 16-bit signed array. Depth of +the output array is determined by dtype parameter. In the second and third cases above, as well as +in the first case, when src1.depth() == src2.depth(), dtype can be set to the default -1. In this +case the output array will have the same depth as the input array, be it src1, src2 or both. +@note Saturation is not applied when the output array has the depth CV_32S. You may even get +result of an incorrect sign in the case of overflow. +@param src1 first input array or a scalar. +@param src2 second input array or a scalar. +@param dst output array of the same size and the same number of channels as the input array. +@param mask optional operation mask; this is an 8-bit single channel array that specifies elements +of the output array to be changed. +@param dtype optional depth of the output array +@sa add, addWeighted, scaleAdd, Mat::convertTo + */ +CV_EXPORTS_W void subtract(InputArray src1, InputArray src2, OutputArray dst, + InputArray mask = noArray(), int dtype = -1); + + +/** @brief Calculates the per-element scaled product of two arrays. + +The function multiply calculates the per-element product of two arrays: + +\f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{scale} \cdot \texttt{src1} (I) \cdot \texttt{src2} (I))\f] + +There is also a @ref MatrixExpressions -friendly variant of the first function. See Mat::mul . + +For a not-per-element matrix product, see gemm . + +@note Saturation is not applied when the output array has the depth +CV_32S. You may even get result of an incorrect sign in the case of +overflow. +@param src1 first input array. +@param src2 second input array of the same size and the same type as src1. +@param dst output array of the same size and type as src1. +@param scale optional scale factor. +@param dtype optional depth of the output array +@sa add, subtract, divide, scaleAdd, addWeighted, accumulate, accumulateProduct, accumulateSquare, +Mat::convertTo +*/ +CV_EXPORTS_W void multiply(InputArray src1, InputArray src2, + OutputArray dst, double scale = 1, int dtype = -1); + +/** @brief Performs per-element division of two arrays or a scalar by an array. + +The functions divide divide one array by another: +\f[\texttt{dst(I) = saturate(src1(I)*scale/src2(I))}\f] +or a scalar by an array when there is no src1 : +\f[\texttt{dst(I) = saturate(scale/src2(I))}\f] + +When src2(I) is zero, dst(I) will also be zero. Different channels of +multi-channel arrays are processed independently. + +@note Saturation is not applied when the output array has the depth CV_32S. You may even get +result of an incorrect sign in the case of overflow. +@param src1 first input array. +@param src2 second input array of the same size and type as src1. +@param scale scalar factor. +@param dst output array of the same size and type as src2. +@param dtype optional depth of the output array; if -1, dst will have depth src2.depth(), but in +case of an array-by-array division, you can only pass -1 when src1.depth()==src2.depth(). +@sa multiply, add, subtract +*/ +CV_EXPORTS_W void divide(InputArray src1, InputArray src2, OutputArray dst, + double scale = 1, int dtype = -1); + +/** @overload */ +CV_EXPORTS_W void divide(double scale, InputArray src2, + OutputArray dst, int dtype = -1); + +/** @brief Calculates the sum of a scaled array and another array. + +The function scaleAdd is one of the classical primitive linear algebra operations, known as DAXPY +or SAXPY in [BLAS](http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms). It calculates +the sum of a scaled array and another array: +\f[\texttt{dst} (I)= \texttt{scale} \cdot \texttt{src1} (I) + \texttt{src2} (I)\f] +The function can also be emulated with a matrix expression, for example: +@code{.cpp} + Mat A(3, 3, CV_64F); + ... + A.row(0) = A.row(1)*2 + A.row(2); +@endcode +@param src1 first input array. +@param alpha scale factor for the first array. +@param src2 second input array of the same size and type as src1. +@param dst output array of the same size and type as src1. +@sa add, addWeighted, subtract, Mat::dot, Mat::convertTo +*/ +CV_EXPORTS_W void scaleAdd(InputArray src1, double alpha, InputArray src2, OutputArray dst); + +/** @brief Calculates the weighted sum of two arrays. + +The function addWeighted calculates the weighted sum of two arrays as follows: +\f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{src1} (I)* \texttt{alpha} + \texttt{src2} (I)* \texttt{beta} + \texttt{gamma} )\f] +where I is a multi-dimensional index of array elements. In case of multi-channel arrays, each +channel is processed independently. +The function can be replaced with a matrix expression: +@code{.cpp} + dst = src1*alpha + src2*beta + gamma; +@endcode +@note Saturation is not applied when the output array has the depth CV_32S. You may even get +result of an incorrect sign in the case of overflow. +@param src1 first input array. +@param alpha weight of the first array elements. +@param src2 second input array of the same size and channel number as src1. +@param beta weight of the second array elements. +@param gamma scalar added to each sum. +@param dst output array that has the same size and number of channels as the input arrays. +@param dtype optional depth of the output array; when both input arrays have the same depth, dtype +can be set to -1, which will be equivalent to src1.depth(). +@sa add, subtract, scaleAdd, Mat::convertTo +*/ +CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2, + double beta, double gamma, OutputArray dst, int dtype = -1); + +/** @brief Scales, calculates absolute values, and converts the result to 8-bit. + +On each element of the input array, the function convertScaleAbs +performs three operations sequentially: scaling, taking an absolute +value, conversion to an unsigned 8-bit type: +\f[\texttt{dst} (I)= \texttt{saturate\_cast} (| \texttt{src} (I)* \texttt{alpha} + \texttt{beta} |)\f] +In case of multi-channel arrays, the function processes each channel +independently. When the output is not 8-bit, the operation can be +emulated by calling the Mat::convertTo method (or by using matrix +expressions) and then by calculating an absolute value of the result. +For example: +@code{.cpp} + Mat_ A(30,30); + randu(A, Scalar(-100), Scalar(100)); + Mat_ B = A*5 + 3; + B = abs(B); + // Mat_ B = abs(A*5+3) will also do the job, + // but it will allocate a temporary matrix +@endcode +@param src input array. +@param dst output array. +@param alpha optional scale factor. +@param beta optional delta added to the scaled values. +@sa Mat::convertTo, cv::abs(const Mat&) +*/ +CV_EXPORTS_W void convertScaleAbs(InputArray src, OutputArray dst, + double alpha = 1, double beta = 0); + +/** @brief Performs a look-up table transform of an array. + +The function LUT fills the output array with values from the look-up table. Indices of the entries +are taken from the input array. That is, the function processes each element of src as follows: +\f[\texttt{dst} (I) \leftarrow \texttt{lut(src(I) + d)}\f] +where +\f[d = \fork{0}{if \texttt{src} has depth \texttt{CV\_8U}}{128}{if \texttt{src} has depth \texttt{CV\_8S}}\f] +@param src input array of 8-bit elements. +@param lut look-up table of 256 elements; in case of multi-channel input array, the table should +either have a single channel (in this case the same table is used for all channels) or the same +number of channels as in the input array. +@param dst output array of the same size and number of channels as src, and the same depth as lut. +@sa convertScaleAbs, Mat::convertTo +*/ +CV_EXPORTS_W void LUT(InputArray src, InputArray lut, OutputArray dst); + +/** @brief Calculates the sum of array elements. + +The functions sum calculate and return the sum of array elements, +independently for each channel. +@param src input array that must have from 1 to 4 channels. +@sa countNonZero, mean, meanStdDev, norm, minMaxLoc, reduce +*/ +CV_EXPORTS_AS(sumElems) Scalar sum(InputArray src); + +/** @brief Counts non-zero array elements. + +The function returns the number of non-zero elements in src : +\f[\sum _{I: \; \texttt{src} (I) \ne0 } 1\f] +@param src single-channel array. +@sa mean, meanStdDev, norm, minMaxLoc, calcCovarMatrix +*/ +CV_EXPORTS_W int countNonZero( InputArray src ); + +/** @brief Returns the list of locations of non-zero pixels + +Given a binary matrix (likely returned from an operation such +as threshold(), compare(), >, ==, etc, return all of +the non-zero indices as a cv::Mat or std::vector (x,y) +For example: +@code{.cpp} + cv::Mat binaryImage; // input, binary image + cv::Mat locations; // output, locations of non-zero pixels + cv::findNonZero(binaryImage, locations); + + // access pixel coordinates + Point pnt = locations.at(i); +@endcode +or +@code{.cpp} + cv::Mat binaryImage; // input, binary image + vector locations; // output, locations of non-zero pixels + cv::findNonZero(binaryImage, locations); + + // access pixel coordinates + Point pnt = locations[i]; +@endcode +@param src single-channel array (type CV_8UC1) +@param idx the output array, type of cv::Mat or std::vector, corresponding to non-zero indices in the input +*/ +CV_EXPORTS_W void findNonZero( InputArray src, OutputArray idx ); + +/** @brief Calculates an average (mean) of array elements. + +The function mean calculates the mean value M of array elements, +independently for each channel, and return it: +\f[\begin{array}{l} N = \sum _{I: \; \texttt{mask} (I) \ne 0} 1 \\ M_c = \left ( \sum _{I: \; \texttt{mask} (I) \ne 0}{ \texttt{mtx} (I)_c} \right )/N \end{array}\f] +When all the mask elements are 0's, the functions return Scalar::all(0) +@param src input array that should have from 1 to 4 channels so that the result can be stored in +Scalar_ . +@param mask optional operation mask. +@sa countNonZero, meanStdDev, norm, minMaxLoc +*/ +CV_EXPORTS_W Scalar mean(InputArray src, InputArray mask = noArray()); + +/** Calculates a mean and standard deviation of array elements. + +The function meanStdDev calculates the mean and the standard deviation M +of array elements independently for each channel and returns it via the +output parameters: +\f[\begin{array}{l} N = \sum _{I, \texttt{mask} (I) \ne 0} 1 \\ \texttt{mean} _c = \frac{\sum_{ I: \; \texttt{mask}(I) \ne 0} \texttt{src} (I)_c}{N} \\ \texttt{stddev} _c = \sqrt{\frac{\sum_{ I: \; \texttt{mask}(I) \ne 0} \left ( \texttt{src} (I)_c - \texttt{mean} _c \right )^2}{N}} \end{array}\f] +When all the mask elements are 0's, the functions return +mean=stddev=Scalar::all(0). +@note The calculated standard deviation is only the diagonal of the +complete normalized covariance matrix. If the full matrix is needed, you +can reshape the multi-channel array M x N to the single-channel array +M\*N x mtx.channels() (only possible when the matrix is continuous) and +then pass the matrix to calcCovarMatrix . +@param src input array that should have from 1 to 4 channels so that the results can be stored in +Scalar_ 's. +@param mean output parameter: calculated mean value. +@param stddev output parameter: calculateded standard deviation. +@param mask optional operation mask. +@sa countNonZero, mean, norm, minMaxLoc, calcCovarMatrix +*/ +CV_EXPORTS_W void meanStdDev(InputArray src, OutputArray mean, OutputArray stddev, + InputArray mask=noArray()); + +/** @brief Calculates an absolute array norm, an absolute difference norm, or a +relative difference norm. + +The functions norm calculate an absolute norm of src1 (when there is no +src2 ): + +\f[norm = \forkthree{\|\texttt{src1}\|_{L_{\infty}} = \max _I | \texttt{src1} (I)|}{if \(\texttt{normType} = \texttt{NORM\_INF}\) } +{ \| \texttt{src1} \| _{L_1} = \sum _I | \texttt{src1} (I)|}{if \(\texttt{normType} = \texttt{NORM\_L1}\) } +{ \| \texttt{src1} \| _{L_2} = \sqrt{\sum_I \texttt{src1}(I)^2} }{if \(\texttt{normType} = \texttt{NORM\_L2}\) }\f] + +or an absolute or relative difference norm if src2 is there: + +\f[norm = \forkthree{\|\texttt{src1}-\texttt{src2}\|_{L_{\infty}} = \max _I | \texttt{src1} (I) - \texttt{src2} (I)|}{if \(\texttt{normType} = \texttt{NORM\_INF}\) } +{ \| \texttt{src1} - \texttt{src2} \| _{L_1} = \sum _I | \texttt{src1} (I) - \texttt{src2} (I)|}{if \(\texttt{normType} = \texttt{NORM\_L1}\) } +{ \| \texttt{src1} - \texttt{src2} \| _{L_2} = \sqrt{\sum_I (\texttt{src1}(I) - \texttt{src2}(I))^2} }{if \(\texttt{normType} = \texttt{NORM\_L2}\) }\f] + +or + +\f[norm = \forkthree{\frac{\|\texttt{src1}-\texttt{src2}\|_{L_{\infty}} }{\|\texttt{src2}\|_{L_{\infty}} }}{if \(\texttt{normType} = \texttt{NORM\_RELATIVE\_INF}\) } +{ \frac{\|\texttt{src1}-\texttt{src2}\|_{L_1} }{\|\texttt{src2}\|_{L_1}} }{if \(\texttt{normType} = \texttt{NORM\_RELATIVE\_L1}\) } +{ \frac{\|\texttt{src1}-\texttt{src2}\|_{L_2} }{\|\texttt{src2}\|_{L_2}} }{if \(\texttt{normType} = \texttt{NORM\_RELATIVE\_L2}\) }\f] + +The functions norm return the calculated norm. + +When the mask parameter is specified and it is not empty, the norm is +calculated only over the region specified by the mask. + +A multi-channel input arrays are treated as a single-channel, that is, +the results for all channels are combined. + +@param src1 first input array. +@param normType type of the norm (see cv::NormTypes). +@param mask optional operation mask; it must have the same size as src1 and CV_8UC1 type. +*/ +CV_EXPORTS_W double norm(InputArray src1, int normType = NORM_L2, InputArray mask = noArray()); + +/** @overload +@param src1 first input array. +@param src2 second input array of the same size and the same type as src1. +@param normType type of the norm (cv::NormTypes). +@param mask optional operation mask; it must have the same size as src1 and CV_8UC1 type. +*/ +CV_EXPORTS_W double norm(InputArray src1, InputArray src2, + int normType = NORM_L2, InputArray mask = noArray()); +/** @overload +@param src first input array. +@param normType type of the norm (see cv::NormTypes). +*/ +CV_EXPORTS double norm( const SparseMat& src, int normType ); + +/** @brief computes PSNR image/video quality metric + +see http://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio for details +@todo document + */ +CV_EXPORTS_W double PSNR(InputArray src1, InputArray src2); + +/** @brief naive nearest neighbor finder + +see http://en.wikipedia.org/wiki/Nearest_neighbor_search +@todo document + */ +CV_EXPORTS_W void batchDistance(InputArray src1, InputArray src2, + OutputArray dist, int dtype, OutputArray nidx, + int normType = NORM_L2, int K = 0, + InputArray mask = noArray(), int update = 0, + bool crosscheck = false); + +/** @brief Normalizes the norm or value range of an array. + +The functions normalize scale and shift the input array elements so that +\f[\| \texttt{dst} \| _{L_p}= \texttt{alpha}\f] +(where p=Inf, 1 or 2) when normType=NORM_INF, NORM_L1, or NORM_L2, respectively; or so that +\f[\min _I \texttt{dst} (I)= \texttt{alpha} , \, \, \max _I \texttt{dst} (I)= \texttt{beta}\f] + +when normType=NORM_MINMAX (for dense arrays only). The optional mask specifies a sub-array to be +normalized. This means that the norm or min-n-max are calculated over the sub-array, and then this +sub-array is modified to be normalized. If you want to only use the mask to calculate the norm or +min-max but modify the whole array, you can use norm and Mat::convertTo. + +In case of sparse matrices, only the non-zero values are analyzed and transformed. Because of this, +the range transformation for sparse matrices is not allowed since it can shift the zero level. + +@param src input array. +@param dst output array of the same size as src . +@param alpha norm value to normalize to or the lower range boundary in case of the range +normalization. +@param beta upper range boundary in case of the range normalization; it is not used for the norm +normalization. +@param norm_type normalization type (see cv::NormTypes). +@param dtype when negative, the output array has the same type as src; otherwise, it has the same +number of channels as src and the depth =CV_MAT_DEPTH(dtype). +@param mask optional operation mask. +@sa norm, Mat::convertTo, SparseMat::convertTo +*/ +CV_EXPORTS_W void normalize( InputArray src, InputOutputArray dst, double alpha = 1, double beta = 0, + int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray()); + +/** @overload +@param src input array. +@param dst output array of the same size as src . +@param alpha norm value to normalize to or the lower range boundary in case of the range +normalization. +@param normType normalization type (see cv::NormTypes). +*/ +CV_EXPORTS void normalize( const SparseMat& src, SparseMat& dst, double alpha, int normType ); + +/** @brief Finds the global minimum and maximum in an array. + +The functions minMaxLoc find the minimum and maximum element values and their positions. The +extremums are searched across the whole array or, if mask is not an empty array, in the specified +array region. + +The functions do not work with multi-channel arrays. If you need to find minimum or maximum +elements across all the channels, use Mat::reshape first to reinterpret the array as +single-channel. Or you may extract the particular channel using either extractImageCOI , or +mixChannels , or split . +@param src input single-channel array. +@param minVal pointer to the returned minimum value; NULL is used if not required. +@param maxVal pointer to the returned maximum value; NULL is used if not required. +@param minLoc pointer to the returned minimum location (in 2D case); NULL is used if not required. +@param maxLoc pointer to the returned maximum location (in 2D case); NULL is used if not required. +@param mask optional mask used to select a sub-array. +@sa max, min, compare, inRange, extractImageCOI, mixChannels, split, Mat::reshape +*/ +CV_EXPORTS_W void minMaxLoc(InputArray src, CV_OUT double* minVal, + CV_OUT double* maxVal = 0, CV_OUT Point* minLoc = 0, + CV_OUT Point* maxLoc = 0, InputArray mask = noArray()); + + +/** @brief Finds the global minimum and maximum in an array + +The function minMaxIdx finds the minimum and maximum element values and their positions. The +extremums are searched across the whole array or, if mask is not an empty array, in the specified +array region. The function does not work with multi-channel arrays. If you need to find minimum or +maximum elements across all the channels, use Mat::reshape first to reinterpret the array as +single-channel. Or you may extract the particular channel using either extractImageCOI , or +mixChannels , or split . In case of a sparse matrix, the minimum is found among non-zero elements +only. +@note When minIdx is not NULL, it must have at least 2 elements (as well as maxIdx), even if src is +a single-row or single-column matrix. In OpenCV (following MATLAB) each array has at least 2 +dimensions, i.e. single-column matrix is Mx1 matrix (and therefore minIdx/maxIdx will be +(i1,0)/(i2,0)) and single-row matrix is 1xN matrix (and therefore minIdx/maxIdx will be +(0,j1)/(0,j2)). +@param src input single-channel array. +@param minVal pointer to the returned minimum value; NULL is used if not required. +@param maxVal pointer to the returned maximum value; NULL is used if not required. +@param minIdx pointer to the returned minimum location (in nD case); NULL is used if not required; +Otherwise, it must point to an array of src.dims elements, the coordinates of the minimum element +in each dimension are stored there sequentially. +@param maxIdx pointer to the returned maximum location (in nD case). NULL is used if not required. +@param mask specified array region +*/ +CV_EXPORTS void minMaxIdx(InputArray src, double* minVal, double* maxVal = 0, + int* minIdx = 0, int* maxIdx = 0, InputArray mask = noArray()); + +/** @overload +@param a input single-channel array. +@param minVal pointer to the returned minimum value; NULL is used if not required. +@param maxVal pointer to the returned maximum value; NULL is used if not required. +@param minIdx pointer to the returned minimum location (in nD case); NULL is used if not required; +Otherwise, it must point to an array of src.dims elements, the coordinates of the minimum element +in each dimension are stored there sequentially. +@param maxIdx pointer to the returned maximum location (in nD case). NULL is used if not required. +*/ +CV_EXPORTS void minMaxLoc(const SparseMat& a, double* minVal, + double* maxVal, int* minIdx = 0, int* maxIdx = 0); + +/** @brief Reduces a matrix to a vector. + +The function reduce reduces the matrix to a vector by treating the matrix rows/columns as a set of +1D vectors and performing the specified operation on the vectors until a single row/column is +obtained. For example, the function can be used to compute horizontal and vertical projections of a +raster image. In case of REDUCE_SUM and REDUCE_AVG , the output may have a larger element +bit-depth to preserve accuracy. And multi-channel arrays are also supported in these two reduction +modes. +@param src input 2D matrix. +@param dst output vector. Its size and type is defined by dim and dtype parameters. +@param dim dimension index along which the matrix is reduced. 0 means that the matrix is reduced to +a single row. 1 means that the matrix is reduced to a single column. +@param rtype reduction operation that could be one of cv::ReduceTypes +@param dtype when negative, the output vector will have the same type as the input matrix, +otherwise, its type will be CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels()). +@sa repeat +*/ +CV_EXPORTS_W void reduce(InputArray src, OutputArray dst, int dim, int rtype, int dtype = -1); + +/** @brief Creates one multichannel array out of several single-channel ones. + +The functions merge merge several arrays to make a single multi-channel array. That is, each +element of the output array will be a concatenation of the elements of the input arrays, where +elements of i-th input array are treated as mv[i].channels()-element vectors. + +The function split does the reverse operation. If you need to shuffle channels in some other +advanced way, use mixChannels . +@param mv input array of matrices to be merged; all the matrices in mv must have the same +size and the same depth. +@param count number of input matrices when mv is a plain C array; it must be greater than zero. +@param dst output array of the same size and the same depth as mv[0]; The number of channels will +be the total number of channels in the matrix array. +@sa mixChannels, split, Mat::reshape +*/ +CV_EXPORTS void merge(const Mat* mv, size_t count, OutputArray dst); + +/** @overload +@param mv input vector of matrices to be merged; all the matrices in mv must have the same +size and the same depth. +@param dst output array of the same size and the same depth as mv[0]; The number of channels will +be the total number of channels in the matrix array. + */ +CV_EXPORTS_W void merge(InputArrayOfArrays mv, OutputArray dst); + +/** @brief Divides a multi-channel array into several single-channel arrays. + +The functions split split a multi-channel array into separate single-channel arrays: +\f[\texttt{mv} [c](I) = \texttt{src} (I)_c\f] +If you need to extract a single channel or do some other sophisticated channel permutation, use +mixChannels . +@param src input multi-channel array. +@param mvbegin output array; the number of arrays must match src.channels(); the arrays themselves are +reallocated, if needed. +@sa merge, mixChannels, cvtColor +*/ +CV_EXPORTS void split(const Mat& src, Mat* mvbegin); + +/** @overload +@param m input multi-channel array. +@param mv output vector of arrays; the arrays themselves are reallocated, if needed. +*/ +CV_EXPORTS_W void split(InputArray m, OutputArrayOfArrays mv); + +/** @brief Copies specified channels from input arrays to the specified channels of +output arrays. + +The functions mixChannels provide an advanced mechanism for shuffling image channels. + +split and merge and some forms of cvtColor are partial cases of mixChannels . + +In the example below, the code splits a 4-channel RGBA image into a 3-channel BGR (with R and B +channels swapped) and a separate alpha-channel image: +@code{.cpp} + Mat rgba( 100, 100, CV_8UC4, Scalar(1,2,3,4) ); + Mat bgr( rgba.rows, rgba.cols, CV_8UC3 ); + Mat alpha( rgba.rows, rgba.cols, CV_8UC1 ); + + // forming an array of matrices is a quite efficient operation, + // because the matrix data is not copied, only the headers + Mat out[] = { bgr, alpha }; + // rgba[0] -> bgr[2], rgba[1] -> bgr[1], + // rgba[2] -> bgr[0], rgba[3] -> alpha[0] + int from_to[] = { 0,2, 1,1, 2,0, 3,3 }; + mixChannels( &rgba, 1, out, 2, from_to, 4 ); +@endcode +@note Unlike many other new-style C++ functions in OpenCV (see the introduction section and +Mat::create ), mixChannels requires the output arrays to be pre-allocated before calling the +function. +@param src input array or vector of matricesl; all of the matrices must have the same size and the +same depth. +@param nsrcs number of matrices in src. +@param dst output array or vector of matrices; all the matrices *must be allocated*; their size and +depth must be the same as in src[0]. +@param ndsts number of matrices in dst. +@param fromTo array of index pairs specifying which channels are copied and where; fromTo[k\*2] is +a 0-based index of the input channel in src, fromTo[k\*2+1] is an index of the output channel in +dst; the continuous channel numbering is used: the first input image channels are indexed from 0 to +src[0].channels()-1, the second input image channels are indexed from src[0].channels() to +src[0].channels() + src[1].channels()-1, and so on, the same scheme is used for the output image +channels; as a special case, when fromTo[k\*2] is negative, the corresponding output channel is +filled with zero . +@param npairs number of index pairs in fromTo. +@sa split, merge, cvtColor +*/ +CV_EXPORTS void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, + const int* fromTo, size_t npairs); + +/** @overload +@param src input array or vector of matricesl; all of the matrices must have the same size and the +same depth. +@param dst output array or vector of matrices; all the matrices *must be allocated*; their size and +depth must be the same as in src[0]. +@param fromTo array of index pairs specifying which channels are copied and where; fromTo[k\*2] is +a 0-based index of the input channel in src, fromTo[k\*2+1] is an index of the output channel in +dst; the continuous channel numbering is used: the first input image channels are indexed from 0 to +src[0].channels()-1, the second input image channels are indexed from src[0].channels() to +src[0].channels() + src[1].channels()-1, and so on, the same scheme is used for the output image +channels; as a special case, when fromTo[k\*2] is negative, the corresponding output channel is +filled with zero . +@param npairs number of index pairs in fromTo. +*/ +CV_EXPORTS void mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, + const int* fromTo, size_t npairs); + +/** @overload +@param src input array or vector of matricesl; all of the matrices must have the same size and the +same depth. +@param dst output array or vector of matrices; all the matrices *must be allocated*; their size and +depth must be the same as in src[0]. +@param fromTo array of index pairs specifying which channels are copied and where; fromTo[k\*2] is +a 0-based index of the input channel in src, fromTo[k\*2+1] is an index of the output channel in +dst; the continuous channel numbering is used: the first input image channels are indexed from 0 to +src[0].channels()-1, the second input image channels are indexed from src[0].channels() to +src[0].channels() + src[1].channels()-1, and so on, the same scheme is used for the output image +channels; as a special case, when fromTo[k\*2] is negative, the corresponding output channel is +filled with zero . +*/ +CV_EXPORTS_W void mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst, + const std::vector& fromTo); + +/** @brief extracts a single channel from src (coi is 0-based index) +@todo document +*/ +CV_EXPORTS_W void extractChannel(InputArray src, OutputArray dst, int coi); + +/** @brief inserts a single channel to dst (coi is 0-based index) +@todo document +*/ +CV_EXPORTS_W void insertChannel(InputArray src, InputOutputArray dst, int coi); + +/** @brief Flips a 2D array around vertical, horizontal, or both axes. + +The function flip flips the array in one of three different ways (row +and column indices are 0-based): +\f[\texttt{dst} _{ij} = +\left\{ +\begin{array}{l l} +\texttt{src} _{\texttt{src.rows}-i-1,j} & if\; \texttt{flipCode} = 0 \\ +\texttt{src} _{i, \texttt{src.cols} -j-1} & if\; \texttt{flipCode} > 0 \\ +\texttt{src} _{ \texttt{src.rows} -i-1, \texttt{src.cols} -j-1} & if\; \texttt{flipCode} < 0 \\ +\end{array} +\right.\f] +The example scenarios of using the function are the following: +* Vertical flipping of the image (flipCode == 0) to switch between + top-left and bottom-left image origin. This is a typical operation + in video processing on Microsoft Windows\* OS. +* Horizontal flipping of the image with the subsequent horizontal + shift and absolute difference calculation to check for a + vertical-axis symmetry (flipCode \> 0). +* Simultaneous horizontal and vertical flipping of the image with + the subsequent shift and absolute difference calculation to check + for a central symmetry (flipCode \< 0). +* Reversing the order of point arrays (flipCode \> 0 or + flipCode == 0). +@param src input array. +@param dst output array of the same size and type as src. +@param flipCode a flag to specify how to flip the array; 0 means +flipping around the x-axis and positive value (for example, 1) means +flipping around y-axis. Negative value (for example, -1) means flipping +around both axes. +@sa transpose , repeat , completeSymm +*/ +CV_EXPORTS_W void flip(InputArray src, OutputArray dst, int flipCode); + +/** @brief Fills the output array with repeated copies of the input array. + +The functions repeat duplicate the input array one or more times along each of the two axes: +\f[\texttt{dst} _{ij}= \texttt{src} _{i\mod src.rows, \; j\mod src.cols }\f] +The second variant of the function is more convenient to use with @ref MatrixExpressions. +@param src input array to replicate. +@param dst output array of the same type as src. +@param ny Flag to specify how many times the src is repeated along the +vertical axis. +@param nx Flag to specify how many times the src is repeated along the +horizontal axis. +@sa reduce +*/ +CV_EXPORTS_W void repeat(InputArray src, int ny, int nx, OutputArray dst); + +/** @overload +@param src input array to replicate. +@param ny Flag to specify how many times the src is repeated along the +vertical axis. +@param nx Flag to specify how many times the src is repeated along the +horizontal axis. + */ +CV_EXPORTS Mat repeat(const Mat& src, int ny, int nx); + +/** @brief Applies horizontal concatenation to given matrices. + +The function horizontally concatenates two or more cv::Mat matrices (with the same number of rows). +@code{.cpp} + cv::Mat matArray[] = { cv::Mat(4, 1, CV_8UC1, cv::Scalar(1)), + cv::Mat(4, 1, CV_8UC1, cv::Scalar(2)), + cv::Mat(4, 1, CV_8UC1, cv::Scalar(3)),}; + + cv::Mat out; + cv::hconcat( matArray, 3, out ); + //out: + //[1, 2, 3; + // 1, 2, 3; + // 1, 2, 3; + // 1, 2, 3] +@endcode +@param src input array or vector of matrices. all of the matrices must have the same number of rows and the same depth. +@param nsrc number of matrices in src. +@param dst output array. It has the same number of rows and depth as the src, and the sum of cols of the src. +@sa cv::vconcat(const Mat*, size_t, OutputArray), @sa cv::vconcat(InputArrayOfArrays, OutputArray) and @sa cv::vconcat(InputArray, InputArray, OutputArray) +*/ +CV_EXPORTS void hconcat(const Mat* src, size_t nsrc, OutputArray dst); +/** @overload + @code{.cpp} + cv::Mat_ A = (cv::Mat_(3, 2) << 1, 4, + 2, 5, + 3, 6); + cv::Mat_ B = (cv::Mat_(3, 2) << 7, 10, + 8, 11, + 9, 12); + + cv::Mat C; + cv::hconcat(A, B, C); + //C: + //[1, 4, 7, 10; + // 2, 5, 8, 11; + // 3, 6, 9, 12] + @endcode + @param src1 first input array to be considered for horizontal concatenation. + @param src2 second input array to be considered for horizontal concatenation. + @param dst output array. It has the same number of rows and depth as the src1 and src2, and the sum of cols of the src1 and src2. + */ +CV_EXPORTS void hconcat(InputArray src1, InputArray src2, OutputArray dst); +/** @overload + @code{.cpp} + std::vector matrices = { cv::Mat(4, 1, CV_8UC1, cv::Scalar(1)), + cv::Mat(4, 1, CV_8UC1, cv::Scalar(2)), + cv::Mat(4, 1, CV_8UC1, cv::Scalar(3)),}; + + cv::Mat out; + cv::hconcat( matrices, out ); + //out: + //[1, 2, 3; + // 1, 2, 3; + // 1, 2, 3; + // 1, 2, 3] + @endcode + @param src input array or vector of matrices. all of the matrices must have the same number of rows and the same depth. + @param dst output array. It has the same number of rows and depth as the src, and the sum of cols of the src. +same depth. + */ +CV_EXPORTS_W void hconcat(InputArrayOfArrays src, OutputArray dst); + +/** @brief Applies vertical concatenation to given matrices. + +The function vertically concatenates two or more cv::Mat matrices (with the same number of cols). +@code{.cpp} + cv::Mat matArray[] = { cv::Mat(1, 4, CV_8UC1, cv::Scalar(1)), + cv::Mat(1, 4, CV_8UC1, cv::Scalar(2)), + cv::Mat(1, 4, CV_8UC1, cv::Scalar(3)),}; + + cv::Mat out; + cv::vconcat( matArray, 3, out ); + //out: + //[1, 1, 1, 1; + // 2, 2, 2, 2; + // 3, 3, 3, 3] +@endcode +@param src input array or vector of matrices. all of the matrices must have the same number of cols and the same depth. +@param nsrc number of matrices in src. +@param dst output array. It has the same number of cols and depth as the src, and the sum of rows of the src. +@sa cv::hconcat(const Mat*, size_t, OutputArray), @sa cv::hconcat(InputArrayOfArrays, OutputArray) and @sa cv::hconcat(InputArray, InputArray, OutputArray) +*/ +CV_EXPORTS void vconcat(const Mat* src, size_t nsrc, OutputArray dst); +/** @overload + @code{.cpp} + cv::Mat_ A = (cv::Mat_(3, 2) << 1, 7, + 2, 8, + 3, 9); + cv::Mat_ B = (cv::Mat_(3, 2) << 4, 10, + 5, 11, + 6, 12); + + cv::Mat C; + cv::vconcat(A, B, C); + //C: + //[1, 7; + // 2, 8; + // 3, 9; + // 4, 10; + // 5, 11; + // 6, 12] + @endcode + @param src1 first input array to be considered for vertical concatenation. + @param src2 second input array to be considered for vertical concatenation. + @param dst output array. It has the same number of cols and depth as the src1 and src2, and the sum of rows of the src1 and src2. + */ +CV_EXPORTS void vconcat(InputArray src1, InputArray src2, OutputArray dst); +/** @overload + @code{.cpp} + std::vector matrices = { cv::Mat(1, 4, CV_8UC1, cv::Scalar(1)), + cv::Mat(1, 4, CV_8UC1, cv::Scalar(2)), + cv::Mat(1, 4, CV_8UC1, cv::Scalar(3)),}; + + cv::Mat out; + cv::vconcat( matrices, out ); + //out: + //[1, 1, 1, 1; + // 2, 2, 2, 2; + // 3, 3, 3, 3] + @endcode + @param src input array or vector of matrices. all of the matrices must have the same number of cols and the same depth + @param dst output array. It has the same number of cols and depth as the src, and the sum of rows of the src. +same depth. + */ +CV_EXPORTS_W void vconcat(InputArrayOfArrays src, OutputArray dst); + +/** @brief computes bitwise conjunction of the two arrays (dst = src1 & src2) +Calculates the per-element bit-wise conjunction of two arrays or an +array and a scalar. + +The function calculates the per-element bit-wise logical conjunction for: +* Two arrays when src1 and src2 have the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) \wedge \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] +* An array and a scalar when src2 is constructed from Scalar or has + the same number of elements as `src1.channels()`: + \f[\texttt{dst} (I) = \texttt{src1} (I) \wedge \texttt{src2} \quad \texttt{if mask} (I) \ne0\f] +* A scalar and an array when src1 is constructed from Scalar or has + the same number of elements as `src2.channels()`: + \f[\texttt{dst} (I) = \texttt{src1} \wedge \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] +In case of floating-point arrays, their machine-specific bit +representations (usually IEEE754-compliant) are used for the operation. +In case of multi-channel arrays, each channel is processed +independently. In the second and third cases above, the scalar is first +converted to the array type. +@param src1 first input array or a scalar. +@param src2 second input array or a scalar. +@param dst output array that has the same size and type as the input +arrays. +@param mask optional operation mask, 8-bit single channel array, that +specifies elements of the output array to be changed. +*/ +CV_EXPORTS_W void bitwise_and(InputArray src1, InputArray src2, + OutputArray dst, InputArray mask = noArray()); + +/** @brief Calculates the per-element bit-wise disjunction of two arrays or an +array and a scalar. + +The function calculates the per-element bit-wise logical disjunction for: +* Two arrays when src1 and src2 have the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) \vee \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] +* An array and a scalar when src2 is constructed from Scalar or has + the same number of elements as `src1.channels()`: + \f[\texttt{dst} (I) = \texttt{src1} (I) \vee \texttt{src2} \quad \texttt{if mask} (I) \ne0\f] +* A scalar and an array when src1 is constructed from Scalar or has + the same number of elements as `src2.channels()`: + \f[\texttt{dst} (I) = \texttt{src1} \vee \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] +In case of floating-point arrays, their machine-specific bit +representations (usually IEEE754-compliant) are used for the operation. +In case of multi-channel arrays, each channel is processed +independently. In the second and third cases above, the scalar is first +converted to the array type. +@param src1 first input array or a scalar. +@param src2 second input array or a scalar. +@param dst output array that has the same size and type as the input +arrays. +@param mask optional operation mask, 8-bit single channel array, that +specifies elements of the output array to be changed. +*/ +CV_EXPORTS_W void bitwise_or(InputArray src1, InputArray src2, + OutputArray dst, InputArray mask = noArray()); + +/** @brief Calculates the per-element bit-wise "exclusive or" operation on two +arrays or an array and a scalar. + +The function calculates the per-element bit-wise logical "exclusive-or" +operation for: +* Two arrays when src1 and src2 have the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) \oplus \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] +* An array and a scalar when src2 is constructed from Scalar or has + the same number of elements as `src1.channels()`: + \f[\texttt{dst} (I) = \texttt{src1} (I) \oplus \texttt{src2} \quad \texttt{if mask} (I) \ne0\f] +* A scalar and an array when src1 is constructed from Scalar or has + the same number of elements as `src2.channels()`: + \f[\texttt{dst} (I) = \texttt{src1} \oplus \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f] +In case of floating-point arrays, their machine-specific bit +representations (usually IEEE754-compliant) are used for the operation. +In case of multi-channel arrays, each channel is processed +independently. In the 2nd and 3rd cases above, the scalar is first +converted to the array type. +@param src1 first input array or a scalar. +@param src2 second input array or a scalar. +@param dst output array that has the same size and type as the input +arrays. +@param mask optional operation mask, 8-bit single channel array, that +specifies elements of the output array to be changed. +*/ +CV_EXPORTS_W void bitwise_xor(InputArray src1, InputArray src2, + OutputArray dst, InputArray mask = noArray()); + +/** @brief Inverts every bit of an array. + +The function calculates per-element bit-wise inversion of the input +array: +\f[\texttt{dst} (I) = \neg \texttt{src} (I)\f] +In case of a floating-point input array, its machine-specific bit +representation (usually IEEE754-compliant) is used for the operation. In +case of multi-channel arrays, each channel is processed independently. +@param src input array. +@param dst output array that has the same size and type as the input +array. +@param mask optional operation mask, 8-bit single channel array, that +specifies elements of the output array to be changed. +*/ +CV_EXPORTS_W void bitwise_not(InputArray src, OutputArray dst, + InputArray mask = noArray()); + +/** @brief Calculates the per-element absolute difference between two arrays or between an array and a scalar. + +The function absdiff calculates: +* Absolute difference between two arrays when they have the same + size and type: + \f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1}(I) - \texttt{src2}(I)|)\f] +* Absolute difference between an array and a scalar when the second + array is constructed from Scalar or has as many elements as the + number of channels in `src1`: + \f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1}(I) - \texttt{src2} |)\f] +* Absolute difference between a scalar and an array when the first + array is constructed from Scalar or has as many elements as the + number of channels in `src2`: + \f[\texttt{dst}(I) = \texttt{saturate} (| \texttt{src1} - \texttt{src2}(I) |)\f] + where I is a multi-dimensional index of array elements. In case of + multi-channel arrays, each channel is processed independently. +@note Saturation is not applied when the arrays have the depth CV_32S. +You may even get a negative value in the case of overflow. +@param src1 first input array or a scalar. +@param src2 second input array or a scalar. +@param dst output array that has the same size and type as input arrays. +@sa cv::abs(const Mat&) +*/ +CV_EXPORTS_W void absdiff(InputArray src1, InputArray src2, OutputArray dst); + +/** @brief Checks if array elements lie between the elements of two other arrays. + +The function checks the range as follows: +- For every element of a single-channel input array: + \f[\texttt{dst} (I)= \texttt{lowerb} (I)_0 \leq \texttt{src} (I)_0 \leq \texttt{upperb} (I)_0\f] +- For two-channel arrays: + \f[\texttt{dst} (I)= \texttt{lowerb} (I)_0 \leq \texttt{src} (I)_0 \leq \texttt{upperb} (I)_0 \land \texttt{lowerb} (I)_1 \leq \texttt{src} (I)_1 \leq \texttt{upperb} (I)_1\f] +- and so forth. + +That is, dst (I) is set to 255 (all 1 -bits) if src (I) is within the +specified 1D, 2D, 3D, ... box and 0 otherwise. + +When the lower and/or upper boundary parameters are scalars, the indexes +(I) at lowerb and upperb in the above formulas should be omitted. +@param src first input array. +@param lowerb inclusive lower boundary array or a scalar. +@param upperb inclusive upper boundary array or a scalar. +@param dst output array of the same size as src and CV_8U type. +*/ +CV_EXPORTS_W void inRange(InputArray src, InputArray lowerb, + InputArray upperb, OutputArray dst); + +/** @brief Performs the per-element comparison of two arrays or an array and scalar value. + +The function compares: +* Elements of two arrays when src1 and src2 have the same size: + \f[\texttt{dst} (I) = \texttt{src1} (I) \,\texttt{cmpop}\, \texttt{src2} (I)\f] +* Elements of src1 with a scalar src2 when src2 is constructed from + Scalar or has a single element: + \f[\texttt{dst} (I) = \texttt{src1}(I) \,\texttt{cmpop}\, \texttt{src2}\f] +* src1 with elements of src2 when src1 is constructed from Scalar or + has a single element: + \f[\texttt{dst} (I) = \texttt{src1} \,\texttt{cmpop}\, \texttt{src2} (I)\f] +When the comparison result is true, the corresponding element of output +array is set to 255. The comparison operations can be replaced with the +equivalent matrix expressions: +@code{.cpp} + Mat dst1 = src1 >= src2; + Mat dst2 = src1 < 8; + ... +@endcode +@param src1 first input array or a scalar; when it is an array, it must have a single channel. +@param src2 second input array or a scalar; when it is an array, it must have a single channel. +@param dst output array of type ref CV_8U that has the same size and the same number of channels as + the input arrays. +@param cmpop a flag, that specifies correspondence between the arrays (cv::CmpTypes) +@sa checkRange, min, max, threshold +*/ +CV_EXPORTS_W void compare(InputArray src1, InputArray src2, OutputArray dst, int cmpop); + +/** @brief Calculates per-element minimum of two arrays or an array and a scalar. + +The functions min calculate the per-element minimum of two arrays: +\f[\texttt{dst} (I)= \min ( \texttt{src1} (I), \texttt{src2} (I))\f] +or array and a scalar: +\f[\texttt{dst} (I)= \min ( \texttt{src1} (I), \texttt{value} )\f] +@param src1 first input array. +@param src2 second input array of the same size and type as src1. +@param dst output array of the same size and type as src1. +@sa max, compare, inRange, minMaxLoc +*/ +CV_EXPORTS_W void min(InputArray src1, InputArray src2, OutputArray dst); +/** @overload +needed to avoid conflicts with const _Tp& std::min(const _Tp&, const _Tp&, _Compare) +*/ +CV_EXPORTS void min(const Mat& src1, const Mat& src2, Mat& dst); +/** @overload +needed to avoid conflicts with const _Tp& std::min(const _Tp&, const _Tp&, _Compare) +*/ +CV_EXPORTS void min(const UMat& src1, const UMat& src2, UMat& dst); + +/** @brief Calculates per-element maximum of two arrays or an array and a scalar. + +The functions max calculate the per-element maximum of two arrays: +\f[\texttt{dst} (I)= \max ( \texttt{src1} (I), \texttt{src2} (I))\f] +or array and a scalar: +\f[\texttt{dst} (I)= \max ( \texttt{src1} (I), \texttt{value} )\f] +@param src1 first input array. +@param src2 second input array of the same size and type as src1 . +@param dst output array of the same size and type as src1. +@sa min, compare, inRange, minMaxLoc, @ref MatrixExpressions +*/ +CV_EXPORTS_W void max(InputArray src1, InputArray src2, OutputArray dst); +/** @overload +needed to avoid conflicts with const _Tp& std::min(const _Tp&, const _Tp&, _Compare) +*/ +CV_EXPORTS void max(const Mat& src1, const Mat& src2, Mat& dst); +/** @overload +needed to avoid conflicts with const _Tp& std::min(const _Tp&, const _Tp&, _Compare) +*/ +CV_EXPORTS void max(const UMat& src1, const UMat& src2, UMat& dst); + +/** @brief Calculates a square root of array elements. + +The functions sqrt calculate a square root of each input array element. +In case of multi-channel arrays, each channel is processed +independently. The accuracy is approximately the same as of the built-in +std::sqrt . +@param src input floating-point array. +@param dst output array of the same size and type as src. +*/ +CV_EXPORTS_W void sqrt(InputArray src, OutputArray dst); + +/** @brief Raises every array element to a power. + +The function pow raises every element of the input array to power : +\f[\texttt{dst} (I) = \fork{\texttt{src}(I)^power}{if \texttt{power} is integer}{|\texttt{src}(I)|^power}{otherwise}\f] + +So, for a non-integer power exponent, the absolute values of input array +elements are used. However, it is possible to get true values for +negative values using some extra operations. In the example below, +computing the 5th root of array src shows: +@code{.cpp} + Mat mask = src < 0; + pow(src, 1./5, dst); + subtract(Scalar::all(0), dst, dst, mask); +@endcode +For some values of power, such as integer values, 0.5 and -0.5, +specialized faster algorithms are used. + +Special values (NaN, Inf) are not handled. +@param src input array. +@param power exponent of power. +@param dst output array of the same size and type as src. +@sa sqrt, exp, log, cartToPolar, polarToCart +*/ +CV_EXPORTS_W void pow(InputArray src, double power, OutputArray dst); + +/** @brief Calculates the exponent of every array element. + +The function exp calculates the exponent of every element of the input +array: +\f[\texttt{dst} [I] = e^{ src(I) }\f] + +The maximum relative error is about 7e-6 for single-precision input and +less than 1e-10 for double-precision input. Currently, the function +converts denormalized values to zeros on output. Special values (NaN, +Inf) are not handled. +@param src input array. +@param dst output array of the same size and type as src. +@sa log , cartToPolar , polarToCart , phase , pow , sqrt , magnitude +*/ +CV_EXPORTS_W void exp(InputArray src, OutputArray dst); + +/** @brief Calculates the natural logarithm of every array element. + +The function log calculates the natural logarithm of the absolute value +of every element of the input array: +\f[\texttt{dst} (I) = \fork{\log |\texttt{src}(I)|}{if \(\texttt{src}(I) \ne 0\) }{\texttt{C}}{otherwise}\f] + +where C is a large negative number (about -700 in the current +implementation). The maximum relative error is about 7e-6 for +single-precision input and less than 1e-10 for double-precision input. +Special values (NaN, Inf) are not handled. +@param src input array. +@param dst output array of the same size and type as src . +@sa exp, cartToPolar, polarToCart, phase, pow, sqrt, magnitude +*/ +CV_EXPORTS_W void log(InputArray src, OutputArray dst); + +/** @brief Calculates x and y coordinates of 2D vectors from their magnitude and angle. + +The function polarToCart calculates the Cartesian coordinates of each 2D +vector represented by the corresponding elements of magnitude and angle: +\f[\begin{array}{l} \texttt{x} (I) = \texttt{magnitude} (I) \cos ( \texttt{angle} (I)) \\ \texttt{y} (I) = \texttt{magnitude} (I) \sin ( \texttt{angle} (I)) \\ \end{array}\f] + +The relative accuracy of the estimated coordinates is about 1e-6. +@param magnitude input floating-point array of magnitudes of 2D vectors; +it can be an empty matrix (=Mat()), in this case, the function assumes +that all the magnitudes are =1; if it is not empty, it must have the +same size and type as angle. +@param angle input floating-point array of angles of 2D vectors. +@param x output array of x-coordinates of 2D vectors; it has the same +size and type as angle. +@param y output array of y-coordinates of 2D vectors; it has the same +size and type as angle. +@param angleInDegrees when true, the input angles are measured in +degrees, otherwise, they are measured in radians. +@sa cartToPolar, magnitude, phase, exp, log, pow, sqrt +*/ +CV_EXPORTS_W void polarToCart(InputArray magnitude, InputArray angle, + OutputArray x, OutputArray y, bool angleInDegrees = false); + +/** @brief Calculates the magnitude and angle of 2D vectors. + +The function cartToPolar calculates either the magnitude, angle, or both +for every 2D vector (x(I),y(I)): +\f[\begin{array}{l} \texttt{magnitude} (I)= \sqrt{\texttt{x}(I)^2+\texttt{y}(I)^2} , \\ \texttt{angle} (I)= \texttt{atan2} ( \texttt{y} (I), \texttt{x} (I))[ \cdot180 / \pi ] \end{array}\f] + +The angles are calculated with accuracy about 0.3 degrees. For the point +(0,0), the angle is set to 0. +@param x array of x-coordinates; this must be a single-precision or +double-precision floating-point array. +@param y array of y-coordinates, that must have the same size and same type as x. +@param magnitude output array of magnitudes of the same size and type as x. +@param angle output array of angles that has the same size and type as +x; the angles are measured in radians (from 0 to 2\*Pi) or in degrees (0 to 360 degrees). +@param angleInDegrees a flag, indicating whether the angles are measured +in radians (which is by default), or in degrees. +@sa Sobel, Scharr +*/ +CV_EXPORTS_W void cartToPolar(InputArray x, InputArray y, + OutputArray magnitude, OutputArray angle, + bool angleInDegrees = false); + +/** @brief Calculates the rotation angle of 2D vectors. + +The function phase calculates the rotation angle of each 2D vector that +is formed from the corresponding elements of x and y : +\f[\texttt{angle} (I) = \texttt{atan2} ( \texttt{y} (I), \texttt{x} (I))\f] + +The angle estimation accuracy is about 0.3 degrees. When x(I)=y(I)=0 , +the corresponding angle(I) is set to 0. +@param x input floating-point array of x-coordinates of 2D vectors. +@param y input array of y-coordinates of 2D vectors; it must have the +same size and the same type as x. +@param angle output array of vector angles; it has the same size and +same type as x . +@param angleInDegrees when true, the function calculates the angle in +degrees, otherwise, they are measured in radians. +*/ +CV_EXPORTS_W void phase(InputArray x, InputArray y, OutputArray angle, + bool angleInDegrees = false); + +/** @brief Calculates the magnitude of 2D vectors. + +The function magnitude calculates the magnitude of 2D vectors formed +from the corresponding elements of x and y arrays: +\f[\texttt{dst} (I) = \sqrt{\texttt{x}(I)^2 + \texttt{y}(I)^2}\f] +@param x floating-point array of x-coordinates of the vectors. +@param y floating-point array of y-coordinates of the vectors; it must +have the same size as x. +@param magnitude output array of the same size and type as x. +@sa cartToPolar, polarToCart, phase, sqrt +*/ +CV_EXPORTS_W void magnitude(InputArray x, InputArray y, OutputArray magnitude); + +/** @brief Checks every element of an input array for invalid values. + +The functions checkRange check that every array element is neither NaN nor infinite. When minVal \< +-DBL_MAX and maxVal \< DBL_MAX, the functions also check that each value is between minVal and +maxVal. In case of multi-channel arrays, each channel is processed independently. If some values +are out of range, position of the first outlier is stored in pos (when pos != NULL). Then, the +functions either return false (when quiet=true) or throw an exception. +@param a input array. +@param quiet a flag, indicating whether the functions quietly return false when the array elements +are out of range or they throw an exception. +@param pos optional output parameter, when not NULL, must be a pointer to array of src.dims +elements. +@param minVal inclusive lower boundary of valid values range. +@param maxVal exclusive upper boundary of valid values range. +*/ +CV_EXPORTS_W bool checkRange(InputArray a, bool quiet = true, CV_OUT Point* pos = 0, + double minVal = -DBL_MAX, double maxVal = DBL_MAX); + +/** @brief converts NaN's to the given number +*/ +CV_EXPORTS_W void patchNaNs(InputOutputArray a, double val = 0); + +/** @brief Performs generalized matrix multiplication. + +The function performs generalized matrix multiplication similar to the +gemm functions in BLAS level 3. For example, +`gemm(src1, src2, alpha, src3, beta, dst, GEMM_1_T + GEMM_3_T)` +corresponds to +\f[\texttt{dst} = \texttt{alpha} \cdot \texttt{src1} ^T \cdot \texttt{src2} + \texttt{beta} \cdot \texttt{src3} ^T\f] + +In case of complex (two-channel) data, performed a complex matrix +multiplication. + +The function can be replaced with a matrix expression. For example, the +above call can be replaced with: +@code{.cpp} + dst = alpha*src1.t()*src2 + beta*src3.t(); +@endcode +@param src1 first multiplied input matrix that could be real(CV_32FC1, +CV_64FC1) or complex(CV_32FC2, CV_64FC2). +@param src2 second multiplied input matrix of the same type as src1. +@param alpha weight of the matrix product. +@param src3 third optional delta matrix added to the matrix product; it +should have the same type as src1 and src2. +@param beta weight of src3. +@param dst output matrix; it has the proper size and the same type as +input matrices. +@param flags operation flags (cv::GemmFlags) +@sa mulTransposed , transform +*/ +CV_EXPORTS_W void gemm(InputArray src1, InputArray src2, double alpha, + InputArray src3, double beta, OutputArray dst, int flags = 0); + +/** @brief Calculates the product of a matrix and its transposition. + +The function mulTransposed calculates the product of src and its +transposition: +\f[\texttt{dst} = \texttt{scale} ( \texttt{src} - \texttt{delta} )^T ( \texttt{src} - \texttt{delta} )\f] +if aTa=true , and +\f[\texttt{dst} = \texttt{scale} ( \texttt{src} - \texttt{delta} ) ( \texttt{src} - \texttt{delta} )^T\f] +otherwise. The function is used to calculate the covariance matrix. With +zero delta, it can be used as a faster substitute for general matrix +product A\*B when B=A' +@param src input single-channel matrix. Note that unlike gemm, the +function can multiply not only floating-point matrices. +@param dst output square matrix. +@param aTa Flag specifying the multiplication ordering. See the +description below. +@param delta Optional delta matrix subtracted from src before the +multiplication. When the matrix is empty ( delta=noArray() ), it is +assumed to be zero, that is, nothing is subtracted. If it has the same +size as src , it is simply subtracted. Otherwise, it is "repeated" (see +repeat ) to cover the full src and then subtracted. Type of the delta +matrix, when it is not empty, must be the same as the type of created +output matrix. See the dtype parameter description below. +@param scale Optional scale factor for the matrix product. +@param dtype Optional type of the output matrix. When it is negative, +the output matrix will have the same type as src . Otherwise, it will be +type=CV_MAT_DEPTH(dtype) that should be either CV_32F or CV_64F . +@sa calcCovarMatrix, gemm, repeat, reduce +*/ +CV_EXPORTS_W void mulTransposed( InputArray src, OutputArray dst, bool aTa, + InputArray delta = noArray(), + double scale = 1, int dtype = -1 ); + +/** @brief Transposes a matrix. + +The function transpose transposes the matrix src : +\f[\texttt{dst} (i,j) = \texttt{src} (j,i)\f] +@note No complex conjugation is done in case of a complex matrix. It it +should be done separately if needed. +@param src input array. +@param dst output array of the same type as src. +*/ +CV_EXPORTS_W void transpose(InputArray src, OutputArray dst); + +/** @brief Performs the matrix transformation of every array element. + +The function transform performs the matrix transformation of every +element of the array src and stores the results in dst : +\f[\texttt{dst} (I) = \texttt{m} \cdot \texttt{src} (I)\f] +(when m.cols=src.channels() ), or +\f[\texttt{dst} (I) = \texttt{m} \cdot [ \texttt{src} (I); 1]\f] +(when m.cols=src.channels()+1 ) + +Every element of the N -channel array src is interpreted as N -element +vector that is transformed using the M x N or M x (N+1) matrix m to +M-element vector - the corresponding element of the output array dst . + +The function may be used for geometrical transformation of +N -dimensional points, arbitrary linear color space transformation (such +as various kinds of RGB to YUV transforms), shuffling the image +channels, and so forth. +@param src input array that must have as many channels (1 to 4) as +m.cols or m.cols-1. +@param dst output array of the same size and depth as src; it has as +many channels as m.rows. +@param m transformation 2x2 or 2x3 floating-point matrix. +@sa perspectiveTransform, getAffineTransform, estimateRigidTransform, warpAffine, warpPerspective +*/ +CV_EXPORTS_W void transform(InputArray src, OutputArray dst, InputArray m ); + +/** @brief Performs the perspective matrix transformation of vectors. + +The function perspectiveTransform transforms every element of src by +treating it as a 2D or 3D vector, in the following way: +\f[(x, y, z) \rightarrow (x'/w, y'/w, z'/w)\f] +where +\f[(x', y', z', w') = \texttt{mat} \cdot \begin{bmatrix} x & y & z & 1 \end{bmatrix}\f] +and +\f[w = \fork{w'}{if \(w' \ne 0\)}{\infty}{otherwise}\f] + +Here a 3D vector transformation is shown. In case of a 2D vector +transformation, the z component is omitted. + +@note The function transforms a sparse set of 2D or 3D vectors. If you +want to transform an image using perspective transformation, use +warpPerspective . If you have an inverse problem, that is, you want to +compute the most probable perspective transformation out of several +pairs of corresponding points, you can use getPerspectiveTransform or +findHomography . +@param src input two-channel or three-channel floating-point array; each +element is a 2D/3D vector to be transformed. +@param dst output array of the same size and type as src. +@param m 3x3 or 4x4 floating-point transformation matrix. +@sa transform, warpPerspective, getPerspectiveTransform, findHomography +*/ +CV_EXPORTS_W void perspectiveTransform(InputArray src, OutputArray dst, InputArray m ); + +/** @brief Copies the lower or the upper half of a square matrix to another half. + +The function completeSymm copies the lower half of a square matrix to +its another half. The matrix diagonal remains unchanged: +* \f$\texttt{mtx}_{ij}=\texttt{mtx}_{ji}\f$ for \f$i > j\f$ if + lowerToUpper=false +* \f$\texttt{mtx}_{ij}=\texttt{mtx}_{ji}\f$ for \f$i < j\f$ if + lowerToUpper=true +@param mtx input-output floating-point square matrix. +@param lowerToUpper operation flag; if true, the lower half is copied to +the upper half. Otherwise, the upper half is copied to the lower half. +@sa flip, transpose +*/ +CV_EXPORTS_W void completeSymm(InputOutputArray mtx, bool lowerToUpper = false); + +/** @brief Initializes a scaled identity matrix. + +The function setIdentity initializes a scaled identity matrix: +\f[\texttt{mtx} (i,j)= \fork{\texttt{value}}{ if \(i=j\)}{0}{otherwise}\f] + +The function can also be emulated using the matrix initializers and the +matrix expressions: +@code + Mat A = Mat::eye(4, 3, CV_32F)*5; + // A will be set to [[5, 0, 0], [0, 5, 0], [0, 0, 5], [0, 0, 0]] +@endcode +@param mtx matrix to initialize (not necessarily square). +@param s value to assign to diagonal elements. +@sa Mat::zeros, Mat::ones, Mat::setTo, Mat::operator= +*/ +CV_EXPORTS_W void setIdentity(InputOutputArray mtx, const Scalar& s = Scalar(1)); + +/** @brief Returns the determinant of a square floating-point matrix. + +The function determinant calculates and returns the determinant of the +specified matrix. For small matrices ( mtx.cols=mtx.rows\<=3 ), the +direct method is used. For larger matrices, the function uses LU +factorization with partial pivoting. + +For symmetric positively-determined matrices, it is also possible to use +eigen decomposition to calculate the determinant. +@param mtx input matrix that must have CV_32FC1 or CV_64FC1 type and +square size. +@sa trace, invert, solve, eigen, @ref MatrixExpressions +*/ +CV_EXPORTS_W double determinant(InputArray mtx); + +/** @brief Returns the trace of a matrix. + +The function trace returns the sum of the diagonal elements of the +matrix mtx . +\f[\mathrm{tr} ( \texttt{mtx} ) = \sum _i \texttt{mtx} (i,i)\f] +@param mtx input matrix. +*/ +CV_EXPORTS_W Scalar trace(InputArray mtx); + +/** @brief Finds the inverse or pseudo-inverse of a matrix. + +The function invert inverts the matrix src and stores the result in dst +. When the matrix src is singular or non-square, the function calculates +the pseudo-inverse matrix (the dst matrix) so that norm(src\*dst - I) is +minimal, where I is an identity matrix. + +In case of the DECOMP_LU method, the function returns non-zero value if +the inverse has been successfully calculated and 0 if src is singular. + +In case of the DECOMP_SVD method, the function returns the inverse +condition number of src (the ratio of the smallest singular value to the +largest singular value) and 0 if src is singular. The SVD method +calculates a pseudo-inverse matrix if src is singular. + +Similarly to DECOMP_LU, the method DECOMP_CHOLESKY works only with +non-singular square matrices that should also be symmetrical and +positively defined. In this case, the function stores the inverted +matrix in dst and returns non-zero. Otherwise, it returns 0. + +@param src input floating-point M x N matrix. +@param dst output matrix of N x M size and the same type as src. +@param flags inversion method (cv::DecompTypes) +@sa solve, SVD +*/ +CV_EXPORTS_W double invert(InputArray src, OutputArray dst, int flags = DECOMP_LU); + +/** @brief Solves one or more linear systems or least-squares problems. + +The function solve solves a linear system or least-squares problem (the +latter is possible with SVD or QR methods, or by specifying the flag +DECOMP_NORMAL ): +\f[\texttt{dst} = \arg \min _X \| \texttt{src1} \cdot \texttt{X} - \texttt{src2} \|\f] + +If DECOMP_LU or DECOMP_CHOLESKY method is used, the function returns 1 +if src1 (or \f$\texttt{src1}^T\texttt{src1}\f$ ) is non-singular. Otherwise, +it returns 0. In the latter case, dst is not valid. Other methods find a +pseudo-solution in case of a singular left-hand side part. + +@note If you want to find a unity-norm solution of an under-defined +singular system \f$\texttt{src1}\cdot\texttt{dst}=0\f$ , the function solve +will not do the work. Use SVD::solveZ instead. + +@param src1 input matrix on the left-hand side of the system. +@param src2 input matrix on the right-hand side of the system. +@param dst output solution. +@param flags solution (matrix inversion) method (cv::DecompTypes) +@sa invert, SVD, eigen +*/ +CV_EXPORTS_W bool solve(InputArray src1, InputArray src2, + OutputArray dst, int flags = DECOMP_LU); + +/** @brief Sorts each row or each column of a matrix. + +The function sort sorts each matrix row or each matrix column in +ascending or descending order. So you should pass two operation flags to +get desired behaviour. If you want to sort matrix rows or columns +lexicographically, you can use STL std::sort generic function with the +proper comparison predicate. + +@param src input single-channel array. +@param dst output array of the same size and type as src. +@param flags operation flags, a combination of cv::SortFlags +@sa sortIdx, randShuffle +*/ +CV_EXPORTS_W void sort(InputArray src, OutputArray dst, int flags); + +/** @brief Sorts each row or each column of a matrix. + +The function sortIdx sorts each matrix row or each matrix column in the +ascending or descending order. So you should pass two operation flags to +get desired behaviour. Instead of reordering the elements themselves, it +stores the indices of sorted elements in the output array. For example: +@code + Mat A = Mat::eye(3,3,CV_32F), B; + sortIdx(A, B, SORT_EVERY_ROW + SORT_ASCENDING); + // B will probably contain + // (because of equal elements in A some permutations are possible): + // [[1, 2, 0], [0, 2, 1], [0, 1, 2]] +@endcode +@param src input single-channel array. +@param dst output integer array of the same size as src. +@param flags operation flags that could be a combination of cv::SortFlags +@sa sort, randShuffle +*/ +CV_EXPORTS_W void sortIdx(InputArray src, OutputArray dst, int flags); + +/** @brief Finds the real roots of a cubic equation. + +The function solveCubic finds the real roots of a cubic equation: +- if coeffs is a 4-element vector: +\f[\texttt{coeffs} [0] x^3 + \texttt{coeffs} [1] x^2 + \texttt{coeffs} [2] x + \texttt{coeffs} [3] = 0\f] +- if coeffs is a 3-element vector: +\f[x^3 + \texttt{coeffs} [0] x^2 + \texttt{coeffs} [1] x + \texttt{coeffs} [2] = 0\f] + +The roots are stored in the roots array. +@param coeffs equation coefficients, an array of 3 or 4 elements. +@param roots output array of real roots that has 1 or 3 elements. +*/ +CV_EXPORTS_W int solveCubic(InputArray coeffs, OutputArray roots); + +/** @brief Finds the real or complex roots of a polynomial equation. + +The function solvePoly finds real and complex roots of a polynomial equation: +\f[\texttt{coeffs} [n] x^{n} + \texttt{coeffs} [n-1] x^{n-1} + ... + \texttt{coeffs} [1] x + \texttt{coeffs} [0] = 0\f] +@param coeffs array of polynomial coefficients. +@param roots output (complex) array of roots. +@param maxIters maximum number of iterations the algorithm does. +*/ +CV_EXPORTS_W double solvePoly(InputArray coeffs, OutputArray roots, int maxIters = 300); + +/** @brief Calculates eigenvalues and eigenvectors of a symmetric matrix. + +The functions eigen calculate just eigenvalues, or eigenvalues and eigenvectors of the symmetric +matrix src: +@code + src*eigenvectors.row(i).t() = eigenvalues.at(i)*eigenvectors.row(i).t() +@endcode +@note in the new and the old interfaces different ordering of eigenvalues and eigenvectors +parameters is used. +@param src input matrix that must have CV_32FC1 or CV_64FC1 type, square size and be symmetrical +(src ^T^ == src). +@param eigenvalues output vector of eigenvalues of the same type as src; the eigenvalues are stored +in the descending order. +@param eigenvectors output matrix of eigenvectors; it has the same size and type as src; the +eigenvectors are stored as subsequent matrix rows, in the same order as the corresponding +eigenvalues. +@sa completeSymm , PCA +*/ +CV_EXPORTS_W bool eigen(InputArray src, OutputArray eigenvalues, + OutputArray eigenvectors = noArray()); + +/** @brief Calculates the covariance matrix of a set of vectors. + +The functions calcCovarMatrix calculate the covariance matrix and, optionally, the mean vector of +the set of input vectors. +@param samples samples stored as separate matrices +@param nsamples number of samples +@param covar output covariance matrix of the type ctype and square size. +@param mean input or output (depending on the flags) array as the average value of the input vectors. +@param flags operation flags as a combination of cv::CovarFlags +@param ctype type of the matrixl; it equals 'CV_64F' by default. +@sa PCA, mulTransposed, Mahalanobis +@todo InputArrayOfArrays +*/ +CV_EXPORTS void calcCovarMatrix( const Mat* samples, int nsamples, Mat& covar, Mat& mean, + int flags, int ctype = CV_64F); + +/** @overload +@note use cv::COVAR_ROWS or cv::COVAR_COLS flag +@param samples samples stored as rows/columns of a single matrix. +@param covar output covariance matrix of the type ctype and square size. +@param mean input or output (depending on the flags) array as the average value of the input vectors. +@param flags operation flags as a combination of cv::CovarFlags +@param ctype type of the matrixl; it equals 'CV_64F' by default. +*/ +CV_EXPORTS_W void calcCovarMatrix( InputArray samples, OutputArray covar, + InputOutputArray mean, int flags, int ctype = CV_64F); + +/** wrap PCA::operator() */ +CV_EXPORTS_W void PCACompute(InputArray data, InputOutputArray mean, + OutputArray eigenvectors, int maxComponents = 0); + +/** wrap PCA::operator() */ +CV_EXPORTS_W void PCACompute(InputArray data, InputOutputArray mean, + OutputArray eigenvectors, double retainedVariance); + +/** wrap PCA::project */ +CV_EXPORTS_W void PCAProject(InputArray data, InputArray mean, + InputArray eigenvectors, OutputArray result); + +/** wrap PCA::backProject */ +CV_EXPORTS_W void PCABackProject(InputArray data, InputArray mean, + InputArray eigenvectors, OutputArray result); + +/** wrap SVD::compute */ +CV_EXPORTS_W void SVDecomp( InputArray src, OutputArray w, OutputArray u, OutputArray vt, int flags = 0 ); + +/** wrap SVD::backSubst */ +CV_EXPORTS_W void SVBackSubst( InputArray w, InputArray u, InputArray vt, + InputArray rhs, OutputArray dst ); + +/** @brief Calculates the Mahalanobis distance between two vectors. + +The function Mahalanobis calculates and returns the weighted distance between two vectors: +\f[d( \texttt{vec1} , \texttt{vec2} )= \sqrt{\sum_{i,j}{\texttt{icovar(i,j)}\cdot(\texttt{vec1}(I)-\texttt{vec2}(I))\cdot(\texttt{vec1(j)}-\texttt{vec2(j)})} }\f] +The covariance matrix may be calculated using the cv::calcCovarMatrix function and then inverted using +the invert function (preferably using the cv::DECOMP_SVD method, as the most accurate). +@param v1 first 1D input vector. +@param v2 second 1D input vector. +@param icovar inverse covariance matrix. +*/ +CV_EXPORTS_W double Mahalanobis(InputArray v1, InputArray v2, InputArray icovar); + +/** @brief Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating-point array. + +The function performs one of the following: +- Forward the Fourier transform of a 1D vector of N elements: + \f[Y = F^{(N)} \cdot X,\f] + where \f$F^{(N)}_{jk}=\exp(-2\pi i j k/N)\f$ and \f$i=\sqrt{-1}\f$ +- Inverse the Fourier transform of a 1D vector of N elements: + \f[\begin{array}{l} X'= \left (F^{(N)} \right )^{-1} \cdot Y = \left (F^{(N)} \right )^* \cdot y \\ X = (1/N) \cdot X, \end{array}\f] + where \f$F^*=\left(\textrm{Re}(F^{(N)})-\textrm{Im}(F^{(N)})\right)^T\f$ +- Forward the 2D Fourier transform of a M x N matrix: + \f[Y = F^{(M)} \cdot X \cdot F^{(N)}\f] +- Inverse the 2D Fourier transform of a M x N matrix: + \f[\begin{array}{l} X'= \left (F^{(M)} \right )^* \cdot Y \cdot \left (F^{(N)} \right )^* \\ X = \frac{1}{M \cdot N} \cdot X' \end{array}\f] + +In case of real (single-channel) data, the output spectrum of the forward Fourier transform or input +spectrum of the inverse Fourier transform can be represented in a packed format called *CCS* +(complex-conjugate-symmetrical). It was borrowed from IPL (Intel\* Image Processing Library). Here +is how 2D *CCS* spectrum looks: +\f[\begin{bmatrix} Re Y_{0,0} & Re Y_{0,1} & Im Y_{0,1} & Re Y_{0,2} & Im Y_{0,2} & \cdots & Re Y_{0,N/2-1} & Im Y_{0,N/2-1} & Re Y_{0,N/2} \\ Re Y_{1,0} & Re Y_{1,1} & Im Y_{1,1} & Re Y_{1,2} & Im Y_{1,2} & \cdots & Re Y_{1,N/2-1} & Im Y_{1,N/2-1} & Re Y_{1,N/2} \\ Im Y_{1,0} & Re Y_{2,1} & Im Y_{2,1} & Re Y_{2,2} & Im Y_{2,2} & \cdots & Re Y_{2,N/2-1} & Im Y_{2,N/2-1} & Im Y_{1,N/2} \\ \hdotsfor{9} \\ Re Y_{M/2-1,0} & Re Y_{M-3,1} & Im Y_{M-3,1} & \hdotsfor{3} & Re Y_{M-3,N/2-1} & Im Y_{M-3,N/2-1}& Re Y_{M/2-1,N/2} \\ Im Y_{M/2-1,0} & Re Y_{M-2,1} & Im Y_{M-2,1} & \hdotsfor{3} & Re Y_{M-2,N/2-1} & Im Y_{M-2,N/2-1}& Im Y_{M/2-1,N/2} \\ Re Y_{M/2,0} & Re Y_{M-1,1} & Im Y_{M-1,1} & \hdotsfor{3} & Re Y_{M-1,N/2-1} & Im Y_{M-1,N/2-1}& Re Y_{M/2,N/2} \end{bmatrix}\f] + +In case of 1D transform of a real vector, the output looks like the first row of the matrix above. + +So, the function chooses an operation mode depending on the flags and size of the input array: +- If DFT_ROWS is set or the input array has a single row or single column, the function + performs a 1D forward or inverse transform of each row of a matrix when DFT_ROWS is set. + Otherwise, it performs a 2D transform. +- If the input array is real and DFT_INVERSE is not set, the function performs a forward 1D or + 2D transform: + - When DFT_COMPLEX_OUTPUT is set, the output is a complex matrix of the same size as + input. + - When DFT_COMPLEX_OUTPUT is not set, the output is a real matrix of the same size as + input. In case of 2D transform, it uses the packed format as shown above. In case of a + single 1D transform, it looks like the first row of the matrix above. In case of + multiple 1D transforms (when using the DFT_ROWS flag), each row of the output matrix + looks like the first row of the matrix above. +- If the input array is complex and either DFT_INVERSE or DFT_REAL_OUTPUT are not set, the + output is a complex array of the same size as input. The function performs a forward or + inverse 1D or 2D transform of the whole input array or each row of the input array + independently, depending on the flags DFT_INVERSE and DFT_ROWS. +- When DFT_INVERSE is set and the input array is real, or it is complex but DFT_REAL_OUTPUT + is set, the output is a real array of the same size as input. The function performs a 1D or 2D + inverse transformation of the whole input array or each individual row, depending on the flags + DFT_INVERSE and DFT_ROWS. + +If DFT_SCALE is set, the scaling is done after the transformation. + +Unlike dct , the function supports arrays of arbitrary size. But only those arrays are processed +efficiently, whose sizes can be factorized in a product of small prime numbers (2, 3, and 5 in the +current implementation). Such an efficient DFT size can be calculated using the getOptimalDFTSize +method. + +The sample below illustrates how to calculate a DFT-based convolution of two 2D real arrays: +@code + void convolveDFT(InputArray A, InputArray B, OutputArray C) + { + // reallocate the output array if needed + C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type()); + Size dftSize; + // calculate the size of DFT transform + dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1); + dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1); + + // allocate temporary buffers and initialize them with 0's + Mat tempA(dftSize, A.type(), Scalar::all(0)); + Mat tempB(dftSize, B.type(), Scalar::all(0)); + + // copy A and B to the top-left corners of tempA and tempB, respectively + Mat roiA(tempA, Rect(0,0,A.cols,A.rows)); + A.copyTo(roiA); + Mat roiB(tempB, Rect(0,0,B.cols,B.rows)); + B.copyTo(roiB); + + // now transform the padded A & B in-place; + // use "nonzeroRows" hint for faster processing + dft(tempA, tempA, 0, A.rows); + dft(tempB, tempB, 0, B.rows); + + // multiply the spectrums; + // the function handles packed spectrum representations well + mulSpectrums(tempA, tempB, tempA); + + // transform the product back from the frequency domain. + // Even though all the result rows will be non-zero, + // you need only the first C.rows of them, and thus you + // pass nonzeroRows == C.rows + dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, C.rows); + + // now copy the result back to C. + tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C); + + // all the temporary buffers will be deallocated automatically + } +@endcode +To optimize this sample, consider the following approaches: +- Since nonzeroRows != 0 is passed to the forward transform calls and since A and B are copied to + the top-left corners of tempA and tempB, respectively, it is not necessary to clear the whole + tempA and tempB. It is only necessary to clear the tempA.cols - A.cols ( tempB.cols - B.cols) + rightmost columns of the matrices. +- This DFT-based convolution does not have to be applied to the whole big arrays, especially if B + is significantly smaller than A or vice versa. Instead, you can calculate convolution by parts. + To do this, you need to split the output array C into multiple tiles. For each tile, estimate + which parts of A and B are required to calculate convolution in this tile. If the tiles in C are + too small, the speed will decrease a lot because of repeated work. In the ultimate case, when + each tile in C is a single pixel, the algorithm becomes equivalent to the naive convolution + algorithm. If the tiles are too big, the temporary arrays tempA and tempB become too big and + there is also a slowdown because of bad cache locality. So, there is an optimal tile size + somewhere in the middle. +- If different tiles in C can be calculated in parallel and, thus, the convolution is done by + parts, the loop can be threaded. + +All of the above improvements have been implemented in matchTemplate and filter2D . Therefore, by +using them, you can get the performance even better than with the above theoretically optimal +implementation. Though, those two functions actually calculate cross-correlation, not convolution, +so you need to "flip" the second convolution operand B vertically and horizontally using flip . +@note +- An example using the discrete fourier transform can be found at + opencv_source_code/samples/cpp/dft.cpp +- (Python) An example using the dft functionality to perform Wiener deconvolution can be found + at opencv_source/samples/python2/deconvolution.py +- (Python) An example rearranging the quadrants of a Fourier image can be found at + opencv_source/samples/python2/dft.py +@param src input array that could be real or complex. +@param dst output array whose size and type depends on the flags . +@param flags transformation flags, representing a combination of the cv::DftFlags +@param nonzeroRows when the parameter is not zero, the function assumes that only the first +nonzeroRows rows of the input array (DFT_INVERSE is not set) or only the first nonzeroRows of the +output array (DFT_INVERSE is set) contain non-zeros, thus, the function can handle the rest of the +rows more efficiently and save some time; this technique is very useful for calculating array +cross-correlation or convolution using DFT. +@sa dct , getOptimalDFTSize , mulSpectrums, filter2D , matchTemplate , flip , cartToPolar , +magnitude , phase +*/ +CV_EXPORTS_W void dft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0); + +/** @brief Calculates the inverse Discrete Fourier Transform of a 1D or 2D array. + +idft(src, dst, flags) is equivalent to dft(src, dst, flags | DFT_INVERSE) . +@note None of dft and idft scales the result by default. So, you should pass DFT_SCALE to one of +dft or idft explicitly to make these transforms mutually inverse. +@sa dft, dct, idct, mulSpectrums, getOptimalDFTSize +@param src input floating-point real or complex array. +@param dst output array whose size and type depend on the flags. +@param flags operation flags (see dft and cv::DftFlags). +@param nonzeroRows number of dst rows to process; the rest of the rows have undefined content (see +the convolution sample in dft description. +*/ +CV_EXPORTS_W void idft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0); + +/** @brief Performs a forward or inverse discrete Cosine transform of 1D or 2D array. + +The function dct performs a forward or inverse discrete Cosine transform (DCT) of a 1D or 2D +floating-point array: +- Forward Cosine transform of a 1D vector of N elements: + \f[Y = C^{(N)} \cdot X\f] + where + \f[C^{(N)}_{jk}= \sqrt{\alpha_j/N} \cos \left ( \frac{\pi(2k+1)j}{2N} \right )\f] + and + \f$\alpha_0=1\f$, \f$\alpha_j=2\f$ for *j \> 0*. +- Inverse Cosine transform of a 1D vector of N elements: + \f[X = \left (C^{(N)} \right )^{-1} \cdot Y = \left (C^{(N)} \right )^T \cdot Y\f] + (since \f$C^{(N)}\f$ is an orthogonal matrix, \f$C^{(N)} \cdot \left(C^{(N)}\right)^T = I\f$ ) +- Forward 2D Cosine transform of M x N matrix: + \f[Y = C^{(N)} \cdot X \cdot \left (C^{(N)} \right )^T\f] +- Inverse 2D Cosine transform of M x N matrix: + \f[X = \left (C^{(N)} \right )^T \cdot X \cdot C^{(N)}\f] + +The function chooses the mode of operation by looking at the flags and size of the input array: +- If (flags & DCT_INVERSE) == 0 , the function does a forward 1D or 2D transform. Otherwise, it + is an inverse 1D or 2D transform. +- If (flags & DCT_ROWS) != 0 , the function performs a 1D transform of each row. +- If the array is a single column or a single row, the function performs a 1D transform. +- If none of the above is true, the function performs a 2D transform. + +@note Currently dct supports even-size arrays (2, 4, 6 ...). For data analysis and approximation, you +can pad the array when necessary. +Also, the function performance depends very much, and not monotonically, on the array size (see +getOptimalDFTSize ). In the current implementation DCT of a vector of size N is calculated via DFT +of a vector of size N/2 . Thus, the optimal DCT size N1 \>= N can be calculated as: +@code + size_t getOptimalDCTSize(size_t N) { return 2*getOptimalDFTSize((N+1)/2); } + N1 = getOptimalDCTSize(N); +@endcode +@param src input floating-point array. +@param dst output array of the same size and type as src . +@param flags transformation flags as a combination of cv::DftFlags (DCT_*) +@sa dft , getOptimalDFTSize , idct +*/ +CV_EXPORTS_W void dct(InputArray src, OutputArray dst, int flags = 0); + +/** @brief Calculates the inverse Discrete Cosine Transform of a 1D or 2D array. + +idct(src, dst, flags) is equivalent to dct(src, dst, flags | DCT_INVERSE). +@param src input floating-point single-channel array. +@param dst output array of the same size and type as src. +@param flags operation flags. +@sa dct, dft, idft, getOptimalDFTSize +*/ +CV_EXPORTS_W void idct(InputArray src, OutputArray dst, int flags = 0); + +/** @brief Performs the per-element multiplication of two Fourier spectrums. + +The function mulSpectrums performs the per-element multiplication of the two CCS-packed or complex +matrices that are results of a real or complex Fourier transform. + +The function, together with dft and idft , may be used to calculate convolution (pass conjB=false ) +or correlation (pass conjB=true ) of two arrays rapidly. When the arrays are complex, they are +simply multiplied (per element) with an optional conjugation of the second-array elements. When the +arrays are real, they are assumed to be CCS-packed (see dft for details). +@param a first input array. +@param b second input array of the same size and type as src1 . +@param c output array of the same size and type as src1 . +@param flags operation flags; currently, the only supported flag is cv::DFT_ROWS, which indicates that +each row of src1 and src2 is an independent 1D Fourier spectrum. If you do not want to use this flag, then simply add a `0` as value. +@param conjB optional flag that conjugates the second input array before the multiplication (true) +or not (false). +*/ +CV_EXPORTS_W void mulSpectrums(InputArray a, InputArray b, OutputArray c, + int flags, bool conjB = false); + +/** @brief Returns the optimal DFT size for a given vector size. + +DFT performance is not a monotonic function of a vector size. Therefore, when you calculate +convolution of two arrays or perform the spectral analysis of an array, it usually makes sense to +pad the input data with zeros to get a bit larger array that can be transformed much faster than the +original one. Arrays whose size is a power-of-two (2, 4, 8, 16, 32, ...) are the fastest to process. +Though, the arrays whose size is a product of 2's, 3's, and 5's (for example, 300 = 5\*5\*3\*2\*2) +are also processed quite efficiently. + +The function getOptimalDFTSize returns the minimum number N that is greater than or equal to vecsize +so that the DFT of a vector of size N can be processed efficiently. In the current implementation N += 2 ^p^ \* 3 ^q^ \* 5 ^r^ for some integer p, q, r. + +The function returns a negative number if vecsize is too large (very close to INT_MAX ). + +While the function cannot be used directly to estimate the optimal vector size for DCT transform +(since the current DCT implementation supports only even-size vectors), it can be easily processed +as getOptimalDFTSize((vecsize+1)/2)\*2. +@param vecsize vector size. +@sa dft , dct , idft , idct , mulSpectrums +*/ +CV_EXPORTS_W int getOptimalDFTSize(int vecsize); + +/** @brief Returns the default random number generator. + +The function theRNG returns the default random number generator. For each thread, there is a +separate random number generator, so you can use the function safely in multi-thread environments. +If you just need to get a single random number using this generator or initialize an array, you can +use randu or randn instead. But if you are going to generate many random numbers inside a loop, it +is much faster to use this function to retrieve the generator and then use RNG::operator _Tp() . +@sa RNG, randu, randn +*/ +CV_EXPORTS RNG& theRNG(); + +/** @brief Generates a single uniformly-distributed random number or an array of random numbers. + +Non-template variant of the function fills the matrix dst with uniformly-distributed +random numbers from the specified range: +\f[\texttt{low} _c \leq \texttt{dst} (I)_c < \texttt{high} _c\f] +@param dst output array of random numbers; the array must be pre-allocated. +@param low inclusive lower boundary of the generated random numbers. +@param high exclusive upper boundary of the generated random numbers. +@sa RNG, randn, theRNG +*/ +CV_EXPORTS_W void randu(InputOutputArray dst, InputArray low, InputArray high); + +/** @brief Fills the array with normally distributed random numbers. + +The function randn fills the matrix dst with normally distributed random numbers with the specified +mean vector and the standard deviation matrix. The generated random numbers are clipped to fit the +value range of the output array data type. +@param dst output array of random numbers; the array must be pre-allocated and have 1 to 4 channels. +@param mean mean value (expectation) of the generated random numbers. +@param stddev standard deviation of the generated random numbers; it can be either a vector (in +which case a diagonal standard deviation matrix is assumed) or a square matrix. +@sa RNG, randu +*/ +CV_EXPORTS_W void randn(InputOutputArray dst, InputArray mean, InputArray stddev); + +/** @brief Shuffles the array elements randomly. + +The function randShuffle shuffles the specified 1D array by randomly choosing pairs of elements and +swapping them. The number of such swap operations will be dst.rows\*dst.cols\*iterFactor . +@param dst input/output numerical 1D array. +@param iterFactor scale factor that determines the number of random swap operations (see the details +below). +@param rng optional random number generator used for shuffling; if it is zero, theRNG () is used +instead. +@sa RNG, sort +*/ +CV_EXPORTS_W void randShuffle(InputOutputArray dst, double iterFactor = 1., RNG* rng = 0); + +/** @brief Principal Component Analysis + +The class is used to calculate a special basis for a set of vectors. The +basis will consist of eigenvectors of the covariance matrix calculated +from the input set of vectors. The class %PCA can also transform +vectors to/from the new coordinate space defined by the basis. Usually, +in this new coordinate system, each vector from the original set (and +any linear combination of such vectors) can be quite accurately +approximated by taking its first few components, corresponding to the +eigenvectors of the largest eigenvalues of the covariance matrix. +Geometrically it means that you calculate a projection of the vector to +a subspace formed by a few eigenvectors corresponding to the dominant +eigenvalues of the covariance matrix. And usually such a projection is +very close to the original vector. So, you can represent the original +vector from a high-dimensional space with a much shorter vector +consisting of the projected vector's coordinates in the subspace. Such a +transformation is also known as Karhunen-Loeve Transform, or KLT. +See http://en.wikipedia.org/wiki/Principal_component_analysis + +The sample below is the function that takes two matrices. The first +function stores a set of vectors (a row per vector) that is used to +calculate PCA. The second function stores another "test" set of vectors +(a row per vector). First, these vectors are compressed with PCA, then +reconstructed back, and then the reconstruction error norm is computed +and printed for each vector. : + +@code{.cpp} +using namespace cv; + +PCA compressPCA(const Mat& pcaset, int maxComponents, + const Mat& testset, Mat& compressed) +{ + PCA pca(pcaset, // pass the data + Mat(), // we do not have a pre-computed mean vector, + // so let the PCA engine to compute it + PCA::DATA_AS_ROW, // indicate that the vectors + // are stored as matrix rows + // (use PCA::DATA_AS_COL if the vectors are + // the matrix columns) + maxComponents // specify, how many principal components to retain + ); + // if there is no test data, just return the computed basis, ready-to-use + if( !testset.data ) + return pca; + CV_Assert( testset.cols == pcaset.cols ); + + compressed.create(testset.rows, maxComponents, testset.type()); + + Mat reconstructed; + for( int i = 0; i < testset.rows; i++ ) + { + Mat vec = testset.row(i), coeffs = compressed.row(i), reconstructed; + // compress the vector, the result will be stored + // in the i-th row of the output matrix + pca.project(vec, coeffs); + // and then reconstruct it + pca.backProject(coeffs, reconstructed); + // and measure the error + printf("%d. diff = %g\n", i, norm(vec, reconstructed, NORM_L2)); + } + return pca; +} +@endcode +@sa calcCovarMatrix, mulTransposed, SVD, dft, dct +*/ +class CV_EXPORTS PCA +{ +public: + enum Flags { DATA_AS_ROW = 0, //!< indicates that the input samples are stored as matrix rows + DATA_AS_COL = 1, //!< indicates that the input samples are stored as matrix columns + USE_AVG = 2 //! + }; + + /** @brief default constructor + + The default constructor initializes an empty %PCA structure. The other + constructors initialize the structure and call PCA::operator()(). + */ + PCA(); + + /** @overload + @param data input samples stored as matrix rows or matrix columns. + @param mean optional mean value; if the matrix is empty (@c noArray()), + the mean is computed from the data. + @param flags operation flags; currently the parameter is only used to + specify the data layout (PCA::Flags) + @param maxComponents maximum number of components that %PCA should + retain; by default, all the components are retained. + */ + PCA(InputArray data, InputArray mean, int flags, int maxComponents = 0); + + /** @overload + @param data input samples stored as matrix rows or matrix columns. + @param mean optional mean value; if the matrix is empty (noArray()), + the mean is computed from the data. + @param flags operation flags; currently the parameter is only used to + specify the data layout (PCA::Flags) + @param retainedVariance Percentage of variance that PCA should retain. + Using this parameter will let the PCA decided how many components to + retain but it will always keep at least 2. + */ + PCA(InputArray data, InputArray mean, int flags, double retainedVariance); + + /** @brief performs %PCA + + The operator performs %PCA of the supplied dataset. It is safe to reuse + the same PCA structure for multiple datasets. That is, if the structure + has been previously used with another dataset, the existing internal + data is reclaimed and the new eigenvalues, @ref eigenvectors , and @ref + mean are allocated and computed. + + The computed eigenvalues are sorted from the largest to the smallest and + the corresponding eigenvectors are stored as eigenvectors rows. + + @param data input samples stored as the matrix rows or as the matrix + columns. + @param mean optional mean value; if the matrix is empty (noArray()), + the mean is computed from the data. + @param flags operation flags; currently the parameter is only used to + specify the data layout. (Flags) + @param maxComponents maximum number of components that PCA should + retain; by default, all the components are retained. + */ + PCA& operator()(InputArray data, InputArray mean, int flags, int maxComponents = 0); + + /** @overload + @param data input samples stored as the matrix rows or as the matrix + columns. + @param mean optional mean value; if the matrix is empty (noArray()), + the mean is computed from the data. + @param flags operation flags; currently the parameter is only used to + specify the data layout. (PCA::Flags) + @param retainedVariance Percentage of variance that %PCA should retain. + Using this parameter will let the %PCA decided how many components to + retain but it will always keep at least 2. + */ + PCA& operator()(InputArray data, InputArray mean, int flags, double retainedVariance); + + /** @brief Projects vector(s) to the principal component subspace. + + The methods project one or more vectors to the principal component + subspace, where each vector projection is represented by coefficients in + the principal component basis. The first form of the method returns the + matrix that the second form writes to the result. So the first form can + be used as a part of expression while the second form can be more + efficient in a processing loop. + @param vec input vector(s); must have the same dimensionality and the + same layout as the input data used at %PCA phase, that is, if + DATA_AS_ROW are specified, then `vec.cols==data.cols` + (vector dimensionality) and `vec.rows` is the number of vectors to + project, and the same is true for the PCA::DATA_AS_COL case. + */ + Mat project(InputArray vec) const; + + /** @overload + @param vec input vector(s); must have the same dimensionality and the + same layout as the input data used at PCA phase, that is, if + DATA_AS_ROW are specified, then `vec.cols==data.cols` + (vector dimensionality) and `vec.rows` is the number of vectors to + project, and the same is true for the PCA::DATA_AS_COL case. + @param result output vectors; in case of PCA::DATA_AS_COL, the + output matrix has as many columns as the number of input vectors, this + means that `result.cols==vec.cols` and the number of rows match the + number of principal components (for example, `maxComponents` parameter + passed to the constructor). + */ + void project(InputArray vec, OutputArray result) const; + + /** @brief Reconstructs vectors from their PC projections. + + The methods are inverse operations to PCA::project. They take PC + coordinates of projected vectors and reconstruct the original vectors. + Unless all the principal components have been retained, the + reconstructed vectors are different from the originals. But typically, + the difference is small if the number of components is large enough (but + still much smaller than the original vector dimensionality). As a + result, PCA is used. + @param vec coordinates of the vectors in the principal component + subspace, the layout and size are the same as of PCA::project output + vectors. + */ + Mat backProject(InputArray vec) const; + + /** @overload + @param vec coordinates of the vectors in the principal component + subspace, the layout and size are the same as of PCA::project output + vectors. + @param result reconstructed vectors; the layout and size are the same as + of PCA::project input vectors. + */ + void backProject(InputArray vec, OutputArray result) const; + + /** @brief write and load PCA matrix + +*/ + void write(FileStorage& fs ) const; + void read(const FileNode& fs); + + Mat eigenvectors; //!< eigenvectors of the covariation matrix + Mat eigenvalues; //!< eigenvalues of the covariation matrix + Mat mean; //!< mean value subtracted before the projection and added after the back projection +}; + +/** @example pca.cpp + An example using %PCA for dimensionality reduction while maintaining an amount of variance + */ + +/** + @brief Linear Discriminant Analysis + @todo document this class + */ +class CV_EXPORTS LDA +{ +public: + /** @brief constructor + Initializes a LDA with num_components (default 0) and specifies how + samples are aligned (default dataAsRow=true). + */ + explicit LDA(int num_components = 0); + + /** Initializes and performs a Discriminant Analysis with Fisher's + Optimization Criterion on given data in src and corresponding labels + in labels. If 0 (or less) number of components are given, they are + automatically determined for given data in computation. + */ + LDA(InputArrayOfArrays src, InputArray labels, int num_components = 0); + + /** Serializes this object to a given filename. + */ + void save(const String& filename) const; + + /** Deserializes this object from a given filename. + */ + void load(const String& filename); + + /** Serializes this object to a given cv::FileStorage. + */ + void save(FileStorage& fs) const; + + /** Deserializes this object from a given cv::FileStorage. + */ + void load(const FileStorage& node); + + /** destructor + */ + ~LDA(); + + /** Compute the discriminants for data in src and labels. + */ + void compute(InputArrayOfArrays src, InputArray labels); + + /** Projects samples into the LDA subspace. + */ + Mat project(InputArray src); + + /** Reconstructs projections from the LDA subspace. + */ + Mat reconstruct(InputArray src); + + /** Returns the eigenvectors of this LDA. + */ + Mat eigenvectors() const { return _eigenvectors; } + + /** Returns the eigenvalues of this LDA. + */ + Mat eigenvalues() const { return _eigenvalues; } + + static Mat subspaceProject(InputArray W, InputArray mean, InputArray src); + static Mat subspaceReconstruct(InputArray W, InputArray mean, InputArray src); + +protected: + bool _dataAsRow; + int _num_components; + Mat _eigenvectors; + Mat _eigenvalues; + + void lda(InputArrayOfArrays src, InputArray labels); +}; + +/** @brief Singular Value Decomposition + +Class for computing Singular Value Decomposition of a floating-point +matrix. The Singular Value Decomposition is used to solve least-square +problems, under-determined linear systems, invert matrices, compute +condition numbers, and so on. + +If you want to compute a condition number of a matrix or an absolute value of +its determinant, you do not need `u` and `vt`. You can pass +flags=SVD::NO_UV|... . Another flag SVD::FULL_UV indicates that full-size u +and vt must be computed, which is not necessary most of the time. + +@sa invert, solve, eigen, determinant +*/ +class CV_EXPORTS SVD +{ +public: + enum Flags { + /** allow the algorithm to modify the decomposed matrix; it can save space and speed up + processing. currently ignored. */ + MODIFY_A = 1, + /** indicates that only a vector of singular values `w` is to be processed, while u and vt + will be set to empty matrices */ + NO_UV = 2, + /** when the matrix is not square, by default the algorithm produces u and vt matrices of + sufficiently large size for the further A reconstruction; if, however, FULL_UV flag is + specified, u and vt will be full-size square orthogonal matrices.*/ + FULL_UV = 4 + }; + + /** @brief the default constructor + + initializes an empty SVD structure + */ + SVD(); + + /** @overload + initializes an empty SVD structure and then calls SVD::operator() + @param src decomposed matrix. + @param flags operation flags (SVD::Flags) + */ + SVD( InputArray src, int flags = 0 ); + + /** @brief the operator that performs SVD. The previously allocated u, w and vt are released. + + The operator performs the singular value decomposition of the supplied + matrix. The u,`vt` , and the vector of singular values w are stored in + the structure. The same SVD structure can be reused many times with + different matrices. Each time, if needed, the previous u,`vt` , and w + are reclaimed and the new matrices are created, which is all handled by + Mat::create. + @param src decomposed matrix. + @param flags operation flags (SVD::Flags) + */ + SVD& operator ()( InputArray src, int flags = 0 ); + + /** @brief decomposes matrix and stores the results to user-provided matrices + + The methods/functions perform SVD of matrix. Unlike SVD::SVD constructor + and SVD::operator(), they store the results to the user-provided + matrices: + + @code{.cpp} + Mat A, w, u, vt; + SVD::compute(A, w, u, vt); + @endcode + + @param src decomposed matrix + @param w calculated singular values + @param u calculated left singular vectors + @param vt transposed matrix of right singular values + @param flags operation flags - see SVD::SVD. + */ + static void compute( InputArray src, OutputArray w, + OutputArray u, OutputArray vt, int flags = 0 ); + + /** @overload + computes singular values of a matrix + @param src decomposed matrix + @param w calculated singular values + @param flags operation flags - see SVD::Flags. + */ + static void compute( InputArray src, OutputArray w, int flags = 0 ); + + /** @brief performs back substitution + */ + static void backSubst( InputArray w, InputArray u, + InputArray vt, InputArray rhs, + OutputArray dst ); + + /** @brief solves an under-determined singular linear system + + The method finds a unit-length solution x of a singular linear system + A\*x = 0. Depending on the rank of A, there can be no solutions, a + single solution or an infinite number of solutions. In general, the + algorithm solves the following problem: + \f[dst = \arg \min _{x: \| x \| =1} \| src \cdot x \|\f] + @param src left-hand-side matrix. + @param dst found solution. + */ + static void solveZ( InputArray src, OutputArray dst ); + + /** @brief performs a singular value back substitution. + + The method calculates a back substitution for the specified right-hand + side: + + \f[\texttt{x} = \texttt{vt} ^T \cdot diag( \texttt{w} )^{-1} \cdot \texttt{u} ^T \cdot \texttt{rhs} \sim \texttt{A} ^{-1} \cdot \texttt{rhs}\f] + + Using this technique you can either get a very accurate solution of the + convenient linear system, or the best (in the least-squares terms) + pseudo-solution of an overdetermined linear system. + + @param rhs right-hand side of a linear system (u\*w\*v')\*dst = rhs to + be solved, where A has been previously decomposed. + + @param dst found solution of the system. + + @note Explicit SVD with the further back substitution only makes sense + if you need to solve many linear systems with the same left-hand side + (for example, src ). If all you need is to solve a single system + (possibly with multiple rhs immediately available), simply call solve + add pass DECOMP_SVD there. It does absolutely the same thing. + */ + void backSubst( InputArray rhs, OutputArray dst ) const; + + /** @todo document */ + template static + void compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ); + + /** @todo document */ + template static + void compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w ); + + /** @todo document */ + template static + void backSubst( const Matx<_Tp, nm, 1>& w, const Matx<_Tp, m, nm>& u, const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, Matx<_Tp, n, nb>& dst ); + + Mat u, w, vt; +}; + +/** @brief Random Number Generator + +Random number generator. It encapsulates the state (currently, a 64-bit +integer) and has methods to return scalar random values and to fill +arrays with random values. Currently it supports uniform and Gaussian +(normal) distributions. The generator uses Multiply-With-Carry +algorithm, introduced by G. Marsaglia ( + ). +Gaussian-distribution random numbers are generated using the Ziggurat +algorithm ( ), +introduced by G. Marsaglia and W. W. Tsang. +*/ +class CV_EXPORTS RNG +{ +public: + enum { UNIFORM = 0, + NORMAL = 1 + }; + + /** @brief constructor + + These are the RNG constructors. The first form sets the state to some + pre-defined value, equal to 2\*\*32-1 in the current implementation. The + second form sets the state to the specified value. If you passed state=0 + , the constructor uses the above default value instead to avoid the + singular random number sequence, consisting of all zeros. + */ + RNG(); + /** @overload + @param state 64-bit value used to initialize the RNG. + */ + RNG(uint64 state); + /**The method updates the state using the MWC algorithm and returns the + next 32-bit random number.*/ + unsigned next(); + + /**Each of the methods updates the state using the MWC algorithm and + returns the next random number of the specified type. In case of integer + types, the returned number is from the available value range for the + specified type. In case of floating-point types, the returned value is + from [0,1) range. + */ + operator uchar(); + /** @overload */ + operator schar(); + /** @overload */ + operator ushort(); + /** @overload */ + operator short(); + /** @overload */ + operator unsigned(); + /** @overload */ + operator int(); + /** @overload */ + operator float(); + /** @overload */ + operator double(); + + /** @brief returns a random integer sampled uniformly from [0, N). + + The methods transform the state using the MWC algorithm and return the + next random number. The first form is equivalent to RNG::next . The + second form returns the random number modulo N , which means that the + result is in the range [0, N) . + */ + unsigned operator ()(); + /** @overload + @param N upper non-inclusive boundary of the returned random number. + */ + unsigned operator ()(unsigned N); + + /** @brief returns uniformly distributed integer random number from [a,b) range + + The methods transform the state using the MWC algorithm and return the + next uniformly-distributed random number of the specified type, deduced + from the input parameter type, from the range [a, b) . There is a nuance + illustrated by the following sample: + + @code{.cpp} + RNG rng; + + // always produces 0 + double a = rng.uniform(0, 1); + + // produces double from [0, 1) + double a1 = rng.uniform((double)0, (double)1); + + // produces float from [0, 1) + double b = rng.uniform(0.f, 1.f); + + // produces double from [0, 1) + double c = rng.uniform(0., 1.); + + // may cause compiler error because of ambiguity: + // RNG::uniform(0, (int)0.999999)? or RNG::uniform((double)0, 0.99999)? + double d = rng.uniform(0, 0.999999); + @endcode + + The compiler does not take into account the type of the variable to + which you assign the result of RNG::uniform . The only thing that + matters to the compiler is the type of a and b parameters. So, if you + want a floating-point random number, but the range boundaries are + integer numbers, either put dots in the end, if they are constants, or + use explicit type cast operators, as in the a1 initialization above. + @param a lower inclusive boundary of the returned random numbers. + @param b upper non-inclusive boundary of the returned random numbers. + */ + int uniform(int a, int b); + /** @overload */ + float uniform(float a, float b); + /** @overload */ + double uniform(double a, double b); + + /** @brief Fills arrays with random numbers. + + @param mat 2D or N-dimensional matrix; currently matrices with more than + 4 channels are not supported by the methods, use Mat::reshape as a + possible workaround. + @param distType distribution type, RNG::UNIFORM or RNG::NORMAL. + @param a first distribution parameter; in case of the uniform + distribution, this is an inclusive lower boundary, in case of the normal + distribution, this is a mean value. + @param b second distribution parameter; in case of the uniform + distribution, this is a non-inclusive upper boundary, in case of the + normal distribution, this is a standard deviation (diagonal of the + standard deviation matrix or the full standard deviation matrix). + @param saturateRange pre-saturation flag; for uniform distribution only; + if true, the method will first convert a and b to the acceptable value + range (according to the mat datatype) and then will generate uniformly + distributed random numbers within the range [saturate(a), saturate(b)), + if saturateRange=false, the method will generate uniformly distributed + random numbers in the original range [a, b) and then will saturate them, + it means, for example, that + theRNG().fill(mat_8u, RNG::UNIFORM, -DBL_MAX, DBL_MAX) will likely + produce array mostly filled with 0's and 255's, since the range (0, 255) + is significantly smaller than [-DBL_MAX, DBL_MAX). + + Each of the methods fills the matrix with the random values from the + specified distribution. As the new numbers are generated, the RNG state + is updated accordingly. In case of multiple-channel images, every + channel is filled independently, which means that RNG cannot generate + samples from the multi-dimensional Gaussian distribution with + non-diagonal covariance matrix directly. To do that, the method + generates samples from multi-dimensional standard Gaussian distribution + with zero mean and identity covariation matrix, and then transforms them + using transform to get samples from the specified Gaussian distribution. + */ + void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange = false ); + + /** @brief Returns the next random number sampled from the Gaussian distribution + @param sigma standard deviation of the distribution. + + The method transforms the state using the MWC algorithm and returns the + next random number from the Gaussian distribution N(0,sigma) . That is, + the mean value of the returned random numbers is zero and the standard + deviation is the specified sigma . + */ + double gaussian(double sigma); + + uint64 state; +}; + +/** @brief Mersenne Twister random number generator + +Inspired by http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c +@todo document + */ +class CV_EXPORTS RNG_MT19937 +{ +public: + RNG_MT19937(); + RNG_MT19937(unsigned s); + void seed(unsigned s); + + unsigned next(); + + operator int(); + operator unsigned(); + operator float(); + operator double(); + + unsigned operator ()(unsigned N); + unsigned operator ()(); + + /** @brief returns uniformly distributed integer random number from [a,b) range + +*/ + int uniform(int a, int b); + /** @brief returns uniformly distributed floating-point random number from [a,b) range + +*/ + float uniform(float a, float b); + /** @brief returns uniformly distributed double-precision floating-point random number from [a,b) range + +*/ + double uniform(double a, double b); + +private: + enum PeriodParameters {N = 624, M = 397}; + unsigned state[N]; + int mti; +}; + +//! @} core_array + +//! @addtogroup core_cluster +//! @{ + +/** @example kmeans.cpp + An example on K-means clustering +*/ + +/** @brief Finds centers of clusters and groups input samples around the clusters. + +The function kmeans implements a k-means algorithm that finds the centers of cluster_count clusters +and groups the input samples around the clusters. As an output, \f$\texttt{labels}_i\f$ contains a +0-based cluster index for the sample stored in the \f$i^{th}\f$ row of the samples matrix. + +@note +- (Python) An example on K-means clustering can be found at + opencv_source_code/samples/python2/kmeans.py +@param data Data for clustering. An array of N-Dimensional points with float coordinates is needed. +Examples of this array can be: +- Mat points(count, 2, CV_32F); +- Mat points(count, 1, CV_32FC2); +- Mat points(1, count, CV_32FC2); +- std::vector\ points(sampleCount); +@param K Number of clusters to split the set by. +@param bestLabels Input/output integer array that stores the cluster indices for every sample. +@param criteria The algorithm termination criteria, that is, the maximum number of iterations and/or +the desired accuracy. The accuracy is specified as criteria.epsilon. As soon as each of the cluster +centers moves by less than criteria.epsilon on some iteration, the algorithm stops. +@param attempts Flag to specify the number of times the algorithm is executed using different +initial labellings. The algorithm returns the labels that yield the best compactness (see the last +function parameter). +@param flags Flag that can take values of cv::KmeansFlags +@param centers Output matrix of the cluster centers, one row per each cluster center. +@return The function returns the compactness measure that is computed as +\f[\sum _i \| \texttt{samples} _i - \texttt{centers} _{ \texttt{labels} _i} \| ^2\f] +after every attempt. The best (minimum) value is chosen and the corresponding labels and the +compactness value are returned by the function. Basically, you can use only the core of the +function, set the number of attempts to 1, initialize labels each time using a custom algorithm, +pass them with the ( flags = KMEANS_USE_INITIAL_LABELS ) flag, and then choose the best +(most-compact) clustering. +*/ +CV_EXPORTS_W double kmeans( InputArray data, int K, InputOutputArray bestLabels, + TermCriteria criteria, int attempts, + int flags, OutputArray centers = noArray() ); + +//! @} core_cluster + +//! @addtogroup core_basic +//! @{ + +/////////////////////////////// Formatted output of cv::Mat /////////////////////////// + +/** @todo document */ +class CV_EXPORTS Formatted +{ +public: + virtual const char* next() = 0; + virtual void reset() = 0; + virtual ~Formatted(); +}; + +/** @todo document */ +class CV_EXPORTS Formatter +{ +public: + enum { FMT_DEFAULT = 0, + FMT_MATLAB = 1, + FMT_CSV = 2, + FMT_PYTHON = 3, + FMT_NUMPY = 4, + FMT_C = 5 + }; + + virtual ~Formatter(); + + virtual Ptr format(const Mat& mtx) const = 0; + + virtual void set32fPrecision(int p = 8) = 0; + virtual void set64fPrecision(int p = 16) = 0; + virtual void setMultiline(bool ml = true) = 0; + + static Ptr get(int fmt = FMT_DEFAULT); + +}; + +//////////////////////////////////////// Algorithm //////////////////////////////////// + +class CV_EXPORTS Algorithm; + +template struct ParamType {}; + + +/** @brief This is a base class for all more or less complex algorithms in OpenCV + +especially for classes of algorithms, for which there can be multiple implementations. The examples +are stereo correspondence (for which there are algorithms like block matching, semi-global block +matching, graph-cut etc.), background subtraction (which can be done using mixture-of-gaussians +models, codebook-based algorithm etc.), optical flow (block matching, Lucas-Kanade, Horn-Schunck +etc.). + +Here is example of SIFT use in your application via Algorithm interface: +@code + #include "opencv2/opencv.hpp" + #include "opencv2/xfeatures2d.hpp" + using namespace cv::xfeatures2d; + + Ptr sift = SIFT::create(); + FileStorage fs("sift_params.xml", FileStorage::READ); + if( fs.isOpened() ) // if we have file with parameters, read them + { + sift->read(fs["sift_params"]); + fs.release(); + } + else // else modify the parameters and store them; user can later edit the file to use different parameters + { + sift->setContrastThreshold(0.01f); // lower the contrast threshold, compared to the default value + { + WriteStructContext ws(fs, "sift_params", CV_NODE_MAP); + sift->write(fs); + } + } + Mat image = imread("myimage.png", 0), descriptors; + vector keypoints; + sift->detectAndCompute(image, noArray(), keypoints, descriptors); +@endcode + */ +class CV_EXPORTS_W Algorithm +{ +public: + Algorithm(); + virtual ~Algorithm(); + + /** @brief Clears the algorithm state + */ + CV_WRAP virtual void clear() {} + + /** @brief Stores algorithm parameters in a file storage + */ + virtual void write(FileStorage& fs) const { (void)fs; } + + /** @brief Reads algorithm parameters from a file storage + */ + virtual void read(const FileNode& fn) { (void)fn; } + + /** @brief Returns true if the Algorithm is empty (e.g. in the very beginning or after unsuccessful read + */ + virtual bool empty() const { return false; } + + /** @brief Reads algorithm from the file node + + This is static template method of Algorithm. It's usage is following (in the case of SVM): + @code + Ptr svm = Algorithm::read(fn); + @endcode + In order to make this method work, the derived class must overwrite Algorithm::read(const + FileNode& fn) and also have static create() method without parameters + (or with all the optional parameters) + */ + template static Ptr<_Tp> read(const FileNode& fn) + { + Ptr<_Tp> obj = _Tp::create(); + obj->read(fn); + return !obj->empty() ? obj : Ptr<_Tp>(); + } + + /** @brief Loads algorithm from the file + + @param filename Name of the file to read. + @param objname The optional name of the node to read (if empty, the first top-level node will be used) + + This is static template method of Algorithm. It's usage is following (in the case of SVM): + @code + Ptr svm = Algorithm::load("my_svm_model.xml"); + @endcode + In order to make this method work, the derived class must overwrite Algorithm::read(const + FileNode& fn). + */ + template static Ptr<_Tp> load(const String& filename, const String& objname=String()) + { + FileStorage fs(filename, FileStorage::READ); + FileNode fn = objname.empty() ? fs.getFirstTopLevelNode() : fs[objname]; + Ptr<_Tp> obj = _Tp::create(); + obj->read(fn); + return !obj->empty() ? obj : Ptr<_Tp>(); + } + + /** @brief Loads algorithm from a String + + @param strModel The string variable containing the model you want to load. + @param objname The optional name of the node to read (if empty, the first top-level node will be used) + + This is static template method of Algorithm. It's usage is following (in the case of SVM): + @code + Ptr svm = Algorithm::loadFromString(myStringModel); + @endcode + */ + template static Ptr<_Tp> loadFromString(const String& strModel, const String& objname=String()) + { + FileStorage fs(strModel, FileStorage::READ + FileStorage::MEMORY); + FileNode fn = objname.empty() ? fs.getFirstTopLevelNode() : fs[objname]; + Ptr<_Tp> obj = _Tp::create(); + obj->read(fn); + return !obj->empty() ? obj : Ptr<_Tp>(); + } + + /** Saves the algorithm to a file. + In order to make this method work, the derived class must implement Algorithm::write(FileStorage& fs). */ + CV_WRAP virtual void save(const String& filename) const; + + /** Returns the algorithm string identifier. + This string is used as top level xml/yml node tag when the object is saved to a file or string. */ + CV_WRAP virtual String getDefaultName() const; +}; + +struct Param { + enum { INT=0, BOOLEAN=1, REAL=2, STRING=3, MAT=4, MAT_VECTOR=5, ALGORITHM=6, FLOAT=7, + UNSIGNED_INT=8, UINT64=9, UCHAR=11 }; +}; + + + +template<> struct ParamType +{ + typedef bool const_param_type; + typedef bool member_type; + + enum { type = Param::BOOLEAN }; +}; + +template<> struct ParamType +{ + typedef int const_param_type; + typedef int member_type; + + enum { type = Param::INT }; +}; + +template<> struct ParamType +{ + typedef double const_param_type; + typedef double member_type; + + enum { type = Param::REAL }; +}; + +template<> struct ParamType +{ + typedef const String& const_param_type; + typedef String member_type; + + enum { type = Param::STRING }; +}; + +template<> struct ParamType +{ + typedef const Mat& const_param_type; + typedef Mat member_type; + + enum { type = Param::MAT }; +}; + +template<> struct ParamType > +{ + typedef const std::vector& const_param_type; + typedef std::vector member_type; + + enum { type = Param::MAT_VECTOR }; +}; + +template<> struct ParamType +{ + typedef const Ptr& const_param_type; + typedef Ptr member_type; + + enum { type = Param::ALGORITHM }; +}; + +template<> struct ParamType +{ + typedef float const_param_type; + typedef float member_type; + + enum { type = Param::FLOAT }; +}; + +template<> struct ParamType +{ + typedef unsigned const_param_type; + typedef unsigned member_type; + + enum { type = Param::UNSIGNED_INT }; +}; + +template<> struct ParamType +{ + typedef uint64 const_param_type; + typedef uint64 member_type; + + enum { type = Param::UINT64 }; +}; + +template<> struct ParamType +{ + typedef uchar const_param_type; + typedef uchar member_type; + + enum { type = Param::UCHAR }; +}; + +//! @} core_basic + +} //namespace cv + +#include "opencv2/core/operations.hpp" +#include "opencv2/core/cvstd.inl.hpp" +#include "opencv2/core/utility.hpp" +#include "opencv2/core/optim.hpp" + +#endif /*__OPENCV_CORE_HPP__*/ diff --git a/include/opencv2/core/affine.hpp b/include/opencv2/core/affine.hpp new file mode 100644 index 0000000..3b527cd --- /dev/null +++ b/include/opencv2/core/affine.hpp @@ -0,0 +1,522 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_AFFINE3_HPP__ +#define __OPENCV_CORE_AFFINE3_HPP__ + +#ifdef __cplusplus + +#include + +namespace cv +{ + +//! @addtogroup core +//! @{ + + /** @brief Affine transform + @todo document + */ + template + class Affine3 + { + public: + typedef T float_type; + typedef Matx Mat3; + typedef Matx Mat4; + typedef Vec Vec3; + + Affine3(); + + //! Augmented affine matrix + Affine3(const Mat4& affine); + + //! Rotation matrix + Affine3(const Mat3& R, const Vec3& t = Vec3::all(0)); + + //! Rodrigues vector + Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); + + //! Combines all contructors above. Supports 4x4, 4x3, 3x3, 1x3, 3x1 sizes of data matrix + explicit Affine3(const Mat& data, const Vec3& t = Vec3::all(0)); + + //! From 16th element array + explicit Affine3(const float_type* vals); + + //! Create identity transform + static Affine3 Identity(); + + //! Rotation matrix + void rotation(const Mat3& R); + + //! Rodrigues vector + void rotation(const Vec3& rvec); + + //! Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; + void rotation(const Mat& data); + + void linear(const Mat3& L); + void translation(const Vec3& t); + + Mat3 rotation() const; + Mat3 linear() const; + Vec3 translation() const; + + //! Rodrigues vector + Vec3 rvec() const; + + Affine3 inv(int method = cv::DECOMP_SVD) const; + + //! a.rotate(R) is equivalent to Affine(R, 0) * a; + Affine3 rotate(const Mat3& R) const; + + //! a.rotate(R) is equivalent to Affine(rvec, 0) * a; + Affine3 rotate(const Vec3& rvec) const; + + //! a.translate(t) is equivalent to Affine(E, t) * a; + Affine3 translate(const Vec3& t) const; + + //! a.concatenate(affine) is equivalent to affine * a; + Affine3 concatenate(const Affine3& affine) const; + + template operator Affine3() const; + + template Affine3 cast() const; + + Mat4 matrix; + +#if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H + Affine3(const Eigen::Transform& affine); + Affine3(const Eigen::Transform& affine); + operator Eigen::Transform() const; + operator Eigen::Transform() const; +#endif + }; + + template static + Affine3 operator*(const Affine3& affine1, const Affine3& affine2); + + template static + V operator*(const Affine3& affine, const V& vector); + + typedef Affine3 Affine3f; + typedef Affine3 Affine3d; + + static Vec3f operator*(const Affine3f& affine, const Vec3f& vector); + static Vec3d operator*(const Affine3d& affine, const Vec3d& vector); + + template class DataType< Affine3<_Tp> > + { + public: + typedef Affine3<_Tp> value_type; + typedef Affine3::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 16, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; + }; + +//! @} core + +} + +//! @cond IGNORED + +/////////////////////////////////////////////////////////////////////////////////// +// Implementaiton + +template inline +cv::Affine3::Affine3() + : matrix(Mat4::eye()) +{} + +template inline +cv::Affine3::Affine3(const Mat4& affine) + : matrix(affine) +{} + +template inline +cv::Affine3::Affine3(const Mat3& R, const Vec3& t) +{ + rotation(R); + translation(t); + matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; + matrix.val[15] = 1; +} + +template inline +cv::Affine3::Affine3(const Vec3& _rvec, const Vec3& t) +{ + rotation(_rvec); + translation(t); + matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; + matrix.val[15] = 1; +} + +template inline +cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) +{ + CV_Assert(data.type() == cv::DataType::type); + + if (data.cols == 4 && data.rows == 4) + { + data.copyTo(matrix); + return; + } + else if (data.cols == 4 && data.rows == 3) + { + rotation(data(Rect(0, 0, 3, 3))); + translation(data(Rect(3, 0, 1, 3))); + return; + } + + rotation(data); + translation(t); + matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; + matrix.val[15] = 1; +} + +template inline +cv::Affine3::Affine3(const float_type* vals) : matrix(vals) +{} + +template inline +cv::Affine3 cv::Affine3::Identity() +{ + return Affine3(cv::Affine3::Mat4::eye()); +} + +template inline +void cv::Affine3::rotation(const Mat3& R) +{ + linear(R); +} + +template inline +void cv::Affine3::rotation(const Vec3& _rvec) +{ + double rx = _rvec[0], ry = _rvec[1], rz = _rvec[2]; + double theta = std::sqrt(rx*rx + ry*ry + rz*rz); + + if (theta < DBL_EPSILON) + rotation(Mat3::eye()); + else + { + const double I[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; + + double c = std::cos(theta); + double s = std::sin(theta); + double c1 = 1. - c; + double itheta = (theta != 0) ? 1./theta : 0.; + + rx *= itheta; ry *= itheta; rz *= itheta; + + double rrt[] = { rx*rx, rx*ry, rx*rz, rx*ry, ry*ry, ry*rz, rx*rz, ry*rz, rz*rz }; + double _r_x_[] = { 0, -rz, ry, rz, 0, -rx, -ry, rx, 0 }; + Mat3 R; + + // R = cos(theta)*I + (1 - cos(theta))*r*rT + sin(theta)*[r_x] + // where [r_x] is [0 -rz ry; rz 0 -rx; -ry rx 0] + for(int k = 0; k < 9; ++k) + R.val[k] = static_cast(c*I[k] + c1*rrt[k] + s*_r_x_[k]); + + rotation(R); + } +} + +//Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; +template inline +void cv::Affine3::rotation(const cv::Mat& data) +{ + CV_Assert(data.type() == cv::DataType::type); + + if (data.cols == 3 && data.rows == 3) + { + Mat3 R; + data.copyTo(R); + rotation(R); + } + else if ((data.cols == 3 && data.rows == 1) || (data.cols == 1 && data.rows == 3)) + { + Vec3 _rvec; + data.reshape(1, 3).copyTo(_rvec); + rotation(_rvec); + } + else + CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); +} + +template inline +void cv::Affine3::linear(const Mat3& L) +{ + matrix.val[0] = L.val[0]; matrix.val[1] = L.val[1]; matrix.val[ 2] = L.val[2]; + matrix.val[4] = L.val[3]; matrix.val[5] = L.val[4]; matrix.val[ 6] = L.val[5]; + matrix.val[8] = L.val[6]; matrix.val[9] = L.val[7]; matrix.val[10] = L.val[8]; +} + +template inline +void cv::Affine3::translation(const Vec3& t) +{ + matrix.val[3] = t[0]; matrix.val[7] = t[1]; matrix.val[11] = t[2]; +} + +template inline +typename cv::Affine3::Mat3 cv::Affine3::rotation() const +{ + return linear(); +} + +template inline +typename cv::Affine3::Mat3 cv::Affine3::linear() const +{ + typename cv::Affine3::Mat3 R; + R.val[0] = matrix.val[0]; R.val[1] = matrix.val[1]; R.val[2] = matrix.val[ 2]; + R.val[3] = matrix.val[4]; R.val[4] = matrix.val[5]; R.val[5] = matrix.val[ 6]; + R.val[6] = matrix.val[8]; R.val[7] = matrix.val[9]; R.val[8] = matrix.val[10]; + return R; +} + +template inline +typename cv::Affine3::Vec3 cv::Affine3::translation() const +{ + return Vec3(matrix.val[3], matrix.val[7], matrix.val[11]); +} + +template inline +typename cv::Affine3::Vec3 cv::Affine3::rvec() const +{ + cv::Vec3d w; + cv::Matx33d u, vt, R = rotation(); + cv::SVD::compute(R, w, u, vt, cv::SVD::FULL_UV + cv::SVD::MODIFY_A); + R = u * vt; + + double rx = R.val[7] - R.val[5]; + double ry = R.val[2] - R.val[6]; + double rz = R.val[3] - R.val[1]; + + double s = std::sqrt((rx*rx + ry*ry + rz*rz)*0.25); + double c = (R.val[0] + R.val[4] + R.val[8] - 1) * 0.5; + c = c > 1.0 ? 1.0 : c < -1.0 ? -1.0 : c; + double theta = acos(c); + + if( s < 1e-5 ) + { + if( c > 0 ) + rx = ry = rz = 0; + else + { + double t; + t = (R.val[0] + 1) * 0.5; + rx = std::sqrt(std::max(t, 0.0)); + t = (R.val[4] + 1) * 0.5; + ry = std::sqrt(std::max(t, 0.0)) * (R.val[1] < 0 ? -1.0 : 1.0); + t = (R.val[8] + 1) * 0.5; + rz = std::sqrt(std::max(t, 0.0)) * (R.val[2] < 0 ? -1.0 : 1.0); + + if( fabs(rx) < fabs(ry) && fabs(rx) < fabs(rz) && (R.val[5] > 0) != (ry*rz > 0) ) + rz = -rz; + theta /= std::sqrt(rx*rx + ry*ry + rz*rz); + rx *= theta; + ry *= theta; + rz *= theta; + } + } + else + { + double vth = 1/(2*s); + vth *= theta; + rx *= vth; ry *= vth; rz *= vth; + } + + return cv::Vec3d(rx, ry, rz); +} + +template inline +cv::Affine3 cv::Affine3::inv(int method) const +{ + return matrix.inv(method); +} + +template inline +cv::Affine3 cv::Affine3::rotate(const Mat3& R) const +{ + Mat3 Lc = linear(); + Vec3 tc = translation(); + Mat4 result; + result.val[12] = result.val[13] = result.val[14] = 0; + result.val[15] = 1; + + for(int j = 0; j < 3; ++j) + { + for(int i = 0; i < 3; ++i) + { + float_type value = 0; + for(int k = 0; k < 3; ++k) + value += R(j, k) * Lc(k, i); + result(j, i) = value; + } + + result(j, 3) = R.row(j).dot(tc.t()); + } + return result; +} + +template inline +cv::Affine3 cv::Affine3::rotate(const Vec3& _rvec) const +{ + return rotate(Affine3f(_rvec).rotation()); +} + +template inline +cv::Affine3 cv::Affine3::translate(const Vec3& t) const +{ + Mat4 m = matrix; + m.val[ 3] += t[0]; + m.val[ 7] += t[1]; + m.val[11] += t[2]; + return m; +} + +template inline +cv::Affine3 cv::Affine3::concatenate(const Affine3& affine) const +{ + return (*this).rotate(affine.rotation()).translate(affine.translation()); +} + +template template inline +cv::Affine3::operator Affine3() const +{ + return Affine3(matrix); +} + +template template inline +cv::Affine3 cv::Affine3::cast() const +{ + return Affine3(matrix); +} + +template inline +cv::Affine3 cv::operator*(const cv::Affine3& affine1, const cv::Affine3& affine2) +{ + return affine2.concatenate(affine1); +} + +template inline +V cv::operator*(const cv::Affine3& affine, const V& v) +{ + const typename Affine3::Mat4& m = affine.matrix; + + V r; + r.x = m.val[0] * v.x + m.val[1] * v.y + m.val[ 2] * v.z + m.val[ 3]; + r.y = m.val[4] * v.x + m.val[5] * v.y + m.val[ 6] * v.z + m.val[ 7]; + r.z = m.val[8] * v.x + m.val[9] * v.y + m.val[10] * v.z + m.val[11]; + return r; +} + +static inline +cv::Vec3f cv::operator*(const cv::Affine3f& affine, const cv::Vec3f& v) +{ + const cv::Matx44f& m = affine.matrix; + cv::Vec3f r; + r.val[0] = m.val[0] * v[0] + m.val[1] * v[1] + m.val[ 2] * v[2] + m.val[ 3]; + r.val[1] = m.val[4] * v[0] + m.val[5] * v[1] + m.val[ 6] * v[2] + m.val[ 7]; + r.val[2] = m.val[8] * v[0] + m.val[9] * v[1] + m.val[10] * v[2] + m.val[11]; + return r; +} + +static inline +cv::Vec3d cv::operator*(const cv::Affine3d& affine, const cv::Vec3d& v) +{ + const cv::Matx44d& m = affine.matrix; + cv::Vec3d r; + r.val[0] = m.val[0] * v[0] + m.val[1] * v[1] + m.val[ 2] * v[2] + m.val[ 3]; + r.val[1] = m.val[4] * v[0] + m.val[5] * v[1] + m.val[ 6] * v[2] + m.val[ 7]; + r.val[2] = m.val[8] * v[0] + m.val[9] * v[1] + m.val[10] * v[2] + m.val[11]; + return r; +} + + + +#if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H + +template inline +cv::Affine3::Affine3(const Eigen::Transform& affine) +{ + cv::Mat(4, 4, cv::DataType::type, affine.matrix().data()).copyTo(matrix); +} + +template inline +cv::Affine3::Affine3(const Eigen::Transform& affine) +{ + Eigen::Transform a = affine; + cv::Mat(4, 4, cv::DataType::type, a.matrix().data()).copyTo(matrix); +} + +template inline +cv::Affine3::operator Eigen::Transform() const +{ + Eigen::Transform r; + cv::Mat hdr(4, 4, cv::DataType::type, r.matrix().data()); + cv::Mat(matrix, false).copyTo(hdr); + return r; +} + +template inline +cv::Affine3::operator Eigen::Transform() const +{ + return this->operator Eigen::Transform(); +} + +#endif /* defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H */ + +//! @endcond + +#endif /* __cplusplus */ + +#endif /* __OPENCV_CORE_AFFINE3_HPP__ */ diff --git a/include/opencv2/core/base.hpp b/include/opencv2/core/base.hpp new file mode 100644 index 0000000..83cc311 --- /dev/null +++ b/include/opencv2/core/base.hpp @@ -0,0 +1,745 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2014, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_BASE_HPP__ +#define __OPENCV_CORE_BASE_HPP__ + +#ifndef __cplusplus +# error base.hpp header must be compiled as C++ +#endif + +#include + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/cvstd.hpp" +#include "opencv2/hal.hpp" + +namespace cv +{ + +//! @addtogroup core_utils +//! @{ + +namespace Error { +//! error codes +enum Code { + StsOk= 0, //!< everithing is ok + StsBackTrace= -1, //!< pseudo error for back trace + StsError= -2, //!< unknown /unspecified error + StsInternal= -3, //!< internal error (bad state) + StsNoMem= -4, //!< insufficient memory + StsBadArg= -5, //!< function arg/param is bad + StsBadFunc= -6, //!< unsupported function + StsNoConv= -7, //!< iter. didn't converge + StsAutoTrace= -8, //!< tracing + HeaderIsNull= -9, //!< image header is NULL + BadImageSize= -10, //!< image size is invalid + BadOffset= -11, //!< offset is invalid + BadDataPtr= -12, //!< + BadStep= -13, //!< + BadModelOrChSeq= -14, //!< + BadNumChannels= -15, //!< + BadNumChannel1U= -16, //!< + BadDepth= -17, //!< + BadAlphaChannel= -18, //!< + BadOrder= -19, //!< + BadOrigin= -20, //!< + BadAlign= -21, //!< + BadCallBack= -22, //!< + BadTileSize= -23, //!< + BadCOI= -24, //!< + BadROISize= -25, //!< + MaskIsTiled= -26, //!< + StsNullPtr= -27, //!< null pointer + StsVecLengthErr= -28, //!< incorrect vector length + StsFilterStructContentErr= -29, //!< incorr. filter structure content + StsKernelStructContentErr= -30, //!< incorr. transform kernel content + StsFilterOffsetErr= -31, //!< incorrect filter ofset value + StsBadSize= -201, //!< the input/output structure size is incorrect + StsDivByZero= -202, //!< division by zero + StsInplaceNotSupported= -203, //!< in-place operation is not supported + StsObjectNotFound= -204, //!< request can't be completed + StsUnmatchedFormats= -205, //!< formats of input/output arrays differ + StsBadFlag= -206, //!< flag is wrong or not supported + StsBadPoint= -207, //!< bad CvPoint + StsBadMask= -208, //!< bad format of mask (neither 8uC1 nor 8sC1) + StsUnmatchedSizes= -209, //!< sizes of input/output structures do not match + StsUnsupportedFormat= -210, //!< the data format/type is not supported by the function + StsOutOfRange= -211, //!< some of parameters are out of range + StsParseError= -212, //!< invalid syntax/structure of the parsed file + StsNotImplemented= -213, //!< the requested function/feature is not implemented + StsBadMemBlock= -214, //!< an allocated block has been corrupted + StsAssert= -215, //!< assertion failed + GpuNotSupported= -216, + GpuApiCallError= -217, + OpenGlNotSupported= -218, + OpenGlApiCallError= -219, + OpenCLApiCallError= -220, + OpenCLDoubleNotSupported= -221, + OpenCLInitError= -222, + OpenCLNoAMDBlasFft= -223 +}; +} //Error + +//! @} core_utils + +//! @addtogroup core_array +//! @{ + +//! matrix decomposition types +enum DecompTypes { + /** Gaussian elimination with the optimal pivot element chosen. */ + DECOMP_LU = 0, + /** singular value decomposition (SVD) method; the system can be over-defined and/or the matrix + src1 can be singular */ + DECOMP_SVD = 1, + /** eigenvalue decomposition; the matrix src1 must be symmetrical */ + DECOMP_EIG = 2, + /** Cholesky \f$LL^T\f$ factorization; the matrix src1 must be symmetrical and positively + defined */ + DECOMP_CHOLESKY = 3, + /** QR factorization; the system can be over-defined and/or the matrix src1 can be singular */ + DECOMP_QR = 4, + /** while all the previous flags are mutually exclusive, this flag can be used together with + any of the previous; it means that the normal equations + \f$\texttt{src1}^T\cdot\texttt{src1}\cdot\texttt{dst}=\texttt{src1}^T\texttt{src2}\f$ are + solved instead of the original system + \f$\texttt{src1}\cdot\texttt{dst}=\texttt{src2}\f$ */ + DECOMP_NORMAL = 16 +}; + +/** norm types +- For one array: +\f[norm = \forkthree{\|\texttt{src1}\|_{L_{\infty}} = \max _I | \texttt{src1} (I)|}{if \(\texttt{normType} = \texttt{NORM\_INF}\) } +{ \| \texttt{src1} \| _{L_1} = \sum _I | \texttt{src1} (I)|}{if \(\texttt{normType} = \texttt{NORM\_L1}\) } +{ \| \texttt{src1} \| _{L_2} = \sqrt{\sum_I \texttt{src1}(I)^2} }{if \(\texttt{normType} = \texttt{NORM\_L2}\) }\f] + +- Absolute norm for two arrays +\f[norm = \forkthree{\|\texttt{src1}-\texttt{src2}\|_{L_{\infty}} = \max _I | \texttt{src1} (I) - \texttt{src2} (I)|}{if \(\texttt{normType} = \texttt{NORM\_INF}\) } +{ \| \texttt{src1} - \texttt{src2} \| _{L_1} = \sum _I | \texttt{src1} (I) - \texttt{src2} (I)|}{if \(\texttt{normType} = \texttt{NORM\_L1}\) } +{ \| \texttt{src1} - \texttt{src2} \| _{L_2} = \sqrt{\sum_I (\texttt{src1}(I) - \texttt{src2}(I))^2} }{if \(\texttt{normType} = \texttt{NORM\_L2}\) }\f] + +- Relative norm for two arrays +\f[norm = \forkthree{\frac{\|\texttt{src1}-\texttt{src2}\|_{L_{\infty}} }{\|\texttt{src2}\|_{L_{\infty}} }}{if \(\texttt{normType} = \texttt{NORM\_RELATIVE\_INF}\) } +{ \frac{\|\texttt{src1}-\texttt{src2}\|_{L_1} }{\|\texttt{src2}\|_{L_1}} }{if \(\texttt{normType} = \texttt{NORM\_RELATIVE\_L1}\) } +{ \frac{\|\texttt{src1}-\texttt{src2}\|_{L_2} }{\|\texttt{src2}\|_{L_2}} }{if \(\texttt{normType} = \texttt{NORM\_RELATIVE\_L2}\) }\f] + */ +enum NormTypes { NORM_INF = 1, + NORM_L1 = 2, + NORM_L2 = 4, + NORM_L2SQR = 5, + NORM_HAMMING = 6, + NORM_HAMMING2 = 7, + NORM_TYPE_MASK = 7, + NORM_RELATIVE = 8, //!< flag + NORM_MINMAX = 32 //!< flag + }; + +//! comparison types +enum CmpTypes { CMP_EQ = 0, //!< src1 is equal to src2. + CMP_GT = 1, //!< src1 is greater than src2. + CMP_GE = 2, //!< src1 is greater than or equal to src2. + CMP_LT = 3, //!< src1 is less than src2. + CMP_LE = 4, //!< src1 is less than or equal to src2. + CMP_NE = 5 //!< src1 is unequal to src2. + }; + +//! generalized matrix multiplication flags +enum GemmFlags { GEMM_1_T = 1, //!< transposes src1 + GEMM_2_T = 2, //!< transposes src2 + GEMM_3_T = 4 //!< transposes src3 + }; + +enum DftFlags { + /** performs an inverse 1D or 2D transform instead of the default forward + transform. */ + DFT_INVERSE = 1, + /** scales the result: divide it by the number of array elements. Normally, it is + combined with DFT_INVERSE. */ + DFT_SCALE = 2, + /** performs a forward or inverse transform of every individual row of the input + matrix; this flag enables you to transform multiple vectors simultaneously and can be used to + decrease the overhead (which is sometimes several times larger than the processing itself) to + perform 3D and higher-dimensional transformations and so forth.*/ + DFT_ROWS = 4, + /** performs a forward transformation of 1D or 2D real array; the result, + though being a complex array, has complex-conjugate symmetry (*CCS*, see the function + description below for details), and such an array can be packed into a real array of the same + size as input, which is the fastest option and which is what the function does by default; + however, you may wish to get a full complex array (for simpler spectrum analysis, and so on) - + pass the flag to enable the function to produce a full-size complex output array. */ + DFT_COMPLEX_OUTPUT = 16, + /** performs an inverse transformation of a 1D or 2D complex array; the + result is normally a complex array of the same size, however, if the input array has + conjugate-complex symmetry (for example, it is a result of forward transformation with + DFT_COMPLEX_OUTPUT flag), the output is a real array; while the function itself does not + check whether the input is symmetrical or not, you can pass the flag and then the function + will assume the symmetry and produce the real output array (note that when the input is packed + into a real array and inverse transformation is executed, the function treats the input as a + packed complex-conjugate symmetrical array, and the output will also be a real array). */ + DFT_REAL_OUTPUT = 32, + /** performs an inverse 1D or 2D transform instead of the default forward transform. */ + DCT_INVERSE = DFT_INVERSE, + /** performs a forward or inverse transform of every individual row of the input + matrix. This flag enables you to transform multiple vectors simultaneously and can be used to + decrease the overhead (which is sometimes several times larger than the processing itself) to + perform 3D and higher-dimensional transforms and so forth.*/ + DCT_ROWS = DFT_ROWS +}; + +//! Various border types, image boundaries are denoted with `|` +//! @see borderInterpolate, copyMakeBorder +enum BorderTypes { + BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i` + BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh` + BORDER_REFLECT = 2, //!< `fedcba|abcdefgh|hgfedcb` + BORDER_WRAP = 3, //!< `cdefgh|abcdefgh|abcdefg` + BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba` + BORDER_TRANSPARENT = 5, //!< `uvwxyz|absdefgh|ijklmno` + + BORDER_REFLECT101 = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101 + BORDER_DEFAULT = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101 + BORDER_ISOLATED = 16 //!< do not look outside of ROI +}; + +//! @} core_array + +//! @addtogroup core_utils +//! @{ + +//! @cond IGNORED + +//////////////// static assert ///////////////// +#define CVAUX_CONCAT_EXP(a, b) a##b +#define CVAUX_CONCAT(a, b) CVAUX_CONCAT_EXP(a,b) + +#if defined(__clang__) +# ifndef __has_extension +# define __has_extension __has_feature /* compatibility, for older versions of clang */ +# endif +# if __has_extension(cxx_static_assert) +# define CV_StaticAssert(condition, reason) static_assert((condition), reason " " #condition) +# endif +#elif defined(__GNUC__) +# if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) +# define CV_StaticAssert(condition, reason) static_assert((condition), reason " " #condition) +# endif +#elif defined(_MSC_VER) +# if _MSC_VER >= 1600 /* MSVC 10 */ +# define CV_StaticAssert(condition, reason) static_assert((condition), reason " " #condition) +# endif +#endif +#ifndef CV_StaticAssert +# if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 2) +# define CV_StaticAssert(condition, reason) ({ extern int __attribute__((error("CV_StaticAssert: " reason " " #condition))) CV_StaticAssert(); ((condition) ? 0 : CV_StaticAssert()); }) +# else + template struct CV_StaticAssert_failed; + template <> struct CV_StaticAssert_failed { enum { val = 1 }; }; + template struct CV_StaticAssert_test {}; +# define CV_StaticAssert(condition, reason)\ + typedef cv::CV_StaticAssert_test< sizeof(cv::CV_StaticAssert_failed< static_cast(condition) >) > CVAUX_CONCAT(CV_StaticAssert_failed_at_, __LINE__) +# endif +#endif + +// Suppress warning "-Wdeprecated-declarations" / C4996 +#if defined(_MSC_VER) + #define CV_DO_PRAGMA(x) __pragma(x) +#elif defined(__GNUC__) + #define CV_DO_PRAGMA(x) _Pragma (#x) +#else + #define CV_DO_PRAGMA(x) +#endif + +#ifdef _MSC_VER +#define CV_SUPPRESS_DEPRECATED_START \ + CV_DO_PRAGMA(warning(push)) \ + CV_DO_PRAGMA(warning(disable: 4996)) +#define CV_SUPPRESS_DEPRECATED_END CV_DO_PRAGMA(warning(pop)) +#elif defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#define CV_SUPPRESS_DEPRECATED_START \ + CV_DO_PRAGMA(GCC diagnostic push) \ + CV_DO_PRAGMA(GCC diagnostic ignored "-Wdeprecated-declarations") +#define CV_SUPPRESS_DEPRECATED_END CV_DO_PRAGMA(GCC diagnostic pop) +#else +#define CV_SUPPRESS_DEPRECATED_START +#define CV_SUPPRESS_DEPRECATED_END +#endif +//! @endcond + +/*! @brief Signals an error and raises the exception. + +By default the function prints information about the error to stderr, +then it either stops if setBreakOnError() had been called before or raises the exception. +It is possible to alternate error processing by using redirectError(). +@param _code - error code (Error::Code) +@param _err - error description +@param _func - function name. Available only when the compiler supports getting it +@param _file - source file name where the error has occured +@param _line - line number in the source file where the error has occured +@see CV_Error, CV_Error_, CV_ErrorNoReturn, CV_ErrorNoReturn_, CV_Assert, CV_DbgAssert + */ +CV_EXPORTS void error(int _code, const String& _err, const char* _func, const char* _file, int _line); + +#ifdef __GNUC__ +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Winvalid-noreturn" +# endif +#endif + +/** same as cv::error, but does not return */ +CV_INLINE CV_NORETURN void errorNoReturn(int _code, const String& _err, const char* _func, const char* _file, int _line) +{ + error(_code, _err, _func, _file, _line); +#ifdef __GNUC__ +# if !defined __clang__ && !defined __APPLE__ + // this suppresses this warning: "noreturn" function does return [enabled by default] + __builtin_trap(); + // or use infinite loop: for (;;) {} +# endif +#endif +} +#ifdef __GNUC__ +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic pop +# endif +#endif + +#if defined __GNUC__ +#define CV_Func __func__ +#elif defined _MSC_VER +#define CV_Func __FUNCTION__ +#else +#define CV_Func "" +#endif + +/** @brief Call the error handler. + +Currently, the error handler prints the error code and the error message to the standard +error stream `stderr`. In the Debug configuration, it then provokes memory access violation, so that +the execution stack and all the parameters can be analyzed by the debugger. In the Release +configuration, the exception is thrown. + +@param code one of Error::Code +@param msg error message +*/ +#define CV_Error( code, msg ) cv::error( code, msg, CV_Func, __FILE__, __LINE__ ) + +/** @brief Call the error handler. + +This macro can be used to construct an error message on-fly to include some dynamic information, +for example: +@code + // note the extra parentheses around the formatted text message + CV_Error_( CV_StsOutOfRange, + ("the value at (%d, %d)=%g is out of range", badPt.x, badPt.y, badValue)); +@endcode +@param code one of Error::Code +@param args printf-like formatted error message in parentheses +*/ +#define CV_Error_( code, args ) cv::error( code, cv::format args, CV_Func, __FILE__, __LINE__ ) + +/** @brief Checks a condition at runtime and throws exception if it fails + +The macros CV_Assert (and CV_DbgAssert(expr)) evaluate the specified expression. If it is 0, the macros +raise an error (see cv::error). The macro CV_Assert checks the condition in both Debug and Release +configurations while CV_DbgAssert is only retained in the Debug configuration. +*/ +#define CV_Assert( expr ) if(!!(expr)) ; else cv::error( cv::Error::StsAssert, #expr, CV_Func, __FILE__, __LINE__ ) + +/** same as CV_Error(code,msg), but does not return */ +#define CV_ErrorNoReturn( code, msg ) cv::errorNoReturn( code, msg, CV_Func, __FILE__, __LINE__ ) + +/** same as CV_Error_(code,args), but does not return */ +#define CV_ErrorNoReturn_( code, args ) cv::errorNoReturn( code, cv::format args, CV_Func, __FILE__, __LINE__ ) + +/** replaced with CV_Assert(expr) in Debug configuration */ +#ifdef _DEBUG +# define CV_DbgAssert(expr) CV_Assert(expr) +#else +# define CV_DbgAssert(expr) +#endif + +/* + * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor + * bit count of A exclusive XOR'ed with B + */ +struct CV_EXPORTS Hamming +{ + enum { normType = NORM_HAMMING }; + typedef unsigned char ValueType; + typedef int ResultType; + + /** this will count the bits in a ^ b + */ + ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const; +}; + +typedef Hamming HammingLUT; + +/////////////////////////////////// inline norms //////////////////////////////////// + +template inline _Tp cv_abs(_Tp x) { return std::abs(x); } +inline int cv_abs(uchar x) { return x; } +inline int cv_abs(schar x) { return std::abs(x); } +inline int cv_abs(ushort x) { return x; } +inline int cv_abs(short x) { return std::abs(x); } + +template static inline +_AccTp normL2Sqr(const _Tp* a, int n) +{ + _AccTp s = 0; + int i=0; +#if CV_ENABLE_UNROLLED + for( ; i <= n - 4; i += 4 ) + { + _AccTp v0 = a[i], v1 = a[i+1], v2 = a[i+2], v3 = a[i+3]; + s += v0*v0 + v1*v1 + v2*v2 + v3*v3; + } +#endif + for( ; i < n; i++ ) + { + _AccTp v = a[i]; + s += v*v; + } + return s; +} + +template static inline +_AccTp normL1(const _Tp* a, int n) +{ + _AccTp s = 0; + int i = 0; +#if CV_ENABLE_UNROLLED + for(; i <= n - 4; i += 4 ) + { + s += (_AccTp)cv_abs(a[i]) + (_AccTp)cv_abs(a[i+1]) + + (_AccTp)cv_abs(a[i+2]) + (_AccTp)cv_abs(a[i+3]); + } +#endif + for( ; i < n; i++ ) + s += cv_abs(a[i]); + return s; +} + +template static inline +_AccTp normInf(const _Tp* a, int n) +{ + _AccTp s = 0; + for( int i = 0; i < n; i++ ) + s = std::max(s, (_AccTp)cv_abs(a[i])); + return s; +} + +template static inline +_AccTp normL2Sqr(const _Tp* a, const _Tp* b, int n) +{ + _AccTp s = 0; + int i= 0; +#if CV_ENABLE_UNROLLED + for(; i <= n - 4; i += 4 ) + { + _AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]); + s += v0*v0 + v1*v1 + v2*v2 + v3*v3; + } +#endif + for( ; i < n; i++ ) + { + _AccTp v = _AccTp(a[i] - b[i]); + s += v*v; + } + return s; +} + +static inline float normL2Sqr(const float* a, const float* b, int n) +{ + float s = 0.f; + for( int i = 0; i < n; i++ ) + { + float v = a[i] - b[i]; + s += v*v; + } + return s; +} + +template static inline +_AccTp normL1(const _Tp* a, const _Tp* b, int n) +{ + _AccTp s = 0; + int i= 0; +#if CV_ENABLE_UNROLLED + for(; i <= n - 4; i += 4 ) + { + _AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]); + s += std::abs(v0) + std::abs(v1) + std::abs(v2) + std::abs(v3); + } +#endif + for( ; i < n; i++ ) + { + _AccTp v = _AccTp(a[i] - b[i]); + s += std::abs(v); + } + return s; +} + +inline float normL1(const float* a, const float* b, int n) +{ + float s = 0.f; + for( int i = 0; i < n; i++ ) + { + s += std::abs(a[i] - b[i]); + } + return s; +} + +inline int normL1(const uchar* a, const uchar* b, int n) +{ + int s = 0; + for( int i = 0; i < n; i++ ) + { + s += std::abs(a[i] - b[i]); + } + return s; +} + +template static inline +_AccTp normInf(const _Tp* a, const _Tp* b, int n) +{ + _AccTp s = 0; + for( int i = 0; i < n; i++ ) + { + _AccTp v0 = a[i] - b[i]; + s = std::max(s, std::abs(v0)); + } + return s; +} + +/** @brief Computes the cube root of an argument. + + The function cubeRoot computes \f$\sqrt[3]{\texttt{val}}\f$. Negative arguments are handled correctly. + NaN and Inf are not handled. The accuracy approaches the maximum possible accuracy for + single-precision data. + @param val A function argument. + */ +CV_EXPORTS_W float cubeRoot(float val); + +/** @brief Calculates the angle of a 2D vector in degrees. + + The function fastAtan2 calculates the full-range angle of an input 2D vector. The angle is measured + in degrees and varies from 0 to 360 degrees. The accuracy is about 0.3 degrees. + @param x x-coordinate of the vector. + @param y y-coordinate of the vector. + */ +CV_EXPORTS_W float fastAtan2(float y, float x); + +/** proxy for hal::LU */ +CV_EXPORTS int LU(float* A, size_t astep, int m, float* b, size_t bstep, int n); +/** proxy for hal::LU */ +CV_EXPORTS int LU(double* A, size_t astep, int m, double* b, size_t bstep, int n); +/** proxy for hal::Cholesky */ +CV_EXPORTS bool Cholesky(float* A, size_t astep, int m, float* b, size_t bstep, int n); +/** proxy for hal::Cholesky */ +CV_EXPORTS bool Cholesky(double* A, size_t astep, int m, double* b, size_t bstep, int n); + +////////////////// forward declarations for important OpenCV types ////////////////// + +//! @cond IGNORED + +template class Vec; +template class Matx; + +template class Complex; +template class Point_; +template class Point3_; +template class Size_; +template class Rect_; +template class Scalar_; + +class CV_EXPORTS RotatedRect; +class CV_EXPORTS Range; +class CV_EXPORTS TermCriteria; +class CV_EXPORTS KeyPoint; +class CV_EXPORTS DMatch; +class CV_EXPORTS RNG; + +class CV_EXPORTS Mat; +class CV_EXPORTS MatExpr; + +class CV_EXPORTS UMat; + +class CV_EXPORTS SparseMat; +typedef Mat MatND; + +template class Mat_; +template class SparseMat_; + +class CV_EXPORTS MatConstIterator; +class CV_EXPORTS SparseMatIterator; +class CV_EXPORTS SparseMatConstIterator; +template class MatIterator_; +template class MatConstIterator_; +template class SparseMatIterator_; +template class SparseMatConstIterator_; + +namespace ogl +{ + class CV_EXPORTS Buffer; + class CV_EXPORTS Texture2D; + class CV_EXPORTS Arrays; +} + +namespace cuda +{ + class CV_EXPORTS GpuMat; + class CV_EXPORTS HostMem; + class CV_EXPORTS Stream; + class CV_EXPORTS Event; +} + +namespace cudev +{ + template class GpuMat_; +} + +namespace ipp +{ +CV_EXPORTS void setIppStatus(int status, const char * const funcname = NULL, const char * const filename = NULL, + int line = 0); +CV_EXPORTS int getIppStatus(); +CV_EXPORTS String getIppErrorLocation(); +CV_EXPORTS bool useIPP(); +CV_EXPORTS void setUseIPP(bool flag); + +} // ipp + +//! @endcond + +//! @} core_utils + +//! @addtogroup core_utils_neon +//! @{ + +#if CV_NEON + +inline int32x2_t cv_vrnd_s32_f32(float32x2_t v) +{ + static int32x2_t v_sign = vdup_n_s32(1 << 31), + v_05 = vreinterpret_s32_f32(vdup_n_f32(0.5f)); + + int32x2_t v_addition = vorr_s32(v_05, vand_s32(v_sign, vreinterpret_s32_f32(v))); + return vcvt_s32_f32(vadd_f32(v, vreinterpret_f32_s32(v_addition))); +} + +inline int32x4_t cv_vrndq_s32_f32(float32x4_t v) +{ + static int32x4_t v_sign = vdupq_n_s32(1 << 31), + v_05 = vreinterpretq_s32_f32(vdupq_n_f32(0.5f)); + + int32x4_t v_addition = vorrq_s32(v_05, vandq_s32(v_sign, vreinterpretq_s32_f32(v))); + return vcvtq_s32_f32(vaddq_f32(v, vreinterpretq_f32_s32(v_addition))); +} + +inline uint32x2_t cv_vrnd_u32_f32(float32x2_t v) +{ + static float32x2_t v_05 = vdup_n_f32(0.5f); + return vcvt_u32_f32(vadd_f32(v, v_05)); +} + +inline uint32x4_t cv_vrndq_u32_f32(float32x4_t v) +{ + static float32x4_t v_05 = vdupq_n_f32(0.5f); + return vcvtq_u32_f32(vaddq_f32(v, v_05)); +} + +inline float32x4_t cv_vrecpq_f32(float32x4_t val) +{ + float32x4_t reciprocal = vrecpeq_f32(val); + reciprocal = vmulq_f32(vrecpsq_f32(val, reciprocal), reciprocal); + reciprocal = vmulq_f32(vrecpsq_f32(val, reciprocal), reciprocal); + return reciprocal; +} + +inline float32x2_t cv_vrecp_f32(float32x2_t val) +{ + float32x2_t reciprocal = vrecpe_f32(val); + reciprocal = vmul_f32(vrecps_f32(val, reciprocal), reciprocal); + reciprocal = vmul_f32(vrecps_f32(val, reciprocal), reciprocal); + return reciprocal; +} + +inline float32x4_t cv_vrsqrtq_f32(float32x4_t val) +{ + float32x4_t e = vrsqrteq_f32(val); + e = vmulq_f32(vrsqrtsq_f32(vmulq_f32(e, e), val), e); + e = vmulq_f32(vrsqrtsq_f32(vmulq_f32(e, e), val), e); + return e; +} + +inline float32x2_t cv_vrsqrt_f32(float32x2_t val) +{ + float32x2_t e = vrsqrte_f32(val); + e = vmul_f32(vrsqrts_f32(vmul_f32(e, e), val), e); + e = vmul_f32(vrsqrts_f32(vmul_f32(e, e), val), e); + return e; +} + +inline float32x4_t cv_vsqrtq_f32(float32x4_t val) +{ + return cv_vrecpq_f32(cv_vrsqrtq_f32(val)); +} + +inline float32x2_t cv_vsqrt_f32(float32x2_t val) +{ + return cv_vrecp_f32(cv_vrsqrt_f32(val)); +} + +#endif + +//! @} core_utils_neon + +} // cv + +#include "sse_utils.hpp" + +#endif //__OPENCV_CORE_BASE_HPP__ diff --git a/include/opencv2/core/bufferpool.hpp b/include/opencv2/core/bufferpool.hpp new file mode 100644 index 0000000..76df2d2 --- /dev/null +++ b/include/opencv2/core/bufferpool.hpp @@ -0,0 +1,31 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. +// +// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved. + +#ifndef __OPENCV_CORE_BUFFER_POOL_HPP__ +#define __OPENCV_CORE_BUFFER_POOL_HPP__ + +namespace cv +{ + +//! @addtogroup core +//! @{ + +class BufferPoolController +{ +protected: + ~BufferPoolController() { } +public: + virtual size_t getReservedSize() const = 0; + virtual size_t getMaxReservedSize() const = 0; + virtual void setMaxReservedSize(size_t size) = 0; + virtual void freeAllReservedBuffers() = 0; +}; + +//! @} + +} + +#endif // __OPENCV_CORE_BUFFER_POOL_HPP__ diff --git a/include/opencv2/core/core.hpp b/include/opencv2/core/core.hpp new file mode 100644 index 0000000..4389183 --- /dev/null +++ b/include/opencv2/core/core.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/core.hpp" diff --git a/include/opencv2/core/core_c.h b/include/opencv2/core/core_c.h new file mode 100644 index 0000000..a0ed632 --- /dev/null +++ b/include/opencv2/core/core_c.h @@ -0,0 +1,3152 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + +#ifndef __OPENCV_CORE_C_H__ +#define __OPENCV_CORE_C_H__ + +#include "opencv2/core/types_c.h" + +#ifdef __cplusplus +# ifdef _MSC_VER +/* disable warning C4190: 'function' has C-linkage specified, but returns UDT 'typename' + which is incompatible with C + + It is OK to disable it because we only extend few plain structures with + C++ construrtors for simpler interoperability with C++ API of the library +*/ +# pragma warning(disable:4190) +# elif defined __clang__ && __clang_major__ >= 3 +# pragma GCC diagnostic ignored "-Wreturn-type-c-linkage" +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup core_c + @{ +*/ + +/****************************************************************************************\ +* Array allocation, deallocation, initialization and access to elements * +\****************************************************************************************/ + +/** `malloc` wrapper. + If there is no enough memory, the function + (as well as other OpenCV functions that call cvAlloc) + raises an error. */ +CVAPI(void*) cvAlloc( size_t size ); + +/** `free` wrapper. + Here and further all the memory releasing functions + (that all call cvFree) take double pointer in order to + to clear pointer to the data after releasing it. + Passing pointer to NULL pointer is Ok: nothing happens in this case +*/ +CVAPI(void) cvFree_( void* ptr ); +#define cvFree(ptr) (cvFree_(*(ptr)), *(ptr)=0) + +/** @brief Creates an image header but does not allocate the image data. + +@param size Image width and height +@param depth Image depth (see cvCreateImage ) +@param channels Number of channels (see cvCreateImage ) + */ +CVAPI(IplImage*) cvCreateImageHeader( CvSize size, int depth, int channels ); + +/** @brief Initializes an image header that was previously allocated. + +The returned IplImage\* points to the initialized header. +@param image Image header to initialize +@param size Image width and height +@param depth Image depth (see cvCreateImage ) +@param channels Number of channels (see cvCreateImage ) +@param origin Top-left IPL_ORIGIN_TL or bottom-left IPL_ORIGIN_BL +@param align Alignment for image rows, typically 4 or 8 bytes + */ +CVAPI(IplImage*) cvInitImageHeader( IplImage* image, CvSize size, int depth, + int channels, int origin CV_DEFAULT(0), + int align CV_DEFAULT(4)); + +/** @brief Creates an image header and allocates the image data. + +This function call is equivalent to the following code: +@code + header = cvCreateImageHeader(size, depth, channels); + cvCreateData(header); +@endcode +@param size Image width and height +@param depth Bit depth of image elements. See IplImage for valid depths. +@param channels Number of channels per pixel. See IplImage for details. This function only creates +images with interleaved channels. + */ +CVAPI(IplImage*) cvCreateImage( CvSize size, int depth, int channels ); + +/** @brief Deallocates an image header. + +This call is an analogue of : +@code + if(image ) + { + iplDeallocate(*image, IPL_IMAGE_HEADER | IPL_IMAGE_ROI); + *image = 0; + } +@endcode +but it does not use IPL functions by default (see the CV_TURN_ON_IPL_COMPATIBILITY macro). +@param image Double pointer to the image header + */ +CVAPI(void) cvReleaseImageHeader( IplImage** image ); + +/** @brief Deallocates the image header and the image data. + +This call is a shortened form of : +@code + if(*image ) + { + cvReleaseData(*image); + cvReleaseImageHeader(image); + } +@endcode +@param image Double pointer to the image header +*/ +CVAPI(void) cvReleaseImage( IplImage** image ); + +/** Creates a copy of IPL image (widthStep may differ) */ +CVAPI(IplImage*) cvCloneImage( const IplImage* image ); + +/** @brief Sets the channel of interest in an IplImage. + +If the ROI is set to NULL and the coi is *not* 0, the ROI is allocated. Most OpenCV functions do +*not* support the COI setting, so to process an individual image/matrix channel one may copy (via +cvCopy or cvSplit) the channel to a separate image/matrix, process it and then copy the result +back (via cvCopy or cvMerge) if needed. +@param image A pointer to the image header +@param coi The channel of interest. 0 - all channels are selected, 1 - first channel is selected, +etc. Note that the channel indices become 1-based. + */ +CVAPI(void) cvSetImageCOI( IplImage* image, int coi ); + +/** @brief Returns the index of the channel of interest. + +Returns the channel of interest of in an IplImage. Returned values correspond to the coi in +cvSetImageCOI. +@param image A pointer to the image header + */ +CVAPI(int) cvGetImageCOI( const IplImage* image ); + +/** @brief Sets an image Region Of Interest (ROI) for a given rectangle. + +If the original image ROI was NULL and the rect is not the whole image, the ROI structure is +allocated. + +Most OpenCV functions support the use of ROI and treat the image rectangle as a separate image. For +example, all of the pixel coordinates are counted from the top-left (or bottom-left) corner of the +ROI, not the original image. +@param image A pointer to the image header +@param rect The ROI rectangle + */ +CVAPI(void) cvSetImageROI( IplImage* image, CvRect rect ); + +/** @brief Resets the image ROI to include the entire image and releases the ROI structure. + +This produces a similar result to the following, but in addition it releases the ROI structure. : +@code + cvSetImageROI(image, cvRect(0, 0, image->width, image->height )); + cvSetImageCOI(image, 0); +@endcode +@param image A pointer to the image header + */ +CVAPI(void) cvResetImageROI( IplImage* image ); + +/** @brief Returns the image ROI. + +If there is no ROI set, cvRect(0,0,image-\>width,image-\>height) is returned. +@param image A pointer to the image header + */ +CVAPI(CvRect) cvGetImageROI( const IplImage* image ); + +/** @brief Creates a matrix header but does not allocate the matrix data. + +The function allocates a new matrix header and returns a pointer to it. The matrix data can then be +allocated using cvCreateData or set explicitly to user-allocated data via cvSetData. +@param rows Number of rows in the matrix +@param cols Number of columns in the matrix +@param type Type of the matrix elements, see cvCreateMat + */ +CVAPI(CvMat*) cvCreateMatHeader( int rows, int cols, int type ); + +#define CV_AUTOSTEP 0x7fffffff + +/** @brief Initializes a pre-allocated matrix header. + +This function is often used to process raw data with OpenCV matrix functions. For example, the +following code computes the matrix product of two matrices, stored as ordinary arrays: +@code + double a[] = { 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12 }; + + double b[] = { 1, 5, 9, + 2, 6, 10, + 3, 7, 11, + 4, 8, 12 }; + + double c[9]; + CvMat Ma, Mb, Mc ; + + cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a); + cvInitMatHeader(&Mb, 4, 3, CV_64FC1, b); + cvInitMatHeader(&Mc, 3, 3, CV_64FC1, c); + + cvMatMulAdd(&Ma, &Mb, 0, &Mc); + // the c array now contains the product of a (3x4) and b (4x3) +@endcode +@param mat A pointer to the matrix header to be initialized +@param rows Number of rows in the matrix +@param cols Number of columns in the matrix +@param type Type of the matrix elements, see cvCreateMat . +@param data Optional: data pointer assigned to the matrix header +@param step Optional: full row width in bytes of the assigned data. By default, the minimal +possible step is used which assumes there are no gaps between subsequent rows of the matrix. + */ +CVAPI(CvMat*) cvInitMatHeader( CvMat* mat, int rows, int cols, + int type, void* data CV_DEFAULT(NULL), + int step CV_DEFAULT(CV_AUTOSTEP) ); + +/** @brief Creates a matrix header and allocates the matrix data. + +The function call is equivalent to the following code: +@code + CvMat* mat = cvCreateMatHeader(rows, cols, type); + cvCreateData(mat); +@endcode +@param rows Number of rows in the matrix +@param cols Number of columns in the matrix +@param type The type of the matrix elements in the form +CV_\\C\ , where S=signed, U=unsigned, F=float. For +example, CV _ 8UC1 means the elements are 8-bit unsigned and the there is 1 channel, and CV _ +32SC2 means the elements are 32-bit signed and there are 2 channels. + */ +CVAPI(CvMat*) cvCreateMat( int rows, int cols, int type ); + +/** @brief Deallocates a matrix. + +The function decrements the matrix data reference counter and deallocates matrix header. If the data +reference counter is 0, it also deallocates the data. : +@code + if(*mat ) + cvDecRefData(*mat); + cvFree((void**)mat); +@endcode +@param mat Double pointer to the matrix + */ +CVAPI(void) cvReleaseMat( CvMat** mat ); + +/** @brief Decrements an array data reference counter. + +The function decrements the data reference counter in a CvMat or CvMatND if the reference counter + +pointer is not NULL. If the counter reaches zero, the data is deallocated. In the current +implementation the reference counter is not NULL only if the data was allocated using the +cvCreateData function. The counter will be NULL in other cases such as: external data was assigned +to the header using cvSetData, header is part of a larger matrix or image, or the header was +converted from an image or n-dimensional matrix header. +@param arr Pointer to an array header + */ +CV_INLINE void cvDecRefData( CvArr* arr ) +{ + if( CV_IS_MAT( arr )) + { + CvMat* mat = (CvMat*)arr; + mat->data.ptr = NULL; + if( mat->refcount != NULL && --*mat->refcount == 0 ) + cvFree( &mat->refcount ); + mat->refcount = NULL; + } + else if( CV_IS_MATND( arr )) + { + CvMatND* mat = (CvMatND*)arr; + mat->data.ptr = NULL; + if( mat->refcount != NULL && --*mat->refcount == 0 ) + cvFree( &mat->refcount ); + mat->refcount = NULL; + } +} + +/** @brief Increments array data reference counter. + +The function increments CvMat or CvMatND data reference counter and returns the new counter value if +the reference counter pointer is not NULL, otherwise it returns zero. +@param arr Array header + */ +CV_INLINE int cvIncRefData( CvArr* arr ) +{ + int refcount = 0; + if( CV_IS_MAT( arr )) + { + CvMat* mat = (CvMat*)arr; + if( mat->refcount != NULL ) + refcount = ++*mat->refcount; + } + else if( CV_IS_MATND( arr )) + { + CvMatND* mat = (CvMatND*)arr; + if( mat->refcount != NULL ) + refcount = ++*mat->refcount; + } + return refcount; +} + + +/** Creates an exact copy of the input matrix (except, may be, step value) */ +CVAPI(CvMat*) cvCloneMat( const CvMat* mat ); + + +/** @brief Returns matrix header corresponding to the rectangular sub-array of input image or matrix. + +The function returns header, corresponding to a specified rectangle of the input array. In other + +words, it allows the user to treat a rectangular part of input array as a stand-alone array. ROI is +taken into account by the function so the sub-array of ROI is actually extracted. +@param arr Input array +@param submat Pointer to the resultant sub-array header +@param rect Zero-based coordinates of the rectangle of interest + */ +CVAPI(CvMat*) cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect ); +#define cvGetSubArr cvGetSubRect + +/** @brief Returns array row or row span. + +The functions return the header, corresponding to a specified row/row span of the input array. +cvGetRow(arr, submat, row) is a shortcut for cvGetRows(arr, submat, row, row+1). +@param arr Input array +@param submat Pointer to the resulting sub-array header +@param start_row Zero-based index of the starting row (inclusive) of the span +@param end_row Zero-based index of the ending row (exclusive) of the span +@param delta_row Index step in the row span. That is, the function extracts every delta_row -th +row from start_row and up to (but not including) end_row . + */ +CVAPI(CvMat*) cvGetRows( const CvArr* arr, CvMat* submat, + int start_row, int end_row, + int delta_row CV_DEFAULT(1)); + +/** @overload +@param arr Input array +@param submat Pointer to the resulting sub-array header +@param row Zero-based index of the selected row +*/ +CV_INLINE CvMat* cvGetRow( const CvArr* arr, CvMat* submat, int row ) +{ + return cvGetRows( arr, submat, row, row + 1, 1 ); +} + + +/** @brief Returns one of more array columns. + +The functions return the header, corresponding to a specified column span of the input array. That + +is, no data is copied. Therefore, any modifications of the submatrix will affect the original array. +If you need to copy the columns, use cvCloneMat. cvGetCol(arr, submat, col) is a shortcut for +cvGetCols(arr, submat, col, col+1). +@param arr Input array +@param submat Pointer to the resulting sub-array header +@param start_col Zero-based index of the starting column (inclusive) of the span +@param end_col Zero-based index of the ending column (exclusive) of the span + */ +CVAPI(CvMat*) cvGetCols( const CvArr* arr, CvMat* submat, + int start_col, int end_col ); + +/** @overload +@param arr Input array +@param submat Pointer to the resulting sub-array header +@param col Zero-based index of the selected column +*/ +CV_INLINE CvMat* cvGetCol( const CvArr* arr, CvMat* submat, int col ) +{ + return cvGetCols( arr, submat, col, col + 1 ); +} + +/** @brief Returns one of array diagonals. + +The function returns the header, corresponding to a specified diagonal of the input array. +@param arr Input array +@param submat Pointer to the resulting sub-array header +@param diag Index of the array diagonal. Zero value corresponds to the main diagonal, -1 +corresponds to the diagonal above the main, 1 corresponds to the diagonal below the main, and so +forth. + */ +CVAPI(CvMat*) cvGetDiag( const CvArr* arr, CvMat* submat, + int diag CV_DEFAULT(0)); + +/** low-level scalar <-> raw data conversion functions */ +CVAPI(void) cvScalarToRawData( const CvScalar* scalar, void* data, int type, + int extend_to_12 CV_DEFAULT(0) ); + +CVAPI(void) cvRawDataToScalar( const void* data, int type, CvScalar* scalar ); + +/** @brief Creates a new matrix header but does not allocate the matrix data. + +The function allocates a header for a multi-dimensional dense array. The array data can further be +allocated using cvCreateData or set explicitly to user-allocated data via cvSetData. +@param dims Number of array dimensions +@param sizes Array of dimension sizes +@param type Type of array elements, see cvCreateMat + */ +CVAPI(CvMatND*) cvCreateMatNDHeader( int dims, const int* sizes, int type ); + +/** @brief Creates the header and allocates the data for a multi-dimensional dense array. + +This function call is equivalent to the following code: +@code + CvMatND* mat = cvCreateMatNDHeader(dims, sizes, type); + cvCreateData(mat); +@endcode +@param dims Number of array dimensions. This must not exceed CV_MAX_DIM (32 by default, but can be +changed at build time). +@param sizes Array of dimension sizes. +@param type Type of array elements, see cvCreateMat . + */ +CVAPI(CvMatND*) cvCreateMatND( int dims, const int* sizes, int type ); + +/** @brief Initializes a pre-allocated multi-dimensional array header. + +@param mat A pointer to the array header to be initialized +@param dims The number of array dimensions +@param sizes An array of dimension sizes +@param type Type of array elements, see cvCreateMat +@param data Optional data pointer assigned to the matrix header + */ +CVAPI(CvMatND*) cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes, + int type, void* data CV_DEFAULT(NULL) ); + +/** @brief Deallocates a multi-dimensional array. + +The function decrements the array data reference counter and releases the array header. If the +reference counter reaches 0, it also deallocates the data. : +@code + if(*mat ) + cvDecRefData(*mat); + cvFree((void**)mat); +@endcode +@param mat Double pointer to the array + */ +CV_INLINE void cvReleaseMatND( CvMatND** mat ) +{ + cvReleaseMat( (CvMat**)mat ); +} + +/** Creates a copy of CvMatND (except, may be, steps) */ +CVAPI(CvMatND*) cvCloneMatND( const CvMatND* mat ); + +/** @brief Creates sparse array. + +The function allocates a multi-dimensional sparse array. Initially the array contain no elements, +that is PtrND and other related functions will return 0 for every index. +@param dims Number of array dimensions. In contrast to the dense matrix, the number of dimensions is +practically unlimited (up to \f$2^{16}\f$ ). +@param sizes Array of dimension sizes +@param type Type of array elements. The same as for CvMat + */ +CVAPI(CvSparseMat*) cvCreateSparseMat( int dims, const int* sizes, int type ); + +/** @brief Deallocates sparse array. + +The function releases the sparse array and clears the array pointer upon exit. +@param mat Double pointer to the array + */ +CVAPI(void) cvReleaseSparseMat( CvSparseMat** mat ); + +/** Creates a copy of CvSparseMat (except, may be, zero items) */ +CVAPI(CvSparseMat*) cvCloneSparseMat( const CvSparseMat* mat ); + +/** @brief Initializes sparse array elements iterator. + +The function initializes iterator of sparse array elements and returns pointer to the first element, +or NULL if the array is empty. +@param mat Input array +@param mat_iterator Initialized iterator + */ +CVAPI(CvSparseNode*) cvInitSparseMatIterator( const CvSparseMat* mat, + CvSparseMatIterator* mat_iterator ); + +/** @brief Returns the next sparse matrix element + +The function moves iterator to the next sparse matrix element and returns pointer to it. In the +current version there is no any particular order of the elements, because they are stored in the +hash table. The sample below demonstrates how to iterate through the sparse matrix: +@code + // print all the non-zero sparse matrix elements and compute their sum + double sum = 0; + int i, dims = cvGetDims(sparsemat); + CvSparseMatIterator it; + CvSparseNode* node = cvInitSparseMatIterator(sparsemat, &it); + + for(; node != 0; node = cvGetNextSparseNode(&it)) + { + int* idx = CV_NODE_IDX(array, node); + float val = *(float*)CV_NODE_VAL(array, node); + printf("M"); + for(i = 0; i < dims; i++ ) + printf("[%d]", idx[i]); + printf("=%g\n", val); + + sum += val; + } + + printf("nTotal sum = %g\n", sum); +@endcode +@param mat_iterator Sparse array iterator + */ +CV_INLINE CvSparseNode* cvGetNextSparseNode( CvSparseMatIterator* mat_iterator ) +{ + if( mat_iterator->node->next ) + return mat_iterator->node = mat_iterator->node->next; + else + { + int idx; + for( idx = ++mat_iterator->curidx; idx < mat_iterator->mat->hashsize; idx++ ) + { + CvSparseNode* node = (CvSparseNode*)mat_iterator->mat->hashtable[idx]; + if( node ) + { + mat_iterator->curidx = idx; + return mat_iterator->node = node; + } + } + return NULL; + } +} + + +#define CV_MAX_ARR 10 + +/** matrix iterator: used for n-ary operations on dense arrays */ +typedef struct CvNArrayIterator +{ + int count; /**< number of arrays */ + int dims; /**< number of dimensions to iterate */ + CvSize size; /**< maximal common linear size: { width = size, height = 1 } */ + uchar* ptr[CV_MAX_ARR]; /**< pointers to the array slices */ + int stack[CV_MAX_DIM]; /**< for internal use */ + CvMatND* hdr[CV_MAX_ARR]; /**< pointers to the headers of the + matrices that are processed */ +} +CvNArrayIterator; + +#define CV_NO_DEPTH_CHECK 1 +#define CV_NO_CN_CHECK 2 +#define CV_NO_SIZE_CHECK 4 + +/** initializes iterator that traverses through several arrays simulteneously + (the function together with cvNextArraySlice is used for + N-ari element-wise operations) */ +CVAPI(int) cvInitNArrayIterator( int count, CvArr** arrs, + const CvArr* mask, CvMatND* stubs, + CvNArrayIterator* array_iterator, + int flags CV_DEFAULT(0) ); + +/** returns zero value if iteration is finished, non-zero (slice length) otherwise */ +CVAPI(int) cvNextNArraySlice( CvNArrayIterator* array_iterator ); + + +/** @brief Returns type of array elements. + +The function returns type of the array elements. In the case of IplImage the type is converted to +CvMat-like representation. For example, if the image has been created as: +@code + IplImage* img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 3); +@endcode +The code cvGetElemType(img) will return CV_8UC3. +@param arr Input array + */ +CVAPI(int) cvGetElemType( const CvArr* arr ); + +/** @brief Return number of array dimensions + +The function returns the array dimensionality and the array of dimension sizes. In the case of +IplImage or CvMat it always returns 2 regardless of number of image/matrix rows. For example, the +following code calculates total number of array elements: +@code + int sizes[CV_MAX_DIM]; + int i, total = 1; + int dims = cvGetDims(arr, size); + for(i = 0; i < dims; i++ ) + total *= sizes[i]; +@endcode +@param arr Input array +@param sizes Optional output vector of the array dimension sizes. For 2d arrays the number of rows +(height) goes first, number of columns (width) next. + */ +CVAPI(int) cvGetDims( const CvArr* arr, int* sizes CV_DEFAULT(NULL) ); + + +/** @brief Returns array size along the specified dimension. + +@param arr Input array +@param index Zero-based dimension index (for matrices 0 means number of rows, 1 means number of +columns; for images 0 means height, 1 means width) + */ +CVAPI(int) cvGetDimSize( const CvArr* arr, int index ); + + +/** @brief Return pointer to a particular array element. + +The functions return a pointer to a specific array element. Number of array dimension should match +to the number of indices passed to the function except for cvPtr1D function that can be used for +sequential access to 1D, 2D or nD dense arrays. + +The functions can be used for sparse arrays as well - if the requested node does not exist they +create it and set it to zero. + +All these as well as other functions accessing array elements ( cvGetND , cvGetRealND , cvSet +, cvSetND , cvSetRealND ) raise an error in case if the element index is out of range. +@param arr Input array +@param idx0 The first zero-based component of the element index +@param type Optional output parameter: type of matrix elements + */ +CVAPI(uchar*) cvPtr1D( const CvArr* arr, int idx0, int* type CV_DEFAULT(NULL)); +/** @overload */ +CVAPI(uchar*) cvPtr2D( const CvArr* arr, int idx0, int idx1, int* type CV_DEFAULT(NULL) ); +/** @overload */ +CVAPI(uchar*) cvPtr3D( const CvArr* arr, int idx0, int idx1, int idx2, + int* type CV_DEFAULT(NULL)); +/** @overload +@param arr Input array +@param idx Array of the element indices +@param type Optional output parameter: type of matrix elements +@param create_node Optional input parameter for sparse matrices. Non-zero value of the parameter +means that the requested element is created if it does not exist already. +@param precalc_hashval Optional input parameter for sparse matrices. If the pointer is not NULL, +the function does not recalculate the node hash value, but takes it from the specified location. +It is useful for speeding up pair-wise operations (TODO: provide an example) +*/ +CVAPI(uchar*) cvPtrND( const CvArr* arr, const int* idx, int* type CV_DEFAULT(NULL), + int create_node CV_DEFAULT(1), + unsigned* precalc_hashval CV_DEFAULT(NULL)); + +/** @brief Return a specific array element. + +The functions return a specific array element. In the case of a sparse array the functions return 0 +if the requested node does not exist (no new node is created by the functions). +@param arr Input array +@param idx0 The first zero-based component of the element index + */ +CVAPI(CvScalar) cvGet1D( const CvArr* arr, int idx0 ); +/** @overload */ +CVAPI(CvScalar) cvGet2D( const CvArr* arr, int idx0, int idx1 ); +/** @overload */ +CVAPI(CvScalar) cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 ); +/** @overload +@param arr Input array +@param idx Array of the element indices +*/ +CVAPI(CvScalar) cvGetND( const CvArr* arr, const int* idx ); + +/** @brief Return a specific element of single-channel 1D, 2D, 3D or nD array. + +Returns a specific element of a single-channel array. If the array has multiple channels, a runtime +error is raised. Note that Get?D functions can be used safely for both single-channel and +multiple-channel arrays though they are a bit slower. + +In the case of a sparse array the functions return 0 if the requested node does not exist (no new +node is created by the functions). +@param arr Input array. Must have a single channel. +@param idx0 The first zero-based component of the element index + */ +CVAPI(double) cvGetReal1D( const CvArr* arr, int idx0 ); +/** @overload */ +CVAPI(double) cvGetReal2D( const CvArr* arr, int idx0, int idx1 ); +/** @overload */ +CVAPI(double) cvGetReal3D( const CvArr* arr, int idx0, int idx1, int idx2 ); +/** @overload +@param arr Input array. Must have a single channel. +@param idx Array of the element indices +*/ +CVAPI(double) cvGetRealND( const CvArr* arr, const int* idx ); + +/** @brief Change the particular array element. + +The functions assign the new value to a particular array element. In the case of a sparse array the +functions create the node if it does not exist yet. +@param arr Input array +@param idx0 The first zero-based component of the element index +@param value The assigned value + */ +CVAPI(void) cvSet1D( CvArr* arr, int idx0, CvScalar value ); +/** @overload */ +CVAPI(void) cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value ); +/** @overload */ +CVAPI(void) cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value ); +/** @overload +@param arr Input array +@param idx Array of the element indices +@param value The assigned value +*/ +CVAPI(void) cvSetND( CvArr* arr, const int* idx, CvScalar value ); + +/** @brief Change a specific array element. + +The functions assign a new value to a specific element of a single-channel array. If the array has +multiple channels, a runtime error is raised. Note that the Set\*D function can be used safely for +both single-channel and multiple-channel arrays, though they are a bit slower. + +In the case of a sparse array the functions create the node if it does not yet exist. +@param arr Input array +@param idx0 The first zero-based component of the element index +@param value The assigned value + */ +CVAPI(void) cvSetReal1D( CvArr* arr, int idx0, double value ); +/** @overload */ +CVAPI(void) cvSetReal2D( CvArr* arr, int idx0, int idx1, double value ); +/** @overload */ +CVAPI(void) cvSetReal3D( CvArr* arr, int idx0, + int idx1, int idx2, double value ); +/** @overload +@param arr Input array +@param idx Array of the element indices +@param value The assigned value +*/ +CVAPI(void) cvSetRealND( CvArr* arr, const int* idx, double value ); + +/** clears element of ND dense array, + in case of sparse arrays it deletes the specified node */ +CVAPI(void) cvClearND( CvArr* arr, const int* idx ); + +/** @brief Returns matrix header for arbitrary array. + +The function returns a matrix header for the input array that can be a matrix - CvMat, an image - +IplImage, or a multi-dimensional dense array - CvMatND (the third option is allowed only if +allowND != 0) . In the case of matrix the function simply returns the input pointer. In the case of +IplImage\* or CvMatND it initializes the header structure with parameters of the current image ROI +and returns &header. Because COI is not supported by CvMat, it is returned separately. + +The function provides an easy way to handle both types of arrays - IplImage and CvMat using the same +code. Input array must have non-zero data pointer, otherwise the function will report an error. + +@note If the input array is IplImage with planar data layout and COI set, the function returns the +pointer to the selected plane and COI == 0. This feature allows user to process IplImage structures +with planar data layout, even though OpenCV does not support such images. +@param arr Input array +@param header Pointer to CvMat structure used as a temporary buffer +@param coi Optional output parameter for storing COI +@param allowND If non-zero, the function accepts multi-dimensional dense arrays (CvMatND\*) and +returns 2D matrix (if CvMatND has two dimensions) or 1D matrix (when CvMatND has 1 dimension or +more than 2 dimensions). The CvMatND array must be continuous. +@sa cvGetImage, cvarrToMat. + */ +CVAPI(CvMat*) cvGetMat( const CvArr* arr, CvMat* header, + int* coi CV_DEFAULT(NULL), + int allowND CV_DEFAULT(0)); + +/** @brief Returns image header for arbitrary array. + +The function returns the image header for the input array that can be a matrix (CvMat) or image +(IplImage). In the case of an image the function simply returns the input pointer. In the case of +CvMat it initializes an image_header structure with the parameters of the input matrix. Note that +if we transform IplImage to CvMat using cvGetMat and then transform CvMat back to IplImage using +this function, we will get different headers if the ROI is set in the original image. +@param arr Input array +@param image_header Pointer to IplImage structure used as a temporary buffer + */ +CVAPI(IplImage*) cvGetImage( const CvArr* arr, IplImage* image_header ); + + +/** @brief Changes the shape of a multi-dimensional array without copying the data. + +The function is an advanced version of cvReshape that can work with multi-dimensional arrays as +well (though it can work with ordinary images and matrices) and change the number of dimensions. + +Below are the two samples from the cvReshape description rewritten using cvReshapeMatND: +@code + IplImage* color_img = cvCreateImage(cvSize(320,240), IPL_DEPTH_8U, 3); + IplImage gray_img_hdr, *gray_img; + gray_img = (IplImage*)cvReshapeMatND(color_img, sizeof(gray_img_hdr), &gray_img_hdr, 1, 0, 0); + ... + int size[] = { 2, 2, 2 }; + CvMatND* mat = cvCreateMatND(3, size, CV_32F); + CvMat row_header, *row; + row = (CvMat*)cvReshapeMatND(mat, sizeof(row_header), &row_header, 0, 1, 0); +@endcode +In C, the header file for this function includes a convenient macro cvReshapeND that does away with +the sizeof_header parameter. So, the lines containing the call to cvReshapeMatND in the examples +may be replaced as follow: +@code + gray_img = (IplImage*)cvReshapeND(color_img, &gray_img_hdr, 1, 0, 0); + ... + row = (CvMat*)cvReshapeND(mat, &row_header, 0, 1, 0); +@endcode +@param arr Input array +@param sizeof_header Size of output header to distinguish between IplImage, CvMat and CvMatND +output headers +@param header Output header to be filled +@param new_cn New number of channels. new_cn = 0 means that the number of channels remains +unchanged. +@param new_dims New number of dimensions. new_dims = 0 means that the number of dimensions +remains the same. +@param new_sizes Array of new dimension sizes. Only new_dims-1 values are used, because the +total number of elements must remain the same. Thus, if new_dims = 1, new_sizes array is not +used. + */ +CVAPI(CvArr*) cvReshapeMatND( const CvArr* arr, + int sizeof_header, CvArr* header, + int new_cn, int new_dims, int* new_sizes ); + +#define cvReshapeND( arr, header, new_cn, new_dims, new_sizes ) \ + cvReshapeMatND( (arr), sizeof(*(header)), (header), \ + (new_cn), (new_dims), (new_sizes)) + +/** @brief Changes shape of matrix/image without copying data. + +The function initializes the CvMat header so that it points to the same data as the original array +but has a different shape - different number of channels, different number of rows, or both. + +The following example code creates one image buffer and two image headers, the first is for a +320x240x3 image and the second is for a 960x240x1 image: +@code + IplImage* color_img = cvCreateImage(cvSize(320,240), IPL_DEPTH_8U, 3); + CvMat gray_mat_hdr; + IplImage gray_img_hdr, *gray_img; + cvReshape(color_img, &gray_mat_hdr, 1); + gray_img = cvGetImage(&gray_mat_hdr, &gray_img_hdr); +@endcode +And the next example converts a 3x3 matrix to a single 1x9 vector: +@code + CvMat* mat = cvCreateMat(3, 3, CV_32F); + CvMat row_header, *row; + row = cvReshape(mat, &row_header, 0, 1); +@endcode +@param arr Input array +@param header Output header to be filled +@param new_cn New number of channels. 'new_cn = 0' means that the number of channels remains +unchanged. +@param new_rows New number of rows. 'new_rows = 0' means that the number of rows remains +unchanged unless it needs to be changed according to new_cn value. +*/ +CVAPI(CvMat*) cvReshape( const CvArr* arr, CvMat* header, + int new_cn, int new_rows CV_DEFAULT(0) ); + +/** Repeats source 2d array several times in both horizontal and + vertical direction to fill destination array */ +CVAPI(void) cvRepeat( const CvArr* src, CvArr* dst ); + +/** @brief Allocates array data + +The function allocates image, matrix or multi-dimensional dense array data. Note that in the case of +matrix types OpenCV allocation functions are used. In the case of IplImage they are used unless +CV_TURN_ON_IPL_COMPATIBILITY() has been called before. In the latter case IPL functions are used +to allocate the data. +@param arr Array header + */ +CVAPI(void) cvCreateData( CvArr* arr ); + +/** @brief Releases array data. + +The function releases the array data. In the case of CvMat or CvMatND it simply calls +cvDecRefData(), that is the function can not deallocate external data. See also the note to +cvCreateData . +@param arr Array header + */ +CVAPI(void) cvReleaseData( CvArr* arr ); + +/** @brief Assigns user data to the array header. + +The function assigns user data to the array header. Header should be initialized before using +cvCreateMatHeader, cvCreateImageHeader, cvCreateMatNDHeader, cvInitMatHeader, +cvInitImageHeader or cvInitMatNDHeader. +@param arr Array header +@param data User data +@param step Full row length in bytes + */ +CVAPI(void) cvSetData( CvArr* arr, void* data, int step ); + +/** @brief Retrieves low-level information about the array. + +The function fills output variables with low-level information about the array data. All output + +parameters are optional, so some of the pointers may be set to NULL. If the array is IplImage with +ROI set, the parameters of ROI are returned. + +The following example shows how to get access to array elements. It computes absolute values of the +array elements : +@code + float* data; + int step; + CvSize size; + + cvGetRawData(array, (uchar**)&data, &step, &size); + step /= sizeof(data[0]); + + for(int y = 0; y < size.height; y++, data += step ) + for(int x = 0; x < size.width; x++ ) + data[x] = (float)fabs(data[x]); +@endcode +@param arr Array header +@param data Output pointer to the whole image origin or ROI origin if ROI is set +@param step Output full row length in bytes +@param roi_size Output ROI size + */ +CVAPI(void) cvGetRawData( const CvArr* arr, uchar** data, + int* step CV_DEFAULT(NULL), + CvSize* roi_size CV_DEFAULT(NULL)); + +/** @brief Returns size of matrix or image ROI. + +The function returns number of rows (CvSize::height) and number of columns (CvSize::width) of the +input matrix or image. In the case of image the size of ROI is returned. +@param arr array header + */ +CVAPI(CvSize) cvGetSize( const CvArr* arr ); + +/** @brief Copies one array to another. + +The function copies selected elements from an input array to an output array: + +\f[\texttt{dst} (I)= \texttt{src} (I) \quad \text{if} \quad \texttt{mask} (I) \ne 0.\f] + +If any of the passed arrays is of IplImage type, then its ROI and COI fields are used. Both arrays +must have the same type, the same number of dimensions, and the same size. The function can also +copy sparse arrays (mask is not supported in this case). +@param src The source array +@param dst The destination array +@param mask Operation mask, 8-bit single channel array; specifies elements of the destination array +to be changed + */ +CVAPI(void) cvCopy( const CvArr* src, CvArr* dst, + const CvArr* mask CV_DEFAULT(NULL) ); + +/** @brief Sets every element of an array to a given value. + +The function copies the scalar value to every selected element of the destination array: +\f[\texttt{arr} (I)= \texttt{value} \quad \text{if} \quad \texttt{mask} (I) \ne 0\f] +If array arr is of IplImage type, then is ROI used, but COI must not be set. +@param arr The destination array +@param value Fill value +@param mask Operation mask, 8-bit single channel array; specifies elements of the destination +array to be changed + */ +CVAPI(void) cvSet( CvArr* arr, CvScalar value, + const CvArr* mask CV_DEFAULT(NULL) ); + +/** @brief Clears the array. + +The function clears the array. In the case of dense arrays (CvMat, CvMatND or IplImage), +cvZero(array) is equivalent to cvSet(array,cvScalarAll(0),0). In the case of sparse arrays all the +elements are removed. +@param arr Array to be cleared + */ +CVAPI(void) cvSetZero( CvArr* arr ); +#define cvZero cvSetZero + + +/** Splits a multi-channel array into the set of single-channel arrays or + extracts particular [color] plane */ +CVAPI(void) cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1, + CvArr* dst2, CvArr* dst3 ); + +/** Merges a set of single-channel arrays into the single multi-channel array + or inserts one particular [color] plane to the array */ +CVAPI(void) cvMerge( const CvArr* src0, const CvArr* src1, + const CvArr* src2, const CvArr* src3, + CvArr* dst ); + +/** Copies several channels from input arrays to + certain channels of output arrays */ +CVAPI(void) cvMixChannels( const CvArr** src, int src_count, + CvArr** dst, int dst_count, + const int* from_to, int pair_count ); + +/** @brief Converts one array to another with optional linear transformation. + +The function has several different purposes, and thus has several different names. It copies one +array to another with optional scaling, which is performed first, and/or optional type conversion, +performed after: + +\f[\texttt{dst} (I) = \texttt{scale} \texttt{src} (I) + ( \texttt{shift} _0, \texttt{shift} _1,...)\f] + +All the channels of multi-channel arrays are processed independently. + +The type of conversion is done with rounding and saturation, that is if the result of scaling + +conversion can not be represented exactly by a value of the destination array element type, it is +set to the nearest representable value on the real axis. +@param src Source array +@param dst Destination array +@param scale Scale factor +@param shift Value added to the scaled source array elements + */ +CVAPI(void) cvConvertScale( const CvArr* src, CvArr* dst, + double scale CV_DEFAULT(1), + double shift CV_DEFAULT(0) ); +#define cvCvtScale cvConvertScale +#define cvScale cvConvertScale +#define cvConvert( src, dst ) cvConvertScale( (src), (dst), 1, 0 ) + + +/** Performs linear transformation on every source array element, + stores absolute value of the result: + dst(x,y,c) = abs(scale*src(x,y,c)+shift). + destination array must have 8u type. + In other cases one may use cvConvertScale + cvAbsDiffS */ +CVAPI(void) cvConvertScaleAbs( const CvArr* src, CvArr* dst, + double scale CV_DEFAULT(1), + double shift CV_DEFAULT(0) ); +#define cvCvtScaleAbs cvConvertScaleAbs + + +/** checks termination criteria validity and + sets eps to default_eps (if it is not set), + max_iter to default_max_iters (if it is not set) +*/ +CVAPI(CvTermCriteria) cvCheckTermCriteria( CvTermCriteria criteria, + double default_eps, + int default_max_iters ); + +/****************************************************************************************\ +* Arithmetic, logic and comparison operations * +\****************************************************************************************/ + +/** dst(mask) = src1(mask) + src2(mask) */ +CVAPI(void) cvAdd( const CvArr* src1, const CvArr* src2, CvArr* dst, + const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(mask) = src(mask) + value */ +CVAPI(void) cvAddS( const CvArr* src, CvScalar value, CvArr* dst, + const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(mask) = src1(mask) - src2(mask) */ +CVAPI(void) cvSub( const CvArr* src1, const CvArr* src2, CvArr* dst, + const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(mask) = src(mask) - value = src(mask) + (-value) */ +CV_INLINE void cvSubS( const CvArr* src, CvScalar value, CvArr* dst, + const CvArr* mask CV_DEFAULT(NULL)) +{ + cvAddS( src, cvScalar( -value.val[0], -value.val[1], -value.val[2], -value.val[3]), + dst, mask ); +} + +/** dst(mask) = value - src(mask) */ +CVAPI(void) cvSubRS( const CvArr* src, CvScalar value, CvArr* dst, + const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(idx) = src1(idx) * src2(idx) * scale + (scaled element-wise multiplication of 2 arrays) */ +CVAPI(void) cvMul( const CvArr* src1, const CvArr* src2, + CvArr* dst, double scale CV_DEFAULT(1) ); + +/** element-wise division/inversion with scaling: + dst(idx) = src1(idx) * scale / src2(idx) + or dst(idx) = scale / src2(idx) if src1 == 0 */ +CVAPI(void) cvDiv( const CvArr* src1, const CvArr* src2, + CvArr* dst, double scale CV_DEFAULT(1)); + +/** dst = src1 * scale + src2 */ +CVAPI(void) cvScaleAdd( const CvArr* src1, CvScalar scale, + const CvArr* src2, CvArr* dst ); +#define cvAXPY( A, real_scalar, B, C ) cvScaleAdd(A, cvRealScalar(real_scalar), B, C) + +/** dst = src1 * alpha + src2 * beta + gamma */ +CVAPI(void) cvAddWeighted( const CvArr* src1, double alpha, + const CvArr* src2, double beta, + double gamma, CvArr* dst ); + +/** @brief Calculates the dot product of two arrays in Euclidean metrics. + +The function calculates and returns the Euclidean dot product of two arrays. + +\f[src1 \bullet src2 = \sum _I ( \texttt{src1} (I) \texttt{src2} (I))\f] + +In the case of multiple channel arrays, the results for all channels are accumulated. In particular, +cvDotProduct(a,a) where a is a complex vector, will return \f$||\texttt{a}||^2\f$. The function can +process multi-dimensional arrays, row by row, layer by layer, and so on. +@param src1 The first source array +@param src2 The second source array + */ +CVAPI(double) cvDotProduct( const CvArr* src1, const CvArr* src2 ); + +/** dst(idx) = src1(idx) & src2(idx) */ +CVAPI(void) cvAnd( const CvArr* src1, const CvArr* src2, + CvArr* dst, const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(idx) = src(idx) & value */ +CVAPI(void) cvAndS( const CvArr* src, CvScalar value, + CvArr* dst, const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(idx) = src1(idx) | src2(idx) */ +CVAPI(void) cvOr( const CvArr* src1, const CvArr* src2, + CvArr* dst, const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(idx) = src(idx) | value */ +CVAPI(void) cvOrS( const CvArr* src, CvScalar value, + CvArr* dst, const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(idx) = src1(idx) ^ src2(idx) */ +CVAPI(void) cvXor( const CvArr* src1, const CvArr* src2, + CvArr* dst, const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(idx) = src(idx) ^ value */ +CVAPI(void) cvXorS( const CvArr* src, CvScalar value, + CvArr* dst, const CvArr* mask CV_DEFAULT(NULL)); + +/** dst(idx) = ~src(idx) */ +CVAPI(void) cvNot( const CvArr* src, CvArr* dst ); + +/** dst(idx) = lower(idx) <= src(idx) < upper(idx) */ +CVAPI(void) cvInRange( const CvArr* src, const CvArr* lower, + const CvArr* upper, CvArr* dst ); + +/** dst(idx) = lower <= src(idx) < upper */ +CVAPI(void) cvInRangeS( const CvArr* src, CvScalar lower, + CvScalar upper, CvArr* dst ); + +#define CV_CMP_EQ 0 +#define CV_CMP_GT 1 +#define CV_CMP_GE 2 +#define CV_CMP_LT 3 +#define CV_CMP_LE 4 +#define CV_CMP_NE 5 + +/** The comparison operation support single-channel arrays only. + Destination image should be 8uC1 or 8sC1 */ + +/** dst(idx) = src1(idx) _cmp_op_ src2(idx) */ +CVAPI(void) cvCmp( const CvArr* src1, const CvArr* src2, CvArr* dst, int cmp_op ); + +/** dst(idx) = src1(idx) _cmp_op_ value */ +CVAPI(void) cvCmpS( const CvArr* src, double value, CvArr* dst, int cmp_op ); + +/** dst(idx) = min(src1(idx),src2(idx)) */ +CVAPI(void) cvMin( const CvArr* src1, const CvArr* src2, CvArr* dst ); + +/** dst(idx) = max(src1(idx),src2(idx)) */ +CVAPI(void) cvMax( const CvArr* src1, const CvArr* src2, CvArr* dst ); + +/** dst(idx) = min(src(idx),value) */ +CVAPI(void) cvMinS( const CvArr* src, double value, CvArr* dst ); + +/** dst(idx) = max(src(idx),value) */ +CVAPI(void) cvMaxS( const CvArr* src, double value, CvArr* dst ); + +/** dst(x,y,c) = abs(src1(x,y,c) - src2(x,y,c)) */ +CVAPI(void) cvAbsDiff( const CvArr* src1, const CvArr* src2, CvArr* dst ); + +/** dst(x,y,c) = abs(src(x,y,c) - value(c)) */ +CVAPI(void) cvAbsDiffS( const CvArr* src, CvArr* dst, CvScalar value ); +#define cvAbs( src, dst ) cvAbsDiffS( (src), (dst), cvScalarAll(0)) + +/****************************************************************************************\ +* Math operations * +\****************************************************************************************/ + +/** Does cartesian->polar coordinates conversion. + Either of output components (magnitude or angle) is optional */ +CVAPI(void) cvCartToPolar( const CvArr* x, const CvArr* y, + CvArr* magnitude, CvArr* angle CV_DEFAULT(NULL), + int angle_in_degrees CV_DEFAULT(0)); + +/** Does polar->cartesian coordinates conversion. + Either of output components (magnitude or angle) is optional. + If magnitude is missing it is assumed to be all 1's */ +CVAPI(void) cvPolarToCart( const CvArr* magnitude, const CvArr* angle, + CvArr* x, CvArr* y, + int angle_in_degrees CV_DEFAULT(0)); + +/** Does powering: dst(idx) = src(idx)^power */ +CVAPI(void) cvPow( const CvArr* src, CvArr* dst, double power ); + +/** Does exponention: dst(idx) = exp(src(idx)). + Overflow is not handled yet. Underflow is handled. + Maximal relative error is ~7e-6 for single-precision input */ +CVAPI(void) cvExp( const CvArr* src, CvArr* dst ); + +/** Calculates natural logarithms: dst(idx) = log(abs(src(idx))). + Logarithm of 0 gives large negative number(~-700) + Maximal relative error is ~3e-7 for single-precision output +*/ +CVAPI(void) cvLog( const CvArr* src, CvArr* dst ); + +/** Fast arctangent calculation */ +CVAPI(float) cvFastArctan( float y, float x ); + +/** Fast cubic root calculation */ +CVAPI(float) cvCbrt( float value ); + +#define CV_CHECK_RANGE 1 +#define CV_CHECK_QUIET 2 +/** Checks array values for NaNs, Infs or simply for too large numbers + (if CV_CHECK_RANGE is set). If CV_CHECK_QUIET is set, + no runtime errors is raised (function returns zero value in case of "bad" values). + Otherwise cvError is called */ +CVAPI(int) cvCheckArr( const CvArr* arr, int flags CV_DEFAULT(0), + double min_val CV_DEFAULT(0), double max_val CV_DEFAULT(0)); +#define cvCheckArray cvCheckArr + +#define CV_RAND_UNI 0 +#define CV_RAND_NORMAL 1 + +/** @brief Fills an array with random numbers and updates the RNG state. + +The function fills the destination array with uniformly or normally distributed random numbers. +@param rng CvRNG state initialized by cvRNG +@param arr The destination array +@param dist_type Distribution type +> - **CV_RAND_UNI** uniform distribution +> - **CV_RAND_NORMAL** normal or Gaussian distribution +@param param1 The first parameter of the distribution. In the case of a uniform distribution it is +the inclusive lower boundary of the random numbers range. In the case of a normal distribution it +is the mean value of the random numbers. +@param param2 The second parameter of the distribution. In the case of a uniform distribution it +is the exclusive upper boundary of the random numbers range. In the case of a normal distribution +it is the standard deviation of the random numbers. +@sa randu, randn, RNG::fill. + */ +CVAPI(void) cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, + CvScalar param1, CvScalar param2 ); + +CVAPI(void) cvRandShuffle( CvArr* mat, CvRNG* rng, + double iter_factor CV_DEFAULT(1.)); + +#define CV_SORT_EVERY_ROW 0 +#define CV_SORT_EVERY_COLUMN 1 +#define CV_SORT_ASCENDING 0 +#define CV_SORT_DESCENDING 16 + +CVAPI(void) cvSort( const CvArr* src, CvArr* dst CV_DEFAULT(NULL), + CvArr* idxmat CV_DEFAULT(NULL), + int flags CV_DEFAULT(0)); + +/** Finds real roots of a cubic equation */ +CVAPI(int) cvSolveCubic( const CvMat* coeffs, CvMat* roots ); + +/** Finds all real and complex roots of a polynomial equation */ +CVAPI(void) cvSolvePoly(const CvMat* coeffs, CvMat *roots2, + int maxiter CV_DEFAULT(20), int fig CV_DEFAULT(100)); + +/****************************************************************************************\ +* Matrix operations * +\****************************************************************************************/ + +/** @brief Calculates the cross product of two 3D vectors. + +The function calculates the cross product of two 3D vectors: +\f[\texttt{dst} = \texttt{src1} \times \texttt{src2}\f] +or: +\f[\begin{array}{l} \texttt{dst} _1 = \texttt{src1} _2 \texttt{src2} _3 - \texttt{src1} _3 \texttt{src2} _2 \\ \texttt{dst} _2 = \texttt{src1} _3 \texttt{src2} _1 - \texttt{src1} _1 \texttt{src2} _3 \\ \texttt{dst} _3 = \texttt{src1} _1 \texttt{src2} _2 - \texttt{src1} _2 \texttt{src2} _1 \end{array}\f] +@param src1 The first source vector +@param src2 The second source vector +@param dst The destination vector + */ +CVAPI(void) cvCrossProduct( const CvArr* src1, const CvArr* src2, CvArr* dst ); + +/** Matrix transform: dst = A*B + C, C is optional */ +#define cvMatMulAdd( src1, src2, src3, dst ) cvGEMM( (src1), (src2), 1., (src3), 1., (dst), 0 ) +#define cvMatMul( src1, src2, dst ) cvMatMulAdd( (src1), (src2), NULL, (dst)) + +#define CV_GEMM_A_T 1 +#define CV_GEMM_B_T 2 +#define CV_GEMM_C_T 4 +/** Extended matrix transform: + dst = alpha*op(A)*op(B) + beta*op(C), where op(X) is X or X^T */ +CVAPI(void) cvGEMM( const CvArr* src1, const CvArr* src2, double alpha, + const CvArr* src3, double beta, CvArr* dst, + int tABC CV_DEFAULT(0)); +#define cvMatMulAddEx cvGEMM + +/** Transforms each element of source array and stores + resultant vectors in destination array */ +CVAPI(void) cvTransform( const CvArr* src, CvArr* dst, + const CvMat* transmat, + const CvMat* shiftvec CV_DEFAULT(NULL)); +#define cvMatMulAddS cvTransform + +/** Does perspective transform on every element of input array */ +CVAPI(void) cvPerspectiveTransform( const CvArr* src, CvArr* dst, + const CvMat* mat ); + +/** Calculates (A-delta)*(A-delta)^T (order=0) or (A-delta)^T*(A-delta) (order=1) */ +CVAPI(void) cvMulTransposed( const CvArr* src, CvArr* dst, int order, + const CvArr* delta CV_DEFAULT(NULL), + double scale CV_DEFAULT(1.) ); + +/** Tranposes matrix. Square matrices can be transposed in-place */ +CVAPI(void) cvTranspose( const CvArr* src, CvArr* dst ); +#define cvT cvTranspose + +/** Completes the symmetric matrix from the lower (LtoR=0) or from the upper (LtoR!=0) part */ +CVAPI(void) cvCompleteSymm( CvMat* matrix, int LtoR CV_DEFAULT(0) ); + +/** Mirror array data around horizontal (flip=0), + vertical (flip=1) or both(flip=-1) axises: + cvFlip(src) flips images vertically and sequences horizontally (inplace) */ +CVAPI(void) cvFlip( const CvArr* src, CvArr* dst CV_DEFAULT(NULL), + int flip_mode CV_DEFAULT(0)); +#define cvMirror cvFlip + + +#define CV_SVD_MODIFY_A 1 +#define CV_SVD_U_T 2 +#define CV_SVD_V_T 4 + +/** Performs Singular Value Decomposition of a matrix */ +CVAPI(void) cvSVD( CvArr* A, CvArr* W, CvArr* U CV_DEFAULT(NULL), + CvArr* V CV_DEFAULT(NULL), int flags CV_DEFAULT(0)); + +/** Performs Singular Value Back Substitution (solves A*X = B): + flags must be the same as in cvSVD */ +CVAPI(void) cvSVBkSb( const CvArr* W, const CvArr* U, + const CvArr* V, const CvArr* B, + CvArr* X, int flags ); + +#define CV_LU 0 +#define CV_SVD 1 +#define CV_SVD_SYM 2 +#define CV_CHOLESKY 3 +#define CV_QR 4 +#define CV_NORMAL 16 + +/** Inverts matrix */ +CVAPI(double) cvInvert( const CvArr* src, CvArr* dst, + int method CV_DEFAULT(CV_LU)); +#define cvInv cvInvert + +/** Solves linear system (src1)*(dst) = (src2) + (returns 0 if src1 is a singular and CV_LU method is used) */ +CVAPI(int) cvSolve( const CvArr* src1, const CvArr* src2, CvArr* dst, + int method CV_DEFAULT(CV_LU)); + +/** Calculates determinant of input matrix */ +CVAPI(double) cvDet( const CvArr* mat ); + +/** Calculates trace of the matrix (sum of elements on the main diagonal) */ +CVAPI(CvScalar) cvTrace( const CvArr* mat ); + +/** Finds eigen values and vectors of a symmetric matrix */ +CVAPI(void) cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, + double eps CV_DEFAULT(0), + int lowindex CV_DEFAULT(-1), + int highindex CV_DEFAULT(-1)); + +///* Finds selected eigen values and vectors of a symmetric matrix */ +//CVAPI(void) cvSelectedEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, +// int lowindex, int highindex ); + +/** Makes an identity matrix (mat_ij = i == j) */ +CVAPI(void) cvSetIdentity( CvArr* mat, CvScalar value CV_DEFAULT(cvRealScalar(1)) ); + +/** Fills matrix with given range of numbers */ +CVAPI(CvArr*) cvRange( CvArr* mat, double start, double end ); + +/** @anchor core_c_CovarFlags +@name Flags for cvCalcCovarMatrix +@see cvCalcCovarMatrix + @{ +*/ + +/** flag for cvCalcCovarMatrix, transpose([v1-avg, v2-avg,...]) * [v1-avg,v2-avg,...] */ +#define CV_COVAR_SCRAMBLED 0 + +/** flag for cvCalcCovarMatrix, [v1-avg, v2-avg,...] * transpose([v1-avg,v2-avg,...]) */ +#define CV_COVAR_NORMAL 1 + +/** flag for cvCalcCovarMatrix, do not calc average (i.e. mean vector) - use the input vector instead + (useful for calculating covariance matrix by parts) */ +#define CV_COVAR_USE_AVG 2 + +/** flag for cvCalcCovarMatrix, scale the covariance matrix coefficients by number of the vectors */ +#define CV_COVAR_SCALE 4 + +/** flag for cvCalcCovarMatrix, all the input vectors are stored in a single matrix, as its rows */ +#define CV_COVAR_ROWS 8 + +/** flag for cvCalcCovarMatrix, all the input vectors are stored in a single matrix, as its columns */ +#define CV_COVAR_COLS 16 + +/** @} */ + +/** Calculates covariation matrix for a set of vectors +@see @ref core_c_CovarFlags "flags" +*/ +CVAPI(void) cvCalcCovarMatrix( const CvArr** vects, int count, + CvArr* cov_mat, CvArr* avg, int flags ); + +#define CV_PCA_DATA_AS_ROW 0 +#define CV_PCA_DATA_AS_COL 1 +#define CV_PCA_USE_AVG 2 +CVAPI(void) cvCalcPCA( const CvArr* data, CvArr* mean, + CvArr* eigenvals, CvArr* eigenvects, int flags ); + +CVAPI(void) cvProjectPCA( const CvArr* data, const CvArr* mean, + const CvArr* eigenvects, CvArr* result ); + +CVAPI(void) cvBackProjectPCA( const CvArr* proj, const CvArr* mean, + const CvArr* eigenvects, CvArr* result ); + +/** Calculates Mahalanobis(weighted) distance */ +CVAPI(double) cvMahalanobis( const CvArr* vec1, const CvArr* vec2, const CvArr* mat ); +#define cvMahalonobis cvMahalanobis + +/****************************************************************************************\ +* Array Statistics * +\****************************************************************************************/ + +/** Finds sum of array elements */ +CVAPI(CvScalar) cvSum( const CvArr* arr ); + +/** Calculates number of non-zero pixels */ +CVAPI(int) cvCountNonZero( const CvArr* arr ); + +/** Calculates mean value of array elements */ +CVAPI(CvScalar) cvAvg( const CvArr* arr, const CvArr* mask CV_DEFAULT(NULL) ); + +/** Calculates mean and standard deviation of pixel values */ +CVAPI(void) cvAvgSdv( const CvArr* arr, CvScalar* mean, CvScalar* std_dev, + const CvArr* mask CV_DEFAULT(NULL) ); + +/** Finds global minimum, maximum and their positions */ +CVAPI(void) cvMinMaxLoc( const CvArr* arr, double* min_val, double* max_val, + CvPoint* min_loc CV_DEFAULT(NULL), + CvPoint* max_loc CV_DEFAULT(NULL), + const CvArr* mask CV_DEFAULT(NULL) ); + +/** @anchor core_c_NormFlags + @name Flags for cvNorm and cvNormalize + @{ +*/ +#define CV_C 1 +#define CV_L1 2 +#define CV_L2 4 +#define CV_NORM_MASK 7 +#define CV_RELATIVE 8 +#define CV_DIFF 16 +#define CV_MINMAX 32 + +#define CV_DIFF_C (CV_DIFF | CV_C) +#define CV_DIFF_L1 (CV_DIFF | CV_L1) +#define CV_DIFF_L2 (CV_DIFF | CV_L2) +#define CV_RELATIVE_C (CV_RELATIVE | CV_C) +#define CV_RELATIVE_L1 (CV_RELATIVE | CV_L1) +#define CV_RELATIVE_L2 (CV_RELATIVE | CV_L2) +/** @} */ + +/** Finds norm, difference norm or relative difference norm for an array (or two arrays) +@see ref core_c_NormFlags "flags" +*/ +CVAPI(double) cvNorm( const CvArr* arr1, const CvArr* arr2 CV_DEFAULT(NULL), + int norm_type CV_DEFAULT(CV_L2), + const CvArr* mask CV_DEFAULT(NULL) ); + +/** @see ref core_c_NormFlags "flags" */ +CVAPI(void) cvNormalize( const CvArr* src, CvArr* dst, + double a CV_DEFAULT(1.), double b CV_DEFAULT(0.), + int norm_type CV_DEFAULT(CV_L2), + const CvArr* mask CV_DEFAULT(NULL) ); + +/** @anchor core_c_ReduceFlags + @name Flags for cvReduce + @{ +*/ +#define CV_REDUCE_SUM 0 +#define CV_REDUCE_AVG 1 +#define CV_REDUCE_MAX 2 +#define CV_REDUCE_MIN 3 +/** @} */ + +/** @see @ref core_c_ReduceFlags "flags" */ +CVAPI(void) cvReduce( const CvArr* src, CvArr* dst, int dim CV_DEFAULT(-1), + int op CV_DEFAULT(CV_REDUCE_SUM) ); + +/****************************************************************************************\ +* Discrete Linear Transforms and Related Functions * +\****************************************************************************************/ + +/** @anchor core_c_DftFlags + @name Flags for cvDFT, cvDCT and cvMulSpectrums + @{ + */ +#define CV_DXT_FORWARD 0 +#define CV_DXT_INVERSE 1 +#define CV_DXT_SCALE 2 /**< divide result by size of array */ +#define CV_DXT_INV_SCALE (CV_DXT_INVERSE + CV_DXT_SCALE) +#define CV_DXT_INVERSE_SCALE CV_DXT_INV_SCALE +#define CV_DXT_ROWS 4 /**< transform each row individually */ +#define CV_DXT_MUL_CONJ 8 /**< conjugate the second argument of cvMulSpectrums */ +/** @} */ + +/** Discrete Fourier Transform: + complex->complex, + real->ccs (forward), + ccs->real (inverse) +@see core_c_DftFlags "flags" +*/ +CVAPI(void) cvDFT( const CvArr* src, CvArr* dst, int flags, + int nonzero_rows CV_DEFAULT(0) ); +#define cvFFT cvDFT + +/** Multiply results of DFTs: DFT(X)*DFT(Y) or DFT(X)*conj(DFT(Y)) +@see core_c_DftFlags "flags" +*/ +CVAPI(void) cvMulSpectrums( const CvArr* src1, const CvArr* src2, + CvArr* dst, int flags ); + +/** Finds optimal DFT vector size >= size0 */ +CVAPI(int) cvGetOptimalDFTSize( int size0 ); + +/** Discrete Cosine Transform +@see core_c_DftFlags "flags" +*/ +CVAPI(void) cvDCT( const CvArr* src, CvArr* dst, int flags ); + +/****************************************************************************************\ +* Dynamic data structures * +\****************************************************************************************/ + +/** Calculates length of sequence slice (with support of negative indices). */ +CVAPI(int) cvSliceLength( CvSlice slice, const CvSeq* seq ); + + +/** Creates new memory storage. + block_size == 0 means that default, + somewhat optimal size, is used (currently, it is 64K) */ +CVAPI(CvMemStorage*) cvCreateMemStorage( int block_size CV_DEFAULT(0)); + + +/** Creates a memory storage that will borrow memory blocks from parent storage */ +CVAPI(CvMemStorage*) cvCreateChildMemStorage( CvMemStorage* parent ); + + +/** Releases memory storage. All the children of a parent must be released before + the parent. A child storage returns all the blocks to parent when it is released */ +CVAPI(void) cvReleaseMemStorage( CvMemStorage** storage ); + + +/** Clears memory storage. This is the only way(!!!) (besides cvRestoreMemStoragePos) + to reuse memory allocated for the storage - cvClearSeq,cvClearSet ... + do not free any memory. + A child storage returns all the blocks to the parent when it is cleared */ +CVAPI(void) cvClearMemStorage( CvMemStorage* storage ); + +/** Remember a storage "free memory" position */ +CVAPI(void) cvSaveMemStoragePos( const CvMemStorage* storage, CvMemStoragePos* pos ); + +/** Restore a storage "free memory" position */ +CVAPI(void) cvRestoreMemStoragePos( CvMemStorage* storage, CvMemStoragePos* pos ); + +/** Allocates continuous buffer of the specified size in the storage */ +CVAPI(void*) cvMemStorageAlloc( CvMemStorage* storage, size_t size ); + +/** Allocates string in memory storage */ +CVAPI(CvString) cvMemStorageAllocString( CvMemStorage* storage, const char* ptr, + int len CV_DEFAULT(-1) ); + +/** Creates new empty sequence that will reside in the specified storage */ +CVAPI(CvSeq*) cvCreateSeq( int seq_flags, size_t header_size, + size_t elem_size, CvMemStorage* storage ); + +/** Changes default size (granularity) of sequence blocks. + The default size is ~1Kbyte */ +CVAPI(void) cvSetSeqBlockSize( CvSeq* seq, int delta_elems ); + + +/** Adds new element to the end of sequence. Returns pointer to the element */ +CVAPI(schar*) cvSeqPush( CvSeq* seq, const void* element CV_DEFAULT(NULL)); + + +/** Adds new element to the beginning of sequence. Returns pointer to it */ +CVAPI(schar*) cvSeqPushFront( CvSeq* seq, const void* element CV_DEFAULT(NULL)); + + +/** Removes the last element from sequence and optionally saves it */ +CVAPI(void) cvSeqPop( CvSeq* seq, void* element CV_DEFAULT(NULL)); + + +/** Removes the first element from sequence and optioanally saves it */ +CVAPI(void) cvSeqPopFront( CvSeq* seq, void* element CV_DEFAULT(NULL)); + + +#define CV_FRONT 1 +#define CV_BACK 0 +/** Adds several new elements to the end of sequence */ +CVAPI(void) cvSeqPushMulti( CvSeq* seq, const void* elements, + int count, int in_front CV_DEFAULT(0) ); + +/** Removes several elements from the end of sequence and optionally saves them */ +CVAPI(void) cvSeqPopMulti( CvSeq* seq, void* elements, + int count, int in_front CV_DEFAULT(0) ); + +/** Inserts a new element in the middle of sequence. + cvSeqInsert(seq,0,elem) == cvSeqPushFront(seq,elem) */ +CVAPI(schar*) cvSeqInsert( CvSeq* seq, int before_index, + const void* element CV_DEFAULT(NULL)); + +/** Removes specified sequence element */ +CVAPI(void) cvSeqRemove( CvSeq* seq, int index ); + + +/** Removes all the elements from the sequence. The freed memory + can be reused later only by the same sequence unless cvClearMemStorage + or cvRestoreMemStoragePos is called */ +CVAPI(void) cvClearSeq( CvSeq* seq ); + + +/** Retrieves pointer to specified sequence element. + Negative indices are supported and mean counting from the end + (e.g -1 means the last sequence element) */ +CVAPI(schar*) cvGetSeqElem( const CvSeq* seq, int index ); + +/** Calculates index of the specified sequence element. + Returns -1 if element does not belong to the sequence */ +CVAPI(int) cvSeqElemIdx( const CvSeq* seq, const void* element, + CvSeqBlock** block CV_DEFAULT(NULL) ); + +/** Initializes sequence writer. The new elements will be added to the end of sequence */ +CVAPI(void) cvStartAppendToSeq( CvSeq* seq, CvSeqWriter* writer ); + + +/** Combination of cvCreateSeq and cvStartAppendToSeq */ +CVAPI(void) cvStartWriteSeq( int seq_flags, int header_size, + int elem_size, CvMemStorage* storage, + CvSeqWriter* writer ); + +/** Closes sequence writer, updates sequence header and returns pointer + to the resultant sequence + (which may be useful if the sequence was created using cvStartWriteSeq)) +*/ +CVAPI(CvSeq*) cvEndWriteSeq( CvSeqWriter* writer ); + + +/** Updates sequence header. May be useful to get access to some of previously + written elements via cvGetSeqElem or sequence reader */ +CVAPI(void) cvFlushSeqWriter( CvSeqWriter* writer ); + + +/** Initializes sequence reader. + The sequence can be read in forward or backward direction */ +CVAPI(void) cvStartReadSeq( const CvSeq* seq, CvSeqReader* reader, + int reverse CV_DEFAULT(0) ); + + +/** Returns current sequence reader position (currently observed sequence element) */ +CVAPI(int) cvGetSeqReaderPos( CvSeqReader* reader ); + + +/** Changes sequence reader position. It may seek to an absolute or + to relative to the current position */ +CVAPI(void) cvSetSeqReaderPos( CvSeqReader* reader, int index, + int is_relative CV_DEFAULT(0)); + +/** Copies sequence content to a continuous piece of memory */ +CVAPI(void*) cvCvtSeqToArray( const CvSeq* seq, void* elements, + CvSlice slice CV_DEFAULT(CV_WHOLE_SEQ) ); + +/** Creates sequence header for array. + After that all the operations on sequences that do not alter the content + can be applied to the resultant sequence */ +CVAPI(CvSeq*) cvMakeSeqHeaderForArray( int seq_type, int header_size, + int elem_size, void* elements, int total, + CvSeq* seq, CvSeqBlock* block ); + +/** Extracts sequence slice (with or without copying sequence elements) */ +CVAPI(CvSeq*) cvSeqSlice( const CvSeq* seq, CvSlice slice, + CvMemStorage* storage CV_DEFAULT(NULL), + int copy_data CV_DEFAULT(0)); + +CV_INLINE CvSeq* cvCloneSeq( const CvSeq* seq, CvMemStorage* storage CV_DEFAULT(NULL)) +{ + return cvSeqSlice( seq, CV_WHOLE_SEQ, storage, 1 ); +} + +/** Removes sequence slice */ +CVAPI(void) cvSeqRemoveSlice( CvSeq* seq, CvSlice slice ); + +/** Inserts a sequence or array into another sequence */ +CVAPI(void) cvSeqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr ); + +/** a < b ? -1 : a > b ? 1 : 0 */ +typedef int (CV_CDECL* CvCmpFunc)(const void* a, const void* b, void* userdata ); + +/** Sorts sequence in-place given element comparison function */ +CVAPI(void) cvSeqSort( CvSeq* seq, CvCmpFunc func, void* userdata CV_DEFAULT(NULL) ); + +/** Finds element in a [sorted] sequence */ +CVAPI(schar*) cvSeqSearch( CvSeq* seq, const void* elem, CvCmpFunc func, + int is_sorted, int* elem_idx, + void* userdata CV_DEFAULT(NULL) ); + +/** Reverses order of sequence elements in-place */ +CVAPI(void) cvSeqInvert( CvSeq* seq ); + +/** Splits sequence into one or more equivalence classes using the specified criteria */ +CVAPI(int) cvSeqPartition( const CvSeq* seq, CvMemStorage* storage, + CvSeq** labels, CvCmpFunc is_equal, void* userdata ); + +/************ Internal sequence functions ************/ +CVAPI(void) cvChangeSeqBlock( void* reader, int direction ); +CVAPI(void) cvCreateSeqBlock( CvSeqWriter* writer ); + + +/** Creates a new set */ +CVAPI(CvSet*) cvCreateSet( int set_flags, int header_size, + int elem_size, CvMemStorage* storage ); + +/** Adds new element to the set and returns pointer to it */ +CVAPI(int) cvSetAdd( CvSet* set_header, CvSetElem* elem CV_DEFAULT(NULL), + CvSetElem** inserted_elem CV_DEFAULT(NULL) ); + +/** Fast variant of cvSetAdd */ +CV_INLINE CvSetElem* cvSetNew( CvSet* set_header ) +{ + CvSetElem* elem = set_header->free_elems; + if( elem ) + { + set_header->free_elems = elem->next_free; + elem->flags = elem->flags & CV_SET_ELEM_IDX_MASK; + set_header->active_count++; + } + else + cvSetAdd( set_header, NULL, &elem ); + return elem; +} + +/** Removes set element given its pointer */ +CV_INLINE void cvSetRemoveByPtr( CvSet* set_header, void* elem ) +{ + CvSetElem* _elem = (CvSetElem*)elem; + assert( _elem->flags >= 0 /*&& (elem->flags & CV_SET_ELEM_IDX_MASK) < set_header->total*/ ); + _elem->next_free = set_header->free_elems; + _elem->flags = (_elem->flags & CV_SET_ELEM_IDX_MASK) | CV_SET_ELEM_FREE_FLAG; + set_header->free_elems = _elem; + set_header->active_count--; +} + +/** Removes element from the set by its index */ +CVAPI(void) cvSetRemove( CvSet* set_header, int index ); + +/** Returns a set element by index. If the element doesn't belong to the set, + NULL is returned */ +CV_INLINE CvSetElem* cvGetSetElem( const CvSet* set_header, int idx ) +{ + CvSetElem* elem = (CvSetElem*)(void *)cvGetSeqElem( (CvSeq*)set_header, idx ); + return elem && CV_IS_SET_ELEM( elem ) ? elem : 0; +} + +/** Removes all the elements from the set */ +CVAPI(void) cvClearSet( CvSet* set_header ); + +/** Creates new graph */ +CVAPI(CvGraph*) cvCreateGraph( int graph_flags, int header_size, + int vtx_size, int edge_size, + CvMemStorage* storage ); + +/** Adds new vertex to the graph */ +CVAPI(int) cvGraphAddVtx( CvGraph* graph, const CvGraphVtx* vtx CV_DEFAULT(NULL), + CvGraphVtx** inserted_vtx CV_DEFAULT(NULL) ); + + +/** Removes vertex from the graph together with all incident edges */ +CVAPI(int) cvGraphRemoveVtx( CvGraph* graph, int index ); +CVAPI(int) cvGraphRemoveVtxByPtr( CvGraph* graph, CvGraphVtx* vtx ); + + +/** Link two vertices specifed by indices or pointers if they + are not connected or return pointer to already existing edge + connecting the vertices. + Functions return 1 if a new edge was created, 0 otherwise */ +CVAPI(int) cvGraphAddEdge( CvGraph* graph, + int start_idx, int end_idx, + const CvGraphEdge* edge CV_DEFAULT(NULL), + CvGraphEdge** inserted_edge CV_DEFAULT(NULL) ); + +CVAPI(int) cvGraphAddEdgeByPtr( CvGraph* graph, + CvGraphVtx* start_vtx, CvGraphVtx* end_vtx, + const CvGraphEdge* edge CV_DEFAULT(NULL), + CvGraphEdge** inserted_edge CV_DEFAULT(NULL) ); + +/** Remove edge connecting two vertices */ +CVAPI(void) cvGraphRemoveEdge( CvGraph* graph, int start_idx, int end_idx ); +CVAPI(void) cvGraphRemoveEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, + CvGraphVtx* end_vtx ); + +/** Find edge connecting two vertices */ +CVAPI(CvGraphEdge*) cvFindGraphEdge( const CvGraph* graph, int start_idx, int end_idx ); +CVAPI(CvGraphEdge*) cvFindGraphEdgeByPtr( const CvGraph* graph, + const CvGraphVtx* start_vtx, + const CvGraphVtx* end_vtx ); +#define cvGraphFindEdge cvFindGraphEdge +#define cvGraphFindEdgeByPtr cvFindGraphEdgeByPtr + +/** Remove all vertices and edges from the graph */ +CVAPI(void) cvClearGraph( CvGraph* graph ); + + +/** Count number of edges incident to the vertex */ +CVAPI(int) cvGraphVtxDegree( const CvGraph* graph, int vtx_idx ); +CVAPI(int) cvGraphVtxDegreeByPtr( const CvGraph* graph, const CvGraphVtx* vtx ); + + +/** Retrieves graph vertex by given index */ +#define cvGetGraphVtx( graph, idx ) (CvGraphVtx*)cvGetSetElem((CvSet*)(graph), (idx)) + +/** Retrieves index of a graph vertex given its pointer */ +#define cvGraphVtxIdx( graph, vtx ) ((vtx)->flags & CV_SET_ELEM_IDX_MASK) + +/** Retrieves index of a graph edge given its pointer */ +#define cvGraphEdgeIdx( graph, edge ) ((edge)->flags & CV_SET_ELEM_IDX_MASK) + +#define cvGraphGetVtxCount( graph ) ((graph)->active_count) +#define cvGraphGetEdgeCount( graph ) ((graph)->edges->active_count) + +#define CV_GRAPH_VERTEX 1 +#define CV_GRAPH_TREE_EDGE 2 +#define CV_GRAPH_BACK_EDGE 4 +#define CV_GRAPH_FORWARD_EDGE 8 +#define CV_GRAPH_CROSS_EDGE 16 +#define CV_GRAPH_ANY_EDGE 30 +#define CV_GRAPH_NEW_TREE 32 +#define CV_GRAPH_BACKTRACKING 64 +#define CV_GRAPH_OVER -1 + +#define CV_GRAPH_ALL_ITEMS -1 + +/** flags for graph vertices and edges */ +#define CV_GRAPH_ITEM_VISITED_FLAG (1 << 30) +#define CV_IS_GRAPH_VERTEX_VISITED(vtx) \ + (((CvGraphVtx*)(vtx))->flags & CV_GRAPH_ITEM_VISITED_FLAG) +#define CV_IS_GRAPH_EDGE_VISITED(edge) \ + (((CvGraphEdge*)(edge))->flags & CV_GRAPH_ITEM_VISITED_FLAG) +#define CV_GRAPH_SEARCH_TREE_NODE_FLAG (1 << 29) +#define CV_GRAPH_FORWARD_EDGE_FLAG (1 << 28) + +typedef struct CvGraphScanner +{ + CvGraphVtx* vtx; /* current graph vertex (or current edge origin) */ + CvGraphVtx* dst; /* current graph edge destination vertex */ + CvGraphEdge* edge; /* current edge */ + + CvGraph* graph; /* the graph */ + CvSeq* stack; /* the graph vertex stack */ + int index; /* the lower bound of certainly visited vertices */ + int mask; /* event mask */ +} +CvGraphScanner; + +/** Creates new graph scanner. */ +CVAPI(CvGraphScanner*) cvCreateGraphScanner( CvGraph* graph, + CvGraphVtx* vtx CV_DEFAULT(NULL), + int mask CV_DEFAULT(CV_GRAPH_ALL_ITEMS)); + +/** Releases graph scanner. */ +CVAPI(void) cvReleaseGraphScanner( CvGraphScanner** scanner ); + +/** Get next graph element */ +CVAPI(int) cvNextGraphItem( CvGraphScanner* scanner ); + +/** Creates a copy of graph */ +CVAPI(CvGraph*) cvCloneGraph( const CvGraph* graph, CvMemStorage* storage ); + + +/** Does look-up transformation. Elements of the source array + (that should be 8uC1 or 8sC1) are used as indexes in lutarr 256-element table */ +CVAPI(void) cvLUT( const CvArr* src, CvArr* dst, const CvArr* lut ); + + +/******************* Iteration through the sequence tree *****************/ +typedef struct CvTreeNodeIterator +{ + const void* node; + int level; + int max_level; +} +CvTreeNodeIterator; + +CVAPI(void) cvInitTreeNodeIterator( CvTreeNodeIterator* tree_iterator, + const void* first, int max_level ); +CVAPI(void*) cvNextTreeNode( CvTreeNodeIterator* tree_iterator ); +CVAPI(void*) cvPrevTreeNode( CvTreeNodeIterator* tree_iterator ); + +/** Inserts sequence into tree with specified "parent" sequence. + If parent is equal to frame (e.g. the most external contour), + then added contour will have null pointer to parent. */ +CVAPI(void) cvInsertNodeIntoTree( void* node, void* parent, void* frame ); + +/** Removes contour from tree (together with the contour children). */ +CVAPI(void) cvRemoveNodeFromTree( void* node, void* frame ); + +/** Gathers pointers to all the sequences, + accessible from the `first`, to the single sequence */ +CVAPI(CvSeq*) cvTreeToNodeSeq( const void* first, int header_size, + CvMemStorage* storage ); + +/** The function implements the K-means algorithm for clustering an array of sample + vectors in a specified number of classes */ +#define CV_KMEANS_USE_INITIAL_LABELS 1 +CVAPI(int) cvKMeans2( const CvArr* samples, int cluster_count, CvArr* labels, + CvTermCriteria termcrit, int attempts CV_DEFAULT(1), + CvRNG* rng CV_DEFAULT(0), int flags CV_DEFAULT(0), + CvArr* _centers CV_DEFAULT(0), double* compactness CV_DEFAULT(0) ); + +/****************************************************************************************\ +* System functions * +\****************************************************************************************/ + +/** Loads optimized functions from IPP, MKL etc. or switches back to pure C code */ +CVAPI(int) cvUseOptimized( int on_off ); + +typedef IplImage* (CV_STDCALL* Cv_iplCreateImageHeader) + (int,int,int,char*,char*,int,int,int,int,int, + IplROI*,IplImage*,void*,IplTileInfo*); +typedef void (CV_STDCALL* Cv_iplAllocateImageData)(IplImage*,int,int); +typedef void (CV_STDCALL* Cv_iplDeallocate)(IplImage*,int); +typedef IplROI* (CV_STDCALL* Cv_iplCreateROI)(int,int,int,int,int); +typedef IplImage* (CV_STDCALL* Cv_iplCloneImage)(const IplImage*); + +/** @brief Makes OpenCV use IPL functions for allocating IplImage and IplROI structures. + +Normally, the function is not called directly. Instead, a simple macro +CV_TURN_ON_IPL_COMPATIBILITY() is used that calls cvSetIPLAllocators and passes there pointers +to IPL allocation functions. : +@code + ... + CV_TURN_ON_IPL_COMPATIBILITY() + ... +@endcode +@param create_header pointer to a function, creating IPL image header. +@param allocate_data pointer to a function, allocating IPL image data. +@param deallocate pointer to a function, deallocating IPL image. +@param create_roi pointer to a function, creating IPL image ROI (i.e. Region of Interest). +@param clone_image pointer to a function, cloning an IPL image. + */ +CVAPI(void) cvSetIPLAllocators( Cv_iplCreateImageHeader create_header, + Cv_iplAllocateImageData allocate_data, + Cv_iplDeallocate deallocate, + Cv_iplCreateROI create_roi, + Cv_iplCloneImage clone_image ); + +#define CV_TURN_ON_IPL_COMPATIBILITY() \ + cvSetIPLAllocators( iplCreateImageHeader, iplAllocateImage, \ + iplDeallocate, iplCreateROI, iplCloneImage ) + +/****************************************************************************************\ +* Data Persistence * +\****************************************************************************************/ + +/********************************** High-level functions ********************************/ + +/** @brief Opens file storage for reading or writing data. + +The function opens file storage for reading or writing data. In the latter case, a new file is +created or an existing file is rewritten. The type of the read or written file is determined by the +filename extension: .xml for XML and .yml or .yaml for YAML. The function returns a pointer to the +CvFileStorage structure. If the file cannot be opened then the function returns NULL. +@param filename Name of the file associated with the storage +@param memstorage Memory storage used for temporary data and for +: storing dynamic structures, such as CvSeq or CvGraph . If it is NULL, a temporary memory + storage is created and used. +@param flags Can be one of the following: +> - **CV_STORAGE_READ** the storage is open for reading +> - **CV_STORAGE_WRITE** the storage is open for writing +@param encoding + */ +CVAPI(CvFileStorage*) cvOpenFileStorage( const char* filename, CvMemStorage* memstorage, + int flags, const char* encoding CV_DEFAULT(NULL) ); + +/** @brief Releases file storage. + +The function closes the file associated with the storage and releases all the temporary structures. +It must be called after all I/O operations with the storage are finished. +@param fs Double pointer to the released file storage + */ +CVAPI(void) cvReleaseFileStorage( CvFileStorage** fs ); + +/** returns attribute value or 0 (NULL) if there is no such attribute */ +CVAPI(const char*) cvAttrValue( const CvAttrList* attr, const char* attr_name ); + +/** @brief Starts writing a new structure. + +The function starts writing a compound structure (collection) that can be a sequence or a map. After +all the structure fields, which can be scalars or structures, are written, cvEndWriteStruct should +be called. The function can be used to group some objects or to implement the write function for a +some user object (see CvTypeInfo). +@param fs File storage +@param name Name of the written structure. The structure can be accessed by this name when the +storage is read. +@param struct_flags A combination one of the following values: +- **CV_NODE_SEQ** the written structure is a sequence (see discussion of CvFileStorage ), + that is, its elements do not have a name. +- **CV_NODE_MAP** the written structure is a map (see discussion of CvFileStorage ), that + is, all its elements have names. +One and only one of the two above flags must be specified +- **CV_NODE_FLOW** the optional flag that makes sense only for YAML streams. It means that + the structure is written as a flow (not as a block), which is more compact. It is + recommended to use this flag for structures or arrays whose elements are all scalars. +@param type_name Optional parameter - the object type name. In + case of XML it is written as a type_id attribute of the structure opening tag. In the case of + YAML it is written after a colon following the structure name (see the example in + CvFileStorage description). Mainly it is used with user objects. When the storage is read, the + encoded type name is used to determine the object type (see CvTypeInfo and cvFindType ). +@param attributes This parameter is not used in the current implementation + */ +CVAPI(void) cvStartWriteStruct( CvFileStorage* fs, const char* name, + int struct_flags, const char* type_name CV_DEFAULT(NULL), + CvAttrList attributes CV_DEFAULT(cvAttrList())); + +/** @brief Finishes writing to a file node collection. +@param fs File storage +@sa cvStartWriteStruct. + */ +CVAPI(void) cvEndWriteStruct( CvFileStorage* fs ); + +/** @brief Writes an integer value. + +The function writes a single integer value (with or without a name) to the file storage. +@param fs File storage +@param name Name of the written value. Should be NULL if and only if the parent structure is a +sequence. +@param value The written value + */ +CVAPI(void) cvWriteInt( CvFileStorage* fs, const char* name, int value ); + +/** @brief Writes a floating-point value. + +The function writes a single floating-point value (with or without a name) to file storage. Special +values are encoded as follows: NaN (Not A Number) as .NaN, infinity as +.Inf or -.Inf. + +The following example shows how to use the low-level writing functions to store custom structures, +such as termination criteria, without registering a new type. : +@code + void write_termcriteria( CvFileStorage* fs, const char* struct_name, + CvTermCriteria* termcrit ) + { + cvStartWriteStruct( fs, struct_name, CV_NODE_MAP, NULL, cvAttrList(0,0)); + cvWriteComment( fs, "termination criteria", 1 ); // just a description + if( termcrit->type & CV_TERMCRIT_ITER ) + cvWriteInteger( fs, "max_iterations", termcrit->max_iter ); + if( termcrit->type & CV_TERMCRIT_EPS ) + cvWriteReal( fs, "accuracy", termcrit->epsilon ); + cvEndWriteStruct( fs ); + } +@endcode +@param fs File storage +@param name Name of the written value. Should be NULL if and only if the parent structure is a +sequence. +@param value The written value +*/ +CVAPI(void) cvWriteReal( CvFileStorage* fs, const char* name, double value ); + +/** @brief Writes a text string. + +The function writes a text string to file storage. +@param fs File storage +@param name Name of the written string . Should be NULL if and only if the parent structure is a +sequence. +@param str The written text string +@param quote If non-zero, the written string is put in quotes, regardless of whether they are +required. Otherwise, if the flag is zero, quotes are used only when they are required (e.g. when +the string starts with a digit or contains spaces). + */ +CVAPI(void) cvWriteString( CvFileStorage* fs, const char* name, + const char* str, int quote CV_DEFAULT(0) ); + +/** @brief Writes a comment. + +The function writes a comment into file storage. The comments are skipped when the storage is read. +@param fs File storage +@param comment The written comment, single-line or multi-line +@param eol_comment If non-zero, the function tries to put the comment at the end of current line. +If the flag is zero, if the comment is multi-line, or if it does not fit at the end of the current +line, the comment starts a new line. + */ +CVAPI(void) cvWriteComment( CvFileStorage* fs, const char* comment, + int eol_comment ); + +/** @brief Writes an object to file storage. + +The function writes an object to file storage. First, the appropriate type info is found using +cvTypeOf. Then, the write method associated with the type info is called. + +Attributes are used to customize the writing procedure. The standard types support the following +attributes (all the dt attributes have the same format as in cvWriteRawData): + +-# CvSeq + - **header_dt** description of user fields of the sequence header that follow CvSeq, or + CvChain (if the sequence is a Freeman chain) or CvContour (if the sequence is a contour or + point sequence) + - **dt** description of the sequence elements. + - **recursive** if the attribute is present and is not equal to "0" or "false", the whole + tree of sequences (contours) is stored. +-# CvGraph + - **header_dt** description of user fields of the graph header that follows CvGraph; + - **vertex_dt** description of user fields of graph vertices + - **edge_dt** description of user fields of graph edges (note that the edge weight is + always written, so there is no need to specify it explicitly) + +Below is the code that creates the YAML file shown in the CvFileStorage description: +@code + #include "cxcore.h" + + int main( int argc, char** argv ) + { + CvMat* mat = cvCreateMat( 3, 3, CV_32F ); + CvFileStorage* fs = cvOpenFileStorage( "example.yml", 0, CV_STORAGE_WRITE ); + + cvSetIdentity( mat ); + cvWrite( fs, "A", mat, cvAttrList(0,0) ); + + cvReleaseFileStorage( &fs ); + cvReleaseMat( &mat ); + return 0; + } +@endcode +@param fs File storage +@param name Name of the written object. Should be NULL if and only if the parent structure is a +sequence. +@param ptr Pointer to the object +@param attributes The attributes of the object. They are specific for each particular type (see +the discussion below). + */ +CVAPI(void) cvWrite( CvFileStorage* fs, const char* name, const void* ptr, + CvAttrList attributes CV_DEFAULT(cvAttrList())); + +/** @brief Starts the next stream. + +The function finishes the currently written stream and starts the next stream. In the case of XML +the file with multiple streams looks like this: +@code{.xml} + + + + + + + ... +@endcode +The YAML file will look like this: +@code{.yaml} + %YAML:1.0 + # stream #1 data + ... + --- + # stream #2 data +@endcode +This is useful for concatenating files or for resuming the writing process. +@param fs File storage + */ +CVAPI(void) cvStartNextStream( CvFileStorage* fs ); + +/** @brief Writes multiple numbers. + +The function writes an array, whose elements consist of single or multiple numbers. The function +call can be replaced with a loop containing a few cvWriteInt and cvWriteReal calls, but a single +call is more efficient. Note that because none of the elements have a name, they should be written +to a sequence rather than a map. +@param fs File storage +@param src Pointer to the written array +@param len Number of the array elements to write +@param dt Specification of each array element, see @ref format_spec "format specification" + */ +CVAPI(void) cvWriteRawData( CvFileStorage* fs, const void* src, + int len, const char* dt ); + +/** @brief Returns a unique pointer for a given name. + +The function returns a unique pointer for each particular file node name. This pointer can be then +passed to the cvGetFileNode function that is faster than cvGetFileNodeByName because it compares +text strings by comparing pointers rather than the strings' content. + +Consider the following example where an array of points is encoded as a sequence of 2-entry maps: +@code + points: + - { x: 10, y: 10 } + - { x: 20, y: 20 } + - { x: 30, y: 30 } + # ... +@endcode +Then, it is possible to get hashed "x" and "y" pointers to speed up decoding of the points. : +@code + #include "cxcore.h" + + int main( int argc, char** argv ) + { + CvFileStorage* fs = cvOpenFileStorage( "points.yml", 0, CV_STORAGE_READ ); + CvStringHashNode* x_key = cvGetHashedNode( fs, "x", -1, 1 ); + CvStringHashNode* y_key = cvGetHashedNode( fs, "y", -1, 1 ); + CvFileNode* points = cvGetFileNodeByName( fs, 0, "points" ); + + if( CV_NODE_IS_SEQ(points->tag) ) + { + CvSeq* seq = points->data.seq; + int i, total = seq->total; + CvSeqReader reader; + cvStartReadSeq( seq, &reader, 0 ); + for( i = 0; i < total; i++ ) + { + CvFileNode* pt = (CvFileNode*)reader.ptr; + #if 1 // faster variant + CvFileNode* xnode = cvGetFileNode( fs, pt, x_key, 0 ); + CvFileNode* ynode = cvGetFileNode( fs, pt, y_key, 0 ); + assert( xnode && CV_NODE_IS_INT(xnode->tag) && + ynode && CV_NODE_IS_INT(ynode->tag)); + int x = xnode->data.i; // or x = cvReadInt( xnode, 0 ); + int y = ynode->data.i; // or y = cvReadInt( ynode, 0 ); + #elif 1 // slower variant; does not use x_key & y_key + CvFileNode* xnode = cvGetFileNodeByName( fs, pt, "x" ); + CvFileNode* ynode = cvGetFileNodeByName( fs, pt, "y" ); + assert( xnode && CV_NODE_IS_INT(xnode->tag) && + ynode && CV_NODE_IS_INT(ynode->tag)); + int x = xnode->data.i; // or x = cvReadInt( xnode, 0 ); + int y = ynode->data.i; // or y = cvReadInt( ynode, 0 ); + #else // the slowest yet the easiest to use variant + int x = cvReadIntByName( fs, pt, "x", 0 ); + int y = cvReadIntByName( fs, pt, "y", 0 ); + #endif + CV_NEXT_SEQ_ELEM( seq->elem_size, reader ); + printf(" + } + } + cvReleaseFileStorage( &fs ); + return 0; + } +@endcode +Please note that whatever method of accessing a map you are using, it is still much slower than +using plain sequences; for example, in the above example, it is more efficient to encode the points +as pairs of integers in a single numeric sequence. +@param fs File storage +@param name Literal node name +@param len Length of the name (if it is known apriori), or -1 if it needs to be calculated +@param create_missing Flag that specifies, whether an absent key should be added into the hash table +*/ +CVAPI(CvStringHashNode*) cvGetHashedKey( CvFileStorage* fs, const char* name, + int len CV_DEFAULT(-1), + int create_missing CV_DEFAULT(0)); + +/** @brief Retrieves one of the top-level nodes of the file storage. + +The function returns one of the top-level file nodes. The top-level nodes do not have a name, they +correspond to the streams that are stored one after another in the file storage. If the index is out +of range, the function returns a NULL pointer, so all the top-level nodes can be iterated by +subsequent calls to the function with stream_index=0,1,..., until the NULL pointer is returned. +This function can be used as a base for recursive traversal of the file storage. +@param fs File storage +@param stream_index Zero-based index of the stream. See cvStartNextStream . In most cases, +there is only one stream in the file; however, there can be several. + */ +CVAPI(CvFileNode*) cvGetRootFileNode( const CvFileStorage* fs, + int stream_index CV_DEFAULT(0) ); + +/** @brief Finds a node in a map or file storage. + +The function finds a file node. It is a faster version of cvGetFileNodeByName (see +cvGetHashedKey discussion). Also, the function can insert a new node, if it is not in the map yet. +@param fs File storage +@param map The parent map. If it is NULL, the function searches a top-level node. If both map and +key are NULLs, the function returns the root file node - a map that contains top-level nodes. +@param key Unique pointer to the node name, retrieved with cvGetHashedKey +@param create_missing Flag that specifies whether an absent node should be added to the map + */ +CVAPI(CvFileNode*) cvGetFileNode( CvFileStorage* fs, CvFileNode* map, + const CvStringHashNode* key, + int create_missing CV_DEFAULT(0) ); + +/** @brief Finds a node in a map or file storage. + +The function finds a file node by name. The node is searched either in map or, if the pointer is +NULL, among the top-level file storage nodes. Using this function for maps and cvGetSeqElem (or +sequence reader) for sequences, it is possible to navigate through the file storage. To speed up +multiple queries for a certain key (e.g., in the case of an array of structures) one may use a +combination of cvGetHashedKey and cvGetFileNode. +@param fs File storage +@param map The parent map. If it is NULL, the function searches in all the top-level nodes +(streams), starting with the first one. +@param name The file node name + */ +CVAPI(CvFileNode*) cvGetFileNodeByName( const CvFileStorage* fs, + const CvFileNode* map, + const char* name ); + +/** @brief Retrieves an integer value from a file node. + +The function returns an integer that is represented by the file node. If the file node is NULL, the +default_value is returned (thus, it is convenient to call the function right after cvGetFileNode +without checking for a NULL pointer). If the file node has type CV_NODE_INT, then node-\>data.i is +returned. If the file node has type CV_NODE_REAL, then node-\>data.f is converted to an integer +and returned. Otherwise the error is reported. +@param node File node +@param default_value The value that is returned if node is NULL + */ +CV_INLINE int cvReadInt( const CvFileNode* node, int default_value CV_DEFAULT(0) ) +{ + return !node ? default_value : + CV_NODE_IS_INT(node->tag) ? node->data.i : + CV_NODE_IS_REAL(node->tag) ? cvRound(node->data.f) : 0x7fffffff; +} + +/** @brief Finds a file node and returns its value. + +The function is a simple superposition of cvGetFileNodeByName and cvReadInt. +@param fs File storage +@param map The parent map. If it is NULL, the function searches a top-level node. +@param name The node name +@param default_value The value that is returned if the file node is not found + */ +CV_INLINE int cvReadIntByName( const CvFileStorage* fs, const CvFileNode* map, + const char* name, int default_value CV_DEFAULT(0) ) +{ + return cvReadInt( cvGetFileNodeByName( fs, map, name ), default_value ); +} + +/** @brief Retrieves a floating-point value from a file node. + +The function returns a floating-point value that is represented by the file node. If the file node +is NULL, the default_value is returned (thus, it is convenient to call the function right after +cvGetFileNode without checking for a NULL pointer). If the file node has type CV_NODE_REAL , +then node-\>data.f is returned. If the file node has type CV_NODE_INT , then node-:math:\>data.f +is converted to floating-point and returned. Otherwise the result is not determined. +@param node File node +@param default_value The value that is returned if node is NULL + */ +CV_INLINE double cvReadReal( const CvFileNode* node, double default_value CV_DEFAULT(0.) ) +{ + return !node ? default_value : + CV_NODE_IS_INT(node->tag) ? (double)node->data.i : + CV_NODE_IS_REAL(node->tag) ? node->data.f : 1e300; +} + +/** @brief Finds a file node and returns its value. + +The function is a simple superposition of cvGetFileNodeByName and cvReadReal . +@param fs File storage +@param map The parent map. If it is NULL, the function searches a top-level node. +@param name The node name +@param default_value The value that is returned if the file node is not found + */ +CV_INLINE double cvReadRealByName( const CvFileStorage* fs, const CvFileNode* map, + const char* name, double default_value CV_DEFAULT(0.) ) +{ + return cvReadReal( cvGetFileNodeByName( fs, map, name ), default_value ); +} + +/** @brief Retrieves a text string from a file node. + +The function returns a text string that is represented by the file node. If the file node is NULL, +the default_value is returned (thus, it is convenient to call the function right after +cvGetFileNode without checking for a NULL pointer). If the file node has type CV_NODE_STR , then +node-:math:\>data.str.ptr is returned. Otherwise the result is not determined. +@param node File node +@param default_value The value that is returned if node is NULL + */ +CV_INLINE const char* cvReadString( const CvFileNode* node, + const char* default_value CV_DEFAULT(NULL) ) +{ + return !node ? default_value : CV_NODE_IS_STRING(node->tag) ? node->data.str.ptr : 0; +} + +/** @brief Finds a file node by its name and returns its value. + +The function is a simple superposition of cvGetFileNodeByName and cvReadString . +@param fs File storage +@param map The parent map. If it is NULL, the function searches a top-level node. +@param name The node name +@param default_value The value that is returned if the file node is not found + */ +CV_INLINE const char* cvReadStringByName( const CvFileStorage* fs, const CvFileNode* map, + const char* name, const char* default_value CV_DEFAULT(NULL) ) +{ + return cvReadString( cvGetFileNodeByName( fs, map, name ), default_value ); +} + + +/** @brief Decodes an object and returns a pointer to it. + +The function decodes a user object (creates an object in a native representation from the file +storage subtree) and returns it. The object to be decoded must be an instance of a registered type +that supports the read method (see CvTypeInfo). The type of the object is determined by the type +name that is encoded in the file. If the object is a dynamic structure, it is created either in +memory storage and passed to cvOpenFileStorage or, if a NULL pointer was passed, in temporary +memory storage, which is released when cvReleaseFileStorage is called. Otherwise, if the object is +not a dynamic structure, it is created in a heap and should be released with a specialized function +or by using the generic cvRelease. +@param fs File storage +@param node The root object node +@param attributes Unused parameter + */ +CVAPI(void*) cvRead( CvFileStorage* fs, CvFileNode* node, + CvAttrList* attributes CV_DEFAULT(NULL)); + +/** @brief Finds an object by name and decodes it. + +The function is a simple superposition of cvGetFileNodeByName and cvRead. +@param fs File storage +@param map The parent map. If it is NULL, the function searches a top-level node. +@param name The node name +@param attributes Unused parameter + */ +CV_INLINE void* cvReadByName( CvFileStorage* fs, const CvFileNode* map, + const char* name, CvAttrList* attributes CV_DEFAULT(NULL) ) +{ + return cvRead( fs, cvGetFileNodeByName( fs, map, name ), attributes ); +} + + +/** @brief Initializes the file node sequence reader. + +The function initializes the sequence reader to read data from a file node. The initialized reader +can be then passed to cvReadRawDataSlice. +@param fs File storage +@param src The file node (a sequence) to read numbers from +@param reader Pointer to the sequence reader + */ +CVAPI(void) cvStartReadRawData( const CvFileStorage* fs, const CvFileNode* src, + CvSeqReader* reader ); + +/** @brief Initializes file node sequence reader. + +The function reads one or more elements from the file node, representing a sequence, to a +user-specified array. The total number of read sequence elements is a product of total and the +number of components in each array element. For example, if dt=2if, the function will read total\*3 +sequence elements. As with any sequence, some parts of the file node sequence can be skipped or read +repeatedly by repositioning the reader using cvSetSeqReaderPos. +@param fs File storage +@param reader The sequence reader. Initialize it with cvStartReadRawData . +@param count The number of elements to read +@param dst Pointer to the destination array +@param dt Specification of each array element. It has the same format as in cvWriteRawData . + */ +CVAPI(void) cvReadRawDataSlice( const CvFileStorage* fs, CvSeqReader* reader, + int count, void* dst, const char* dt ); + +/** @brief Reads multiple numbers. + +The function reads elements from a file node that represents a sequence of scalars. +@param fs File storage +@param src The file node (a sequence) to read numbers from +@param dst Pointer to the destination array +@param dt Specification of each array element. It has the same format as in cvWriteRawData . + */ +CVAPI(void) cvReadRawData( const CvFileStorage* fs, const CvFileNode* src, + void* dst, const char* dt ); + +/** @brief Writes a file node to another file storage. + +The function writes a copy of a file node to file storage. Possible applications of the function are +merging several file storages into one and conversion between XML and YAML formats. +@param fs Destination file storage +@param new_node_name New name of the file node in the destination file storage. To keep the +existing name, use cvcvGetFileNodeName +@param node The written node +@param embed If the written node is a collection and this parameter is not zero, no extra level of +hierarchy is created. Instead, all the elements of node are written into the currently written +structure. Of course, map elements can only be embedded into another map, and sequence elements +can only be embedded into another sequence. + */ +CVAPI(void) cvWriteFileNode( CvFileStorage* fs, const char* new_node_name, + const CvFileNode* node, int embed ); + +/** @brief Returns the name of a file node. + +The function returns the name of a file node or NULL, if the file node does not have a name or if +node is NULL. +@param node File node + */ +CVAPI(const char*) cvGetFileNodeName( const CvFileNode* node ); + +/*********************************** Adding own types ***********************************/ + +/** @brief Registers a new type. + +The function registers a new type, which is described by info . The function creates a copy of the +structure, so the user should delete it after calling the function. +@param info Type info structure + */ +CVAPI(void) cvRegisterType( const CvTypeInfo* info ); + +/** @brief Unregisters the type. + +The function unregisters a type with a specified name. If the name is unknown, it is possible to +locate the type info by an instance of the type using cvTypeOf or by iterating the type list, +starting from cvFirstType, and then calling cvUnregisterType(info-\>typeName). +@param type_name Name of an unregistered type + */ +CVAPI(void) cvUnregisterType( const char* type_name ); + +/** @brief Returns the beginning of a type list. + +The function returns the first type in the list of registered types. Navigation through the list can +be done via the prev and next fields of the CvTypeInfo structure. + */ +CVAPI(CvTypeInfo*) cvFirstType(void); + +/** @brief Finds a type by its name. + +The function finds a registered type by its name. It returns NULL if there is no type with the +specified name. +@param type_name Type name + */ +CVAPI(CvTypeInfo*) cvFindType( const char* type_name ); + +/** @brief Returns the type of an object. + +The function finds the type of a given object. It iterates through the list of registered types and +calls the is_instance function/method for every type info structure with that object until one of +them returns non-zero or until the whole list has been traversed. In the latter case, the function +returns NULL. +@param struct_ptr The object pointer + */ +CVAPI(CvTypeInfo*) cvTypeOf( const void* struct_ptr ); + +/** @brief Releases an object. + +The function finds the type of a given object and calls release with the double pointer. +@param struct_ptr Double pointer to the object + */ +CVAPI(void) cvRelease( void** struct_ptr ); + +/** @brief Makes a clone of an object. + +The function finds the type of a given object and calls clone with the passed object. Of course, if +you know the object type, for example, struct_ptr is CvMat\*, it is faster to call the specific +function, like cvCloneMat. +@param struct_ptr The object to clone + */ +CVAPI(void*) cvClone( const void* struct_ptr ); + +/** @brief Saves an object to a file. + +The function saves an object to a file. It provides a simple interface to cvWrite . +@param filename File name +@param struct_ptr Object to save +@param name Optional object name. If it is NULL, the name will be formed from filename . +@param comment Optional comment to put in the beginning of the file +@param attributes Optional attributes passed to cvWrite + */ +CVAPI(void) cvSave( const char* filename, const void* struct_ptr, + const char* name CV_DEFAULT(NULL), + const char* comment CV_DEFAULT(NULL), + CvAttrList attributes CV_DEFAULT(cvAttrList())); + +/** @brief Loads an object from a file. + +The function loads an object from a file. It basically reads the specified file, find the first +top-level node and calls cvRead for that node. If the file node does not have type information or +the type information can not be found by the type name, the function returns NULL. After the object +is loaded, the file storage is closed and all the temporary buffers are deleted. Thus, to load a +dynamic structure, such as a sequence, contour, or graph, one should pass a valid memory storage +destination to the function. +@param filename File name +@param memstorage Memory storage for dynamic structures, such as CvSeq or CvGraph . It is not used +for matrices or images. +@param name Optional object name. If it is NULL, the first top-level object in the storage will be +loaded. +@param real_name Optional output parameter that will contain the name of the loaded object +(useful if name=NULL ) + */ +CVAPI(void*) cvLoad( const char* filename, + CvMemStorage* memstorage CV_DEFAULT(NULL), + const char* name CV_DEFAULT(NULL), + const char** real_name CV_DEFAULT(NULL) ); + +/*********************************** Measuring Execution Time ***************************/ + +/** helper functions for RNG initialization and accurate time measurement: + uses internal clock counter on x86 */ +CVAPI(int64) cvGetTickCount( void ); +CVAPI(double) cvGetTickFrequency( void ); + +/*********************************** CPU capabilities ***********************************/ + +CVAPI(int) cvCheckHardwareSupport(int feature); + +/*********************************** Multi-Threading ************************************/ + +/** retrieve/set the number of threads used in OpenMP implementations */ +CVAPI(int) cvGetNumThreads( void ); +CVAPI(void) cvSetNumThreads( int threads CV_DEFAULT(0) ); +/** get index of the thread being executed */ +CVAPI(int) cvGetThreadNum( void ); + + +/********************************** Error Handling **************************************/ + +/** Get current OpenCV error status */ +CVAPI(int) cvGetErrStatus( void ); + +/** Sets error status silently */ +CVAPI(void) cvSetErrStatus( int status ); + +#define CV_ErrModeLeaf 0 /* Print error and exit program */ +#define CV_ErrModeParent 1 /* Print error and continue */ +#define CV_ErrModeSilent 2 /* Don't print and continue */ + +/** Retrives current error processing mode */ +CVAPI(int) cvGetErrMode( void ); + +/** Sets error processing mode, returns previously used mode */ +CVAPI(int) cvSetErrMode( int mode ); + +/** Sets error status and performs some additonal actions (displaying message box, + writing message to stderr, terminating application etc.) + depending on the current error mode */ +CVAPI(void) cvError( int status, const char* func_name, + const char* err_msg, const char* file_name, int line ); + +/** Retrieves textual description of the error given its code */ +CVAPI(const char*) cvErrorStr( int status ); + +/** Retrieves detailed information about the last error occured */ +CVAPI(int) cvGetErrInfo( const char** errcode_desc, const char** description, + const char** filename, int* line ); + +/** Maps IPP error codes to the counterparts from OpenCV */ +CVAPI(int) cvErrorFromIppStatus( int ipp_status ); + +typedef int (CV_CDECL *CvErrorCallback)( int status, const char* func_name, + const char* err_msg, const char* file_name, int line, void* userdata ); + +/** Assigns a new error-handling function */ +CVAPI(CvErrorCallback) cvRedirectError( CvErrorCallback error_handler, + void* userdata CV_DEFAULT(NULL), + void** prev_userdata CV_DEFAULT(NULL) ); + +/** Output nothing */ +CVAPI(int) cvNulDevReport( int status, const char* func_name, const char* err_msg, + const char* file_name, int line, void* userdata ); + +/** Output to console(fprintf(stderr,...)) */ +CVAPI(int) cvStdErrReport( int status, const char* func_name, const char* err_msg, + const char* file_name, int line, void* userdata ); + +/** Output to MessageBox(WIN32) */ +CVAPI(int) cvGuiBoxReport( int status, const char* func_name, const char* err_msg, + const char* file_name, int line, void* userdata ); + +#define OPENCV_ERROR(status,func,context) \ +cvError((status),(func),(context),__FILE__,__LINE__) + +#define OPENCV_ASSERT(expr,func,context) \ +{if (! (expr)) \ +{OPENCV_ERROR(CV_StsInternal,(func),(context));}} + +#define OPENCV_CALL( Func ) \ +{ \ +Func; \ +} + + +/** CV_FUNCNAME macro defines icvFuncName constant which is used by CV_ERROR macro */ +#ifdef CV_NO_FUNC_NAMES +#define CV_FUNCNAME( Name ) +#define cvFuncName "" +#else +#define CV_FUNCNAME( Name ) \ +static char cvFuncName[] = Name +#endif + + +/** + CV_ERROR macro unconditionally raises error with passed code and message. + After raising error, control will be transferred to the exit label. + */ +#define CV_ERROR( Code, Msg ) \ +{ \ + cvError( (Code), cvFuncName, Msg, __FILE__, __LINE__ ); \ + __CV_EXIT__; \ +} + +/** + CV_CHECK macro checks error status after CV (or IPL) + function call. If error detected, control will be transferred to the exit + label. + */ +#define CV_CHECK() \ +{ \ + if( cvGetErrStatus() < 0 ) \ + CV_ERROR( CV_StsBackTrace, "Inner function failed." ); \ +} + + +/** + CV_CALL macro calls CV (or IPL) function, checks error status and + signals a error if the function failed. Useful in "parent node" + error procesing mode + */ +#define CV_CALL( Func ) \ +{ \ + Func; \ + CV_CHECK(); \ +} + + +/** Runtime assertion macro */ +#define CV_ASSERT( Condition ) \ +{ \ + if( !(Condition) ) \ + CV_ERROR( CV_StsInternal, "Assertion: " #Condition " failed" ); \ +} + +#define __CV_BEGIN__ { +#define __CV_END__ goto exit; exit: ; } +#define __CV_EXIT__ goto exit + +/** @} core_c */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus + +//! @addtogroup core_c_glue +//! @{ + +//! class for automatic module/RTTI data registration/unregistration +struct CV_EXPORTS CvType +{ + CvType( const char* type_name, + CvIsInstanceFunc is_instance, CvReleaseFunc release=0, + CvReadFunc read=0, CvWriteFunc write=0, CvCloneFunc clone=0 ); + ~CvType(); + CvTypeInfo* info; + + static CvTypeInfo* first; + static CvTypeInfo* last; +}; + +//! @} + +#include "opencv2/core/utility.hpp" + +namespace cv +{ + +//! @addtogroup core_c_glue +//! @{ + +/////////////////////////////////////////// glue /////////////////////////////////////////// + +//! converts array (CvMat or IplImage) to cv::Mat +CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false, + bool allowND=true, int coiMode=0, + AutoBuffer* buf=0); + +static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMode=0) +{ + return cvarrToMat(arr, copyData, true, coiMode); +} + + +//! extracts Channel of Interest from CvMat or IplImage and makes cv::Mat out of it. +CV_EXPORTS void extractImageCOI(const CvArr* arr, OutputArray coiimg, int coi=-1); +//! inserts single-channel cv::Mat into a multi-channel CvMat or IplImage +CV_EXPORTS void insertImageCOI(InputArray coiimg, CvArr* arr, int coi=-1); + + + +////// specialized implementations of DefaultDeleter::operator() for classic OpenCV types ////// + +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvMat* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(IplImage* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvMatND* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvSparseMat* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvMemStorage* obj) const; + +////////////// convenient wrappers for operating old-style dynamic structures ////////////// + +template class SeqIterator; + +typedef Ptr MemStorage; + +/*! + Template Sequence Class derived from CvSeq + + The class provides more convenient access to sequence elements, + STL-style operations and iterators. + + \note The class is targeted for simple data types, + i.e. no constructors or destructors + are called for the sequence elements. +*/ +template class Seq +{ +public: + typedef SeqIterator<_Tp> iterator; + typedef SeqIterator<_Tp> const_iterator; + + //! the default constructor + Seq(); + //! the constructor for wrapping CvSeq structure. The real element type in CvSeq should match _Tp. + Seq(const CvSeq* seq); + //! creates the empty sequence that resides in the specified storage + Seq(MemStorage& storage, int headerSize = sizeof(CvSeq)); + //! returns read-write reference to the specified element + _Tp& operator [](int idx); + //! returns read-only reference to the specified element + const _Tp& operator[](int idx) const; + //! returns iterator pointing to the beginning of the sequence + SeqIterator<_Tp> begin() const; + //! returns iterator pointing to the element following the last sequence element + SeqIterator<_Tp> end() const; + //! returns the number of elements in the sequence + size_t size() const; + //! returns the type of sequence elements (CV_8UC1 ... CV_64FC(CV_CN_MAX) ...) + int type() const; + //! returns the depth of sequence elements (CV_8U ... CV_64F) + int depth() const; + //! returns the number of channels in each sequence element + int channels() const; + //! returns the size of each sequence element + size_t elemSize() const; + //! returns index of the specified sequence element + size_t index(const _Tp& elem) const; + //! appends the specified element to the end of the sequence + void push_back(const _Tp& elem); + //! appends the specified element to the front of the sequence + void push_front(const _Tp& elem); + //! appends zero or more elements to the end of the sequence + void push_back(const _Tp* elems, size_t count); + //! appends zero or more elements to the front of the sequence + void push_front(const _Tp* elems, size_t count); + //! inserts the specified element to the specified position + void insert(int idx, const _Tp& elem); + //! inserts zero or more elements to the specified position + void insert(int idx, const _Tp* elems, size_t count); + //! removes element at the specified position + void remove(int idx); + //! removes the specified subsequence + void remove(const Range& r); + + //! returns reference to the first sequence element + _Tp& front(); + //! returns read-only reference to the first sequence element + const _Tp& front() const; + //! returns reference to the last sequence element + _Tp& back(); + //! returns read-only reference to the last sequence element + const _Tp& back() const; + //! returns true iff the sequence contains no elements + bool empty() const; + + //! removes all the elements from the sequence + void clear(); + //! removes the first element from the sequence + void pop_front(); + //! removes the last element from the sequence + void pop_back(); + //! removes zero or more elements from the beginning of the sequence + void pop_front(_Tp* elems, size_t count); + //! removes zero or more elements from the end of the sequence + void pop_back(_Tp* elems, size_t count); + + //! copies the whole sequence or the sequence slice to the specified vector + void copyTo(std::vector<_Tp>& vec, const Range& range=Range::all()) const; + //! returns the vector containing all the sequence elements + operator std::vector<_Tp>() const; + + CvSeq* seq; +}; + + +/*! + STL-style Sequence Iterator inherited from the CvSeqReader structure +*/ +template class SeqIterator : public CvSeqReader +{ +public: + //! the default constructor + SeqIterator(); + //! the constructor setting the iterator to the beginning or to the end of the sequence + SeqIterator(const Seq<_Tp>& seq, bool seekEnd=false); + //! positions the iterator within the sequence + void seek(size_t pos); + //! reports the current iterator position + size_t tell() const; + //! returns reference to the current sequence element + _Tp& operator *(); + //! returns read-only reference to the current sequence element + const _Tp& operator *() const; + //! moves iterator to the next sequence element + SeqIterator& operator ++(); + //! moves iterator to the next sequence element + SeqIterator operator ++(int) const; + //! moves iterator to the previous sequence element + SeqIterator& operator --(); + //! moves iterator to the previous sequence element + SeqIterator operator --(int) const; + + //! moves iterator forward by the specified offset (possibly negative) + SeqIterator& operator +=(int); + //! moves iterator backward by the specified offset (possibly negative) + SeqIterator& operator -=(int); + + // this is index of the current element module seq->total*2 + // (to distinguish between 0 and seq->total) + int index; +}; + + + +// bridge C++ => C Seq API +CV_EXPORTS schar* seqPush( CvSeq* seq, const void* element=0); +CV_EXPORTS schar* seqPushFront( CvSeq* seq, const void* element=0); +CV_EXPORTS void seqPop( CvSeq* seq, void* element=0); +CV_EXPORTS void seqPopFront( CvSeq* seq, void* element=0); +CV_EXPORTS void seqPopMulti( CvSeq* seq, void* elements, + int count, int in_front=0 ); +CV_EXPORTS void seqRemove( CvSeq* seq, int index ); +CV_EXPORTS void clearSeq( CvSeq* seq ); +CV_EXPORTS schar* getSeqElem( const CvSeq* seq, int index ); +CV_EXPORTS void seqRemoveSlice( CvSeq* seq, CvSlice slice ); +CV_EXPORTS void seqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr ); + +template inline Seq<_Tp>::Seq() : seq(0) {} +template inline Seq<_Tp>::Seq( const CvSeq* _seq ) : seq((CvSeq*)_seq) +{ + CV_Assert(!_seq || _seq->elem_size == sizeof(_Tp)); +} + +template inline Seq<_Tp>::Seq( MemStorage& storage, + int headerSize ) +{ + CV_Assert(headerSize >= (int)sizeof(CvSeq)); + seq = cvCreateSeq(DataType<_Tp>::type, headerSize, sizeof(_Tp), storage); +} + +template inline _Tp& Seq<_Tp>::operator [](int idx) +{ return *(_Tp*)getSeqElem(seq, idx); } + +template inline const _Tp& Seq<_Tp>::operator [](int idx) const +{ return *(_Tp*)getSeqElem(seq, idx); } + +template inline SeqIterator<_Tp> Seq<_Tp>::begin() const +{ return SeqIterator<_Tp>(*this); } + +template inline SeqIterator<_Tp> Seq<_Tp>::end() const +{ return SeqIterator<_Tp>(*this, true); } + +template inline size_t Seq<_Tp>::size() const +{ return seq ? seq->total : 0; } + +template inline int Seq<_Tp>::type() const +{ return seq ? CV_MAT_TYPE(seq->flags) : 0; } + +template inline int Seq<_Tp>::depth() const +{ return seq ? CV_MAT_DEPTH(seq->flags) : 0; } + +template inline int Seq<_Tp>::channels() const +{ return seq ? CV_MAT_CN(seq->flags) : 0; } + +template inline size_t Seq<_Tp>::elemSize() const +{ return seq ? seq->elem_size : 0; } + +template inline size_t Seq<_Tp>::index(const _Tp& elem) const +{ return cvSeqElemIdx(seq, &elem); } + +template inline void Seq<_Tp>::push_back(const _Tp& elem) +{ cvSeqPush(seq, &elem); } + +template inline void Seq<_Tp>::push_front(const _Tp& elem) +{ cvSeqPushFront(seq, &elem); } + +template inline void Seq<_Tp>::push_back(const _Tp* elem, size_t count) +{ cvSeqPushMulti(seq, elem, (int)count, 0); } + +template inline void Seq<_Tp>::push_front(const _Tp* elem, size_t count) +{ cvSeqPushMulti(seq, elem, (int)count, 1); } + +template inline _Tp& Seq<_Tp>::back() +{ return *(_Tp*)getSeqElem(seq, -1); } + +template inline const _Tp& Seq<_Tp>::back() const +{ return *(const _Tp*)getSeqElem(seq, -1); } + +template inline _Tp& Seq<_Tp>::front() +{ return *(_Tp*)getSeqElem(seq, 0); } + +template inline const _Tp& Seq<_Tp>::front() const +{ return *(const _Tp*)getSeqElem(seq, 0); } + +template inline bool Seq<_Tp>::empty() const +{ return !seq || seq->total == 0; } + +template inline void Seq<_Tp>::clear() +{ if(seq) clearSeq(seq); } + +template inline void Seq<_Tp>::pop_back() +{ seqPop(seq); } + +template inline void Seq<_Tp>::pop_front() +{ seqPopFront(seq); } + +template inline void Seq<_Tp>::pop_back(_Tp* elem, size_t count) +{ seqPopMulti(seq, elem, (int)count, 0); } + +template inline void Seq<_Tp>::pop_front(_Tp* elem, size_t count) +{ seqPopMulti(seq, elem, (int)count, 1); } + +template inline void Seq<_Tp>::insert(int idx, const _Tp& elem) +{ seqInsert(seq, idx, &elem); } + +template inline void Seq<_Tp>::insert(int idx, const _Tp* elems, size_t count) +{ + CvMat m = cvMat(1, count, DataType<_Tp>::type, elems); + seqInsertSlice(seq, idx, &m); +} + +template inline void Seq<_Tp>::remove(int idx) +{ seqRemove(seq, idx); } + +template inline void Seq<_Tp>::remove(const Range& r) +{ seqRemoveSlice(seq, cvSlice(r.start, r.end)); } + +template inline void Seq<_Tp>::copyTo(std::vector<_Tp>& vec, const Range& range) const +{ + size_t len = !seq ? 0 : range == Range::all() ? seq->total : range.end - range.start; + vec.resize(len); + if( seq && len ) + cvCvtSeqToArray(seq, &vec[0], range); +} + +template inline Seq<_Tp>::operator std::vector<_Tp>() const +{ + std::vector<_Tp> vec; + copyTo(vec); + return vec; +} + +template inline SeqIterator<_Tp>::SeqIterator() +{ memset(this, 0, sizeof(*this)); } + +template inline SeqIterator<_Tp>::SeqIterator(const Seq<_Tp>& _seq, bool seekEnd) +{ + cvStartReadSeq(_seq.seq, this); + index = seekEnd ? _seq.seq->total : 0; +} + +template inline void SeqIterator<_Tp>::seek(size_t pos) +{ + cvSetSeqReaderPos(this, (int)pos, false); + index = pos; +} + +template inline size_t SeqIterator<_Tp>::tell() const +{ return index; } + +template inline _Tp& SeqIterator<_Tp>::operator *() +{ return *(_Tp*)ptr; } + +template inline const _Tp& SeqIterator<_Tp>::operator *() const +{ return *(const _Tp*)ptr; } + +template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator ++() +{ + CV_NEXT_SEQ_ELEM(sizeof(_Tp), *this); + if( ++index >= seq->total*2 ) + index = 0; + return *this; +} + +template inline SeqIterator<_Tp> SeqIterator<_Tp>::operator ++(int) const +{ + SeqIterator<_Tp> it = *this; + ++*this; + return it; +} + +template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator --() +{ + CV_PREV_SEQ_ELEM(sizeof(_Tp), *this); + if( --index < 0 ) + index = seq->total*2-1; + return *this; +} + +template inline SeqIterator<_Tp> SeqIterator<_Tp>::operator --(int) const +{ + SeqIterator<_Tp> it = *this; + --*this; + return it; +} + +template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator +=(int delta) +{ + cvSetSeqReaderPos(this, delta, 1); + index += delta; + int n = seq->total*2; + if( index < 0 ) + index += n; + if( index >= n ) + index -= n; + return *this; +} + +template inline SeqIterator<_Tp>& SeqIterator<_Tp>::operator -=(int delta) +{ + return (*this += -delta); +} + +template inline ptrdiff_t operator - (const SeqIterator<_Tp>& a, + const SeqIterator<_Tp>& b) +{ + ptrdiff_t delta = a.index - b.index, n = a.seq->total; + if( delta > n || delta < -n ) + delta += delta < 0 ? n : -n; + return delta; +} + +template inline bool operator == (const SeqIterator<_Tp>& a, + const SeqIterator<_Tp>& b) +{ + return a.seq == b.seq && a.index == b.index; +} + +template inline bool operator != (const SeqIterator<_Tp>& a, + const SeqIterator<_Tp>& b) +{ + return !(a == b); +} + +//! @} + +} // cv + +#endif + +#endif diff --git a/include/opencv2/core/cuda.hpp b/include/opencv2/core/cuda.hpp new file mode 100644 index 0000000..a9c7a39 --- /dev/null +++ b/include/opencv2/core/cuda.hpp @@ -0,0 +1,845 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CUDA_HPP__ +#define __OPENCV_CORE_CUDA_HPP__ + +#ifndef __cplusplus +# error cuda.hpp header must be compiled as C++ +#endif + +#include "opencv2/core.hpp" +#include "opencv2/core/cuda_types.hpp" + +/** + @defgroup cuda CUDA-accelerated Computer Vision + @{ + @defgroup cudacore Core part + @{ + @defgroup cudacore_init Initalization and Information + @defgroup cudacore_struct Data Structures + @} + @} + */ + +namespace cv { namespace cuda { + +//! @addtogroup cudacore_struct +//! @{ + +//=================================================================================== +// GpuMat +//=================================================================================== + +/** @brief Base storage class for GPU memory with reference counting. + +Its interface matches the Mat interface with the following limitations: + +- no arbitrary dimensions support (only 2D) +- no functions that return references to their data (because references on GPU are not valid for + CPU) +- no expression templates technique support + +Beware that the latter limitation may lead to overloaded matrix operators that cause memory +allocations. The GpuMat class is convertible to cuda::PtrStepSz and cuda::PtrStep so it can be +passed directly to the kernel. + +@note In contrast with Mat, in most cases GpuMat::isContinuous() == false . This means that rows are +aligned to a size depending on the hardware. Single-row GpuMat is always a continuous matrix. + +@note You are not recommended to leave static or global GpuMat variables allocated, that is, to rely +on its destructor. The destruction order of such variables and CUDA context is undefined. GPU memory +release function returns error if the CUDA context has been destroyed before. + +@sa Mat + */ +class CV_EXPORTS GpuMat +{ +public: + class CV_EXPORTS Allocator + { + public: + virtual ~Allocator() {} + + // allocator must fill data, step and refcount fields + virtual bool allocate(GpuMat* mat, int rows, int cols, size_t elemSize) = 0; + virtual void free(GpuMat* mat) = 0; + }; + + //! default allocator + static Allocator* defaultAllocator(); + static void setDefaultAllocator(Allocator* allocator); + + //! default constructor + explicit GpuMat(Allocator* allocator = defaultAllocator()); + + //! constructs GpuMat of the specified size and type + GpuMat(int rows, int cols, int type, Allocator* allocator = defaultAllocator()); + GpuMat(Size size, int type, Allocator* allocator = defaultAllocator()); + + //! constucts GpuMat and fills it with the specified value _s + GpuMat(int rows, int cols, int type, Scalar s, Allocator* allocator = defaultAllocator()); + GpuMat(Size size, int type, Scalar s, Allocator* allocator = defaultAllocator()); + + //! copy constructor + GpuMat(const GpuMat& m); + + //! constructor for GpuMat headers pointing to user-allocated data + GpuMat(int rows, int cols, int type, void* data, size_t step = Mat::AUTO_STEP); + GpuMat(Size size, int type, void* data, size_t step = Mat::AUTO_STEP); + + //! creates a GpuMat header for a part of the bigger matrix + GpuMat(const GpuMat& m, Range rowRange, Range colRange); + GpuMat(const GpuMat& m, Rect roi); + + //! builds GpuMat from host memory (Blocking call) + explicit GpuMat(InputArray arr, Allocator* allocator = defaultAllocator()); + + //! destructor - calls release() + ~GpuMat(); + + //! assignment operators + GpuMat& operator =(const GpuMat& m); + + //! allocates new GpuMat data unless the GpuMat already has specified size and type + void create(int rows, int cols, int type); + void create(Size size, int type); + + //! decreases reference counter, deallocate the data when reference counter reaches 0 + void release(); + + //! swaps with other smart pointer + void swap(GpuMat& mat); + + //! pefroms upload data to GpuMat (Blocking call) + void upload(InputArray arr); + + //! pefroms upload data to GpuMat (Non-Blocking call) + void upload(InputArray arr, Stream& stream); + + //! pefroms download data from device to host memory (Blocking call) + void download(OutputArray dst) const; + + //! pefroms download data from device to host memory (Non-Blocking call) + void download(OutputArray dst, Stream& stream) const; + + //! returns deep copy of the GpuMat, i.e. the data is copied + GpuMat clone() const; + + //! copies the GpuMat content to device memory (Blocking call) + void copyTo(OutputArray dst) const; + + //! copies the GpuMat content to device memory (Non-Blocking call) + void copyTo(OutputArray dst, Stream& stream) const; + + //! copies those GpuMat elements to "m" that are marked with non-zero mask elements (Blocking call) + void copyTo(OutputArray dst, InputArray mask) const; + + //! copies those GpuMat elements to "m" that are marked with non-zero mask elements (Non-Blocking call) + void copyTo(OutputArray dst, InputArray mask, Stream& stream) const; + + //! sets some of the GpuMat elements to s (Blocking call) + GpuMat& setTo(Scalar s); + + //! sets some of the GpuMat elements to s (Non-Blocking call) + GpuMat& setTo(Scalar s, Stream& stream); + + //! sets some of the GpuMat elements to s, according to the mask (Blocking call) + GpuMat& setTo(Scalar s, InputArray mask); + + //! sets some of the GpuMat elements to s, according to the mask (Non-Blocking call) + GpuMat& setTo(Scalar s, InputArray mask, Stream& stream); + + //! converts GpuMat to another datatype (Blocking call) + void convertTo(OutputArray dst, int rtype) const; + + //! converts GpuMat to another datatype (Non-Blocking call) + void convertTo(OutputArray dst, int rtype, Stream& stream) const; + + //! converts GpuMat to another datatype with scaling (Blocking call) + void convertTo(OutputArray dst, int rtype, double alpha, double beta = 0.0) const; + + //! converts GpuMat to another datatype with scaling (Non-Blocking call) + void convertTo(OutputArray dst, int rtype, double alpha, Stream& stream) const; + + //! converts GpuMat to another datatype with scaling (Non-Blocking call) + void convertTo(OutputArray dst, int rtype, double alpha, double beta, Stream& stream) const; + + void assignTo(GpuMat& m, int type=-1) const; + + //! returns pointer to y-th row + uchar* ptr(int y = 0); + const uchar* ptr(int y = 0) const; + + //! template version of the above method + template _Tp* ptr(int y = 0); + template const _Tp* ptr(int y = 0) const; + + template operator PtrStepSz<_Tp>() const; + template operator PtrStep<_Tp>() const; + + //! returns a new GpuMat header for the specified row + GpuMat row(int y) const; + + //! returns a new GpuMat header for the specified column + GpuMat col(int x) const; + + //! ... for the specified row span + GpuMat rowRange(int startrow, int endrow) const; + GpuMat rowRange(Range r) const; + + //! ... for the specified column span + GpuMat colRange(int startcol, int endcol) const; + GpuMat colRange(Range r) const; + + //! extracts a rectangular sub-GpuMat (this is a generalized form of row, rowRange etc.) + GpuMat operator ()(Range rowRange, Range colRange) const; + GpuMat operator ()(Rect roi) const; + + //! creates alternative GpuMat header for the same data, with different + //! number of channels and/or different number of rows + GpuMat reshape(int cn, int rows = 0) const; + + //! locates GpuMat header within a parent GpuMat + void locateROI(Size& wholeSize, Point& ofs) const; + + //! moves/resizes the current GpuMat ROI inside the parent GpuMat + GpuMat& adjustROI(int dtop, int dbottom, int dleft, int dright); + + //! returns true iff the GpuMat data is continuous + //! (i.e. when there are no gaps between successive rows) + bool isContinuous() const; + + //! returns element size in bytes + size_t elemSize() const; + + //! returns the size of element channel in bytes + size_t elemSize1() const; + + //! returns element type + int type() const; + + //! returns element type + int depth() const; + + //! returns number of channels + int channels() const; + + //! returns step/elemSize1() + size_t step1() const; + + //! returns GpuMat size : width == number of columns, height == number of rows + Size size() const; + + //! returns true if GpuMat data is NULL + bool empty() const; + + /*! includes several bit-fields: + - the magic signature + - continuity flag + - depth + - number of channels + */ + int flags; + + //! the number of rows and columns + int rows, cols; + + //! a distance between successive rows in bytes; includes the gap if any + size_t step; + + //! pointer to the data + uchar* data; + + //! pointer to the reference counter; + //! when GpuMat points to user-allocated data, the pointer is NULL + int* refcount; + + //! helper fields used in locateROI and adjustROI + uchar* datastart; + const uchar* dataend; + + //! allocator + Allocator* allocator; +}; + +/** @brief Creates a continuous matrix. + +@param rows Row count. +@param cols Column count. +@param type Type of the matrix. +@param arr Destination matrix. This parameter changes only if it has a proper type and area ( +\f$\texttt{rows} \times \texttt{cols}\f$ ). + +Matrix is called continuous if its elements are stored continuously, that is, without gaps at the +end of each row. + */ +CV_EXPORTS void createContinuous(int rows, int cols, int type, OutputArray arr); + +/** @brief Ensures that the size of a matrix is big enough and the matrix has a proper type. + +@param rows Minimum desired number of rows. +@param cols Minimum desired number of columns. +@param type Desired matrix type. +@param arr Destination matrix. + +The function does not reallocate memory if the matrix has proper attributes already. + */ +CV_EXPORTS void ensureSizeIsEnough(int rows, int cols, int type, OutputArray arr); + +//! BufferPool management (must be called before Stream creation) +CV_EXPORTS void setBufferPoolUsage(bool on); +CV_EXPORTS void setBufferPoolConfig(int deviceId, size_t stackSize, int stackCount); + +//=================================================================================== +// HostMem +//=================================================================================== + +/** @brief Class with reference counting wrapping special memory type allocation functions from CUDA. + +Its interface is also Mat-like but with additional memory type parameters. + +- **PAGE_LOCKED** sets a page locked memory type used commonly for fast and asynchronous + uploading/downloading data from/to GPU. +- **SHARED** specifies a zero copy memory allocation that enables mapping the host memory to GPU + address space, if supported. +- **WRITE_COMBINED** sets the write combined buffer that is not cached by CPU. Such buffers are + used to supply GPU with data when GPU only reads it. The advantage is a better CPU cache + utilization. + +@note Allocation size of such memory types is usually limited. For more details, see *CUDA 2.2 +Pinned Memory APIs* document or *CUDA C Programming Guide*. + */ +class CV_EXPORTS HostMem +{ +public: + enum AllocType { PAGE_LOCKED = 1, SHARED = 2, WRITE_COMBINED = 4 }; + + static MatAllocator* getAllocator(AllocType alloc_type = PAGE_LOCKED); + + explicit HostMem(AllocType alloc_type = PAGE_LOCKED); + + HostMem(const HostMem& m); + + HostMem(int rows, int cols, int type, AllocType alloc_type = PAGE_LOCKED); + HostMem(Size size, int type, AllocType alloc_type = PAGE_LOCKED); + + //! creates from host memory with coping data + explicit HostMem(InputArray arr, AllocType alloc_type = PAGE_LOCKED); + + ~HostMem(); + + HostMem& operator =(const HostMem& m); + + //! swaps with other smart pointer + void swap(HostMem& b); + + //! returns deep copy of the matrix, i.e. the data is copied + HostMem clone() const; + + //! allocates new matrix data unless the matrix already has specified size and type. + void create(int rows, int cols, int type); + void create(Size size, int type); + + //! creates alternative HostMem header for the same data, with different + //! number of channels and/or different number of rows + HostMem reshape(int cn, int rows = 0) const; + + //! decrements reference counter and released memory if needed. + void release(); + + //! returns matrix header with disabled reference counting for HostMem data. + Mat createMatHeader() const; + + /** @brief Maps CPU memory to GPU address space and creates the cuda::GpuMat header without reference counting + for it. + + This can be done only if memory was allocated with the SHARED flag and if it is supported by the + hardware. Laptops often share video and CPU memory, so address spaces can be mapped, which + eliminates an extra copy. + */ + GpuMat createGpuMatHeader() const; + + // Please see cv::Mat for descriptions + bool isContinuous() const; + size_t elemSize() const; + size_t elemSize1() const; + int type() const; + int depth() const; + int channels() const; + size_t step1() const; + Size size() const; + bool empty() const; + + // Please see cv::Mat for descriptions + int flags; + int rows, cols; + size_t step; + + uchar* data; + int* refcount; + + uchar* datastart; + const uchar* dataend; + + AllocType alloc_type; +}; + +/** @brief Page-locks the memory of matrix and maps it for the device(s). + +@param m Input matrix. + */ +CV_EXPORTS void registerPageLocked(Mat& m); + +/** @brief Unmaps the memory of matrix and makes it pageable again. + +@param m Input matrix. + */ +CV_EXPORTS void unregisterPageLocked(Mat& m); + +//=================================================================================== +// Stream +//=================================================================================== + +/** @brief This class encapsulates a queue of asynchronous calls. + +@note Currently, you may face problems if an operation is enqueued twice with different data. Some +functions use the constant GPU memory, and next call may update the memory before the previous one +has been finished. But calling different operations asynchronously is safe because each operation +has its own constant buffer. Memory copy/upload/download/set operations to the buffers you hold are +also safe. : + */ +class CV_EXPORTS Stream +{ + typedef void (Stream::*bool_type)() const; + void this_type_does_not_support_comparisons() const {} + +public: + typedef void (*StreamCallback)(int status, void* userData); + + //! creates a new asynchronous stream + Stream(); + + /** @brief Returns true if the current stream queue is finished. Otherwise, it returns false. + */ + bool queryIfComplete() const; + + /** @brief Blocks the current CPU thread until all operations in the stream are complete. + */ + void waitForCompletion(); + + /** @brief Makes a compute stream wait on an event. + */ + void waitEvent(const Event& event); + + /** @brief Adds a callback to be called on the host after all currently enqueued items in the stream have + completed. + + @note Callbacks must not make any CUDA API calls. Callbacks must not perform any synchronization + that may depend on outstanding device work or other callbacks that are not mandated to run earlier. + Callbacks without a mandated order (in independent streams) execute in undefined order and may be + serialized. + */ + void enqueueHostCallback(StreamCallback callback, void* userData); + + //! return Stream object for default CUDA stream + static Stream& Null(); + + //! returns true if stream object is not default (!= 0) + operator bool_type() const; + + class Impl; + +private: + Ptr impl_; + Stream(const Ptr& impl); + + friend struct StreamAccessor; + friend class BufferPool; + friend class DefaultDeviceInitializer; +}; + +class CV_EXPORTS Event +{ +public: + enum CreateFlags + { + DEFAULT = 0x00, /**< Default event flag */ + BLOCKING_SYNC = 0x01, /**< Event uses blocking synchronization */ + DISABLE_TIMING = 0x02, /**< Event will not record timing data */ + INTERPROCESS = 0x04 /**< Event is suitable for interprocess use. DisableTiming must be set */ + }; + + explicit Event(CreateFlags flags = DEFAULT); + + //! records an event + void record(Stream& stream = Stream::Null()); + + //! queries an event's status + bool queryIfComplete() const; + + //! waits for an event to complete + void waitForCompletion(); + + //! computes the elapsed time between events + static float elapsedTime(const Event& start, const Event& end); + + class Impl; + +private: + Ptr impl_; + + friend struct EventAccessor; +}; + +//! @} cudacore_struct + +//=================================================================================== +// Initialization & Info +//=================================================================================== + +//! @addtogroup cudacore_init +//! @{ + +/** @brief Returns the number of installed CUDA-enabled devices. + +Use this function before any other CUDA functions calls. If OpenCV is compiled without CUDA support, +this function returns 0. + */ +CV_EXPORTS int getCudaEnabledDeviceCount(); + +/** @brief Sets a device and initializes it for the current thread. + +@param device System index of a CUDA device starting with 0. + +If the call of this function is omitted, a default device is initialized at the fist CUDA usage. + */ +CV_EXPORTS void setDevice(int device); + +/** @brief Returns the current device index set by cuda::setDevice or initialized by default. + */ +CV_EXPORTS int getDevice(); + +/** @brief Explicitly destroys and cleans up all resources associated with the current device in the current +process. + +Any subsequent API call to this device will reinitialize the device. + */ +CV_EXPORTS void resetDevice(); + +/** @brief Enumeration providing CUDA computing features. + */ +enum FeatureSet +{ + FEATURE_SET_COMPUTE_10 = 10, + FEATURE_SET_COMPUTE_11 = 11, + FEATURE_SET_COMPUTE_12 = 12, + FEATURE_SET_COMPUTE_13 = 13, + FEATURE_SET_COMPUTE_20 = 20, + FEATURE_SET_COMPUTE_21 = 21, + FEATURE_SET_COMPUTE_30 = 30, + FEATURE_SET_COMPUTE_32 = 32, + FEATURE_SET_COMPUTE_35 = 35, + FEATURE_SET_COMPUTE_50 = 50, + + GLOBAL_ATOMICS = FEATURE_SET_COMPUTE_11, + SHARED_ATOMICS = FEATURE_SET_COMPUTE_12, + NATIVE_DOUBLE = FEATURE_SET_COMPUTE_13, + WARP_SHUFFLE_FUNCTIONS = FEATURE_SET_COMPUTE_30, + DYNAMIC_PARALLELISM = FEATURE_SET_COMPUTE_35 +}; + +//! checks whether current device supports the given feature +CV_EXPORTS bool deviceSupports(FeatureSet feature_set); + +/** @brief Class providing a set of static methods to check what NVIDIA\* card architecture the CUDA module was +built for. + +According to the CUDA C Programming Guide Version 3.2: "PTX code produced for some specific compute +capability can always be compiled to binary code of greater or equal compute capability". + */ +class CV_EXPORTS TargetArchs +{ +public: + /** @brief The following method checks whether the module was built with the support of the given feature: + + @param feature_set Features to be checked. See :ocvcuda::FeatureSet. + */ + static bool builtWith(FeatureSet feature_set); + + /** @brief There is a set of methods to check whether the module contains intermediate (PTX) or binary CUDA + code for the given architecture(s): + + @param major Major compute capability version. + @param minor Minor compute capability version. + */ + static bool has(int major, int minor); + static bool hasPtx(int major, int minor); + static bool hasBin(int major, int minor); + + static bool hasEqualOrLessPtx(int major, int minor); + static bool hasEqualOrGreater(int major, int minor); + static bool hasEqualOrGreaterPtx(int major, int minor); + static bool hasEqualOrGreaterBin(int major, int minor); +}; + +/** @brief Class providing functionality for querying the specified GPU properties. + */ +class CV_EXPORTS DeviceInfo +{ +public: + //! creates DeviceInfo object for the current GPU + DeviceInfo(); + + /** @brief The constructors. + + @param device_id System index of the CUDA device starting with 0. + + Constructs the DeviceInfo object for the specified device. If device_id parameter is missed, it + constructs an object for the current device. + */ + DeviceInfo(int device_id); + + /** @brief Returns system index of the CUDA device starting with 0. + */ + int deviceID() const; + + //! ASCII string identifying device + const char* name() const; + + //! global memory available on device in bytes + size_t totalGlobalMem() const; + + //! shared memory available per block in bytes + size_t sharedMemPerBlock() const; + + //! 32-bit registers available per block + int regsPerBlock() const; + + //! warp size in threads + int warpSize() const; + + //! maximum pitch in bytes allowed by memory copies + size_t memPitch() const; + + //! maximum number of threads per block + int maxThreadsPerBlock() const; + + //! maximum size of each dimension of a block + Vec3i maxThreadsDim() const; + + //! maximum size of each dimension of a grid + Vec3i maxGridSize() const; + + //! clock frequency in kilohertz + int clockRate() const; + + //! constant memory available on device in bytes + size_t totalConstMem() const; + + //! major compute capability + int majorVersion() const; + + //! minor compute capability + int minorVersion() const; + + //! alignment requirement for textures + size_t textureAlignment() const; + + //! pitch alignment requirement for texture references bound to pitched memory + size_t texturePitchAlignment() const; + + //! number of multiprocessors on device + int multiProcessorCount() const; + + //! specified whether there is a run time limit on kernels + bool kernelExecTimeoutEnabled() const; + + //! device is integrated as opposed to discrete + bool integrated() const; + + //! device can map host memory with cudaHostAlloc/cudaHostGetDevicePointer + bool canMapHostMemory() const; + + enum ComputeMode + { + ComputeModeDefault, /**< default compute mode (Multiple threads can use cudaSetDevice with this device) */ + ComputeModeExclusive, /**< compute-exclusive-thread mode (Only one thread in one process will be able to use cudaSetDevice with this device) */ + ComputeModeProhibited, /**< compute-prohibited mode (No threads can use cudaSetDevice with this device) */ + ComputeModeExclusiveProcess /**< compute-exclusive-process mode (Many threads in one process will be able to use cudaSetDevice with this device) */ + }; + + //! compute mode + ComputeMode computeMode() const; + + //! maximum 1D texture size + int maxTexture1D() const; + + //! maximum 1D mipmapped texture size + int maxTexture1DMipmap() const; + + //! maximum size for 1D textures bound to linear memory + int maxTexture1DLinear() const; + + //! maximum 2D texture dimensions + Vec2i maxTexture2D() const; + + //! maximum 2D mipmapped texture dimensions + Vec2i maxTexture2DMipmap() const; + + //! maximum dimensions (width, height, pitch) for 2D textures bound to pitched memory + Vec3i maxTexture2DLinear() const; + + //! maximum 2D texture dimensions if texture gather operations have to be performed + Vec2i maxTexture2DGather() const; + + //! maximum 3D texture dimensions + Vec3i maxTexture3D() const; + + //! maximum Cubemap texture dimensions + int maxTextureCubemap() const; + + //! maximum 1D layered texture dimensions + Vec2i maxTexture1DLayered() const; + + //! maximum 2D layered texture dimensions + Vec3i maxTexture2DLayered() const; + + //! maximum Cubemap layered texture dimensions + Vec2i maxTextureCubemapLayered() const; + + //! maximum 1D surface size + int maxSurface1D() const; + + //! maximum 2D surface dimensions + Vec2i maxSurface2D() const; + + //! maximum 3D surface dimensions + Vec3i maxSurface3D() const; + + //! maximum 1D layered surface dimensions + Vec2i maxSurface1DLayered() const; + + //! maximum 2D layered surface dimensions + Vec3i maxSurface2DLayered() const; + + //! maximum Cubemap surface dimensions + int maxSurfaceCubemap() const; + + //! maximum Cubemap layered surface dimensions + Vec2i maxSurfaceCubemapLayered() const; + + //! alignment requirements for surfaces + size_t surfaceAlignment() const; + + //! device can possibly execute multiple kernels concurrently + bool concurrentKernels() const; + + //! device has ECC support enabled + bool ECCEnabled() const; + + //! PCI bus ID of the device + int pciBusID() const; + + //! PCI device ID of the device + int pciDeviceID() const; + + //! PCI domain ID of the device + int pciDomainID() const; + + //! true if device is a Tesla device using TCC driver, false otherwise + bool tccDriver() const; + + //! number of asynchronous engines + int asyncEngineCount() const; + + //! device shares a unified address space with the host + bool unifiedAddressing() const; + + //! peak memory clock frequency in kilohertz + int memoryClockRate() const; + + //! global memory bus width in bits + int memoryBusWidth() const; + + //! size of L2 cache in bytes + int l2CacheSize() const; + + //! maximum resident threads per multiprocessor + int maxThreadsPerMultiProcessor() const; + + //! gets free and total device memory + void queryMemory(size_t& totalMemory, size_t& freeMemory) const; + size_t freeMemory() const; + size_t totalMemory() const; + + /** @brief Provides information on CUDA feature support. + + @param feature_set Features to be checked. See cuda::FeatureSet. + + This function returns true if the device has the specified CUDA feature. Otherwise, it returns false + */ + bool supports(FeatureSet feature_set) const; + + /** @brief Checks the CUDA module and device compatibility. + + This function returns true if the CUDA module can be run on the specified device. Otherwise, it + returns false . + */ + bool isCompatible() const; + +private: + int device_id_; +}; + +CV_EXPORTS void printCudaDeviceInfo(int device); +CV_EXPORTS void printShortCudaDeviceInfo(int device); + +//! @} cudacore_init + +}} // namespace cv { namespace cuda { + + +#include "opencv2/core/cuda.inl.hpp" + +#endif /* __OPENCV_CORE_CUDA_HPP__ */ diff --git a/include/opencv2/core/cuda.inl.hpp b/include/opencv2/core/cuda.inl.hpp new file mode 100644 index 0000000..1285b1a --- /dev/null +++ b/include/opencv2/core/cuda.inl.hpp @@ -0,0 +1,621 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CUDAINL_HPP__ +#define __OPENCV_CORE_CUDAINL_HPP__ + +#include "opencv2/core/cuda.hpp" + +//! @cond IGNORED + +namespace cv { namespace cuda { + +//=================================================================================== +// GpuMat +//=================================================================================== + +inline +GpuMat::GpuMat(Allocator* allocator_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), allocator(allocator_) +{} + +inline +GpuMat::GpuMat(int rows_, int cols_, int type_, Allocator* allocator_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), allocator(allocator_) +{ + if (rows_ > 0 && cols_ > 0) + create(rows_, cols_, type_); +} + +inline +GpuMat::GpuMat(Size size_, int type_, Allocator* allocator_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), allocator(allocator_) +{ + if (size_.height > 0 && size_.width > 0) + create(size_.height, size_.width, type_); +} + +inline +GpuMat::GpuMat(int rows_, int cols_, int type_, Scalar s_, Allocator* allocator_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), allocator(allocator_) +{ + if (rows_ > 0 && cols_ > 0) + { + create(rows_, cols_, type_); + setTo(s_); + } +} + +inline +GpuMat::GpuMat(Size size_, int type_, Scalar s_, Allocator* allocator_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), allocator(allocator_) +{ + if (size_.height > 0 && size_.width > 0) + { + create(size_.height, size_.width, type_); + setTo(s_); + } +} + +inline +GpuMat::GpuMat(const GpuMat& m) + : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), refcount(m.refcount), datastart(m.datastart), dataend(m.dataend), allocator(m.allocator) +{ + if (refcount) + CV_XADD(refcount, 1); +} + +inline +GpuMat::GpuMat(InputArray arr, Allocator* allocator_) : + flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), allocator(allocator_) +{ + upload(arr); +} + +inline +GpuMat::~GpuMat() +{ + release(); +} + +inline +GpuMat& GpuMat::operator =(const GpuMat& m) +{ + if (this != &m) + { + GpuMat temp(m); + swap(temp); + } + + return *this; +} + +inline +void GpuMat::create(Size size_, int type_) +{ + create(size_.height, size_.width, type_); +} + +inline +void GpuMat::swap(GpuMat& b) +{ + std::swap(flags, b.flags); + std::swap(rows, b.rows); + std::swap(cols, b.cols); + std::swap(step, b.step); + std::swap(data, b.data); + std::swap(datastart, b.datastart); + std::swap(dataend, b.dataend); + std::swap(refcount, b.refcount); + std::swap(allocator, b.allocator); +} + +inline +GpuMat GpuMat::clone() const +{ + GpuMat m; + copyTo(m); + return m; +} + +inline +void GpuMat::copyTo(OutputArray dst, InputArray mask) const +{ + copyTo(dst, mask, Stream::Null()); +} + +inline +GpuMat& GpuMat::setTo(Scalar s) +{ + return setTo(s, Stream::Null()); +} + +inline +GpuMat& GpuMat::setTo(Scalar s, InputArray mask) +{ + return setTo(s, mask, Stream::Null()); +} + +inline +void GpuMat::convertTo(OutputArray dst, int rtype) const +{ + convertTo(dst, rtype, Stream::Null()); +} + +inline +void GpuMat::convertTo(OutputArray dst, int rtype, double alpha, double beta) const +{ + convertTo(dst, rtype, alpha, beta, Stream::Null()); +} + +inline +void GpuMat::convertTo(OutputArray dst, int rtype, double alpha, Stream& stream) const +{ + convertTo(dst, rtype, alpha, 0.0, stream); +} + +inline +void GpuMat::assignTo(GpuMat& m, int _type) const +{ + if (_type < 0) + m = *this; + else + convertTo(m, _type); +} + +inline +uchar* GpuMat::ptr(int y) +{ + CV_DbgAssert( (unsigned)y < (unsigned)rows ); + return data + step * y; +} + +inline +const uchar* GpuMat::ptr(int y) const +{ + CV_DbgAssert( (unsigned)y < (unsigned)rows ); + return data + step * y; +} + +template inline +_Tp* GpuMat::ptr(int y) +{ + return (_Tp*)ptr(y); +} + +template inline +const _Tp* GpuMat::ptr(int y) const +{ + return (const _Tp*)ptr(y); +} + +template inline +GpuMat::operator PtrStepSz() const +{ + return PtrStepSz(rows, cols, (T*)data, step); +} + +template inline +GpuMat::operator PtrStep() const +{ + return PtrStep((T*)data, step); +} + +inline +GpuMat GpuMat::row(int y) const +{ + return GpuMat(*this, Range(y, y+1), Range::all()); +} + +inline +GpuMat GpuMat::col(int x) const +{ + return GpuMat(*this, Range::all(), Range(x, x+1)); +} + +inline +GpuMat GpuMat::rowRange(int startrow, int endrow) const +{ + return GpuMat(*this, Range(startrow, endrow), Range::all()); +} + +inline +GpuMat GpuMat::rowRange(Range r) const +{ + return GpuMat(*this, r, Range::all()); +} + +inline +GpuMat GpuMat::colRange(int startcol, int endcol) const +{ + return GpuMat(*this, Range::all(), Range(startcol, endcol)); +} + +inline +GpuMat GpuMat::colRange(Range r) const +{ + return GpuMat(*this, Range::all(), r); +} + +inline +GpuMat GpuMat::operator ()(Range rowRange_, Range colRange_) const +{ + return GpuMat(*this, rowRange_, colRange_); +} + +inline +GpuMat GpuMat::operator ()(Rect roi) const +{ + return GpuMat(*this, roi); +} + +inline +bool GpuMat::isContinuous() const +{ + return (flags & Mat::CONTINUOUS_FLAG) != 0; +} + +inline +size_t GpuMat::elemSize() const +{ + return CV_ELEM_SIZE(flags); +} + +inline +size_t GpuMat::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int GpuMat::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int GpuMat::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int GpuMat::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +size_t GpuMat::step1() const +{ + return step / elemSize1(); +} + +inline +Size GpuMat::size() const +{ + return Size(cols, rows); +} + +inline +bool GpuMat::empty() const +{ + return data == 0; +} + +static inline +GpuMat createContinuous(int rows, int cols, int type) +{ + GpuMat m; + createContinuous(rows, cols, type, m); + return m; +} + +static inline +void createContinuous(Size size, int type, OutputArray arr) +{ + createContinuous(size.height, size.width, type, arr); +} + +static inline +GpuMat createContinuous(Size size, int type) +{ + GpuMat m; + createContinuous(size, type, m); + return m; +} + +static inline +void ensureSizeIsEnough(Size size, int type, OutputArray arr) +{ + ensureSizeIsEnough(size.height, size.width, type, arr); +} + +static inline +void swap(GpuMat& a, GpuMat& b) +{ + a.swap(b); +} + +//=================================================================================== +// HostMem +//=================================================================================== + +inline +HostMem::HostMem(AllocType alloc_type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(alloc_type_) +{ +} + +inline +HostMem::HostMem(const HostMem& m) + : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data), refcount(m.refcount), datastart(m.datastart), dataend(m.dataend), alloc_type(m.alloc_type) +{ + if( refcount ) + CV_XADD(refcount, 1); +} + +inline +HostMem::HostMem(int rows_, int cols_, int type_, AllocType alloc_type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(alloc_type_) +{ + if (rows_ > 0 && cols_ > 0) + create(rows_, cols_, type_); +} + +inline +HostMem::HostMem(Size size_, int type_, AllocType alloc_type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(alloc_type_) +{ + if (size_.height > 0 && size_.width > 0) + create(size_.height, size_.width, type_); +} + +inline +HostMem::HostMem(InputArray arr, AllocType alloc_type_) + : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0), alloc_type(alloc_type_) +{ + arr.getMat().copyTo(*this); +} + +inline +HostMem::~HostMem() +{ + release(); +} + +inline +HostMem& HostMem::operator =(const HostMem& m) +{ + if (this != &m) + { + HostMem temp(m); + swap(temp); + } + + return *this; +} + +inline +void HostMem::swap(HostMem& b) +{ + std::swap(flags, b.flags); + std::swap(rows, b.rows); + std::swap(cols, b.cols); + std::swap(step, b.step); + std::swap(data, b.data); + std::swap(datastart, b.datastart); + std::swap(dataend, b.dataend); + std::swap(refcount, b.refcount); + std::swap(alloc_type, b.alloc_type); +} + +inline +HostMem HostMem::clone() const +{ + HostMem m(size(), type(), alloc_type); + createMatHeader().copyTo(m); + return m; +} + +inline +void HostMem::create(Size size_, int type_) +{ + create(size_.height, size_.width, type_); +} + +inline +Mat HostMem::createMatHeader() const +{ + return Mat(size(), type(), data, step); +} + +inline +bool HostMem::isContinuous() const +{ + return (flags & Mat::CONTINUOUS_FLAG) != 0; +} + +inline +size_t HostMem::elemSize() const +{ + return CV_ELEM_SIZE(flags); +} + +inline +size_t HostMem::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int HostMem::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int HostMem::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int HostMem::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +size_t HostMem::step1() const +{ + return step / elemSize1(); +} + +inline +Size HostMem::size() const +{ + return Size(cols, rows); +} + +inline +bool HostMem::empty() const +{ + return data == 0; +} + +static inline +void swap(HostMem& a, HostMem& b) +{ + a.swap(b); +} + +//=================================================================================== +// Stream +//=================================================================================== + +inline +Stream::Stream(const Ptr& impl) + : impl_(impl) +{ +} + +//=================================================================================== +// Initialization & Info +//=================================================================================== + +inline +bool TargetArchs::has(int major, int minor) +{ + return hasPtx(major, minor) || hasBin(major, minor); +} + +inline +bool TargetArchs::hasEqualOrGreater(int major, int minor) +{ + return hasEqualOrGreaterPtx(major, minor) || hasEqualOrGreaterBin(major, minor); +} + +inline +DeviceInfo::DeviceInfo() +{ + device_id_ = getDevice(); +} + +inline +DeviceInfo::DeviceInfo(int device_id) +{ + CV_Assert( device_id >= 0 && device_id < getCudaEnabledDeviceCount() ); + device_id_ = device_id; +} + +inline +int DeviceInfo::deviceID() const +{ + return device_id_; +} + +inline +size_t DeviceInfo::freeMemory() const +{ + size_t _totalMemory, _freeMemory; + queryMemory(_totalMemory, _freeMemory); + return _freeMemory; +} + +inline +size_t DeviceInfo::totalMemory() const +{ + size_t _totalMemory, _freeMemory; + queryMemory(_totalMemory, _freeMemory); + return _totalMemory; +} + +inline +bool DeviceInfo::supports(FeatureSet feature_set) const +{ + int version = majorVersion() * 10 + minorVersion(); + return version >= feature_set; +} + + +}} // namespace cv { namespace cuda { + +//=================================================================================== +// Mat +//=================================================================================== + +namespace cv { + +inline +Mat::Mat(const cuda::GpuMat& m) + : flags(0), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows) +{ + m.download(*this); +} + +} + +//! @endcond + +#endif // __OPENCV_CORE_CUDAINL_HPP__ diff --git a/include/opencv2/core/cuda/block.hpp b/include/opencv2/core/cuda/block.hpp new file mode 100644 index 0000000..0c6f063 --- /dev/null +++ b/include/opencv2/core/cuda/block.hpp @@ -0,0 +1,211 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_DEVICE_BLOCK_HPP__ +#define __OPENCV_CUDA_DEVICE_BLOCK_HPP__ + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + struct Block + { + static __device__ __forceinline__ unsigned int id() + { + return blockIdx.x; + } + + static __device__ __forceinline__ unsigned int stride() + { + return blockDim.x * blockDim.y * blockDim.z; + } + + static __device__ __forceinline__ void sync() + { + __syncthreads(); + } + + static __device__ __forceinline__ int flattenedThreadId() + { + return threadIdx.z * blockDim.x * blockDim.y + threadIdx.y * blockDim.x + threadIdx.x; + } + + template + static __device__ __forceinline__ void fill(It beg, It end, const T& value) + { + int STRIDE = stride(); + It t = beg + flattenedThreadId(); + + for(; t < end; t += STRIDE) + *t = value; + } + + template + static __device__ __forceinline__ void yota(OutIt beg, OutIt end, T value) + { + int STRIDE = stride(); + int tid = flattenedThreadId(); + value += tid; + + for(OutIt t = beg + tid; t < end; t += STRIDE, value += STRIDE) + *t = value; + } + + template + static __device__ __forceinline__ void copy(InIt beg, InIt end, OutIt out) + { + int STRIDE = stride(); + InIt t = beg + flattenedThreadId(); + OutIt o = out + (t - beg); + + for(; t < end; t += STRIDE, o += STRIDE) + *o = *t; + } + + template + static __device__ __forceinline__ void transfrom(InIt beg, InIt end, OutIt out, UnOp op) + { + int STRIDE = stride(); + InIt t = beg + flattenedThreadId(); + OutIt o = out + (t - beg); + + for(; t < end; t += STRIDE, o += STRIDE) + *o = op(*t); + } + + template + static __device__ __forceinline__ void transfrom(InIt1 beg1, InIt1 end1, InIt2 beg2, OutIt out, BinOp op) + { + int STRIDE = stride(); + InIt1 t1 = beg1 + flattenedThreadId(); + InIt2 t2 = beg2 + flattenedThreadId(); + OutIt o = out + (t1 - beg1); + + for(; t1 < end1; t1 += STRIDE, t2 += STRIDE, o += STRIDE) + *o = op(*t1, *t2); + } + + template + static __device__ __forceinline__ void reduce(volatile T* buffer, BinOp op) + { + int tid = flattenedThreadId(); + T val = buffer[tid]; + + if (CTA_SIZE >= 1024) { if (tid < 512) buffer[tid] = val = op(val, buffer[tid + 512]); __syncthreads(); } + if (CTA_SIZE >= 512) { if (tid < 256) buffer[tid] = val = op(val, buffer[tid + 256]); __syncthreads(); } + if (CTA_SIZE >= 256) { if (tid < 128) buffer[tid] = val = op(val, buffer[tid + 128]); __syncthreads(); } + if (CTA_SIZE >= 128) { if (tid < 64) buffer[tid] = val = op(val, buffer[tid + 64]); __syncthreads(); } + + if (tid < 32) + { + if (CTA_SIZE >= 64) { buffer[tid] = val = op(val, buffer[tid + 32]); } + if (CTA_SIZE >= 32) { buffer[tid] = val = op(val, buffer[tid + 16]); } + if (CTA_SIZE >= 16) { buffer[tid] = val = op(val, buffer[tid + 8]); } + if (CTA_SIZE >= 8) { buffer[tid] = val = op(val, buffer[tid + 4]); } + if (CTA_SIZE >= 4) { buffer[tid] = val = op(val, buffer[tid + 2]); } + if (CTA_SIZE >= 2) { buffer[tid] = val = op(val, buffer[tid + 1]); } + } + } + + template + static __device__ __forceinline__ T reduce(volatile T* buffer, T init, BinOp op) + { + int tid = flattenedThreadId(); + T val = buffer[tid] = init; + __syncthreads(); + + if (CTA_SIZE >= 1024) { if (tid < 512) buffer[tid] = val = op(val, buffer[tid + 512]); __syncthreads(); } + if (CTA_SIZE >= 512) { if (tid < 256) buffer[tid] = val = op(val, buffer[tid + 256]); __syncthreads(); } + if (CTA_SIZE >= 256) { if (tid < 128) buffer[tid] = val = op(val, buffer[tid + 128]); __syncthreads(); } + if (CTA_SIZE >= 128) { if (tid < 64) buffer[tid] = val = op(val, buffer[tid + 64]); __syncthreads(); } + + if (tid < 32) + { + if (CTA_SIZE >= 64) { buffer[tid] = val = op(val, buffer[tid + 32]); } + if (CTA_SIZE >= 32) { buffer[tid] = val = op(val, buffer[tid + 16]); } + if (CTA_SIZE >= 16) { buffer[tid] = val = op(val, buffer[tid + 8]); } + if (CTA_SIZE >= 8) { buffer[tid] = val = op(val, buffer[tid + 4]); } + if (CTA_SIZE >= 4) { buffer[tid] = val = op(val, buffer[tid + 2]); } + if (CTA_SIZE >= 2) { buffer[tid] = val = op(val, buffer[tid + 1]); } + } + __syncthreads(); + return buffer[0]; + } + + template + static __device__ __forceinline__ void reduce_n(T* data, unsigned int n, BinOp op) + { + int ftid = flattenedThreadId(); + int sft = stride(); + + if (sft < n) + { + for (unsigned int i = sft + ftid; i < n; i += sft) + data[ftid] = op(data[ftid], data[i]); + + __syncthreads(); + + n = sft; + } + + while (n > 1) + { + unsigned int half = n/2; + + if (ftid < half) + data[ftid] = op(data[ftid], data[n - ftid - 1]); + + __syncthreads(); + + n = n - half; + } + } + }; +}}} + +//! @endcond + +#endif /* __OPENCV_CUDA_DEVICE_BLOCK_HPP__ */ diff --git a/include/opencv2/core/cuda/border_interpolate.hpp b/include/opencv2/core/cuda/border_interpolate.hpp new file mode 100644 index 0000000..ba72669 --- /dev/null +++ b/include/opencv2/core/cuda/border_interpolate.hpp @@ -0,0 +1,722 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_BORDER_INTERPOLATE_HPP__ +#define __OPENCV_CUDA_BORDER_INTERPOLATE_HPP__ + +#include "saturate_cast.hpp" +#include "vec_traits.hpp" +#include "vec_math.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + ////////////////////////////////////////////////////////////// + // BrdConstant + + template struct BrdRowConstant + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdRowConstant(int width_, const D& val_ = VecTraits::all(0)) : width(width_), val(val_) {} + + template __device__ __forceinline__ D at_low(int x, const T* data) const + { + return x >= 0 ? saturate_cast(data[x]) : val; + } + + template __device__ __forceinline__ D at_high(int x, const T* data) const + { + return x < width ? saturate_cast(data[x]) : val; + } + + template __device__ __forceinline__ D at(int x, const T* data) const + { + return (x >= 0 && x < width) ? saturate_cast(data[x]) : val; + } + + int width; + D val; + }; + + template struct BrdColConstant + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdColConstant(int height_, const D& val_ = VecTraits::all(0)) : height(height_), val(val_) {} + + template __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const + { + return y >= 0 ? saturate_cast(*(const T*)((const char*)data + y * step)) : val; + } + + template __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const + { + return y < height ? saturate_cast(*(const T*)((const char*)data + y * step)) : val; + } + + template __device__ __forceinline__ D at(int y, const T* data, size_t step) const + { + return (y >= 0 && y < height) ? saturate_cast(*(const T*)((const char*)data + y * step)) : val; + } + + int height; + D val; + }; + + template struct BrdConstant + { + typedef D result_type; + + __host__ __device__ __forceinline__ BrdConstant(int height_, int width_, const D& val_ = VecTraits::all(0)) : height(height_), width(width_), val(val_) + { + } + + template __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const + { + return (x >= 0 && x < width && y >= 0 && y < height) ? saturate_cast(((const T*)((const uchar*)data + y * step))[x]) : val; + } + + template __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const + { + return (x >= 0 && x < width && y >= 0 && y < height) ? saturate_cast(src(y, x)) : val; + } + + int height; + int width; + D val; + }; + + ////////////////////////////////////////////////////////////// + // BrdReplicate + + template struct BrdRowReplicate + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdRowReplicate(int width) : last_col(width - 1) {} + template __host__ __device__ __forceinline__ BrdRowReplicate(int width, U) : last_col(width - 1) {} + + __device__ __forceinline__ int idx_col_low(int x) const + { + return ::max(x, 0); + } + + __device__ __forceinline__ int idx_col_high(int x) const + { + return ::min(x, last_col); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return idx_col_low(idx_col_high(x)); + } + + template __device__ __forceinline__ D at_low(int x, const T* data) const + { + return saturate_cast(data[idx_col_low(x)]); + } + + template __device__ __forceinline__ D at_high(int x, const T* data) const + { + return saturate_cast(data[idx_col_high(x)]); + } + + template __device__ __forceinline__ D at(int x, const T* data) const + { + return saturate_cast(data[idx_col(x)]); + } + + int last_col; + }; + + template struct BrdColReplicate + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdColReplicate(int height) : last_row(height - 1) {} + template __host__ __device__ __forceinline__ BrdColReplicate(int height, U) : last_row(height - 1) {} + + __device__ __forceinline__ int idx_row_low(int y) const + { + return ::max(y, 0); + } + + __device__ __forceinline__ int idx_row_high(int y) const + { + return ::min(y, last_row); + } + + __device__ __forceinline__ int idx_row(int y) const + { + return idx_row_low(idx_row_high(y)); + } + + template __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const + { + return saturate_cast(*(const T*)((const char*)data + idx_row_low(y) * step)); + } + + template __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const + { + return saturate_cast(*(const T*)((const char*)data + idx_row_high(y) * step)); + } + + template __device__ __forceinline__ D at(int y, const T* data, size_t step) const + { + return saturate_cast(*(const T*)((const char*)data + idx_row(y) * step)); + } + + int last_row; + }; + + template struct BrdReplicate + { + typedef D result_type; + + __host__ __device__ __forceinline__ BrdReplicate(int height, int width) : last_row(height - 1), last_col(width - 1) {} + template __host__ __device__ __forceinline__ BrdReplicate(int height, int width, U) : last_row(height - 1), last_col(width - 1) {} + + __device__ __forceinline__ int idx_row_low(int y) const + { + return ::max(y, 0); + } + + __device__ __forceinline__ int idx_row_high(int y) const + { + return ::min(y, last_row); + } + + __device__ __forceinline__ int idx_row(int y) const + { + return idx_row_low(idx_row_high(y)); + } + + __device__ __forceinline__ int idx_col_low(int x) const + { + return ::max(x, 0); + } + + __device__ __forceinline__ int idx_col_high(int x) const + { + return ::min(x, last_col); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return idx_col_low(idx_col_high(x)); + } + + template __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const + { + return saturate_cast(((const T*)((const char*)data + idx_row(y) * step))[idx_col(x)]); + } + + template __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const + { + return saturate_cast(src(idx_row(y), idx_col(x))); + } + + int last_row; + int last_col; + }; + + ////////////////////////////////////////////////////////////// + // BrdReflect101 + + template struct BrdRowReflect101 + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdRowReflect101(int width) : last_col(width - 1) {} + template __host__ __device__ __forceinline__ BrdRowReflect101(int width, U) : last_col(width - 1) {} + + __device__ __forceinline__ int idx_col_low(int x) const + { + return ::abs(x) % (last_col + 1); + } + + __device__ __forceinline__ int idx_col_high(int x) const + { + return ::abs(last_col - ::abs(last_col - x)) % (last_col + 1); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return idx_col_low(idx_col_high(x)); + } + + template __device__ __forceinline__ D at_low(int x, const T* data) const + { + return saturate_cast(data[idx_col_low(x)]); + } + + template __device__ __forceinline__ D at_high(int x, const T* data) const + { + return saturate_cast(data[idx_col_high(x)]); + } + + template __device__ __forceinline__ D at(int x, const T* data) const + { + return saturate_cast(data[idx_col(x)]); + } + + int last_col; + }; + + template struct BrdColReflect101 + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdColReflect101(int height) : last_row(height - 1) {} + template __host__ __device__ __forceinline__ BrdColReflect101(int height, U) : last_row(height - 1) {} + + __device__ __forceinline__ int idx_row_low(int y) const + { + return ::abs(y) % (last_row + 1); + } + + __device__ __forceinline__ int idx_row_high(int y) const + { + return ::abs(last_row - ::abs(last_row - y)) % (last_row + 1); + } + + __device__ __forceinline__ int idx_row(int y) const + { + return idx_row_low(idx_row_high(y)); + } + + template __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row_low(y) * step)); + } + + template __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row_high(y) * step)); + } + + template __device__ __forceinline__ D at(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row(y) * step)); + } + + int last_row; + }; + + template struct BrdReflect101 + { + typedef D result_type; + + __host__ __device__ __forceinline__ BrdReflect101(int height, int width) : last_row(height - 1), last_col(width - 1) {} + template __host__ __device__ __forceinline__ BrdReflect101(int height, int width, U) : last_row(height - 1), last_col(width - 1) {} + + __device__ __forceinline__ int idx_row_low(int y) const + { + return ::abs(y) % (last_row + 1); + } + + __device__ __forceinline__ int idx_row_high(int y) const + { + return ::abs(last_row - ::abs(last_row - y)) % (last_row + 1); + } + + __device__ __forceinline__ int idx_row(int y) const + { + return idx_row_low(idx_row_high(y)); + } + + __device__ __forceinline__ int idx_col_low(int x) const + { + return ::abs(x) % (last_col + 1); + } + + __device__ __forceinline__ int idx_col_high(int x) const + { + return ::abs(last_col - ::abs(last_col - x)) % (last_col + 1); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return idx_col_low(idx_col_high(x)); + } + + template __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const + { + return saturate_cast(((const T*)((const char*)data + idx_row(y) * step))[idx_col(x)]); + } + + template __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const + { + return saturate_cast(src(idx_row(y), idx_col(x))); + } + + int last_row; + int last_col; + }; + + ////////////////////////////////////////////////////////////// + // BrdReflect + + template struct BrdRowReflect + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdRowReflect(int width) : last_col(width - 1) {} + template __host__ __device__ __forceinline__ BrdRowReflect(int width, U) : last_col(width - 1) {} + + __device__ __forceinline__ int idx_col_low(int x) const + { + return (::abs(x) - (x < 0)) % (last_col + 1); + } + + __device__ __forceinline__ int idx_col_high(int x) const + { + return ::abs(last_col - ::abs(last_col - x) + (x > last_col)) % (last_col + 1); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return idx_col_high(::abs(x) - (x < 0)); + } + + template __device__ __forceinline__ D at_low(int x, const T* data) const + { + return saturate_cast(data[idx_col_low(x)]); + } + + template __device__ __forceinline__ D at_high(int x, const T* data) const + { + return saturate_cast(data[idx_col_high(x)]); + } + + template __device__ __forceinline__ D at(int x, const T* data) const + { + return saturate_cast(data[idx_col(x)]); + } + + int last_col; + }; + + template struct BrdColReflect + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdColReflect(int height) : last_row(height - 1) {} + template __host__ __device__ __forceinline__ BrdColReflect(int height, U) : last_row(height - 1) {} + + __device__ __forceinline__ int idx_row_low(int y) const + { + return (::abs(y) - (y < 0)) % (last_row + 1); + } + + __device__ __forceinline__ int idx_row_high(int y) const + { + return ::abs(last_row - ::abs(last_row - y) + (y > last_row)) % (last_row + 1); + } + + __device__ __forceinline__ int idx_row(int y) const + { + return idx_row_high(::abs(y) - (y < 0)); + } + + template __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row_low(y) * step)); + } + + template __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row_high(y) * step)); + } + + template __device__ __forceinline__ D at(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row(y) * step)); + } + + int last_row; + }; + + template struct BrdReflect + { + typedef D result_type; + + __host__ __device__ __forceinline__ BrdReflect(int height, int width) : last_row(height - 1), last_col(width - 1) {} + template __host__ __device__ __forceinline__ BrdReflect(int height, int width, U) : last_row(height - 1), last_col(width - 1) {} + + __device__ __forceinline__ int idx_row_low(int y) const + { + return (::abs(y) - (y < 0)) % (last_row + 1); + } + + __device__ __forceinline__ int idx_row_high(int y) const + { + return /*::abs*/(last_row - ::abs(last_row - y) + (y > last_row)) /*% (last_row + 1)*/; + } + + __device__ __forceinline__ int idx_row(int y) const + { + return idx_row_low(idx_row_high(y)); + } + + __device__ __forceinline__ int idx_col_low(int x) const + { + return (::abs(x) - (x < 0)) % (last_col + 1); + } + + __device__ __forceinline__ int idx_col_high(int x) const + { + return (last_col - ::abs(last_col - x) + (x > last_col)); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return idx_col_low(idx_col_high(x)); + } + + template __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const + { + return saturate_cast(((const T*)((const char*)data + idx_row(y) * step))[idx_col(x)]); + } + + template __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const + { + return saturate_cast(src(idx_row(y), idx_col(x))); + } + + int last_row; + int last_col; + }; + + ////////////////////////////////////////////////////////////// + // BrdWrap + + template struct BrdRowWrap + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdRowWrap(int width_) : width(width_) {} + template __host__ __device__ __forceinline__ BrdRowWrap(int width_, U) : width(width_) {} + + __device__ __forceinline__ int idx_col_low(int x) const + { + return (x >= 0) * x + (x < 0) * (x - ((x - width + 1) / width) * width); + } + + __device__ __forceinline__ int idx_col_high(int x) const + { + return (x < width) * x + (x >= width) * (x % width); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return idx_col_high(idx_col_low(x)); + } + + template __device__ __forceinline__ D at_low(int x, const T* data) const + { + return saturate_cast(data[idx_col_low(x)]); + } + + template __device__ __forceinline__ D at_high(int x, const T* data) const + { + return saturate_cast(data[idx_col_high(x)]); + } + + template __device__ __forceinline__ D at(int x, const T* data) const + { + return saturate_cast(data[idx_col(x)]); + } + + int width; + }; + + template struct BrdColWrap + { + typedef D result_type; + + explicit __host__ __device__ __forceinline__ BrdColWrap(int height_) : height(height_) {} + template __host__ __device__ __forceinline__ BrdColWrap(int height_, U) : height(height_) {} + + __device__ __forceinline__ int idx_row_low(int y) const + { + return (y >= 0) * y + (y < 0) * (y - ((y - height + 1) / height) * height); + } + + __device__ __forceinline__ int idx_row_high(int y) const + { + return (y < height) * y + (y >= height) * (y % height); + } + + __device__ __forceinline__ int idx_row(int y) const + { + return idx_row_high(idx_row_low(y)); + } + + template __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row_low(y) * step)); + } + + template __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row_high(y) * step)); + } + + template __device__ __forceinline__ D at(int y, const T* data, size_t step) const + { + return saturate_cast(*(const D*)((const char*)data + idx_row(y) * step)); + } + + int height; + }; + + template struct BrdWrap + { + typedef D result_type; + + __host__ __device__ __forceinline__ BrdWrap(int height_, int width_) : + height(height_), width(width_) + { + } + template + __host__ __device__ __forceinline__ BrdWrap(int height_, int width_, U) : + height(height_), width(width_) + { + } + + __device__ __forceinline__ int idx_row_low(int y) const + { + return (y >= 0) * y + (y < 0) * (y - ((y - height + 1) / height) * height); + } + + __device__ __forceinline__ int idx_row_high(int y) const + { + return (y < height) * y + (y >= height) * (y % height); + } + + __device__ __forceinline__ int idx_row(int y) const + { + return idx_row_high(idx_row_low(y)); + } + + __device__ __forceinline__ int idx_col_low(int x) const + { + return (x >= 0) * x + (x < 0) * (x - ((x - width + 1) / width) * width); + } + + __device__ __forceinline__ int idx_col_high(int x) const + { + return (x < width) * x + (x >= width) * (x % width); + } + + __device__ __forceinline__ int idx_col(int x) const + { + return idx_col_high(idx_col_low(x)); + } + + template __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const + { + return saturate_cast(((const T*)((const char*)data + idx_row(y) * step))[idx_col(x)]); + } + + template __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const + { + return saturate_cast(src(idx_row(y), idx_col(x))); + } + + int height; + int width; + }; + + ////////////////////////////////////////////////////////////// + // BorderReader + + template struct BorderReader + { + typedef typename B::result_type elem_type; + typedef typename Ptr2D::index_type index_type; + + __host__ __device__ __forceinline__ BorderReader(const Ptr2D& ptr_, const B& b_) : ptr(ptr_), b(b_) {} + + __device__ __forceinline__ elem_type operator ()(index_type y, index_type x) const + { + return b.at(y, x, ptr); + } + + Ptr2D ptr; + B b; + }; + + // under win32 there is some bug with templated types that passed as kernel parameters + // with this specialization all works fine + template struct BorderReader< Ptr2D, BrdConstant > + { + typedef typename BrdConstant::result_type elem_type; + typedef typename Ptr2D::index_type index_type; + + __host__ __device__ __forceinline__ BorderReader(const Ptr2D& src_, const BrdConstant& b) : + src(src_), height(b.height), width(b.width), val(b.val) + { + } + + __device__ __forceinline__ D operator ()(index_type y, index_type x) const + { + return (x >= 0 && x < width && y >= 0 && y < height) ? saturate_cast(src(y, x)) : val; + } + + Ptr2D src; + int height; + int width; + D val; + }; +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_BORDER_INTERPOLATE_HPP__ diff --git a/include/opencv2/core/cuda/color.hpp b/include/opencv2/core/cuda/color.hpp new file mode 100644 index 0000000..6faf8c9 --- /dev/null +++ b/include/opencv2/core/cuda/color.hpp @@ -0,0 +1,309 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_COLOR_HPP__ +#define __OPENCV_CUDA_COLOR_HPP__ + +#include "detail/color_detail.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + // All OPENCV_CUDA_IMPLEMENT_*_TRAITS(ColorSpace1_to_ColorSpace2, ...) macros implements + // template class ColorSpace1_to_ColorSpace2_traits + // { + // typedef ... functor_type; + // static __host__ __device__ functor_type create_functor(); + // }; + + OPENCV_CUDA_IMPLEMENT_RGB2RGB_TRAITS(bgr_to_rgb, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2RGB_TRAITS(bgr_to_bgra, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_RGB2RGB_TRAITS(bgr_to_rgba, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2RGB_TRAITS(bgra_to_bgr, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2RGB_TRAITS(bgra_to_rgb, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2RGB_TRAITS(bgra_to_rgba, 4, 4, 2) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(bgr_to_bgr555, 3, 0, 5) + OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(bgr_to_bgr565, 3, 0, 6) + OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(rgb_to_bgr555, 3, 2, 5) + OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(rgb_to_bgr565, 3, 2, 6) + OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(bgra_to_bgr555, 4, 0, 5) + OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(bgra_to_bgr565, 4, 0, 6) + OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(rgba_to_bgr555, 4, 2, 5) + OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(rgba_to_bgr565, 4, 2, 6) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(bgr555_to_rgb, 3, 2, 5) + OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(bgr565_to_rgb, 3, 2, 6) + OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(bgr555_to_bgr, 3, 0, 5) + OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(bgr565_to_bgr, 3, 0, 6) + OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(bgr555_to_rgba, 4, 2, 5) + OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(bgr565_to_rgba, 4, 2, 6) + OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(bgr555_to_bgra, 4, 0, 5) + OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(bgr565_to_bgra, 4, 0, 6) + + #undef OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_GRAY2RGB_TRAITS(gray_to_bgr, 3) + OPENCV_CUDA_IMPLEMENT_GRAY2RGB_TRAITS(gray_to_bgra, 4) + + #undef OPENCV_CUDA_IMPLEMENT_GRAY2RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_GRAY2RGB5x5_TRAITS(gray_to_bgr555, 5) + OPENCV_CUDA_IMPLEMENT_GRAY2RGB5x5_TRAITS(gray_to_bgr565, 6) + + #undef OPENCV_CUDA_IMPLEMENT_GRAY2RGB5x5_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB5x52GRAY_TRAITS(bgr555_to_gray, 5) + OPENCV_CUDA_IMPLEMENT_RGB5x52GRAY_TRAITS(bgr565_to_gray, 6) + + #undef OPENCV_CUDA_IMPLEMENT_RGB5x52GRAY_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2GRAY_TRAITS(rgb_to_gray, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2GRAY_TRAITS(bgr_to_gray, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2GRAY_TRAITS(rgba_to_gray, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2GRAY_TRAITS(bgra_to_gray, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2GRAY_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(rgb_to_yuv, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(rgba_to_yuv, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(rgb_to_yuv4, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(rgba_to_yuv4, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(bgr_to_yuv, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(bgra_to_yuv, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(bgr_to_yuv4, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(bgra_to_yuv4, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS + + OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_rgb, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_rgba, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_rgb, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_rgba, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_bgr, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_bgra, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_bgr, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_bgra, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(rgb_to_YCrCb, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(rgba_to_YCrCb, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(rgb_to_YCrCb4, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(rgba_to_YCrCb4, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(bgr_to_YCrCb, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(bgra_to_YCrCb, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(bgr_to_YCrCb4, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(bgra_to_YCrCb4, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS + + OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb_to_rgb, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb_to_rgba, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb4_to_rgb, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb4_to_rgba, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb_to_bgr, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb_to_bgra, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb4_to_bgr, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb4_to_bgra, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(rgb_to_xyz, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(rgba_to_xyz, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(rgb_to_xyz4, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(rgba_to_xyz4, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(bgr_to_xyz, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(bgra_to_xyz, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(bgr_to_xyz4, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(bgra_to_xyz4, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS + + OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(xyz_to_rgb, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(xyz4_to_rgb, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(xyz_to_rgba, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(xyz4_to_rgba, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(xyz_to_bgr, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(xyz4_to_bgr, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(xyz_to_bgra, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(xyz4_to_bgra, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(rgb_to_hsv, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(rgba_to_hsv, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(rgb_to_hsv4, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(rgba_to_hsv4, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(bgr_to_hsv, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(bgra_to_hsv, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(bgr_to_hsv4, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(bgra_to_hsv4, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS + + OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(hsv_to_rgb, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(hsv_to_rgba, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(hsv4_to_rgb, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(hsv4_to_rgba, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(hsv_to_bgr, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(hsv_to_bgra, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(hsv4_to_bgr, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(hsv4_to_bgra, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(rgb_to_hls, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(rgba_to_hls, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(rgb_to_hls4, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(rgba_to_hls4, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(bgr_to_hls, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(bgra_to_hls, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(bgr_to_hls4, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(bgra_to_hls4, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS + + OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(hls_to_rgb, 3, 3, 2) + OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(hls_to_rgba, 3, 4, 2) + OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(hls4_to_rgb, 4, 3, 2) + OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(hls4_to_rgba, 4, 4, 2) + OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(hls_to_bgr, 3, 3, 0) + OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(hls_to_bgra, 3, 4, 0) + OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(hls4_to_bgr, 4, 3, 0) + OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(hls4_to_bgra, 4, 4, 0) + + #undef OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(rgb_to_lab, 3, 3, true, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(rgba_to_lab, 4, 3, true, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(rgb_to_lab4, 3, 4, true, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(rgba_to_lab4, 4, 4, true, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(bgr_to_lab, 3, 3, true, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(bgra_to_lab, 4, 3, true, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(bgr_to_lab4, 3, 4, true, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(bgra_to_lab4, 4, 4, true, 0) + + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(lrgb_to_lab, 3, 3, false, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(lrgba_to_lab, 4, 3, false, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(lrgb_to_lab4, 3, 4, false, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(lrgba_to_lab4, 4, 4, false, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(lbgr_to_lab, 3, 3, false, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(lbgra_to_lab, 4, 3, false, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(lbgr_to_lab4, 3, 4, false, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(lbgra_to_lab4, 4, 4, false, 0) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS + + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab_to_rgb, 3, 3, true, 2) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_rgb, 4, 3, true, 2) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab_to_rgba, 3, 4, true, 2) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_rgba, 4, 4, true, 2) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab_to_bgr, 3, 3, true, 0) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_bgr, 4, 3, true, 0) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab_to_bgra, 3, 4, true, 0) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_bgra, 4, 4, true, 0) + + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab_to_lrgb, 3, 3, false, 2) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_lrgb, 4, 3, false, 2) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab_to_lrgba, 3, 4, false, 2) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_lrgba, 4, 4, false, 2) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab_to_lbgr, 3, 3, false, 0) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_lbgr, 4, 3, false, 0) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab_to_lbgra, 3, 4, false, 0) + OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_lbgra, 4, 4, false, 0) + + #undef OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS + + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(rgb_to_luv, 3, 3, true, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(rgba_to_luv, 4, 3, true, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(rgb_to_luv4, 3, 4, true, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(rgba_to_luv4, 4, 4, true, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(bgr_to_luv, 3, 3, true, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(bgra_to_luv, 4, 3, true, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(bgr_to_luv4, 3, 4, true, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(bgra_to_luv4, 4, 4, true, 0) + + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(lrgb_to_luv, 3, 3, false, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(lrgba_to_luv, 4, 3, false, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(lrgb_to_luv4, 3, 4, false, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(lrgba_to_luv4, 4, 4, false, 2) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(lbgr_to_luv, 3, 3, false, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(lbgra_to_luv, 4, 3, false, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(lbgr_to_luv4, 3, 4, false, 0) + OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(lbgra_to_luv4, 4, 4, false, 0) + + #undef OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS + + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv_to_rgb, 3, 3, true, 2) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_rgb, 4, 3, true, 2) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv_to_rgba, 3, 4, true, 2) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_rgba, 4, 4, true, 2) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv_to_bgr, 3, 3, true, 0) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_bgr, 4, 3, true, 0) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv_to_bgra, 3, 4, true, 0) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_bgra, 4, 4, true, 0) + + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv_to_lrgb, 3, 3, false, 2) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lrgb, 4, 3, false, 2) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv_to_lrgba, 3, 4, false, 2) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lrgba, 4, 4, false, 2) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv_to_lbgr, 3, 3, false, 0) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lbgr, 4, 3, false, 0) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv_to_lbgra, 3, 4, false, 0) + OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lbgra, 4, 4, false, 0) + + #undef OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_BORDER_INTERPOLATE_HPP__ diff --git a/include/opencv2/core/cuda/common.hpp b/include/opencv2/core/cuda/common.hpp new file mode 100644 index 0000000..b93c3ef --- /dev/null +++ b/include/opencv2/core/cuda/common.hpp @@ -0,0 +1,109 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_COMMON_HPP__ +#define __OPENCV_CUDA_COMMON_HPP__ + +#include +#include "opencv2/core/cuda_types.hpp" +#include "opencv2/core/cvdef.h" +#include "opencv2/core/base.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +#ifndef CV_PI_F + #ifndef CV_PI + #define CV_PI_F 3.14159265f + #else + #define CV_PI_F ((float)CV_PI) + #endif +#endif + +namespace cv { namespace cuda { + static inline void checkCudaError(cudaError_t err, const char* file, const int line, const char* func) + { + if (cudaSuccess != err) + cv::error(cv::Error::GpuApiCallError, cudaGetErrorString(err), func, file, line); + } +}} + +#ifndef cudaSafeCall + #define cudaSafeCall(expr) cv::cuda::checkCudaError(expr, __FILE__, __LINE__, CV_Func) +#endif + +namespace cv { namespace cuda +{ + template static inline bool isAligned(const T* ptr, size_t size) + { + return reinterpret_cast(ptr) % size == 0; + } + + static inline bool isAligned(size_t step, size_t size) + { + return step % size == 0; + } +}} + +namespace cv { namespace cuda +{ + namespace device + { + __host__ __device__ __forceinline__ int divUp(int total, int grain) + { + return (total + grain - 1) / grain; + } + + template inline void bindTexture(const textureReference* tex, const PtrStepSz& img) + { + cudaChannelFormatDesc desc = cudaCreateChannelDesc(); + cudaSafeCall( cudaBindTexture2D(0, tex, img.ptr(), &desc, img.cols, img.rows, img.step) ); + } + } +}} + +//! @endcond + +#endif // __OPENCV_CUDA_COMMON_HPP__ diff --git a/include/opencv2/core/cuda/datamov_utils.hpp b/include/opencv2/core/cuda/datamov_utils.hpp new file mode 100644 index 0000000..bb02cf9 --- /dev/null +++ b/include/opencv2/core/cuda/datamov_utils.hpp @@ -0,0 +1,113 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_DATAMOV_UTILS_HPP__ +#define __OPENCV_CUDA_DATAMOV_UTILS_HPP__ + +#include "common.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + #if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 200 + + // for Fermi memory space is detected automatically + template struct ForceGlob + { + __device__ __forceinline__ static void Load(const T* ptr, int offset, T& val) { val = ptr[offset]; } + }; + + #else // __CUDA_ARCH__ >= 200 + + #if defined(_WIN64) || defined(__LP64__) + // 64-bit register modifier for inlined asm + #define OPENCV_CUDA_ASM_PTR "l" + #else + // 32-bit register modifier for inlined asm + #define OPENCV_CUDA_ASM_PTR "r" + #endif + + template struct ForceGlob; + + #define OPENCV_CUDA_DEFINE_FORCE_GLOB(base_type, ptx_type, reg_mod) \ + template <> struct ForceGlob \ + { \ + __device__ __forceinline__ static void Load(const base_type* ptr, int offset, base_type& val) \ + { \ + asm("ld.global."#ptx_type" %0, [%1];" : "="#reg_mod(val) : OPENCV_CUDA_ASM_PTR(ptr + offset)); \ + } \ + }; + + #define OPENCV_CUDA_DEFINE_FORCE_GLOB_B(base_type, ptx_type) \ + template <> struct ForceGlob \ + { \ + __device__ __forceinline__ static void Load(const base_type* ptr, int offset, base_type& val) \ + { \ + asm("ld.global."#ptx_type" %0, [%1];" : "=r"(*reinterpret_cast(&val)) : OPENCV_CUDA_ASM_PTR(ptr + offset)); \ + } \ + }; + + OPENCV_CUDA_DEFINE_FORCE_GLOB_B(uchar, u8) + OPENCV_CUDA_DEFINE_FORCE_GLOB_B(schar, s8) + OPENCV_CUDA_DEFINE_FORCE_GLOB_B(char, b8) + OPENCV_CUDA_DEFINE_FORCE_GLOB (ushort, u16, h) + OPENCV_CUDA_DEFINE_FORCE_GLOB (short, s16, h) + OPENCV_CUDA_DEFINE_FORCE_GLOB (uint, u32, r) + OPENCV_CUDA_DEFINE_FORCE_GLOB (int, s32, r) + OPENCV_CUDA_DEFINE_FORCE_GLOB (float, f32, f) + OPENCV_CUDA_DEFINE_FORCE_GLOB (double, f64, d) + + #undef OPENCV_CUDA_DEFINE_FORCE_GLOB + #undef OPENCV_CUDA_DEFINE_FORCE_GLOB_B + #undef OPENCV_CUDA_ASM_PTR + + #endif // __CUDA_ARCH__ >= 200 +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_DATAMOV_UTILS_HPP__ diff --git a/include/opencv2/core/cuda/detail/color_detail.hpp b/include/opencv2/core/cuda/detail/color_detail.hpp new file mode 100644 index 0000000..1151806 --- /dev/null +++ b/include/opencv2/core/cuda/detail/color_detail.hpp @@ -0,0 +1,1980 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_COLOR_DETAIL_HPP__ +#define __OPENCV_CUDA_COLOR_DETAIL_HPP__ + +#include "../common.hpp" +#include "../vec_traits.hpp" +#include "../saturate_cast.hpp" +#include "../limits.hpp" +#include "../functional.hpp" + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + #ifndef CV_DESCALE + #define CV_DESCALE(x, n) (((x) + (1 << ((n)-1))) >> (n)) + #endif + + namespace color_detail + { + template struct ColorChannel + { + typedef float worktype_f; + static __device__ __forceinline__ T max() { return numeric_limits::max(); } + static __device__ __forceinline__ T half() { return (T)(max()/2 + 1); } + }; + + template<> struct ColorChannel + { + typedef float worktype_f; + static __device__ __forceinline__ float max() { return 1.f; } + static __device__ __forceinline__ float half() { return 0.5f; } + }; + + template static __device__ __forceinline__ void setAlpha(typename TypeVec::vec_type& vec, T val) + { + } + + template static __device__ __forceinline__ void setAlpha(typename TypeVec::vec_type& vec, T val) + { + vec.w = val; + } + + template static __device__ __forceinline__ T getAlpha(const typename TypeVec::vec_type& vec) + { + return ColorChannel::max(); + } + + template static __device__ __forceinline__ T getAlpha(const typename TypeVec::vec_type& vec) + { + return vec.w; + } + + enum + { + yuv_shift = 14, + xyz_shift = 12, + R2Y = 4899, + G2Y = 9617, + B2Y = 1868, + BLOCK_SIZE = 256 + }; + } + +////////////////// Various 3/4-channel to 3/4-channel RGB transformations ///////////////// + + namespace color_detail + { + template struct RGB2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ typename TypeVec::vec_type operator()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + dst.x = (&src.x)[bidx]; + dst.y = src.y; + dst.z = (&src.x)[bidx^2]; + setAlpha(dst, getAlpha(src)); + + return dst; + } + + __host__ __device__ __forceinline__ RGB2RGB() {} + __host__ __device__ __forceinline__ RGB2RGB(const RGB2RGB&) {} + }; + + template <> struct RGB2RGB : unary_function + { + __device__ uint operator()(uint src) const + { + uint dst = 0; + + dst |= (0xffu & (src >> 16)); + dst |= (0xffu & (src >> 8)) << 8; + dst |= (0xffu & (src)) << 16; + dst |= (0xffu & (src >> 24)) << 24; + + return dst; + } + + __host__ __device__ __forceinline__ RGB2RGB() {} + __host__ __device__ __forceinline__ RGB2RGB(const RGB2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2RGB_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +/////////// Transforming 16-bit (565 or 555) RGB to/from 24/32-bit (888[8]) RGB ////////// + + namespace color_detail + { + template struct RGB2RGB5x5Converter; + template struct RGB2RGB5x5Converter<6, bidx> + { + static __device__ __forceinline__ ushort cvt(const uchar3& src) + { + return (ushort)(((&src.x)[bidx] >> 3) | ((src.y & ~3) << 3) | (((&src.x)[bidx^2] & ~7) << 8)); + } + + static __device__ __forceinline__ ushort cvt(uint src) + { + uint b = 0xffu & (src >> (bidx * 8)); + uint g = 0xffu & (src >> 8); + uint r = 0xffu & (src >> ((bidx ^ 2) * 8)); + return (ushort)((b >> 3) | ((g & ~3) << 3) | ((r & ~7) << 8)); + } + }; + + template struct RGB2RGB5x5Converter<5, bidx> + { + static __device__ __forceinline__ ushort cvt(const uchar3& src) + { + return (ushort)(((&src.x)[bidx] >> 3) | ((src.y & ~7) << 2) | (((&src.x)[bidx^2] & ~7) << 7)); + } + + static __device__ __forceinline__ ushort cvt(uint src) + { + uint b = 0xffu & (src >> (bidx * 8)); + uint g = 0xffu & (src >> 8); + uint r = 0xffu & (src >> ((bidx ^ 2) * 8)); + uint a = 0xffu & (src >> 24); + return (ushort)((b >> 3) | ((g & ~7) << 2) | ((r & ~7) << 7) | (a * 0x8000)); + } + }; + + template struct RGB2RGB5x5; + + template struct RGB2RGB5x5<3, bidx,green_bits> : unary_function + { + __device__ __forceinline__ ushort operator()(const uchar3& src) const + { + return RGB2RGB5x5Converter::cvt(src); + } + + __host__ __device__ __forceinline__ RGB2RGB5x5() {} + __host__ __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5&) {} + }; + + template struct RGB2RGB5x5<4, bidx,green_bits> : unary_function + { + __device__ __forceinline__ ushort operator()(uint src) const + { + return RGB2RGB5x5Converter::cvt(src); + } + + __host__ __device__ __forceinline__ RGB2RGB5x5() {} + __host__ __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2RGB5x5_TRAITS(name, scn, bidx, green_bits) \ + struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2RGB5x5 functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + template struct RGB5x52RGBConverter; + + template struct RGB5x52RGBConverter<5, bidx> + { + static __device__ __forceinline__ void cvt(uint src, uchar3& dst) + { + (&dst.x)[bidx] = src << 3; + dst.y = (src >> 2) & ~7; + (&dst.x)[bidx ^ 2] = (src >> 7) & ~7; + } + + static __device__ __forceinline__ void cvt(uint src, uint& dst) + { + dst = 0; + + dst |= (0xffu & (src << 3)) << (bidx * 8); + dst |= (0xffu & ((src >> 2) & ~7)) << 8; + dst |= (0xffu & ((src >> 7) & ~7)) << ((bidx ^ 2) * 8); + dst |= ((src & 0x8000) * 0xffu) << 24; + } + }; + + template struct RGB5x52RGBConverter<6, bidx> + { + static __device__ __forceinline__ void cvt(uint src, uchar3& dst) + { + (&dst.x)[bidx] = src << 3; + dst.y = (src >> 3) & ~3; + (&dst.x)[bidx ^ 2] = (src >> 8) & ~7; + } + + static __device__ __forceinline__ void cvt(uint src, uint& dst) + { + dst = 0xffu << 24; + + dst |= (0xffu & (src << 3)) << (bidx * 8); + dst |= (0xffu &((src >> 3) & ~3)) << 8; + dst |= (0xffu & ((src >> 8) & ~7)) << ((bidx ^ 2) * 8); + } + }; + + template struct RGB5x52RGB; + + template struct RGB5x52RGB<3, bidx, green_bits> : unary_function + { + __device__ __forceinline__ uchar3 operator()(ushort src) const + { + uchar3 dst; + RGB5x52RGBConverter::cvt(src, dst); + return dst; + } + __host__ __device__ __forceinline__ RGB5x52RGB() {} + __host__ __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB&) {} + + }; + + template struct RGB5x52RGB<4, bidx, green_bits> : unary_function + { + __device__ __forceinline__ uint operator()(ushort src) const + { + uint dst; + RGB5x52RGBConverter::cvt(src, dst); + return dst; + } + __host__ __device__ __forceinline__ RGB5x52RGB() {} + __host__ __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB5x52RGB_TRAITS(name, dcn, bidx, green_bits) \ + struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB5x52RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +///////////////////////////////// Grayscale to Color //////////////////////////////// + + namespace color_detail + { + template struct Gray2RGB : unary_function::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator()(T src) const + { + typename TypeVec::vec_type dst; + + dst.z = dst.y = dst.x = src; + setAlpha(dst, ColorChannel::max()); + + return dst; + } + __host__ __device__ __forceinline__ Gray2RGB() {} + __host__ __device__ __forceinline__ Gray2RGB(const Gray2RGB&) {} + }; + + template <> struct Gray2RGB : unary_function + { + __device__ __forceinline__ uint operator()(uint src) const + { + uint dst = 0xffu << 24; + + dst |= src; + dst |= src << 8; + dst |= src << 16; + + return dst; + } + __host__ __device__ __forceinline__ Gray2RGB() {} + __host__ __device__ __forceinline__ Gray2RGB(const Gray2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_GRAY2RGB_TRAITS(name, dcn) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::Gray2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + template struct Gray2RGB5x5Converter; + template<> struct Gray2RGB5x5Converter<6> + { + static __device__ __forceinline__ ushort cvt(uint t) + { + return (ushort)((t >> 3) | ((t & ~3) << 3) | ((t & ~7) << 8)); + } + }; + + template<> struct Gray2RGB5x5Converter<5> + { + static __device__ __forceinline__ ushort cvt(uint t) + { + t >>= 3; + return (ushort)(t | (t << 5) | (t << 10)); + } + }; + + template struct Gray2RGB5x5 : unary_function + { + __device__ __forceinline__ ushort operator()(uint src) const + { + return Gray2RGB5x5Converter::cvt(src); + } + + __host__ __device__ __forceinline__ Gray2RGB5x5() {} + __host__ __device__ __forceinline__ Gray2RGB5x5(const Gray2RGB5x5&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_GRAY2RGB5x5_TRAITS(name, green_bits) \ + struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::Gray2RGB5x5 functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +///////////////////////////////// Color to Grayscale //////////////////////////////// + + namespace color_detail + { + template struct RGB5x52GrayConverter; + template <> struct RGB5x52GrayConverter<6> + { + static __device__ __forceinline__ uchar cvt(uint t) + { + return (uchar)CV_DESCALE(((t << 3) & 0xf8) * B2Y + ((t >> 3) & 0xfc) * G2Y + ((t >> 8) & 0xf8) * R2Y, yuv_shift); + } + }; + + template <> struct RGB5x52GrayConverter<5> + { + static __device__ __forceinline__ uchar cvt(uint t) + { + return (uchar)CV_DESCALE(((t << 3) & 0xf8) * B2Y + ((t >> 2) & 0xf8) * G2Y + ((t >> 7) & 0xf8) * R2Y, yuv_shift); + } + }; + + template struct RGB5x52Gray : unary_function + { + __device__ __forceinline__ uchar operator()(uint src) const + { + return RGB5x52GrayConverter::cvt(src); + } + __host__ __device__ __forceinline__ RGB5x52Gray() {} + __host__ __device__ __forceinline__ RGB5x52Gray(const RGB5x52Gray&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB5x52GRAY_TRAITS(name, green_bits) \ + struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB5x52Gray functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + template static __device__ __forceinline__ T RGB2GrayConvert(const T* src) + { + return (T)CV_DESCALE((unsigned)(src[bidx] * B2Y + src[1] * G2Y + src[bidx^2] * R2Y), yuv_shift); + } + + template static __device__ __forceinline__ uchar RGB2GrayConvert(uint src) + { + uint b = 0xffu & (src >> (bidx * 8)); + uint g = 0xffu & (src >> 8); + uint r = 0xffu & (src >> ((bidx ^ 2) * 8)); + return CV_DESCALE((uint)(b * B2Y + g * G2Y + r * R2Y), yuv_shift); + } + + template static __device__ __forceinline__ float RGB2GrayConvert(const float* src) + { + return src[bidx] * 0.114f + src[1] * 0.587f + src[bidx^2] * 0.299f; + } + + template struct RGB2Gray : unary_function::vec_type, T> + { + __device__ __forceinline__ T operator()(const typename TypeVec::vec_type& src) const + { + return RGB2GrayConvert(&src.x); + } + __host__ __device__ __forceinline__ RGB2Gray() {} + __host__ __device__ __forceinline__ RGB2Gray(const RGB2Gray&) {} + }; + + template struct RGB2Gray : unary_function + { + __device__ __forceinline__ uchar operator()(uint src) const + { + return RGB2GrayConvert(src); + } + __host__ __device__ __forceinline__ RGB2Gray() {} + __host__ __device__ __forceinline__ RGB2Gray(const RGB2Gray&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2GRAY_TRAITS(name, scn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2Gray functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +///////////////////////////////////// RGB <-> YUV ////////////////////////////////////// + + namespace color_detail + { + __constant__ float c_RGB2YUVCoeffs_f[5] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f }; + __constant__ int c_RGB2YUVCoeffs_i[5] = { B2Y, G2Y, R2Y, 8061, 14369 }; + + template static __device__ void RGB2YUVConvert(const T* src, D& dst) + { + const int delta = ColorChannel::half() * (1 << yuv_shift); + + const int Y = CV_DESCALE(src[0] * c_RGB2YUVCoeffs_i[bidx^2] + src[1] * c_RGB2YUVCoeffs_i[1] + src[2] * c_RGB2YUVCoeffs_i[bidx], yuv_shift); + const int Cr = CV_DESCALE((src[bidx^2] - Y) * c_RGB2YUVCoeffs_i[3] + delta, yuv_shift); + const int Cb = CV_DESCALE((src[bidx] - Y) * c_RGB2YUVCoeffs_i[4] + delta, yuv_shift); + + dst.x = saturate_cast(Y); + dst.y = saturate_cast(Cr); + dst.z = saturate_cast(Cb); + } + + template static __device__ __forceinline__ void RGB2YUVConvert(const float* src, D& dst) + { + dst.x = src[0] * c_RGB2YUVCoeffs_f[bidx^2] + src[1] * c_RGB2YUVCoeffs_f[1] + src[2] * c_RGB2YUVCoeffs_f[bidx]; + dst.y = (src[bidx^2] - dst.x) * c_RGB2YUVCoeffs_f[3] + ColorChannel::half(); + dst.z = (src[bidx] - dst.x) * c_RGB2YUVCoeffs_f[4] + ColorChannel::half(); + } + + template struct RGB2YUV + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + RGB2YUVConvert(&src.x, dst); + return dst; + } + __host__ __device__ __forceinline__ RGB2YUV() {} + __host__ __device__ __forceinline__ RGB2YUV(const RGB2YUV&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2YUV_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2YUV functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + __constant__ float c_YUV2RGBCoeffs_f[5] = { 2.032f, -0.395f, -0.581f, 1.140f }; + __constant__ int c_YUV2RGBCoeffs_i[5] = { 33292, -6472, -9519, 18678 }; + + template static __device__ void YUV2RGBConvert(const T& src, D* dst) + { + const int b = src.x + CV_DESCALE((src.z - ColorChannel::half()) * c_YUV2RGBCoeffs_i[3], yuv_shift); + + const int g = src.x + CV_DESCALE((src.z - ColorChannel::half()) * c_YUV2RGBCoeffs_i[2] + + (src.y - ColorChannel::half()) * c_YUV2RGBCoeffs_i[1], yuv_shift); + + const int r = src.x + CV_DESCALE((src.y - ColorChannel::half()) * c_YUV2RGBCoeffs_i[0], yuv_shift); + + dst[bidx] = saturate_cast(b); + dst[1] = saturate_cast(g); + dst[bidx^2] = saturate_cast(r); + } + + template static __device__ uint YUV2RGBConvert(uint src) + { + const int x = 0xff & (src); + const int y = 0xff & (src >> 8); + const int z = 0xff & (src >> 16); + + const int b = x + CV_DESCALE((z - ColorChannel::half()) * c_YUV2RGBCoeffs_i[3], yuv_shift); + + const int g = x + CV_DESCALE((z - ColorChannel::half()) * c_YUV2RGBCoeffs_i[2] + + (y - ColorChannel::half()) * c_YUV2RGBCoeffs_i[1], yuv_shift); + + const int r = x + CV_DESCALE((y - ColorChannel::half()) * c_YUV2RGBCoeffs_i[0], yuv_shift); + + uint dst = 0xffu << 24; + + dst |= saturate_cast(b) << (bidx * 8); + dst |= saturate_cast(g) << 8; + dst |= saturate_cast(r) << ((bidx ^ 2) * 8); + + return dst; + } + + template static __device__ __forceinline__ void YUV2RGBConvert(const T& src, float* dst) + { + dst[bidx] = src.x + (src.z - ColorChannel::half()) * c_YUV2RGBCoeffs_f[3]; + + dst[1] = src.x + (src.z - ColorChannel::half()) * c_YUV2RGBCoeffs_f[2] + + (src.y - ColorChannel::half()) * c_YUV2RGBCoeffs_f[1]; + + dst[bidx^2] = src.x + (src.y - ColorChannel::half()) * c_YUV2RGBCoeffs_f[0]; + } + + template struct YUV2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + YUV2RGBConvert(src, &dst.x); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + __host__ __device__ __forceinline__ YUV2RGB() {} + __host__ __device__ __forceinline__ YUV2RGB(const YUV2RGB&) {} + }; + + template struct YUV2RGB : unary_function + { + __device__ __forceinline__ uint operator ()(uint src) const + { + return YUV2RGBConvert(src); + } + __host__ __device__ __forceinline__ YUV2RGB() {} + __host__ __device__ __forceinline__ YUV2RGB(const YUV2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_YUV2RGB_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::YUV2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +///////////////////////////////////// RGB <-> YCrCb ////////////////////////////////////// + + namespace color_detail + { + __constant__ float c_RGB2YCrCbCoeffs_f[5] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f}; + __constant__ int c_RGB2YCrCbCoeffs_i[5] = {R2Y, G2Y, B2Y, 11682, 9241}; + + template static __device__ void RGB2YCrCbConvert(const T* src, D& dst) + { + const int delta = ColorChannel::half() * (1 << yuv_shift); + + const int Y = CV_DESCALE(src[0] * c_RGB2YCrCbCoeffs_i[bidx^2] + src[1] * c_RGB2YCrCbCoeffs_i[1] + src[2] * c_RGB2YCrCbCoeffs_i[bidx], yuv_shift); + const int Cr = CV_DESCALE((src[bidx^2] - Y) * c_RGB2YCrCbCoeffs_i[3] + delta, yuv_shift); + const int Cb = CV_DESCALE((src[bidx] - Y) * c_RGB2YCrCbCoeffs_i[4] + delta, yuv_shift); + + dst.x = saturate_cast(Y); + dst.y = saturate_cast(Cr); + dst.z = saturate_cast(Cb); + } + + template static __device__ uint RGB2YCrCbConvert(uint src) + { + const int delta = ColorChannel::half() * (1 << yuv_shift); + + const int Y = CV_DESCALE((0xffu & src) * c_RGB2YCrCbCoeffs_i[bidx^2] + (0xffu & (src >> 8)) * c_RGB2YCrCbCoeffs_i[1] + (0xffu & (src >> 16)) * c_RGB2YCrCbCoeffs_i[bidx], yuv_shift); + const int Cr = CV_DESCALE(((0xffu & (src >> ((bidx ^ 2) * 8))) - Y) * c_RGB2YCrCbCoeffs_i[3] + delta, yuv_shift); + const int Cb = CV_DESCALE(((0xffu & (src >> (bidx * 8))) - Y) * c_RGB2YCrCbCoeffs_i[4] + delta, yuv_shift); + + uint dst = 0; + + dst |= saturate_cast(Y); + dst |= saturate_cast(Cr) << 8; + dst |= saturate_cast(Cb) << 16; + + return dst; + } + + template static __device__ __forceinline__ void RGB2YCrCbConvert(const float* src, D& dst) + { + dst.x = src[0] * c_RGB2YCrCbCoeffs_f[bidx^2] + src[1] * c_RGB2YCrCbCoeffs_f[1] + src[2] * c_RGB2YCrCbCoeffs_f[bidx]; + dst.y = (src[bidx^2] - dst.x) * c_RGB2YCrCbCoeffs_f[3] + ColorChannel::half(); + dst.z = (src[bidx] - dst.x) * c_RGB2YCrCbCoeffs_f[4] + ColorChannel::half(); + } + + template struct RGB2YCrCb + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + RGB2YCrCbConvert(&src.x, dst); + return dst; + } + __host__ __device__ __forceinline__ RGB2YCrCb() {} + __host__ __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb&) {} + }; + + template struct RGB2YCrCb : unary_function + { + __device__ __forceinline__ uint operator ()(uint src) const + { + return RGB2YCrCbConvert(src); + } + + __host__ __device__ __forceinline__ RGB2YCrCb() {} + __host__ __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2YCrCb_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2YCrCb functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + __constant__ float c_YCrCb2RGBCoeffs_f[5] = {1.403f, -0.714f, -0.344f, 1.773f}; + __constant__ int c_YCrCb2RGBCoeffs_i[5] = {22987, -11698, -5636, 29049}; + + template static __device__ void YCrCb2RGBConvert(const T& src, D* dst) + { + const int b = src.x + CV_DESCALE((src.z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[3], yuv_shift); + const int g = src.x + CV_DESCALE((src.z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[2] + (src.y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[1], yuv_shift); + const int r = src.x + CV_DESCALE((src.y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[0], yuv_shift); + + dst[bidx] = saturate_cast(b); + dst[1] = saturate_cast(g); + dst[bidx^2] = saturate_cast(r); + } + + template static __device__ uint YCrCb2RGBConvert(uint src) + { + const int x = 0xff & (src); + const int y = 0xff & (src >> 8); + const int z = 0xff & (src >> 16); + + const int b = x + CV_DESCALE((z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[3], yuv_shift); + const int g = x + CV_DESCALE((z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[2] + (y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[1], yuv_shift); + const int r = x + CV_DESCALE((y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_i[0], yuv_shift); + + uint dst = 0xffu << 24; + + dst |= saturate_cast(b) << (bidx * 8); + dst |= saturate_cast(g) << 8; + dst |= saturate_cast(r) << ((bidx ^ 2) * 8); + + return dst; + } + + template __device__ __forceinline__ void YCrCb2RGBConvert(const T& src, float* dst) + { + dst[bidx] = src.x + (src.z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_f[3]; + dst[1] = src.x + (src.z - ColorChannel::half()) * c_YCrCb2RGBCoeffs_f[2] + (src.y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_f[1]; + dst[bidx^2] = src.x + (src.y - ColorChannel::half()) * c_YCrCb2RGBCoeffs_f[0]; + } + + template struct YCrCb2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + YCrCb2RGBConvert(src, &dst.x); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + __host__ __device__ __forceinline__ YCrCb2RGB() {} + __host__ __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB&) {} + }; + + template struct YCrCb2RGB : unary_function + { + __device__ __forceinline__ uint operator ()(uint src) const + { + return YCrCb2RGBConvert(src); + } + __host__ __device__ __forceinline__ YCrCb2RGB() {} + __host__ __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_YCrCb2RGB_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::YCrCb2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +////////////////////////////////////// RGB <-> XYZ /////////////////////////////////////// + + namespace color_detail + { + __constant__ float c_RGB2XYZ_D65f[9] = { 0.412453f, 0.357580f, 0.180423f, 0.212671f, 0.715160f, 0.072169f, 0.019334f, 0.119193f, 0.950227f }; + __constant__ int c_RGB2XYZ_D65i[9] = { 1689, 1465, 739, 871, 2929, 296, 79, 488, 3892 }; + + template static __device__ __forceinline__ void RGB2XYZConvert(const T* src, D& dst) + { + dst.z = saturate_cast(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[6] + src[1] * c_RGB2XYZ_D65i[7] + src[bidx] * c_RGB2XYZ_D65i[8], xyz_shift)); + dst.x = saturate_cast(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[0] + src[1] * c_RGB2XYZ_D65i[1] + src[bidx] * c_RGB2XYZ_D65i[2], xyz_shift)); + dst.y = saturate_cast(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[3] + src[1] * c_RGB2XYZ_D65i[4] + src[bidx] * c_RGB2XYZ_D65i[5], xyz_shift)); + } + + template static __device__ __forceinline__ uint RGB2XYZConvert(uint src) + { + const uint b = 0xffu & (src >> (bidx * 8)); + const uint g = 0xffu & (src >> 8); + const uint r = 0xffu & (src >> ((bidx ^ 2) * 8)); + + const uint x = saturate_cast(CV_DESCALE(r * c_RGB2XYZ_D65i[0] + g * c_RGB2XYZ_D65i[1] + b * c_RGB2XYZ_D65i[2], xyz_shift)); + const uint y = saturate_cast(CV_DESCALE(r * c_RGB2XYZ_D65i[3] + g * c_RGB2XYZ_D65i[4] + b * c_RGB2XYZ_D65i[5], xyz_shift)); + const uint z = saturate_cast(CV_DESCALE(r * c_RGB2XYZ_D65i[6] + g * c_RGB2XYZ_D65i[7] + b * c_RGB2XYZ_D65i[8], xyz_shift)); + + uint dst = 0; + + dst |= x; + dst |= y << 8; + dst |= z << 16; + + return dst; + } + + template static __device__ __forceinline__ void RGB2XYZConvert(const float* src, D& dst) + { + dst.x = src[bidx^2] * c_RGB2XYZ_D65f[0] + src[1] * c_RGB2XYZ_D65f[1] + src[bidx] * c_RGB2XYZ_D65f[2]; + dst.y = src[bidx^2] * c_RGB2XYZ_D65f[3] + src[1] * c_RGB2XYZ_D65f[4] + src[bidx] * c_RGB2XYZ_D65f[5]; + dst.z = src[bidx^2] * c_RGB2XYZ_D65f[6] + src[1] * c_RGB2XYZ_D65f[7] + src[bidx] * c_RGB2XYZ_D65f[8]; + } + + template struct RGB2XYZ + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + RGB2XYZConvert(&src.x, dst); + + return dst; + } + __host__ __device__ __forceinline__ RGB2XYZ() {} + __host__ __device__ __forceinline__ RGB2XYZ(const RGB2XYZ&) {} + }; + + template struct RGB2XYZ : unary_function + { + __device__ __forceinline__ uint operator()(uint src) const + { + return RGB2XYZConvert(src); + } + __host__ __device__ __forceinline__ RGB2XYZ() {} + __host__ __device__ __forceinline__ RGB2XYZ(const RGB2XYZ&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2XYZ_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2XYZ functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + __constant__ float c_XYZ2sRGB_D65f[9] = { 3.240479f, -1.53715f, -0.498535f, -0.969256f, 1.875991f, 0.041556f, 0.055648f, -0.204043f, 1.057311f }; + __constant__ int c_XYZ2sRGB_D65i[9] = { 13273, -6296, -2042, -3970, 7684, 170, 228, -836, 4331 }; + + template static __device__ __forceinline__ void XYZ2RGBConvert(const T& src, D* dst) + { + dst[bidx^2] = saturate_cast(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[0] + src.y * c_XYZ2sRGB_D65i[1] + src.z * c_XYZ2sRGB_D65i[2], xyz_shift)); + dst[1] = saturate_cast(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[3] + src.y * c_XYZ2sRGB_D65i[4] + src.z * c_XYZ2sRGB_D65i[5], xyz_shift)); + dst[bidx] = saturate_cast(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[6] + src.y * c_XYZ2sRGB_D65i[7] + src.z * c_XYZ2sRGB_D65i[8], xyz_shift)); + } + + template static __device__ __forceinline__ uint XYZ2RGBConvert(uint src) + { + const int x = 0xff & src; + const int y = 0xff & (src >> 8); + const int z = 0xff & (src >> 16); + + const uint r = saturate_cast(CV_DESCALE(x * c_XYZ2sRGB_D65i[0] + y * c_XYZ2sRGB_D65i[1] + z * c_XYZ2sRGB_D65i[2], xyz_shift)); + const uint g = saturate_cast(CV_DESCALE(x * c_XYZ2sRGB_D65i[3] + y * c_XYZ2sRGB_D65i[4] + z * c_XYZ2sRGB_D65i[5], xyz_shift)); + const uint b = saturate_cast(CV_DESCALE(x * c_XYZ2sRGB_D65i[6] + y * c_XYZ2sRGB_D65i[7] + z * c_XYZ2sRGB_D65i[8], xyz_shift)); + + uint dst = 0xffu << 24; + + dst |= b << (bidx * 8); + dst |= g << 8; + dst |= r << ((bidx ^ 2) * 8); + + return dst; + } + + template static __device__ __forceinline__ void XYZ2RGBConvert(const T& src, float* dst) + { + dst[bidx^2] = src.x * c_XYZ2sRGB_D65f[0] + src.y * c_XYZ2sRGB_D65f[1] + src.z * c_XYZ2sRGB_D65f[2]; + dst[1] = src.x * c_XYZ2sRGB_D65f[3] + src.y * c_XYZ2sRGB_D65f[4] + src.z * c_XYZ2sRGB_D65f[5]; + dst[bidx] = src.x * c_XYZ2sRGB_D65f[6] + src.y * c_XYZ2sRGB_D65f[7] + src.z * c_XYZ2sRGB_D65f[8]; + } + + template struct XYZ2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + XYZ2RGBConvert(src, &dst.x); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + __host__ __device__ __forceinline__ XYZ2RGB() {} + __host__ __device__ __forceinline__ XYZ2RGB(const XYZ2RGB&) {} + }; + + template struct XYZ2RGB : unary_function + { + __device__ __forceinline__ uint operator()(uint src) const + { + return XYZ2RGBConvert(src); + } + __host__ __device__ __forceinline__ XYZ2RGB() {} + __host__ __device__ __forceinline__ XYZ2RGB(const XYZ2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_XYZ2RGB_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::XYZ2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +////////////////////////////////////// RGB <-> HSV /////////////////////////////////////// + + namespace color_detail + { + __constant__ int c_HsvDivTable [256] = {0, 1044480, 522240, 348160, 261120, 208896, 174080, 149211, 130560, 116053, 104448, 94953, 87040, 80345, 74606, 69632, 65280, 61440, 58027, 54973, 52224, 49737, 47476, 45412, 43520, 41779, 40172, 38684, 37303, 36017, 34816, 33693, 32640, 31651, 30720, 29842, 29013, 28229, 27486, 26782, 26112, 25475, 24869, 24290, 23738, 23211, 22706, 22223, 21760, 21316, 20890, 20480, 20086, 19707, 19342, 18991, 18651, 18324, 18008, 17703, 17408, 17123, 16846, 16579, 16320, 16069, 15825, 15589, 15360, 15137, 14921, 14711, 14507, 14308, 14115, 13926, 13743, 13565, 13391, 13221, 13056, 12895, 12738, 12584, 12434, 12288, 12145, 12006, 11869, 11736, 11605, 11478, 11353, 11231, 11111, 10995, 10880, 10768, 10658, 10550, 10445, 10341, 10240, 10141, 10043, 9947, 9854, 9761, 9671, 9582, 9495, 9410, 9326, 9243, 9162, 9082, 9004, 8927, 8852, 8777, 8704, 8632, 8561, 8492, 8423, 8356, 8290, 8224, 8160, 8097, 8034, 7973, 7913, 7853, 7795, 7737, 7680, 7624, 7569, 7514, 7461, 7408, 7355, 7304, 7253, 7203, 7154, 7105, 7057, 7010, 6963, 6917, 6872, 6827, 6782, 6739, 6695, 6653, 6611, 6569, 6528, 6487, 6447, 6408, 6369, 6330, 6292, 6254, 6217, 6180, 6144, 6108, 6073, 6037, 6003, 5968, 5935, 5901, 5868, 5835, 5803, 5771, 5739, 5708, 5677, 5646, 5615, 5585, 5556, 5526, 5497, 5468, 5440, 5412, 5384, 5356, 5329, 5302, 5275, 5249, 5222, 5196, 5171, 5145, 5120, 5095, 5070, 5046, 5022, 4998, 4974, 4950, 4927, 4904, 4881, 4858, 4836, 4813, 4791, 4769, 4748, 4726, 4705, 4684, 4663, 4642, 4622, 4601, 4581, 4561, 4541, 4522, 4502, 4483, 4464, 4445, 4426, 4407, 4389, 4370, 4352, 4334, 4316, 4298, 4281, 4263, 4246, 4229, 4212, 4195, 4178, 4161, 4145, 4128, 4112, 4096}; + __constant__ int c_HsvDivTable180[256] = {0, 122880, 61440, 40960, 30720, 24576, 20480, 17554, 15360, 13653, 12288, 11171, 10240, 9452, 8777, 8192, 7680, 7228, 6827, 6467, 6144, 5851, 5585, 5343, 5120, 4915, 4726, 4551, 4389, 4237, 4096, 3964, 3840, 3724, 3614, 3511, 3413, 3321, 3234, 3151, 3072, 2997, 2926, 2858, 2793, 2731, 2671, 2614, 2560, 2508, 2458, 2409, 2363, 2318, 2276, 2234, 2194, 2156, 2119, 2083, 2048, 2014, 1982, 1950, 1920, 1890, 1862, 1834, 1807, 1781, 1755, 1731, 1707, 1683, 1661, 1638, 1617, 1596, 1575, 1555, 1536, 1517, 1499, 1480, 1463, 1446, 1429, 1412, 1396, 1381, 1365, 1350, 1336, 1321, 1307, 1293, 1280, 1267, 1254, 1241, 1229, 1217, 1205, 1193, 1182, 1170, 1159, 1148, 1138, 1127, 1117, 1107, 1097, 1087, 1078, 1069, 1059, 1050, 1041, 1033, 1024, 1016, 1007, 999, 991, 983, 975, 968, 960, 953, 945, 938, 931, 924, 917, 910, 904, 897, 890, 884, 878, 871, 865, 859, 853, 847, 842, 836, 830, 825, 819, 814, 808, 803, 798, 793, 788, 783, 778, 773, 768, 763, 759, 754, 749, 745, 740, 736, 731, 727, 723, 719, 714, 710, 706, 702, 698, 694, 690, 686, 683, 679, 675, 671, 668, 664, 661, 657, 654, 650, 647, 643, 640, 637, 633, 630, 627, 624, 621, 617, 614, 611, 608, 605, 602, 599, 597, 594, 591, 588, 585, 582, 580, 577, 574, 572, 569, 566, 564, 561, 559, 556, 554, 551, 549, 546, 544, 541, 539, 537, 534, 532, 530, 527, 525, 523, 521, 518, 516, 514, 512, 510, 508, 506, 504, 502, 500, 497, 495, 493, 492, 490, 488, 486, 484, 482}; + __constant__ int c_HsvDivTable256[256] = {0, 174763, 87381, 58254, 43691, 34953, 29127, 24966, 21845, 19418, 17476, 15888, 14564, 13443, 12483, 11651, 10923, 10280, 9709, 9198, 8738, 8322, 7944, 7598, 7282, 6991, 6722, 6473, 6242, 6026, 5825, 5638, 5461, 5296, 5140, 4993, 4855, 4723, 4599, 4481, 4369, 4263, 4161, 4064, 3972, 3884, 3799, 3718, 3641, 3567, 3495, 3427, 3361, 3297, 3236, 3178, 3121, 3066, 3013, 2962, 2913, 2865, 2819, 2774, 2731, 2689, 2648, 2608, 2570, 2533, 2497, 2461, 2427, 2394, 2362, 2330, 2300, 2270, 2241, 2212, 2185, 2158, 2131, 2106, 2081, 2056, 2032, 2009, 1986, 1964, 1942, 1920, 1900, 1879, 1859, 1840, 1820, 1802, 1783, 1765, 1748, 1730, 1713, 1697, 1680, 1664, 1649, 1633, 1618, 1603, 1589, 1574, 1560, 1547, 1533, 1520, 1507, 1494, 1481, 1469, 1456, 1444, 1432, 1421, 1409, 1398, 1387, 1376, 1365, 1355, 1344, 1334, 1324, 1314, 1304, 1295, 1285, 1276, 1266, 1257, 1248, 1239, 1231, 1222, 1214, 1205, 1197, 1189, 1181, 1173, 1165, 1157, 1150, 1142, 1135, 1128, 1120, 1113, 1106, 1099, 1092, 1085, 1079, 1072, 1066, 1059, 1053, 1046, 1040, 1034, 1028, 1022, 1016, 1010, 1004, 999, 993, 987, 982, 976, 971, 966, 960, 955, 950, 945, 940, 935, 930, 925, 920, 915, 910, 906, 901, 896, 892, 887, 883, 878, 874, 869, 865, 861, 857, 853, 848, 844, 840, 836, 832, 828, 824, 820, 817, 813, 809, 805, 802, 798, 794, 791, 787, 784, 780, 777, 773, 770, 767, 763, 760, 757, 753, 750, 747, 744, 741, 737, 734, 731, 728, 725, 722, 719, 716, 713, 710, 708, 705, 702, 699, 696, 694, 691, 688, 685}; + + template static __device__ void RGB2HSVConvert(const uchar* src, D& dst) + { + const int hsv_shift = 12; + const int* hdiv_table = hr == 180 ? c_HsvDivTable180 : c_HsvDivTable256; + + int b = src[bidx], g = src[1], r = src[bidx^2]; + int h, s, v = b; + int vmin = b, diff; + int vr, vg; + + v = ::max(v, g); + v = ::max(v, r); + vmin = ::min(vmin, g); + vmin = ::min(vmin, r); + + diff = v - vmin; + vr = (v == r) * -1; + vg = (v == g) * -1; + + s = (diff * c_HsvDivTable[v] + (1 << (hsv_shift-1))) >> hsv_shift; + h = (vr & (g - b)) + (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff)))); + h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift; + h += (h < 0) * hr; + + dst.x = saturate_cast(h); + dst.y = (uchar)s; + dst.z = (uchar)v; + } + + template static __device__ uint RGB2HSVConvert(uint src) + { + const int hsv_shift = 12; + const int* hdiv_table = hr == 180 ? c_HsvDivTable180 : c_HsvDivTable256; + + const int b = 0xff & (src >> (bidx * 8)); + const int g = 0xff & (src >> 8); + const int r = 0xff & (src >> ((bidx ^ 2) * 8)); + + int h, s, v = b; + int vmin = b, diff; + int vr, vg; + + v = ::max(v, g); + v = ::max(v, r); + vmin = ::min(vmin, g); + vmin = ::min(vmin, r); + + diff = v - vmin; + vr = (v == r) * -1; + vg = (v == g) * -1; + + s = (diff * c_HsvDivTable[v] + (1 << (hsv_shift-1))) >> hsv_shift; + h = (vr & (g - b)) + (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff)))); + h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift; + h += (h < 0) * hr; + + uint dst = 0; + + dst |= saturate_cast(h); + dst |= (0xffu & s) << 8; + dst |= (0xffu & v) << 16; + + return dst; + } + + template static __device__ void RGB2HSVConvert(const float* src, D& dst) + { + const float hscale = hr * (1.f / 360.f); + + float b = src[bidx], g = src[1], r = src[bidx^2]; + float h, s, v; + + float vmin, diff; + + v = vmin = r; + v = fmax(v, g); + v = fmax(v, b); + vmin = fmin(vmin, g); + vmin = fmin(vmin, b); + + diff = v - vmin; + s = diff / (float)(::fabs(v) + numeric_limits::epsilon()); + diff = (float)(60. / (diff + numeric_limits::epsilon())); + + h = (v == r) * (g - b) * diff; + h += (v != r && v == g) * ((b - r) * diff + 120.f); + h += (v != r && v != g) * ((r - g) * diff + 240.f); + h += (h < 0) * 360.f; + + dst.x = h * hscale; + dst.y = s; + dst.z = v; + } + + template struct RGB2HSV + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + RGB2HSVConvert(&src.x, dst); + + return dst; + } + __host__ __device__ __forceinline__ RGB2HSV() {} + __host__ __device__ __forceinline__ RGB2HSV(const RGB2HSV&) {} + }; + + template struct RGB2HSV : unary_function + { + __device__ __forceinline__ uint operator()(uint src) const + { + return RGB2HSVConvert(src); + } + __host__ __device__ __forceinline__ RGB2HSV() {} + __host__ __device__ __forceinline__ RGB2HSV(const RGB2HSV&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2HSV_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2HSV functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template struct name ## _full_traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2HSV functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template <> struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2HSV functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template <> struct name ## _full_traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2HSV functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + __constant__ int c_HsvSectorData[6][3] = { {1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0} }; + + template static __device__ void HSV2RGBConvert(const T& src, float* dst) + { + const float hscale = 6.f / hr; + + float h = src.x, s = src.y, v = src.z; + float b = v, g = v, r = v; + + if (s != 0) + { + h *= hscale; + + if( h < 0 ) + do h += 6; while( h < 0 ); + else if( h >= 6 ) + do h -= 6; while( h >= 6 ); + + int sector = __float2int_rd(h); + h -= sector; + + if ( (unsigned)sector >= 6u ) + { + sector = 0; + h = 0.f; + } + + float tab[4]; + tab[0] = v; + tab[1] = v * (1.f - s); + tab[2] = v * (1.f - s * h); + tab[3] = v * (1.f - s * (1.f - h)); + + b = tab[c_HsvSectorData[sector][0]]; + g = tab[c_HsvSectorData[sector][1]]; + r = tab[c_HsvSectorData[sector][2]]; + } + + dst[bidx] = b; + dst[1] = g; + dst[bidx^2] = r; + } + + template static __device__ void HSV2RGBConvert(const T& src, uchar* dst) + { + float3 buf; + + buf.x = src.x; + buf.y = src.y * (1.f / 255.f); + buf.z = src.z * (1.f / 255.f); + + HSV2RGBConvert(buf, &buf.x); + + dst[0] = saturate_cast(buf.x * 255.f); + dst[1] = saturate_cast(buf.y * 255.f); + dst[2] = saturate_cast(buf.z * 255.f); + } + + template static __device__ uint HSV2RGBConvert(uint src) + { + float3 buf; + + buf.x = src & 0xff; + buf.y = ((src >> 8) & 0xff) * (1.f/255.f); + buf.z = ((src >> 16) & 0xff) * (1.f/255.f); + + HSV2RGBConvert(buf, &buf.x); + + uint dst = 0xffu << 24; + + dst |= saturate_cast(buf.x * 255.f); + dst |= saturate_cast(buf.y * 255.f) << 8; + dst |= saturate_cast(buf.z * 255.f) << 16; + + return dst; + } + + template struct HSV2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + HSV2RGBConvert(src, &dst.x); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + __host__ __device__ __forceinline__ HSV2RGB() {} + __host__ __device__ __forceinline__ HSV2RGB(const HSV2RGB&) {} + }; + + template struct HSV2RGB : unary_function + { + __device__ __forceinline__ uint operator()(uint src) const + { + return HSV2RGBConvert(src); + } + __host__ __device__ __forceinline__ HSV2RGB() {} + __host__ __device__ __forceinline__ HSV2RGB(const HSV2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_HSV2RGB_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::HSV2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template struct name ## _full_traits \ + { \ + typedef ::cv::cuda::device::color_detail::HSV2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template <> struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::HSV2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template <> struct name ## _full_traits \ + { \ + typedef ::cv::cuda::device::color_detail::HSV2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +/////////////////////////////////////// RGB <-> HLS //////////////////////////////////////// + + namespace color_detail + { + template static __device__ void RGB2HLSConvert(const float* src, D& dst) + { + const float hscale = hr * (1.f / 360.f); + + float b = src[bidx], g = src[1], r = src[bidx^2]; + float h = 0.f, s = 0.f, l; + float vmin, vmax, diff; + + vmax = vmin = r; + vmax = fmax(vmax, g); + vmax = fmax(vmax, b); + vmin = fmin(vmin, g); + vmin = fmin(vmin, b); + + diff = vmax - vmin; + l = (vmax + vmin) * 0.5f; + + if (diff > numeric_limits::epsilon()) + { + s = (l < 0.5f) * diff / (vmax + vmin); + s += (l >= 0.5f) * diff / (2.0f - vmax - vmin); + + diff = 60.f / diff; + + h = (vmax == r) * (g - b) * diff; + h += (vmax != r && vmax == g) * ((b - r) * diff + 120.f); + h += (vmax != r && vmax != g) * ((r - g) * diff + 240.f); + h += (h < 0.f) * 360.f; + } + + dst.x = h * hscale; + dst.y = l; + dst.z = s; + } + + template static __device__ void RGB2HLSConvert(const uchar* src, D& dst) + { + float3 buf; + + buf.x = src[0] * (1.f / 255.f); + buf.y = src[1] * (1.f / 255.f); + buf.z = src[2] * (1.f / 255.f); + + RGB2HLSConvert(&buf.x, buf); + + dst.x = saturate_cast(buf.x); + dst.y = saturate_cast(buf.y*255.f); + dst.z = saturate_cast(buf.z*255.f); + } + + template static __device__ uint RGB2HLSConvert(uint src) + { + float3 buf; + + buf.x = (0xff & src) * (1.f / 255.f); + buf.y = (0xff & (src >> 8)) * (1.f / 255.f); + buf.z = (0xff & (src >> 16)) * (1.f / 255.f); + + RGB2HLSConvert(&buf.x, buf); + + uint dst = 0xffu << 24; + + dst |= saturate_cast(buf.x); + dst |= saturate_cast(buf.y * 255.f) << 8; + dst |= saturate_cast(buf.z * 255.f) << 16; + + return dst; + } + + template struct RGB2HLS + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + RGB2HLSConvert(&src.x, dst); + + return dst; + } + __host__ __device__ __forceinline__ RGB2HLS() {} + __host__ __device__ __forceinline__ RGB2HLS(const RGB2HLS&) {} + }; + + template struct RGB2HLS : unary_function + { + __device__ __forceinline__ uint operator()(uint src) const + { + return RGB2HLSConvert(src); + } + __host__ __device__ __forceinline__ RGB2HLS() {} + __host__ __device__ __forceinline__ RGB2HLS(const RGB2HLS&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2HLS_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2HLS functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template struct name ## _full_traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2HLS functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template <> struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2HLS functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template <> struct name ## _full_traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2HLS functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + __constant__ int c_HlsSectorData[6][3] = { {1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0} }; + + template static __device__ void HLS2RGBConvert(const T& src, float* dst) + { + const float hscale = 6.0f / hr; + + float h = src.x, l = src.y, s = src.z; + float b = l, g = l, r = l; + + if (s != 0) + { + float p2 = (l <= 0.5f) * l * (1 + s); + p2 += (l > 0.5f) * (l + s - l * s); + float p1 = 2 * l - p2; + + h *= hscale; + + if( h < 0 ) + do h += 6; while( h < 0 ); + else if( h >= 6 ) + do h -= 6; while( h >= 6 ); + + int sector; + sector = __float2int_rd(h); + + h -= sector; + + float tab[4]; + tab[0] = p2; + tab[1] = p1; + tab[2] = p1 + (p2 - p1) * (1 - h); + tab[3] = p1 + (p2 - p1) * h; + + b = tab[c_HlsSectorData[sector][0]]; + g = tab[c_HlsSectorData[sector][1]]; + r = tab[c_HlsSectorData[sector][2]]; + } + + dst[bidx] = b; + dst[1] = g; + dst[bidx^2] = r; + } + + template static __device__ void HLS2RGBConvert(const T& src, uchar* dst) + { + float3 buf; + + buf.x = src.x; + buf.y = src.y * (1.f / 255.f); + buf.z = src.z * (1.f / 255.f); + + HLS2RGBConvert(buf, &buf.x); + + dst[0] = saturate_cast(buf.x * 255.f); + dst[1] = saturate_cast(buf.y * 255.f); + dst[2] = saturate_cast(buf.z * 255.f); + } + + template static __device__ uint HLS2RGBConvert(uint src) + { + float3 buf; + + buf.x = 0xff & src; + buf.y = (0xff & (src >> 8)) * (1.f / 255.f); + buf.z = (0xff & (src >> 16)) * (1.f / 255.f); + + HLS2RGBConvert(buf, &buf.x); + + uint dst = 0xffu << 24; + + dst |= saturate_cast(buf.x * 255.f); + dst |= saturate_cast(buf.y * 255.f) << 8; + dst |= saturate_cast(buf.z * 255.f) << 16; + + return dst; + } + + template struct HLS2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + HLS2RGBConvert(src, &dst.x); + setAlpha(dst, ColorChannel::max()); + + return dst; + } + __host__ __device__ __forceinline__ HLS2RGB() {} + __host__ __device__ __forceinline__ HLS2RGB(const HLS2RGB&) {} + }; + + template struct HLS2RGB : unary_function + { + __device__ __forceinline__ uint operator()(uint src) const + { + return HLS2RGBConvert(src); + } + __host__ __device__ __forceinline__ HLS2RGB() {} + __host__ __device__ __forceinline__ HLS2RGB(const HLS2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_HLS2RGB_TRAITS(name, scn, dcn, bidx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::HLS2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template struct name ## _full_traits \ + { \ + typedef ::cv::cuda::device::color_detail::HLS2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template <> struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::HLS2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; \ + template <> struct name ## _full_traits \ + { \ + typedef ::cv::cuda::device::color_detail::HLS2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +///////////////////////////////////// RGB <-> Lab ///////////////////////////////////// + + namespace color_detail + { + enum + { + LAB_CBRT_TAB_SIZE = 1024, + GAMMA_TAB_SIZE = 1024, + lab_shift = xyz_shift, + gamma_shift = 3, + lab_shift2 = (lab_shift + gamma_shift), + LAB_CBRT_TAB_SIZE_B = (256 * 3 / 2 * (1 << gamma_shift)) + }; + + __constant__ ushort c_sRGBGammaTab_b[] = {0,1,1,2,2,3,4,4,5,6,6,7,8,8,9,10,11,11,12,13,14,15,16,17,19,20,21,22,24,25,26,28,29,31,33,34,36,38,40,41,43,45,47,49,51,54,56,58,60,63,65,68,70,73,75,78,81,83,86,89,92,95,98,101,105,108,111,115,118,121,125,129,132,136,140,144,147,151,155,160,164,168,172,176,181,185,190,194,199,204,209,213,218,223,228,233,239,244,249,255,260,265,271,277,282,288,294,300,306,312,318,324,331,337,343,350,356,363,370,376,383,390,397,404,411,418,426,433,440,448,455,463,471,478,486,494,502,510,518,527,535,543,552,560,569,578,586,595,604,613,622,631,641,650,659,669,678,688,698,707,717,727,737,747,757,768,778,788,799,809,820,831,842,852,863,875,886,897,908,920,931,943,954,966,978,990,1002,1014,1026,1038,1050,1063,1075,1088,1101,1113,1126,1139,1152,1165,1178,1192,1205,1218,1232,1245,1259,1273,1287,1301,1315,1329,1343,1357,1372,1386,1401,1415,1430,1445,1460,1475,1490,1505,1521,1536,1551,1567,1583,1598,1614,1630,1646,1662,1678,1695,1711,1728,1744,1761,1778,1794,1811,1828,1846,1863,1880,1897,1915,1933,1950,1968,1986,2004,2022,2040}; + + __device__ __forceinline__ int LabCbrt_b(int i) + { + float x = i * (1.f / (255.f * (1 << gamma_shift))); + return (1 << lab_shift2) * (x < 0.008856f ? x * 7.787f + 0.13793103448275862f : ::cbrtf(x)); + } + + template + __device__ __forceinline__ void RGB2LabConvert_b(const T& src, D& dst) + { + const int Lscale = (116 * 255 + 50) / 100; + const int Lshift = -((16 * 255 * (1 << lab_shift2) + 50) / 100); + + int B = blueIdx == 0 ? src.x : src.z; + int G = src.y; + int R = blueIdx == 0 ? src.z : src.x; + + if (srgb) + { + B = c_sRGBGammaTab_b[B]; + G = c_sRGBGammaTab_b[G]; + R = c_sRGBGammaTab_b[R]; + } + else + { + B <<= 3; + G <<= 3; + R <<= 3; + } + + int fX = LabCbrt_b(CV_DESCALE(B * 778 + G * 1541 + R * 1777, lab_shift)); + int fY = LabCbrt_b(CV_DESCALE(B * 296 + G * 2929 + R * 871, lab_shift)); + int fZ = LabCbrt_b(CV_DESCALE(B * 3575 + G * 448 + R * 73, lab_shift)); + + int L = CV_DESCALE(Lscale * fY + Lshift, lab_shift2); + int a = CV_DESCALE(500 * (fX - fY) + 128 * (1 << lab_shift2), lab_shift2); + int b = CV_DESCALE(200 * (fY - fZ) + 128 * (1 << lab_shift2), lab_shift2); + + dst.x = saturate_cast(L); + dst.y = saturate_cast(a); + dst.z = saturate_cast(b); + } + + __device__ __forceinline__ float splineInterpolate(float x, const float* tab, int n) + { + int ix = ::min(::max(int(x), 0), n-1); + x -= ix; + tab += ix * 4; + return ((tab[3] * x + tab[2]) * x + tab[1]) * x + tab[0]; + } + + __constant__ float c_sRGBGammaTab[] = {0,7.55853e-05,0.,-7.51331e-13,7.55853e-05,7.55853e-05,-2.25399e-12,3.75665e-12,0.000151171,7.55853e-05,9.01597e-12,-6.99932e-12,0.000226756,7.55853e-05,-1.1982e-11,2.41277e-12,0.000302341,7.55853e-05,-4.74369e-12,1.19001e-11,0.000377927,7.55853e-05,3.09568e-11,-2.09095e-11,0.000453512,7.55853e-05,-3.17718e-11,1.35303e-11,0.000529097,7.55853e-05,8.81905e-12,-4.10782e-12,0.000604683,7.55853e-05,-3.50439e-12,2.90097e-12,0.000680268,7.55853e-05,5.19852e-12,-7.49607e-12,0.000755853,7.55853e-05,-1.72897e-11,2.70833e-11,0.000831439,7.55854e-05,6.39602e-11,-4.26295e-11,0.000907024,7.55854e-05,-6.39282e-11,2.70193e-11,0.000982609,7.55853e-05,1.71298e-11,-7.24017e-12,0.00105819,7.55853e-05,-4.59077e-12,1.94137e-12,0.00113378,7.55853e-05,1.23333e-12,-5.25291e-13,0.00120937,7.55853e-05,-3.42545e-13,1.59799e-13,0.00128495,7.55853e-05,1.36852e-13,-1.13904e-13,0.00136054,7.55853e-05,-2.04861e-13,2.95818e-13,0.00143612,7.55853e-05,6.82594e-13,-1.06937e-12,0.00151171,7.55853e-05,-2.52551e-12,3.98166e-12,0.00158729,7.55853e-05,9.41946e-12,-1.48573e-11,0.00166288,7.55853e-05,-3.51523e-11,5.54474e-11,0.00173846,7.55854e-05,1.3119e-10,-9.0517e-11,0.00181405,7.55854e-05,-1.40361e-10,7.37899e-11,0.00188963,7.55853e-05,8.10085e-11,-8.82272e-11,0.00196522,7.55852e-05,-1.83673e-10,1.62704e-10,0.0020408,7.55853e-05,3.04438e-10,-2.13341e-10,0.00211639,7.55853e-05,-3.35586e-10,2.25e-10,0.00219197,7.55853e-05,3.39414e-10,-2.20997e-10,0.00226756,7.55853e-05,-3.23576e-10,1.93326e-10,0.00234315,7.55853e-05,2.564e-10,-8.66446e-11,0.00241873,7.55855e-05,-3.53328e-12,-7.9578e-11,0.00249432,7.55853e-05,-2.42267e-10,1.72126e-10,0.0025699,7.55853e-05,2.74111e-10,-1.43265e-10,0.00264549,7.55854e-05,-1.55683e-10,-6.47292e-11,0.00272107,7.55849e-05,-3.4987e-10,8.67842e-10,0.00279666,7.55868e-05,2.25366e-09,-3.8723e-09,0.00287224,7.55797e-05,-9.36325e-09,1.5087e-08,0.00294783,7.56063e-05,3.58978e-08,-5.69415e-08,0.00302341,7.55072e-05,-1.34927e-07,2.13144e-07,0.003099,7.58768e-05,5.04507e-07,1.38713e-07,0.00317552,7.7302e-05,9.20646e-07,-1.55186e-07,0.00325359,7.86777e-05,4.55087e-07,4.26813e-08,0.00333276,7.97159e-05,5.83131e-07,-1.06495e-08,0.00341305,8.08502e-05,5.51182e-07,3.87467e-09,0.00349446,8.19642e-05,5.62806e-07,-1.92586e-10,0.00357698,8.30892e-05,5.62228e-07,1.0866e-09,0.00366063,8.4217e-05,5.65488e-07,5.02818e-10,0.00374542,8.53494e-05,5.66997e-07,8.60211e-10,0.00383133,8.6486e-05,5.69577e-07,7.13044e-10,0.00391839,8.76273e-05,5.71716e-07,4.78527e-10,0.00400659,8.87722e-05,5.73152e-07,1.09818e-09,0.00409594,8.99218e-05,5.76447e-07,2.50964e-10,0.00418644,9.10754e-05,5.772e-07,1.15762e-09,0.00427809,9.22333e-05,5.80672e-07,2.40865e-10,0.0043709,9.33954e-05,5.81395e-07,1.13854e-09,0.00446488,9.45616e-05,5.84811e-07,3.27267e-10,0.00456003,9.57322e-05,5.85792e-07,8.1197e-10,0.00465635,9.69062e-05,5.88228e-07,6.15823e-10,0.00475384,9.80845e-05,5.90076e-07,9.15747e-10,0.00485252,9.92674e-05,5.92823e-07,3.778e-10,0.00495238,0.000100454,5.93956e-07,8.32623e-10,0.00505343,0.000101645,5.96454e-07,4.82695e-10,0.00515567,0.000102839,5.97902e-07,9.61904e-10,0.00525911,0.000104038,6.00788e-07,3.26281e-10,0.00536375,0.00010524,6.01767e-07,9.926e-10,0.00546959,0.000106447,6.04745e-07,3.59933e-10,0.00557664,0.000107657,6.05824e-07,8.2728e-10,0.0056849,0.000108871,6.08306e-07,5.21898e-10,0.00579438,0.00011009,6.09872e-07,8.10492e-10,0.00590508,0.000111312,6.12303e-07,4.27046e-10,0.00601701,0.000112538,6.13585e-07,7.40878e-10,0.00613016,0.000113767,6.15807e-07,8.00469e-10,0.00624454,0.000115001,6.18209e-07,2.48178e-10,0.00636016,0.000116238,6.18953e-07,1.00073e-09,0.00647702,0.000117479,6.21955e-07,4.05654e-10,0.00659512,0.000118724,6.23172e-07,6.36192e-10,0.00671447,0.000119973,6.25081e-07,7.74927e-10,0.00683507,0.000121225,6.27406e-07,4.54975e-10,0.00695692,0.000122481,6.28771e-07,6.64841e-10,0.00708003,0.000123741,6.30765e-07,6.10972e-10,0.00720441,0.000125004,6.32598e-07,6.16543e-10,0.00733004,0.000126271,6.34448e-07,6.48204e-10,0.00745695,0.000127542,6.36392e-07,5.15835e-10,0.00758513,0.000128816,6.3794e-07,5.48103e-10,0.00771458,0.000130094,6.39584e-07,1.01706e-09,0.00784532,0.000131376,6.42635e-07,4.0283e-11,0.00797734,0.000132661,6.42756e-07,6.84471e-10,0.00811064,0.000133949,6.4481e-07,9.47144e-10,0.00824524,0.000135241,6.47651e-07,1.83472e-10,0.00838112,0.000136537,6.48201e-07,1.11296e-09,0.00851831,0.000137837,6.5154e-07,2.13163e-11,0.0086568,0.00013914,6.51604e-07,6.64462e-10,0.00879659,0.000140445,6.53598e-07,1.04613e-09,0.00893769,0.000141756,6.56736e-07,-1.92377e-10,0.0090801,0.000143069,6.56159e-07,1.58601e-09,0.00922383,0.000144386,6.60917e-07,-5.63754e-10,0.00936888,0.000145706,6.59226e-07,1.60033e-09,0.00951524,0.000147029,6.64027e-07,-2.49543e-10,0.00966294,0.000148356,6.63278e-07,1.26043e-09,0.00981196,0.000149687,6.67059e-07,-1.35572e-10,0.00996231,0.00015102,6.66653e-07,1.14458e-09,0.010114,0.000152357,6.70086e-07,2.13864e-10,0.010267,0.000153698,6.70728e-07,7.93856e-10,0.0104214,0.000155042,6.73109e-07,3.36077e-10,0.0105771,0.000156389,6.74118e-07,6.55765e-10,0.0107342,0.000157739,6.76085e-07,7.66211e-10,0.0108926,0.000159094,6.78384e-07,4.66116e-12,0.0110524,0.000160451,6.78398e-07,1.07775e-09,0.0112135,0.000161811,6.81631e-07,3.41023e-10,0.011376,0.000163175,6.82654e-07,3.5205e-10,0.0115398,0.000164541,6.8371e-07,1.04473e-09,0.0117051,0.000165912,6.86844e-07,1.25757e-10,0.0118717,0.000167286,6.87222e-07,3.14818e-10,0.0120396,0.000168661,6.88166e-07,1.40886e-09,0.012209,0.000170042,6.92393e-07,-3.62244e-10,0.0123797,0.000171425,6.91306e-07,9.71397e-10,0.0125518,0.000172811,6.9422e-07,2.02003e-10,0.0127253,0.0001742,6.94826e-07,1.01448e-09,0.0129002,0.000175593,6.97869e-07,3.96653e-10,0.0130765,0.00017699,6.99059e-07,1.92927e-10,0.0132542,0.000178388,6.99638e-07,6.94305e-10,0.0134333,0.00017979,7.01721e-07,7.55108e-10,0.0136138,0.000181195,7.03986e-07,1.05918e-11,0.0137957,0.000182603,7.04018e-07,1.06513e-09,0.013979,0.000184015,7.07214e-07,3.85512e-10,0.0141637,0.00018543,7.0837e-07,1.86769e-10,0.0143499,0.000186848,7.0893e-07,7.30116e-10,0.0145374,0.000188268,7.11121e-07,6.17983e-10,0.0147264,0.000189692,7.12975e-07,5.23282e-10,0.0149168,0.000191119,7.14545e-07,8.28398e-11,0.0151087,0.000192549,7.14793e-07,1.0081e-09,0.0153019,0.000193981,7.17817e-07,5.41244e-10,0.0154966,0.000195418,7.19441e-07,-3.7907e-10,0.0156928,0.000196856,7.18304e-07,1.90641e-09,0.0158903,0.000198298,7.24023e-07,-7.27387e-10,0.0160893,0.000199744,7.21841e-07,1.00317e-09,0.0162898,0.000201191,7.24851e-07,4.39949e-10,0.0164917,0.000202642,7.2617e-07,9.6234e-10,0.0166951,0.000204097,7.29057e-07,-5.64019e-10,0.0168999,0.000205554,7.27365e-07,1.29374e-09,0.0171062,0.000207012,7.31247e-07,9.77025e-10,0.017314,0.000208478,7.34178e-07,-1.47651e-09,0.0175232,0.000209942,7.29748e-07,3.06636e-09,0.0177338,0.00021141,7.38947e-07,-1.47573e-09,0.017946,0.000212884,7.3452e-07,9.7386e-10,0.0181596,0.000214356,7.37442e-07,1.30562e-09,0.0183747,0.000215835,7.41358e-07,-6.08376e-10,0.0185913,0.000217315,7.39533e-07,1.12785e-09,0.0188093,0.000218798,7.42917e-07,-1.77711e-10,0.0190289,0.000220283,7.42384e-07,1.44562e-09,0.0192499,0.000221772,7.46721e-07,-1.68825e-11,0.0194724,0.000223266,7.4667e-07,4.84533e-10,0.0196964,0.000224761,7.48124e-07,-5.85298e-11,0.0199219,0.000226257,7.47948e-07,1.61217e-09,0.0201489,0.000227757,7.52785e-07,-8.02136e-10,0.0203775,0.00022926,7.50378e-07,1.59637e-09,0.0206075,0.000230766,7.55167e-07,4.47168e-12,0.020839,0.000232276,7.55181e-07,2.48387e-10,0.021072,0.000233787,7.55926e-07,8.6474e-10,0.0213066,0.000235302,7.5852e-07,1.78299e-11,0.0215426,0.000236819,7.58573e-07,9.26567e-10,0.0217802,0.000238339,7.61353e-07,1.34529e-12,0.0220193,0.000239862,7.61357e-07,9.30659e-10,0.0222599,0.000241387,7.64149e-07,1.34529e-12,0.0225021,0.000242915,7.64153e-07,9.26567e-10,0.0227458,0.000244447,7.66933e-07,1.76215e-11,0.022991,0.00024598,7.66986e-07,8.65536e-10,0.0232377,0.000247517,7.69582e-07,2.45677e-10,0.023486,0.000249057,7.70319e-07,1.44193e-11,0.0237358,0.000250598,7.70363e-07,1.55918e-09,0.0239872,0.000252143,7.7504e-07,-6.63173e-10,0.0242401,0.000253691,7.73051e-07,1.09357e-09,0.0244946,0.000255241,7.76331e-07,1.41919e-11,0.0247506,0.000256793,7.76374e-07,7.12248e-10,0.0250082,0.000258348,7.78511e-07,8.62049e-10,0.0252673,0.000259908,7.81097e-07,-4.35061e-10,0.025528,0.000261469,7.79792e-07,8.7825e-10,0.0257902,0.000263031,7.82426e-07,6.47181e-10,0.0260541,0.000264598,7.84368e-07,2.58448e-10,0.0263194,0.000266167,7.85143e-07,1.81558e-10,0.0265864,0.000267738,7.85688e-07,8.78041e-10,0.0268549,0.000269312,7.88322e-07,3.15102e-11,0.027125,0.000270889,7.88417e-07,8.58525e-10,0.0273967,0.000272468,7.90992e-07,2.59812e-10,0.02767,0.000274051,7.91772e-07,-3.5224e-11,0.0279448,0.000275634,7.91666e-07,1.74377e-09,0.0282212,0.000277223,7.96897e-07,-1.35196e-09,0.0284992,0.000278813,7.92841e-07,1.80141e-09,0.0287788,0.000280404,7.98246e-07,-2.65629e-10,0.0290601,0.000281999,7.97449e-07,1.12374e-09,0.0293428,0.000283598,8.0082e-07,-5.04106e-10,0.0296272,0.000285198,7.99308e-07,8.92764e-10,0.0299132,0.000286799,8.01986e-07,6.58379e-10,0.0302008,0.000288405,8.03961e-07,1.98971e-10,0.0304901,0.000290014,8.04558e-07,4.08382e-10,0.0307809,0.000291624,8.05783e-07,3.01839e-11,0.0310733,0.000293236,8.05874e-07,1.33343e-09,0.0313673,0.000294851,8.09874e-07,2.2419e-10,0.031663,0.000296472,8.10547e-07,-3.67606e-10,0.0319603,0.000298092,8.09444e-07,1.24624e-09,0.0322592,0.000299714,8.13182e-07,-8.92025e-10,0.0325597,0.000301338,8.10506e-07,2.32183e-09,0.0328619,0.000302966,8.17472e-07,-9.44719e-10,0.0331657,0.000304598,8.14638e-07,1.45703e-09,0.0334711,0.000306232,8.19009e-07,-1.15805e-09,0.0337781,0.000307866,8.15535e-07,3.17507e-09,0.0340868,0.000309507,8.2506e-07,-4.09161e-09,0.0343971,0.000311145,8.12785e-07,5.74079e-09,0.0347091,0.000312788,8.30007e-07,-3.97034e-09,0.0350227,0.000314436,8.18096e-07,2.68985e-09,0.035338,0.00031608,8.26166e-07,6.61676e-10,0.0356549,0.000317734,8.28151e-07,-1.61123e-09,0.0359734,0.000319386,8.23317e-07,2.05786e-09,0.0362936,0.000321038,8.29491e-07,8.30388e-10,0.0366155,0.0003227,8.31982e-07,-1.65424e-09,0.036939,0.000324359,8.27019e-07,2.06129e-09,0.0372642,0.000326019,8.33203e-07,8.59719e-10,0.0375911,0.000327688,8.35782e-07,-1.77488e-09,0.0379196,0.000329354,8.30458e-07,2.51464e-09,0.0382498,0.000331023,8.38002e-07,-8.33135e-10,0.0385817,0.000332696,8.35502e-07,8.17825e-10,0.0389152,0.00033437,8.37956e-07,1.28718e-09,0.0392504,0.00033605,8.41817e-07,-2.2413e-09,0.0395873,0.000337727,8.35093e-07,3.95265e-09,0.0399258,0.000339409,8.46951e-07,-2.39332e-09,0.0402661,0.000341095,8.39771e-07,1.89533e-09,0.040608,0.000342781,8.45457e-07,-1.46271e-09,0.0409517,0.000344467,8.41069e-07,3.95554e-09,0.041297,0.000346161,8.52936e-07,-3.18369e-09,0.041644,0.000347857,8.43385e-07,1.32873e-09,0.0419927,0.000349548,8.47371e-07,1.59402e-09,0.0423431,0.000351248,8.52153e-07,-2.54336e-10,0.0426952,0.000352951,8.5139e-07,-5.76676e-10,0.043049,0.000354652,8.4966e-07,2.56114e-09,0.0434045,0.000356359,8.57343e-07,-2.21744e-09,0.0437617,0.000358067,8.50691e-07,2.58344e-09,0.0441206,0.000359776,8.58441e-07,-6.65826e-10,0.0444813,0.000361491,8.56444e-07,7.99218e-11,0.0448436,0.000363204,8.56684e-07,3.46063e-10,0.0452077,0.000364919,8.57722e-07,2.26116e-09,0.0455734,0.000366641,8.64505e-07,-1.94005e-09,0.045941,0.000368364,8.58685e-07,1.77384e-09,0.0463102,0.000370087,8.64007e-07,-1.43005e-09,0.0466811,0.000371811,8.59717e-07,3.94634e-09,0.0470538,0.000373542,8.71556e-07,-3.17946e-09,0.0474282,0.000375276,8.62017e-07,1.32104e-09,0.0478043,0.000377003,8.6598e-07,1.62045e-09,0.0481822,0.00037874,8.70842e-07,-3.52297e-10,0.0485618,0.000380481,8.69785e-07,-2.11211e-10,0.0489432,0.00038222,8.69151e-07,1.19716e-09,0.0493263,0.000383962,8.72743e-07,-8.52026e-10,0.0497111,0.000385705,8.70187e-07,2.21092e-09,0.0500977,0.000387452,8.76819e-07,-5.41339e-10,0.050486,0.000389204,8.75195e-07,-4.5361e-11,0.0508761,0.000390954,8.75059e-07,7.22669e-10,0.0512679,0.000392706,8.77227e-07,8.79936e-10,0.0516615,0.000394463,8.79867e-07,-5.17048e-10,0.0520568,0.000396222,8.78316e-07,1.18833e-09,0.0524539,0.000397982,8.81881e-07,-5.11022e-10,0.0528528,0.000399744,8.80348e-07,8.55683e-10,0.0532534,0.000401507,8.82915e-07,8.13562e-10,0.0536558,0.000403276,8.85356e-07,-3.84603e-10,0.05406,0.000405045,8.84202e-07,7.24962e-10,0.0544659,0.000406816,8.86377e-07,1.20986e-09,0.0548736,0.000408592,8.90006e-07,-1.83896e-09,0.0552831,0.000410367,8.84489e-07,2.42071e-09,0.0556944,0.000412143,8.91751e-07,-3.93413e-10,0.0561074,0.000413925,8.90571e-07,-8.46967e-10,0.0565222,0.000415704,8.8803e-07,3.78122e-09,0.0569388,0.000417491,8.99374e-07,-3.1021e-09,0.0573572,0.000419281,8.90068e-07,1.17658e-09,0.0577774,0.000421064,8.93597e-07,2.12117e-09,0.0581993,0.000422858,8.99961e-07,-2.21068e-09,0.0586231,0.000424651,8.93329e-07,2.9961e-09,0.0590486,0.000426447,9.02317e-07,-2.32311e-09,0.059476,0.000428244,8.95348e-07,2.57122e-09,0.0599051,0.000430043,9.03062e-07,-5.11098e-10,0.0603361,0.000431847,9.01528e-07,-5.27166e-10,0.0607688,0.000433649,8.99947e-07,2.61984e-09,0.0612034,0.000435457,9.07806e-07,-2.50141e-09,0.0616397,0.000437265,9.00302e-07,3.66045e-09,0.0620779,0.000439076,9.11283e-07,-4.68977e-09,0.0625179,0.000440885,8.97214e-07,7.64783e-09,0.0629597,0.000442702,9.20158e-07,-7.27499e-09,0.0634033,0.000444521,8.98333e-07,6.55113e-09,0.0638487,0.000446337,9.17986e-07,-4.02844e-09,0.0642959,0.000448161,9.05901e-07,2.11196e-09,0.064745,0.000449979,9.12236e-07,3.03125e-09,0.0651959,0.000451813,9.2133e-07,-6.78648e-09,0.0656486,0.000453635,9.00971e-07,9.21375e-09,0.0661032,0.000455464,9.28612e-07,-7.71684e-09,0.0665596,0.000457299,9.05462e-07,6.7522e-09,0.0670178,0.00045913,9.25718e-07,-4.3907e-09,0.0674778,0.000460968,9.12546e-07,3.36e-09,0.0679397,0.000462803,9.22626e-07,-1.59876e-09,0.0684034,0.000464644,9.1783e-07,3.0351e-09,0.068869,0.000466488,9.26935e-07,-3.09101e-09,0.0693364,0.000468333,9.17662e-07,1.8785e-09,0.0698057,0.000470174,9.23298e-07,3.02733e-09,0.0702768,0.00047203,9.3238e-07,-6.53722e-09,0.0707497,0.000473875,9.12768e-07,8.22054e-09,0.0712245,0.000475725,9.37429e-07,-3.99325e-09,0.0717012,0.000477588,9.2545e-07,3.01839e-10,0.0721797,0.00047944,9.26355e-07,2.78597e-09,0.0726601,0.000481301,9.34713e-07,-3.99507e-09,0.0731423,0.000483158,9.22728e-07,5.7435e-09,0.0736264,0.000485021,9.39958e-07,-4.07776e-09,0.0741123,0.000486888,9.27725e-07,3.11695e-09,0.0746002,0.000488753,9.37076e-07,-9.39394e-10,0.0750898,0.000490625,9.34258e-07,6.4055e-10,0.0755814,0.000492495,9.3618e-07,-1.62265e-09,0.0760748,0.000494363,9.31312e-07,5.84995e-09,0.0765701,0.000496243,9.48861e-07,-6.87601e-09,0.0770673,0.00049812,9.28233e-07,6.75296e-09,0.0775664,0.000499997,9.48492e-07,-5.23467e-09,0.0780673,0.000501878,9.32788e-07,6.73523e-09,0.0785701,0.000503764,9.52994e-07,-6.80514e-09,0.0790748,0.000505649,9.32578e-07,5.5842e-09,0.0795814,0.000507531,9.49331e-07,-6.30583e-10,0.0800899,0.000509428,9.47439e-07,-3.0618e-09,0.0806003,0.000511314,9.38254e-07,5.4273e-09,0.0811125,0.000513206,9.54536e-07,-3.74627e-09,0.0816267,0.000515104,9.43297e-07,2.10713e-09,0.0821427,0.000516997,9.49618e-07,2.76839e-09,0.0826607,0.000518905,9.57924e-07,-5.73006e-09,0.0831805,0.000520803,9.40733e-07,5.25072e-09,0.0837023,0.0005227,9.56486e-07,-3.71718e-10,0.084226,0.000524612,9.5537e-07,-3.76404e-09,0.0847515,0.000526512,9.44078e-07,7.97735e-09,0.085279,0.000528424,9.6801e-07,-5.79367e-09,0.0858084,0.000530343,9.50629e-07,2.96268e-10,0.0863397,0.000532245,9.51518e-07,4.6086e-09,0.0868729,0.000534162,9.65344e-07,-3.82947e-09,0.087408,0.000536081,9.53856e-07,3.25861e-09,0.087945,0.000537998,9.63631e-07,-1.7543e-09,0.088484,0.00053992,9.58368e-07,3.75849e-09,0.0890249,0.000541848,9.69644e-07,-5.82891e-09,0.0895677,0.00054377,9.52157e-07,4.65593e-09,0.0901124,0.000545688,9.66125e-07,2.10643e-09,0.0906591,0.000547627,9.72444e-07,-5.63099e-09,0.0912077,0.000549555,9.55551e-07,5.51627e-09,0.0917582,0.000551483,9.721e-07,-1.53292e-09,0.0923106,0.000553422,9.67501e-07,6.15311e-10,0.092865,0.000555359,9.69347e-07,-9.28291e-10,0.0934213,0.000557295,9.66562e-07,3.09774e-09,0.0939796,0.000559237,9.75856e-07,-4.01186e-09,0.0945398,0.000561177,9.6382e-07,5.49892e-09,0.095102,0.000563121,9.80317e-07,-3.08258e-09,0.0956661,0.000565073,9.71069e-07,-6.19176e-10,0.0962321,0.000567013,9.69212e-07,5.55932e-09,0.0968001,0.000568968,9.8589e-07,-6.71704e-09,0.09737,0.00057092,9.65738e-07,6.40762e-09,0.0979419,0.00057287,9.84961e-07,-4.0122e-09,0.0985158,0.000574828,9.72925e-07,2.19059e-09,0.0990916,0.000576781,9.79496e-07,2.70048e-09,0.0996693,0.000578748,9.87598e-07,-5.54193e-09,0.100249,0.000580706,9.70972e-07,4.56597e-09,0.100831,0.000582662,9.8467e-07,2.17923e-09,0.101414,0.000584638,9.91208e-07,-5.83232e-09,0.102,0.000586603,9.73711e-07,6.24884e-09,0.102588,0.000588569,9.92457e-07,-4.26178e-09,0.103177,0.000590541,9.79672e-07,3.34781e-09,0.103769,0.00059251,9.89715e-07,-1.67904e-09,0.104362,0.000594485,9.84678e-07,3.36839e-09,0.104958,0.000596464,9.94783e-07,-4.34397e-09,0.105555,0.000598441,9.81751e-07,6.55696e-09,0.106155,0.000600424,1.00142e-06,-6.98272e-09,0.106756,0.000602406,9.80474e-07,6.4728e-09,0.107359,0.000604386,9.99893e-07,-4.00742e-09,0.107965,0.000606374,9.8787e-07,2.10654e-09,0.108572,0.000608356,9.9419e-07,3.0318e-09,0.109181,0.000610353,1.00329e-06,-6.7832e-09,0.109793,0.00061234,9.82936e-07,9.1998e-09,0.110406,0.000614333,1.01054e-06,-7.6642e-09,0.111021,0.000616331,9.87543e-07,6.55579e-09,0.111639,0.000618326,1.00721e-06,-3.65791e-09,0.112258,0.000620329,9.96236e-07,6.25467e-10,0.112879,0.000622324,9.98113e-07,1.15593e-09,0.113503,0.000624323,1.00158e-06,2.20158e-09,0.114128,0.000626333,1.00819e-06,-2.51191e-09,0.114755,0.000628342,1.00065e-06,3.95517e-10,0.115385,0.000630345,1.00184e-06,9.29807e-10,0.116016,0.000632351,1.00463e-06,3.33599e-09,0.116649,0.00063437,1.01463e-06,-6.82329e-09,0.117285,0.000636379,9.94163e-07,9.05595e-09,0.117922,0.000638395,1.02133e-06,-7.04862e-09,0.118562,0.000640416,1.00019e-06,4.23737e-09,0.119203,0.000642429,1.0129e-06,-2.45033e-09,0.119847,0.000644448,1.00555e-06,5.56395e-09,0.120492,0.000646475,1.02224e-06,-4.9043e-09,0.121139,0.000648505,1.00753e-06,-8.47952e-10,0.121789,0.000650518,1.00498e-06,8.29622e-09,0.122441,0.000652553,1.02987e-06,-9.98538e-09,0.123094,0.000654582,9.99914e-07,9.2936e-09,0.12375,0.00065661,1.02779e-06,-4.83707e-09,0.124407,0.000658651,1.01328e-06,2.60411e-09,0.125067,0.000660685,1.0211e-06,-5.57945e-09,0.125729,0.000662711,1.00436e-06,1.22631e-08,0.126392,0.000664756,1.04115e-06,-1.36704e-08,0.127058,0.000666798,1.00014e-06,1.26161e-08,0.127726,0.000668836,1.03798e-06,-6.99155e-09,0.128396,0.000670891,1.01701e-06,4.48836e-10,0.129068,0.000672926,1.01836e-06,5.19606e-09,0.129742,0.000674978,1.03394e-06,-6.3319e-09,0.130418,0.000677027,1.01495e-06,5.2305e-09,0.131096,0.000679073,1.03064e-06,3.11123e-10,0.131776,0.000681135,1.03157e-06,-6.47511e-09,0.132458,0.000683179,1.01215e-06,1.06882e-08,0.133142,0.000685235,1.04421e-06,-6.47519e-09,0.133829,0.000687304,1.02479e-06,3.11237e-10,0.134517,0.000689355,1.02572e-06,5.23035e-09,0.135207,0.000691422,1.04141e-06,-6.3316e-09,0.1359,0.000693486,1.02242e-06,5.19484e-09,0.136594,0.000695546,1.038e-06,4.53497e-10,0.137291,0.000697623,1.03936e-06,-7.00891e-09,0.137989,0.000699681,1.01834e-06,1.2681e-08,0.13869,0.000701756,1.05638e-06,-1.39128e-08,0.139393,0.000703827,1.01464e-06,1.31679e-08,0.140098,0.000705896,1.05414e-06,-8.95659e-09,0.140805,0.000707977,1.02727e-06,7.75742e-09,0.141514,0.000710055,1.05055e-06,-7.17182e-09,0.142225,0.000712135,1.02903e-06,6.02862e-09,0.142938,0.000714211,1.04712e-06,-2.04163e-09,0.143653,0.000716299,1.04099e-06,2.13792e-09,0.144371,0.000718387,1.04741e-06,-6.51009e-09,0.14509,0.000720462,1.02787e-06,9.00123e-09,0.145812,0.000722545,1.05488e-06,3.07523e-10,0.146535,0.000724656,1.0558e-06,-1.02312e-08,0.147261,0.000726737,1.02511e-06,1.0815e-08,0.147989,0.000728819,1.05755e-06,-3.22681e-09,0.148719,0.000730925,1.04787e-06,2.09244e-09,0.14945,0.000733027,1.05415e-06,-5.143e-09,0.150185,0.00073512,1.03872e-06,3.57844e-09,0.150921,0.000737208,1.04946e-06,5.73027e-09,0.151659,0.000739324,1.06665e-06,-1.15983e-08,0.152399,0.000741423,1.03185e-06,1.08605e-08,0.153142,0.000743519,1.06443e-06,-2.04106e-09,0.153886,0.000745642,1.05831e-06,-2.69642e-09,0.154633,0.00074775,1.05022e-06,-2.07425e-09,0.155382,0.000749844,1.044e-06,1.09934e-08,0.156133,0.000751965,1.07698e-06,-1.20972e-08,0.156886,0.000754083,1.04069e-06,7.59288e-09,0.157641,0.000756187,1.06347e-06,-3.37305e-09,0.158398,0.000758304,1.05335e-06,5.89921e-09,0.159158,0.000760428,1.07104e-06,-5.32248e-09,0.159919,0.000762554,1.05508e-06,4.8927e-10,0.160683,0.000764666,1.05654e-06,3.36547e-09,0.161448,0.000766789,1.06664e-06,9.50081e-10,0.162216,0.000768925,1.06949e-06,-7.16568e-09,0.162986,0.000771043,1.04799e-06,1.28114e-08,0.163758,0.000773177,1.08643e-06,-1.42774e-08,0.164533,0.000775307,1.0436e-06,1.44956e-08,0.165309,0.000777438,1.08708e-06,-1.39025e-08,0.166087,0.00077957,1.04538e-06,1.13118e-08,0.166868,0.000781695,1.07931e-06,-1.54224e-09,0.167651,0.000783849,1.07468e-06,-5.14312e-09,0.168436,0.000785983,1.05925e-06,7.21381e-09,0.169223,0.000788123,1.0809e-06,-8.81096e-09,0.170012,0.000790259,1.05446e-06,1.31289e-08,0.170803,0.000792407,1.09385e-06,-1.39022e-08,0.171597,0.000794553,1.05214e-06,1.26775e-08,0.172392,0.000796695,1.09018e-06,-7.00557e-09,0.17319,0.000798855,1.06916e-06,4.43796e-10,0.17399,0.000800994,1.07049e-06,5.23031e-09,0.174792,0.000803151,1.08618e-06,-6.46397e-09,0.175596,0.000805304,1.06679e-06,5.72444e-09,0.176403,0.000807455,1.08396e-06,-1.53254e-09,0.177211,0.000809618,1.07937e-06,4.05673e-10,0.178022,0.000811778,1.08058e-06,-9.01916e-11,0.178835,0.000813939,1.08031e-06,-4.49821e-11,0.17965,0.000816099,1.08018e-06,2.70234e-10,0.180467,0.00081826,1.08099e-06,-1.03603e-09,0.181286,0.000820419,1.07788e-06,3.87392e-09,0.182108,0.000822587,1.0895e-06,4.41522e-10,0.182932,0.000824767,1.09083e-06,-5.63997e-09,0.183758,0.000826932,1.07391e-06,7.21707e-09,0.184586,0.000829101,1.09556e-06,-8.32718e-09,0.185416,0.000831267,1.07058e-06,1.11907e-08,0.186248,0.000833442,1.10415e-06,-6.63336e-09,0.187083,0.00083563,1.08425e-06,4.41484e-10,0.187919,0.0008378,1.08557e-06,4.86754e-09,0.188758,0.000839986,1.10017e-06,-5.01041e-09,0.189599,0.000842171,1.08514e-06,2.72811e-10,0.190443,0.000844342,1.08596e-06,3.91916e-09,0.191288,0.000846526,1.09772e-06,-1.04819e-09,0.192136,0.000848718,1.09457e-06,2.73531e-10,0.192985,0.000850908,1.0954e-06,-4.58916e-11,0.193837,0.000853099,1.09526e-06,-9.01158e-11,0.194692,0.000855289,1.09499e-06,4.06506e-10,0.195548,0.00085748,1.09621e-06,-1.53595e-09,0.196407,0.000859668,1.0916e-06,5.73717e-09,0.197267,0.000861869,1.10881e-06,-6.51164e-09,0.19813,0.000864067,1.08928e-06,5.40831e-09,0.198995,0.000866261,1.1055e-06,-2.20401e-10,0.199863,0.000868472,1.10484e-06,-4.52652e-09,0.200732,0.000870668,1.09126e-06,3.42508e-09,0.201604,0.000872861,1.10153e-06,5.72762e-09,0.202478,0.000875081,1.11872e-06,-1.14344e-08,0.203354,0.000877284,1.08441e-06,1.02076e-08,0.204233,0.000879484,1.11504e-06,4.06355e-10,0.205113,0.000881715,1.11626e-06,-1.18329e-08,0.205996,0.000883912,1.08076e-06,1.71227e-08,0.206881,0.000886125,1.13213e-06,-1.19546e-08,0.207768,0.000888353,1.09626e-06,8.93465e-10,0.208658,0.000890548,1.09894e-06,8.38062e-09,0.209549,0.000892771,1.12408e-06,-4.61353e-09,0.210443,0.000895006,1.11024e-06,-4.82756e-09,0.211339,0.000897212,1.09576e-06,9.02245e-09,0.212238,0.00089943,1.12283e-06,-1.45997e-09,0.213138,0.000901672,1.11845e-06,-3.18255e-09,0.214041,0.000903899,1.1089e-06,-7.11073e-10,0.214946,0.000906115,1.10677e-06,6.02692e-09,0.215853,0.000908346,1.12485e-06,-8.49548e-09,0.216763,0.00091057,1.09936e-06,1.30537e-08,0.217675,0.000912808,1.13852e-06,-1.3917e-08,0.218588,0.000915044,1.09677e-06,1.28121e-08,0.219505,0.000917276,1.13521e-06,-7.5288e-09,0.220423,0.000919523,1.11262e-06,2.40205e-09,0.221344,0.000921756,1.11983e-06,-2.07941e-09,0.222267,0.000923989,1.11359e-06,5.91551e-09,0.223192,0.000926234,1.13134e-06,-6.68149e-09,0.224119,0.000928477,1.11129e-06,5.90929e-09,0.225049,0.000930717,1.12902e-06,-2.05436e-09,0.22598,0.000932969,1.12286e-06,2.30807e-09,0.226915,0.000935222,1.12978e-06,-7.17796e-09,0.227851,0.00093746,1.10825e-06,1.15028e-08,0.228789,0.000939711,1.14276e-06,-9.03083e-09,0.22973,0.000941969,1.11566e-06,9.71932e-09,0.230673,0.00094423,1.14482e-06,-1.49452e-08,0.231619,0.000946474,1.09998e-06,2.02591e-08,0.232566,0.000948735,1.16076e-06,-2.13879e-08,0.233516,0.000950993,1.0966e-06,2.05888e-08,0.234468,0.000953247,1.15837e-06,-1.62642e-08,0.235423,0.000955515,1.10957e-06,1.46658e-08,0.236379,0.000957779,1.15357e-06,-1.25966e-08,0.237338,0.000960048,1.11578e-06,5.91793e-09,0.238299,0.000962297,1.13353e-06,3.82602e-09,0.239263,0.000964576,1.14501e-06,-6.3208e-09,0.240229,0.000966847,1.12605e-06,6.55613e-09,0.241197,0.000969119,1.14572e-06,-5.00268e-09,0.242167,0.000971395,1.13071e-06,-1.44659e-09,0.243139,0.000973652,1.12637e-06,1.07891e-08,0.244114,0.000975937,1.15874e-06,-1.19073e-08,0.245091,0.000978219,1.12302e-06,7.03782e-09,0.246071,0.000980486,1.14413e-06,-1.34276e-09,0.247052,0.00098277,1.1401e-06,-1.66669e-09,0.248036,0.000985046,1.1351e-06,8.00935e-09,0.249022,0.00098734,1.15913e-06,-1.54694e-08,0.250011,0.000989612,1.11272e-06,2.4066e-08,0.251002,0.000991909,1.18492e-06,-2.11901e-08,0.251995,0.000994215,1.12135e-06,1.08973e-09,0.25299,0.000996461,1.12462e-06,1.68311e-08,0.253988,0.000998761,1.17511e-06,-8.8094e-09,0.254987,0.00100109,1.14868e-06,-1.13958e-08,0.25599,0.00100335,1.1145e-06,2.45902e-08,0.256994,0.00100565,1.18827e-06,-2.73603e-08,0.258001,0.00100795,1.10618e-06,2.52464e-08,0.25901,0.00101023,1.18192e-06,-1.40207e-08,0.260021,0.00101256,1.13986e-06,1.03387e-09,0.261035,0.00101484,1.14296e-06,9.8853e-09,0.262051,0.00101715,1.17262e-06,-1.07726e-08,0.263069,0.00101947,1.1403e-06,3.40272e-09,0.26409,0.00102176,1.15051e-06,-2.83827e-09,0.265113,0.00102405,1.142e-06,7.95039e-09,0.266138,0.00102636,1.16585e-06,8.39047e-10,0.267166,0.00102869,1.16836e-06,-1.13066e-08,0.268196,0.00103099,1.13444e-06,1.4585e-08,0.269228,0.00103331,1.1782e-06,-1.72314e-08,0.270262,0.00103561,1.1265e-06,2.45382e-08,0.271299,0.00103794,1.20012e-06,-2.13166e-08,0.272338,0.00104028,1.13617e-06,1.12364e-09,0.273379,0.00104255,1.13954e-06,1.68221e-08,0.274423,0.00104488,1.19001e-06,-8.80736e-09,0.275469,0.00104723,1.16358e-06,-1.13948e-08,0.276518,0.00104953,1.1294e-06,2.45839e-08,0.277568,0.00105186,1.20315e-06,-2.73361e-08,0.278621,0.00105418,1.12114e-06,2.51559e-08,0.279677,0.0010565,1.19661e-06,-1.36832e-08,0.280734,0.00105885,1.15556e-06,-2.25706e-10,0.281794,0.00106116,1.15488e-06,1.45862e-08,0.282857,0.00106352,1.19864e-06,-2.83167e-08,0.283921,0.00106583,1.11369e-06,3.90759e-08,0.284988,0.00106817,1.23092e-06,-3.85801e-08,0.286058,0.00107052,1.11518e-06,2.58375e-08,0.287129,0.00107283,1.19269e-06,-5.16498e-09,0.288203,0.0010752,1.1772e-06,-5.17768e-09,0.28928,0.00107754,1.16167e-06,-3.92671e-09,0.290358,0.00107985,1.14988e-06,2.08846e-08,0.29144,0.00108221,1.21254e-06,-2.00072e-08,0.292523,0.00108458,1.15252e-06,-4.60659e-10,0.293609,0.00108688,1.15114e-06,2.18499e-08,0.294697,0.00108925,1.21669e-06,-2.73343e-08,0.295787,0.0010916,1.13468e-06,2.78826e-08,0.29688,0.00109395,1.21833e-06,-2.45915e-08,0.297975,0.00109632,1.14456e-06,1.08787e-08,0.299073,0.00109864,1.17719e-06,1.08788e-08,0.300172,0.00110102,1.20983e-06,-2.45915e-08,0.301275,0.00110337,1.13605e-06,2.78828e-08,0.302379,0.00110573,1.2197e-06,-2.73348e-08,0.303486,0.00110808,1.1377e-06,2.18518e-08,0.304595,0.00111042,1.20325e-06,-4.67556e-10,0.305707,0.00111283,1.20185e-06,-1.99816e-08,0.306821,0.00111517,1.14191e-06,2.07891e-08,0.307937,0.00111752,1.20427e-06,-3.57026e-09,0.309056,0.00111992,1.19356e-06,-6.50797e-09,0.310177,0.00112228,1.17404e-06,-2.00165e-10,0.3113,0.00112463,1.17344e-06,7.30874e-09,0.312426,0.001127,1.19536e-06,7.67424e-10,0.313554,0.00112939,1.19767e-06,-1.03784e-08,0.314685,0.00113176,1.16653e-06,1.09437e-08,0.315818,0.00113412,1.19936e-06,-3.59406e-09,0.316953,0.00113651,1.18858e-06,3.43251e-09,0.318091,0.0011389,1.19888e-06,-1.0136e-08,0.319231,0.00114127,1.16847e-06,7.30915e-09,0.320374,0.00114363,1.1904e-06,1.07018e-08,0.321518,0.00114604,1.2225e-06,-2.03137e-08,0.322666,0.00114842,1.16156e-06,1.09484e-08,0.323815,0.00115078,1.19441e-06,6.32224e-09,0.324967,0.00115319,1.21337e-06,-6.43509e-09,0.326122,0.00115559,1.19407e-06,-1.03842e-08,0.327278,0.00115795,1.16291e-06,1.81697e-08,0.328438,0.00116033,1.21742e-06,-2.6901e-09,0.329599,0.00116276,1.20935e-06,-7.40939e-09,0.330763,0.00116515,1.18713e-06,2.52533e-09,0.331929,0.00116754,1.1947e-06,-2.69191e-09,0.333098,0.00116992,1.18663e-06,8.24218e-09,0.334269,0.00117232,1.21135e-06,-4.74377e-10,0.335443,0.00117474,1.20993e-06,-6.34471e-09,0.336619,0.00117714,1.1909e-06,-3.94922e-09,0.337797,0.00117951,1.17905e-06,2.21417e-08,0.338978,0.00118193,1.24547e-06,-2.50128e-08,0.340161,0.00118435,1.17043e-06,1.8305e-08,0.341346,0.00118674,1.22535e-06,-1.84048e-08,0.342534,0.00118914,1.17013e-06,2.55121e-08,0.343725,0.00119156,1.24667e-06,-2.40389e-08,0.344917,0.00119398,1.17455e-06,1.10389e-08,0.346113,0.00119636,1.20767e-06,9.68574e-09,0.34731,0.0011988,1.23673e-06,-1.99797e-08,0.34851,0.00120122,1.17679e-06,1.06284e-08,0.349713,0.0012036,1.20867e-06,7.26868e-09,0.350917,0.00120604,1.23048e-06,-9.90072e-09,0.352125,0.00120847,1.20078e-06,2.53177e-09,0.353334,0.00121088,1.20837e-06,-2.26199e-10,0.354546,0.0012133,1.20769e-06,-1.62705e-09,0.355761,0.00121571,1.20281e-06,6.73435e-09,0.356978,0.00121813,1.22302e-06,4.49207e-09,0.358197,0.00122059,1.23649e-06,-2.47027e-08,0.359419,0.00122299,1.16238e-06,3.47142e-08,0.360643,0.00122542,1.26653e-06,-2.47472e-08,0.36187,0.00122788,1.19229e-06,4.66965e-09,0.363099,0.00123028,1.20629e-06,6.06872e-09,0.36433,0.00123271,1.2245e-06,8.57729e-10,0.365564,0.00123516,1.22707e-06,-9.49952e-09,0.366801,0.00123759,1.19858e-06,7.33792e-09,0.36804,0.00124001,1.22059e-06,9.95025e-09,0.369281,0.00124248,1.25044e-06,-1.73366e-08,0.370525,0.00124493,1.19843e-06,-2.08464e-10,0.371771,0.00124732,1.1978e-06,1.81704e-08,0.373019,0.00124977,1.25232e-06,-1.28683e-08,0.37427,0.00125224,1.21371e-06,3.50042e-09,0.375524,0.00125468,1.22421e-06,-1.1335e-09,0.37678,0.00125712,1.22081e-06,1.03345e-09,0.378038,0.00125957,1.22391e-06,-3.00023e-09,0.379299,0.00126201,1.21491e-06,1.09676e-08,0.380562,0.00126447,1.24781e-06,-1.10676e-08,0.381828,0.00126693,1.21461e-06,3.50042e-09,0.383096,0.00126937,1.22511e-06,-2.93403e-09,0.384366,0.00127181,1.21631e-06,8.23574e-09,0.385639,0.00127427,1.24102e-06,-2.06607e-10,0.386915,0.00127675,1.2404e-06,-7.40935e-09,0.388193,0.00127921,1.21817e-06,4.1761e-11,0.389473,0.00128165,1.21829e-06,7.24223e-09,0.390756,0.0012841,1.24002e-06,7.91564e-10,0.392042,0.00128659,1.2424e-06,-1.04086e-08,0.393329,0.00128904,1.21117e-06,1.10405e-08,0.39462,0.0012915,1.24429e-06,-3.951e-09,0.395912,0.00129397,1.23244e-06,4.7634e-09,0.397208,0.00129645,1.24673e-06,-1.51025e-08,0.398505,0.0012989,1.20142e-06,2.58443e-08,0.399805,0.00130138,1.27895e-06,-2.86702e-08,0.401108,0.00130385,1.19294e-06,2.92318e-08,0.402413,0.00130632,1.28064e-06,-2.86524e-08,0.403721,0.0013088,1.19468e-06,2.57731e-08,0.405031,0.00131127,1.272e-06,-1.48355e-08,0.406343,0.00131377,1.2275e-06,3.76652e-09,0.407658,0.00131623,1.23879e-06,-2.30784e-10,0.408976,0.00131871,1.2381e-06,-2.84331e-09,0.410296,0.00132118,1.22957e-06,1.16041e-08,0.411618,0.00132367,1.26438e-06,-1.37708e-08,0.412943,0.00132616,1.22307e-06,1.36768e-08,0.41427,0.00132865,1.2641e-06,-1.1134e-08,0.4156,0.00133114,1.2307e-06,1.05714e-09,0.416933,0.00133361,1.23387e-06,6.90538e-09,0.418267,0.00133609,1.25459e-06,1.12372e-09,0.419605,0.00133861,1.25796e-06,-1.14002e-08,0.420945,0.00134109,1.22376e-06,1.46747e-08,0.422287,0.00134358,1.26778e-06,-1.7496e-08,0.423632,0.00134606,1.21529e-06,2.5507e-08,0.424979,0.00134857,1.29182e-06,-2.49272e-08,0.426329,0.00135108,1.21703e-06,1.45972e-08,0.427681,0.00135356,1.26083e-06,-3.65935e-09,0.429036,0.00135607,1.24985e-06,4.00178e-11,0.430393,0.00135857,1.24997e-06,3.49917e-09,0.431753,0.00136108,1.26047e-06,-1.40366e-08,0.433116,0.00136356,1.21836e-06,2.28448e-08,0.43448,0.00136606,1.28689e-06,-1.77378e-08,0.435848,0.00136858,1.23368e-06,1.83043e-08,0.437218,0.0013711,1.28859e-06,-2.56769e-08,0.43859,0.0013736,1.21156e-06,2.47987e-08,0.439965,0.0013761,1.28595e-06,-1.39133e-08,0.441342,0.00137863,1.24421e-06,1.05202e-09,0.442722,0.00138112,1.24737e-06,9.70507e-09,0.444104,0.00138365,1.27649e-06,-1.00698e-08,0.445489,0.00138617,1.24628e-06,7.72123e-10,0.446877,0.00138867,1.24859e-06,6.98132e-09,0.448267,0.00139118,1.26954e-06,1.10477e-09,0.449659,0.00139373,1.27285e-06,-1.14003e-08,0.451054,0.00139624,1.23865e-06,1.4694e-08,0.452452,0.00139876,1.28273e-06,-1.75734e-08,0.453852,0.00140127,1.23001e-06,2.5797e-08,0.455254,0.00140381,1.3074e-06,-2.60097e-08,0.456659,0.00140635,1.22937e-06,1.86371e-08,0.458067,0.00140886,1.28529e-06,-1.8736e-08,0.459477,0.00141137,1.22908e-06,2.65048e-08,0.46089,0.00141391,1.30859e-06,-2.76784e-08,0.462305,0.00141645,1.22556e-06,2.46043e-08,0.463722,0.00141897,1.29937e-06,-1.11341e-08,0.465143,0.00142154,1.26597e-06,-9.87033e-09,0.466565,0.00142404,1.23636e-06,2.08131e-08,0.467991,0.00142657,1.2988e-06,-1.37773e-08,0.469419,0.00142913,1.25746e-06,4.49378e-09,0.470849,0.00143166,1.27094e-06,-4.19781e-09,0.472282,0.00143419,1.25835e-06,1.22975e-08,0.473717,0.00143674,1.29524e-06,-1.51902e-08,0.475155,0.00143929,1.24967e-06,1.86608e-08,0.476596,0.00144184,1.30566e-06,-2.96506e-08,0.478039,0.00144436,1.2167e-06,4.03368e-08,0.479485,0.00144692,1.33771e-06,-4.22896e-08,0.480933,0.00144947,1.21085e-06,3.94148e-08,0.482384,0.00145201,1.32909e-06,-2.59626e-08,0.483837,0.00145459,1.2512e-06,4.83124e-09,0.485293,0.0014571,1.2657e-06,6.63757e-09,0.486751,0.00145966,1.28561e-06,-1.57911e-09,0.488212,0.00146222,1.28087e-06,-3.21468e-10,0.489676,0.00146478,1.27991e-06,2.86517e-09,0.491142,0.00146735,1.2885e-06,-1.11392e-08,0.49261,0.00146989,1.25508e-06,1.18893e-08,0.494081,0.00147244,1.29075e-06,-6.61574e-09,0.495555,0.001475,1.27091e-06,1.45736e-08,0.497031,0.00147759,1.31463e-06,-2.18759e-08,0.49851,0.00148015,1.249e-06,1.33252e-08,0.499992,0.00148269,1.28897e-06,-1.62277e-09,0.501476,0.00148526,1.28411e-06,-6.83421e-09,0.502962,0.00148781,1.2636e-06,2.89596e-08,0.504451,0.00149042,1.35048e-06,-4.93997e-08,0.505943,0.00149298,1.20228e-06,4.94299e-08,0.507437,0.00149553,1.35057e-06,-2.91107e-08,0.508934,0.00149814,1.26324e-06,7.40848e-09,0.510434,0.00150069,1.28547e-06,-5.23187e-10,0.511936,0.00150326,1.2839e-06,-5.31585e-09,0.51344,0.00150581,1.26795e-06,2.17866e-08,0.514947,0.00150841,1.33331e-06,-2.22257e-08,0.516457,0.00151101,1.26663e-06,7.51178e-09,0.517969,0.00151357,1.28917e-06,-7.82128e-09,0.519484,0.00151613,1.2657e-06,2.37733e-08,0.521002,0.00151873,1.33702e-06,-2.76674e-08,0.522522,0.00152132,1.25402e-06,2.72917e-08,0.524044,0.00152391,1.3359e-06,-2.18949e-08,0.525569,0.00152652,1.27021e-06,6.83372e-10,0.527097,0.00152906,1.27226e-06,1.91613e-08,0.528628,0.00153166,1.32974e-06,-1.77241e-08,0.53016,0.00153427,1.27657e-06,-7.86963e-09,0.531696,0.0015368,1.25296e-06,4.92027e-08,0.533234,0.00153945,1.40057e-06,-6.9732e-08,0.534775,0.00154204,1.19138e-06,5.09114e-08,0.536318,0.00154458,1.34411e-06,-1.4704e-08,0.537864,0.00154722,1.3e-06,7.9048e-09,0.539413,0.00154984,1.32371e-06,-1.69152e-08,0.540964,0.00155244,1.27297e-06,1.51355e-10,0.542517,0.00155499,1.27342e-06,1.63099e-08,0.544074,0.00155758,1.32235e-06,-5.78647e-09,0.545633,0.00156021,1.30499e-06,6.83599e-09,0.547194,0.00156284,1.3255e-06,-2.15575e-08,0.548758,0.00156543,1.26083e-06,1.97892e-08,0.550325,0.00156801,1.32019e-06,2.00525e-09,0.551894,0.00157065,1.32621e-06,-2.78103e-08,0.553466,0.00157322,1.24278e-06,4.96314e-08,0.555041,0.00157586,1.39167e-06,-5.1506e-08,0.556618,0.00157849,1.23716e-06,3.71835e-08,0.558198,0.00158107,1.34871e-06,-3.76233e-08,0.55978,0.00158366,1.23584e-06,5.37052e-08,0.561365,0.00158629,1.39695e-06,-5.79884e-08,0.562953,0.00158891,1.22299e-06,5.90392e-08,0.564543,0.00159153,1.4001e-06,-5.89592e-08,0.566136,0.00159416,1.22323e-06,5.7588e-08,0.567731,0.00159678,1.39599e-06,-5.21835e-08,0.569329,0.00159941,1.23944e-06,3.19369e-08,0.57093,0.00160199,1.33525e-06,-1.59594e-08,0.572533,0.00160461,1.28737e-06,3.19006e-08,0.574139,0.00160728,1.38307e-06,-5.20383e-08,0.575748,0.00160989,1.22696e-06,5.70431e-08,0.577359,0.00161251,1.39809e-06,-5.69247e-08,0.578973,0.00161514,1.22731e-06,5.14463e-08,0.580589,0.00161775,1.38165e-06,-2.9651e-08,0.582208,0.00162042,1.2927e-06,7.55339e-09,0.58383,0.00162303,1.31536e-06,-5.62636e-10,0.585455,0.00162566,1.31367e-06,-5.30281e-09,0.587081,0.00162827,1.29776e-06,2.17738e-08,0.588711,0.00163093,1.36309e-06,-2.21875e-08,0.590343,0.00163359,1.29652e-06,7.37164e-09,0.591978,0.00163621,1.31864e-06,-7.29907e-09,0.593616,0.00163882,1.29674e-06,2.18247e-08,0.595256,0.00164148,1.36221e-06,-2.03952e-08,0.596899,0.00164414,1.30103e-06,1.51241e-10,0.598544,0.00164675,1.30148e-06,1.97902e-08,0.600192,0.00164941,1.36085e-06,-1.97074e-08,0.601843,0.00165207,1.30173e-06,-5.65175e-10,0.603496,0.00165467,1.30004e-06,2.1968e-08,0.605152,0.00165734,1.36594e-06,-2.77024e-08,0.606811,0.00165999,1.28283e-06,2.92369e-08,0.608472,0.00166264,1.37054e-06,-2.96407e-08,0.610136,0.00166529,1.28162e-06,2.97215e-08,0.611803,0.00166795,1.37079e-06,-2.96408e-08,0.613472,0.0016706,1.28186e-06,2.92371e-08,0.615144,0.00167325,1.36957e-06,-2.77031e-08,0.616819,0.00167591,1.28647e-06,2.19708e-08,0.618496,0.00167855,1.35238e-06,-5.75407e-10,0.620176,0.00168125,1.35065e-06,-1.9669e-08,0.621858,0.00168389,1.29164e-06,1.96468e-08,0.623544,0.00168653,1.35058e-06,6.86403e-10,0.625232,0.00168924,1.35264e-06,-2.23924e-08,0.626922,0.00169187,1.28547e-06,2.92788e-08,0.628615,0.00169453,1.3733e-06,-3.51181e-08,0.630311,0.00169717,1.26795e-06,5.15889e-08,0.63201,0.00169987,1.42272e-06,-5.2028e-08,0.633711,0.00170255,1.26663e-06,3.73139e-08,0.635415,0.0017052,1.37857e-06,-3.76227e-08,0.637121,0.00170784,1.2657e-06,5.35722e-08,0.63883,0.00171054,1.42642e-06,-5.74567e-08,0.640542,0.00171322,1.25405e-06,5.70456e-08,0.642257,0.0017159,1.42519e-06,-5.15163e-08,0.643974,0.00171859,1.27064e-06,2.98103e-08,0.645694,0.00172122,1.36007e-06,-8.12016e-09,0.647417,0.00172392,1.33571e-06,2.67039e-09,0.649142,0.0017266,1.34372e-06,-2.56152e-09,0.65087,0.00172928,1.33604e-06,7.57571e-09,0.6526,0.00173197,1.35876e-06,-2.77413e-08,0.654334,0.00173461,1.27554e-06,4.3785e-08,0.65607,0.00173729,1.40689e-06,-2.81896e-08,0.657808,0.00174002,1.32233e-06,9.36893e-09,0.65955,0.00174269,1.35043e-06,-9.28617e-09,0.661294,0.00174536,1.32257e-06,2.77757e-08,0.66304,0.00174809,1.4059e-06,-4.2212e-08,0.66479,0.00175078,1.27926e-06,2.1863e-08,0.666542,0.0017534,1.34485e-06,1.43648e-08,0.668297,0.00175613,1.38795e-06,-1.97177e-08,0.670054,0.00175885,1.3288e-06,4.90115e-09,0.671814,0.00176152,1.3435e-06,1.13232e-10,0.673577,0.00176421,1.34384e-06,-5.3542e-09,0.675343,0.00176688,1.32778e-06,2.13035e-08,0.677111,0.0017696,1.39169e-06,-2.02553e-08,0.678882,0.00177232,1.33092e-06,1.13005e-10,0.680656,0.00177499,1.33126e-06,1.98031e-08,0.682432,0.00177771,1.39067e-06,-1.97211e-08,0.684211,0.00178043,1.33151e-06,-5.2349e-10,0.685993,0.00178309,1.32994e-06,2.18151e-08,0.687777,0.00178582,1.39538e-06,-2.71325e-08,0.689564,0.00178853,1.31398e-06,2.71101e-08,0.691354,0.00179124,1.39531e-06,-2.17035e-08,0.693147,0.00179396,1.3302e-06,9.92865e-11,0.694942,0.00179662,1.3305e-06,2.13063e-08,0.69674,0.00179935,1.39442e-06,-2.57198e-08,0.698541,0.00180206,1.31726e-06,2.19682e-08,0.700344,0.00180476,1.38317e-06,-2.54852e-09,0.70215,0.00180752,1.37552e-06,-1.17741e-08,0.703959,0.00181023,1.3402e-06,-9.95999e-09,0.705771,0.00181288,1.31032e-06,5.16141e-08,0.707585,0.00181566,1.46516e-06,-7.72869e-08,0.709402,0.00181836,1.2333e-06,7.87197e-08,0.711222,0.00182106,1.46946e-06,-5.87781e-08,0.713044,0.00182382,1.29312e-06,3.71834e-08,0.714869,0.00182652,1.40467e-06,-3.03511e-08,0.716697,0.00182924,1.31362e-06,2.46161e-08,0.718528,0.00183194,1.38747e-06,-8.5087e-09,0.720361,0.00183469,1.36194e-06,9.41892e-09,0.722197,0.00183744,1.3902e-06,-2.91671e-08,0.724036,0.00184014,1.3027e-06,4.76448e-08,0.725878,0.00184288,1.44563e-06,-4.22028e-08,0.727722,0.00184565,1.31902e-06,1.95682e-09,0.729569,0.00184829,1.3249e-06,3.43754e-08,0.731419,0.00185104,1.42802e-06,-2.0249e-08,0.733271,0.00185384,1.36727e-06,-1.29838e-08,0.735126,0.00185654,1.32832e-06,1.25794e-08,0.736984,0.00185923,1.36606e-06,2.22711e-08,0.738845,0.00186203,1.43287e-06,-4.20594e-08,0.740708,0.00186477,1.3067e-06,2.67571e-08,0.742574,0.00186746,1.38697e-06,-5.36424e-09,0.744443,0.00187022,1.37087e-06,-5.30023e-09,0.746315,0.00187295,1.35497e-06,2.65653e-08,0.748189,0.00187574,1.43467e-06,-4.13564e-08,0.750066,0.00187848,1.3106e-06,1.9651e-08,0.751946,0.00188116,1.36955e-06,2.23572e-08,0.753828,0.00188397,1.43663e-06,-4.9475e-08,0.755714,0.00188669,1.2882e-06,5.63335e-08,0.757602,0.00188944,1.4572e-06,-5.66499e-08,0.759493,0.00189218,1.28725e-06,5.10567e-08,0.761386,0.00189491,1.44042e-06,-2.83677e-08,0.763283,0.00189771,1.35532e-06,2.80962e-09,0.765182,0.00190042,1.36375e-06,1.71293e-08,0.767083,0.0019032,1.41513e-06,-1.17221e-08,0.768988,0.001906,1.37997e-06,-2.98453e-08,0.770895,0.00190867,1.29043e-06,7.14987e-08,0.772805,0.00191146,1.50493e-06,-7.73354e-08,0.774718,0.00191424,1.27292e-06,5.90292e-08,0.776634,0.00191697,1.45001e-06,-3.9572e-08,0.778552,0.00191975,1.33129e-06,3.9654e-08,0.780473,0.00192253,1.45026e-06,-5.94395e-08,0.782397,0.00192525,1.27194e-06,7.88945e-08,0.784324,0.00192803,1.50862e-06,-7.73249e-08,0.786253,0.00193082,1.27665e-06,5.15913e-08,0.788185,0.00193352,1.43142e-06,-9.83099e-09,0.79012,0.00193636,1.40193e-06,-1.22672e-08,0.792058,0.00193912,1.36513e-06,-7.05275e-10,0.793999,0.00194185,1.36301e-06,1.50883e-08,0.795942,0.00194462,1.40828e-06,-4.33147e-11,0.797888,0.00194744,1.40815e-06,-1.49151e-08,0.799837,0.00195021,1.3634e-06,9.93244e-11,0.801788,0.00195294,1.3637e-06,1.45179e-08,0.803743,0.00195571,1.40725e-06,1.43363e-09,0.8057,0.00195853,1.41155e-06,-2.02525e-08,0.80766,0.00196129,1.35079e-06,1.99718e-08,0.809622,0.00196405,1.41071e-06,-3.01649e-11,0.811588,0.00196687,1.41062e-06,-1.9851e-08,0.813556,0.00196964,1.35107e-06,1.98296e-08,0.815527,0.0019724,1.41056e-06,1.37485e-10,0.817501,0.00197522,1.41097e-06,-2.03796e-08,0.819477,0.00197798,1.34983e-06,2.17763e-08,0.821457,0.00198074,1.41516e-06,-7.12085e-09,0.823439,0.00198355,1.3938e-06,6.70707e-09,0.825424,0.00198636,1.41392e-06,-1.97074e-08,0.827412,0.00198913,1.35479e-06,1.25179e-08,0.829402,0.00199188,1.39235e-06,2.92405e-08,0.831396,0.00199475,1.48007e-06,-6.98755e-08,0.833392,0.0019975,1.27044e-06,7.14477e-08,0.835391,0.00200026,1.48479e-06,-3.71014e-08,0.837392,0.00200311,1.37348e-06,1.73533e-08,0.839397,0.00200591,1.42554e-06,-3.23118e-08,0.841404,0.00200867,1.32861e-06,5.2289e-08,0.843414,0.00201148,1.48547e-06,-5.76348e-08,0.845427,0.00201428,1.31257e-06,5.9041e-08,0.847443,0.00201708,1.48969e-06,-5.93197e-08,0.849461,0.00201988,1.31173e-06,5.90289e-08,0.851482,0.00202268,1.48882e-06,-5.75864e-08,0.853507,0.00202549,1.31606e-06,5.21075e-08,0.855533,0.00202828,1.47238e-06,-3.16344e-08,0.857563,0.00203113,1.37748e-06,1.48257e-08,0.859596,0.00203393,1.42196e-06,-2.76684e-08,0.861631,0.00203669,1.33895e-06,3.62433e-08,0.863669,0.00203947,1.44768e-06,1.90463e-09,0.86571,0.00204237,1.45339e-06,-4.38617e-08,0.867754,0.00204515,1.32181e-06,5.43328e-08,0.8698,0.00204796,1.48481e-06,-5.42603e-08,0.87185,0.00205076,1.32203e-06,4.34989e-08,0.873902,0.00205354,1.45252e-06,-5.26029e-10,0.875957,0.00205644,1.45095e-06,-4.13949e-08,0.878015,0.00205922,1.32676e-06,4.68962e-08,0.880075,0.00206201,1.46745e-06,-2.69807e-08,0.882139,0.00206487,1.38651e-06,1.42181e-09,0.884205,0.00206764,1.39077e-06,2.12935e-08,0.886274,0.00207049,1.45465e-06,-2.69912e-08,0.888346,0.00207332,1.37368e-06,2.70664e-08,0.890421,0.00207615,1.45488e-06,-2.16698e-08,0.892498,0.00207899,1.38987e-06,8.14756e-12,0.894579,0.00208177,1.38989e-06,2.16371e-08,0.896662,0.00208462,1.45481e-06,-2.6952e-08,0.898748,0.00208744,1.37395e-06,2.65663e-08,0.900837,0.00209027,1.45365e-06,-1.97084e-08,0.902928,0.00209312,1.39452e-06,-7.33731e-09,0.905023,0.00209589,1.37251e-06,4.90578e-08,0.90712,0.00209878,1.51968e-06,-6.96845e-08,0.90922,0.00210161,1.31063e-06,5.08664e-08,0.911323,0.00210438,1.46323e-06,-1.45717e-08,0.913429,0.00210727,1.41952e-06,7.42038e-09,0.915538,0.00211013,1.44178e-06,-1.51097e-08,0.917649,0.00211297,1.39645e-06,-6.58618e-09,0.919764,0.00211574,1.37669e-06,4.14545e-08,0.921881,0.00211862,1.50105e-06,-4.00222e-08,0.924001,0.0021215,1.38099e-06,-5.7518e-10,0.926124,0.00212426,1.37926e-06,4.23229e-08,0.92825,0.00212714,1.50623e-06,-4.9507e-08,0.930378,0.00213001,1.35771e-06,3.64958e-08,0.93251,0.00213283,1.4672e-06,-3.68713e-08,0.934644,0.00213566,1.35658e-06,5.13848e-08,0.936781,0.00213852,1.51074e-06,-4.94585e-08,0.938921,0.0021414,1.36236e-06,2.72399e-08,0.941064,0.0021442,1.44408e-06,1.0372e-10,0.943209,0.00214709,1.44439e-06,-2.76547e-08,0.945358,0.0021499,1.36143e-06,5.09106e-08,0.947509,0.00215277,1.51416e-06,-5.67784e-08,0.949663,0.00215563,1.34382e-06,5.69935e-08,0.95182,0.00215849,1.5148e-06,-5.19861e-08,0.95398,0.00216136,1.35885e-06,3.17417e-08,0.956143,0.00216418,1.45407e-06,-1.53758e-08,0.958309,0.00216704,1.40794e-06,2.97615e-08,0.960477,0.00216994,1.49723e-06,-4.40657e-08,0.962649,0.00217281,1.36503e-06,2.72919e-08,0.964823,0.00217562,1.44691e-06,-5.49729e-09,0.967,0.0021785,1.43041e-06,-5.30273e-09,0.96918,0.00218134,1.41451e-06,2.67084e-08,0.971363,0.00218425,1.49463e-06,-4.19265e-08,0.973548,0.00218711,1.36885e-06,2.17881e-08,0.975737,0.00218992,1.43422e-06,1.43789e-08,0.977928,0.00219283,1.47735e-06,-1.96989e-08,0.980122,0.00219572,1.41826e-06,4.81221e-09,0.98232,0.00219857,1.43269e-06,4.50048e-10,0.98452,0.00220144,1.43404e-06,-6.61237e-09,0.986722,0.00220429,1.41421e-06,2.59993e-08,0.988928,0.0022072,1.4922e-06,-3.77803e-08,0.991137,0.00221007,1.37886e-06,5.9127e-09,0.993348,0.00221284,1.3966e-06,1.33339e-07,0.995563,0.00221604,1.79662e-06,-5.98872e-07,0.99778,0.00222015,0.,0.}; + + template + __device__ __forceinline__ void RGB2LabConvert_f(const T& src, D& dst) + { + const float _1_3 = 1.0f / 3.0f; + const float _a = 16.0f / 116.0f; + + float B = blueIdx == 0 ? src.x : src.z; + float G = src.y; + float R = blueIdx == 0 ? src.z : src.x; + + if (srgb) + { + B = splineInterpolate(B * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + } + + float X = B * 0.189828f + G * 0.376219f + R * 0.433953f; + float Y = B * 0.072169f + G * 0.715160f + R * 0.212671f; + float Z = B * 0.872766f + G * 0.109477f + R * 0.017758f; + + float FX = X > 0.008856f ? ::powf(X, _1_3) : (7.787f * X + _a); + float FY = Y > 0.008856f ? ::powf(Y, _1_3) : (7.787f * Y + _a); + float FZ = Z > 0.008856f ? ::powf(Z, _1_3) : (7.787f * Z + _a); + + float L = Y > 0.008856f ? (116.f * FY - 16.f) : (903.3f * Y); + float a = 500.f * (FX - FY); + float b = 200.f * (FY - FZ); + + dst.x = L; + dst.y = a; + dst.z = b; + } + + template struct RGB2Lab; + template + struct RGB2Lab + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + RGB2LabConvert_b(src, dst); + + return dst; + } + __host__ __device__ __forceinline__ RGB2Lab() {} + __host__ __device__ __forceinline__ RGB2Lab(const RGB2Lab&) {} + }; + template + struct RGB2Lab + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + RGB2LabConvert_f(src, dst); + + return dst; + } + __host__ __device__ __forceinline__ RGB2Lab() {} + __host__ __device__ __forceinline__ RGB2Lab(const RGB2Lab&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2Lab_TRAITS(name, scn, dcn, srgb, blueIdx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2Lab functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + __constant__ float c_sRGBInvGammaTab[] = {0,0.0126255,0.,-8.33961e-06,0.0126172,0.0126005,-2.50188e-05,4.1698e-05,0.0252344,0.0126756,0.000100075,-0.000158451,0.0378516,0.0124004,-0.000375277,-0.000207393,0.0496693,0.0110276,-0.000997456,0.00016837,0.0598678,0.00953783,-0.000492346,2.07235e-05,0.068934,0.00861531,-0.000430176,3.62876e-05,0.0771554,0.00786382,-0.000321313,1.87625e-05,0.0847167,0.00727748,-0.000265025,1.53594e-05,0.0917445,0.00679351,-0.000218947,1.10545e-05,0.0983301,0.00638877,-0.000185784,8.66984e-06,0.104542,0.00604322,-0.000159774,6.82996e-06,0.110432,0.00574416,-0.000139284,5.51008e-06,0.116042,0.00548212,-0.000122754,4.52322e-06,0.121406,0.00525018,-0.000109184,3.75557e-06,0.126551,0.00504308,-9.79177e-05,3.17134e-06,0.131499,0.00485676,-8.84037e-05,2.68469e-06,0.13627,0.004688,-8.03496e-05,2.31725e-06,0.14088,0.00453426,-7.33978e-05,2.00868e-06,0.145343,0.00439349,-6.73718e-05,1.74775e-06,0.149671,0.00426399,-6.21286e-05,1.53547e-06,0.153875,0.00414434,-5.75222e-05,1.364e-06,0.157963,0.00403338,-5.34301e-05,1.20416e-06,0.161944,0.00393014,-4.98177e-05,1.09114e-06,0.165825,0.00383377,-4.65443e-05,9.57987e-07,0.169613,0.00374356,-4.36703e-05,8.88359e-07,0.173314,0.00365888,-4.10052e-05,7.7849e-07,0.176933,0.00357921,-3.86697e-05,7.36254e-07,0.180474,0.00350408,-3.6461e-05,6.42534e-07,0.183942,0.00343308,-3.45334e-05,6.12614e-07,0.187342,0.00336586,-3.26955e-05,5.42894e-07,0.190675,0.00330209,-3.10669e-05,5.08967e-07,0.193947,0.00324149,-2.954e-05,4.75977e-07,0.197159,0.00318383,-2.8112e-05,4.18343e-07,0.200315,0.00312887,-2.6857e-05,4.13651e-07,0.203418,0.00307639,-2.5616e-05,3.70847e-07,0.206469,0.00302627,-2.45035e-05,3.3813e-07,0.209471,0.00297828,-2.34891e-05,3.32999e-07,0.212426,0.0029323,-2.24901e-05,2.96826e-07,0.215336,0.00288821,-2.15996e-05,2.82736e-07,0.218203,0.00284586,-2.07514e-05,2.70961e-07,0.221029,0.00280517,-1.99385e-05,2.42744e-07,0.223814,0.00276602,-1.92103e-05,2.33277e-07,0.226561,0.0027283,-1.85105e-05,2.2486e-07,0.229271,0.00269195,-1.78359e-05,2.08383e-07,0.231945,0.00265691,-1.72108e-05,1.93305e-07,0.234585,0.00262307,-1.66308e-05,1.80687e-07,0.237192,0.00259035,-1.60888e-05,1.86632e-07,0.239766,0.00255873,-1.55289e-05,1.60569e-07,0.24231,0.00252815,-1.50472e-05,1.54566e-07,0.244823,0.00249852,-1.45835e-05,1.59939e-07,0.247307,0.00246983,-1.41037e-05,1.29549e-07,0.249763,0.00244202,-1.3715e-05,1.41429e-07,0.252191,0.00241501,-1.32907e-05,1.39198e-07,0.254593,0.00238885,-1.28731e-05,1.06444e-07,0.256969,0.00236342,-1.25538e-05,1.2048e-07,0.25932,0.00233867,-1.21924e-05,1.26892e-07,0.261647,0.00231467,-1.18117e-05,8.72084e-08,0.26395,0.00229131,-1.15501e-05,1.20323e-07,0.26623,0.00226857,-1.11891e-05,8.71514e-08,0.268487,0.00224645,-1.09276e-05,9.73165e-08,0.270723,0.00222489,-1.06357e-05,8.98259e-08,0.272937,0.00220389,-1.03662e-05,7.98218e-08,0.275131,0.00218339,-1.01267e-05,9.75254e-08,0.277304,0.00216343,-9.83416e-06,6.65195e-08,0.279458,0.00214396,-9.63461e-06,8.34313e-08,0.281592,0.00212494,-9.38431e-06,7.65919e-08,0.283708,0.00210641,-9.15454e-06,5.7236e-08,0.285805,0.00208827,-8.98283e-06,8.18939e-08,0.287885,0.00207055,-8.73715e-06,6.2224e-08,0.289946,0.00205326,-8.55047e-06,5.66388e-08,0.291991,0.00203633,-8.38056e-06,6.88491e-08,0.294019,0.00201978,-8.17401e-06,5.53955e-08,0.296031,0.00200359,-8.00782e-06,6.71971e-08,0.298027,0.00198778,-7.80623e-06,3.34439e-08,0.300007,0.00197227,-7.7059e-06,6.7248e-08,0.301971,0.00195706,-7.50416e-06,5.51915e-08,0.303921,0.00194221,-7.33858e-06,3.98124e-08,0.305856,0.00192766,-7.21915e-06,5.37795e-08,0.307776,0.00191338,-7.05781e-06,4.30919e-08,0.309683,0.00189939,-6.92853e-06,4.20744e-08,0.311575,0.00188566,-6.80231e-06,5.68321e-08,0.313454,0.00187223,-6.63181e-06,2.86195e-08,0.31532,0.00185905,-6.54595e-06,3.73075e-08,0.317172,0.00184607,-6.43403e-06,6.05684e-08,0.319012,0.00183338,-6.25233e-06,1.84426e-08,0.320839,0.00182094,-6.197e-06,4.44757e-08,0.322654,0.00180867,-6.06357e-06,4.20729e-08,0.324456,0.00179667,-5.93735e-06,2.56511e-08,0.326247,0.00178488,-5.8604e-06,3.41368e-08,0.328026,0.00177326,-5.75799e-06,4.64177e-08,0.329794,0.00176188,-5.61874e-06,1.86107e-08,0.33155,0.0017507,-5.5629e-06,2.81511e-08,0.333295,0.00173966,-5.47845e-06,4.75987e-08,0.335029,0.00172884,-5.33565e-06,1.98726e-08,0.336753,0.00171823,-5.27604e-06,2.19226e-08,0.338466,0.00170775,-5.21027e-06,4.14483e-08,0.340169,0.00169745,-5.08592e-06,2.09017e-08,0.341861,0.00168734,-5.02322e-06,2.39561e-08,0.343543,0.00167737,-4.95135e-06,3.22852e-08,0.345216,0.00166756,-4.85449e-06,2.57173e-08,0.346878,0.00165793,-4.77734e-06,1.38569e-08,0.348532,0.00164841,-4.73577e-06,3.80634e-08,0.350175,0.00163906,-4.62158e-06,1.27043e-08,0.35181,0.00162985,-4.58347e-06,3.03279e-08,0.353435,0.00162078,-4.49249e-06,1.49961e-08,0.355051,0.00161184,-4.4475e-06,2.88977e-08,0.356659,0.00160303,-4.3608e-06,1.84241e-08,0.358257,0.00159436,-4.30553e-06,1.6616e-08,0.359848,0.0015858,-4.25568e-06,3.43218e-08,0.361429,0.00157739,-4.15272e-06,-4.89172e-09,0.363002,0.00156907,-4.16739e-06,4.48498e-08,0.364567,0.00156087,-4.03284e-06,4.30676e-09,0.366124,0.00155282,-4.01992e-06,2.73303e-08,0.367673,0.00154486,-3.93793e-06,5.58036e-09,0.369214,0.001537,-3.92119e-06,3.97554e-08,0.370747,0.00152928,-3.80193e-06,-1.55904e-08,0.372272,0.00152163,-3.8487e-06,5.24081e-08,0.37379,0.00151409,-3.69147e-06,-1.52272e-08,0.375301,0.00150666,-3.73715e-06,3.83028e-08,0.376804,0.0014993,-3.62225e-06,1.10278e-08,0.378299,0.00149209,-3.58916e-06,6.99326e-09,0.379788,0.00148493,-3.56818e-06,2.06038e-08,0.381269,0.00147786,-3.50637e-06,2.98009e-08,0.382744,0.00147093,-3.41697e-06,-2.05978e-08,0.384211,0.00146404,-3.47876e-06,5.25899e-08,0.385672,0.00145724,-3.32099e-06,-1.09471e-08,0.387126,0.00145056,-3.35383e-06,2.10009e-08,0.388573,0.00144392,-3.29083e-06,1.63501e-08,0.390014,0.00143739,-3.24178e-06,3.00641e-09,0.391448,0.00143091,-3.23276e-06,3.12282e-08,0.392875,0.00142454,-3.13908e-06,-8.70932e-09,0.394297,0.00141824,-3.16521e-06,3.34114e-08,0.395712,0.00141201,-3.06497e-06,-5.72754e-09,0.397121,0.00140586,-3.08215e-06,1.9301e-08,0.398524,0.00139975,-3.02425e-06,1.7931e-08,0.39992,0.00139376,-2.97046e-06,-1.61822e-09,0.401311,0.00138781,-2.97531e-06,1.83442e-08,0.402696,0.00138192,-2.92028e-06,1.76485e-08,0.404075,0.00137613,-2.86733e-06,4.68617e-10,0.405448,0.00137039,-2.86593e-06,1.02794e-08,0.406816,0.00136469,-2.83509e-06,1.80179e-08,0.408178,0.00135908,-2.78104e-06,7.05594e-09,0.409534,0.00135354,-2.75987e-06,1.33633e-08,0.410885,0.00134806,-2.71978e-06,-9.04568e-10,0.41223,0.00134261,-2.72249e-06,2.0057e-08,0.41357,0.00133723,-2.66232e-06,1.00841e-08,0.414905,0.00133194,-2.63207e-06,-7.88835e-10,0.416234,0.00132667,-2.63444e-06,2.28734e-08,0.417558,0.00132147,-2.56582e-06,-1.29785e-09,0.418877,0.00131633,-2.56971e-06,1.21205e-08,0.420191,0.00131123,-2.53335e-06,1.24202e-08,0.421499,0.0013062,-2.49609e-06,-2.19681e-09,0.422803,0.0013012,-2.50268e-06,2.61696e-08,0.424102,0.00129628,-2.42417e-06,-1.30747e-08,0.425396,0.00129139,-2.46339e-06,2.6129e-08,0.426685,0.00128654,-2.38501e-06,-2.03454e-09,0.427969,0.00128176,-2.39111e-06,1.18115e-08,0.429248,0.00127702,-2.35567e-06,1.43932e-08,0.430523,0.00127235,-2.31249e-06,-9.77965e-09,0.431793,0.00126769,-2.34183e-06,2.47253e-08,0.433058,0.00126308,-2.26766e-06,2.85278e-10,0.434319,0.00125855,-2.2668e-06,3.93614e-09,0.435575,0.00125403,-2.25499e-06,1.37722e-08,0.436827,0.00124956,-2.21368e-06,5.79803e-10,0.438074,0.00124513,-2.21194e-06,1.37112e-08,0.439317,0.00124075,-2.1708e-06,4.17973e-09,0.440556,0.00123642,-2.15826e-06,-6.27703e-10,0.44179,0.0012321,-2.16015e-06,2.81332e-08,0.44302,0.00122787,-2.07575e-06,-2.24985e-08,0.444246,0.00122365,-2.14324e-06,3.20586e-08,0.445467,0.00121946,-2.04707e-06,-1.6329e-08,0.446685,0.00121532,-2.09605e-06,3.32573e-08,0.447898,0.00121122,-1.99628e-06,-2.72927e-08,0.449107,0.00120715,-2.07816e-06,4.6111e-08,0.450312,0.00120313,-1.93983e-06,-3.79416e-08,0.451514,0.00119914,-2.05365e-06,4.60507e-08,0.452711,0.00119517,-1.9155e-06,-2.7052e-08,0.453904,0.00119126,-1.99666e-06,3.23551e-08,0.455093,0.00118736,-1.89959e-06,-1.29613e-08,0.456279,0.00118352,-1.93848e-06,1.94905e-08,0.45746,0.0011797,-1.88e-06,-5.39588e-09,0.458638,0.00117593,-1.89619e-06,2.09282e-09,0.459812,0.00117214,-1.88991e-06,2.68267e-08,0.460982,0.00116844,-1.80943e-06,-1.99925e-08,0.462149,0.00116476,-1.86941e-06,2.3341e-08,0.463312,0.00116109,-1.79939e-06,-1.37674e-08,0.464471,0.00115745,-1.84069e-06,3.17287e-08,0.465627,0.00115387,-1.7455e-06,-2.37407e-08,0.466779,0.00115031,-1.81673e-06,3.34315e-08,0.467927,0.00114677,-1.71643e-06,-2.05786e-08,0.469073,0.00114328,-1.77817e-06,1.90802e-08,0.470214,0.00113978,-1.72093e-06,3.86247e-09,0.471352,0.00113635,-1.70934e-06,-4.72759e-09,0.472487,0.00113292,-1.72352e-06,1.50478e-08,0.473618,0.00112951,-1.67838e-06,4.14108e-09,0.474746,0.00112617,-1.66595e-06,-1.80986e-09,0.47587,0.00112283,-1.67138e-06,3.09816e-09,0.476991,0.0011195,-1.66209e-06,1.92198e-08,0.478109,0.00111623,-1.60443e-06,-2.03726e-08,0.479224,0.00111296,-1.66555e-06,3.2468e-08,0.480335,0.00110973,-1.56814e-06,-2.00922e-08,0.481443,0.00110653,-1.62842e-06,1.80983e-08,0.482548,0.00110333,-1.57413e-06,7.30362e-09,0.48365,0.0011002,-1.55221e-06,-1.75107e-08,0.484749,0.00109705,-1.60475e-06,3.29373e-08,0.485844,0.00109393,-1.50594e-06,-2.48315e-08,0.486937,0.00109085,-1.58043e-06,3.65865e-08,0.488026,0.0010878,-1.47067e-06,-3.21078e-08,0.489112,0.00108476,-1.56699e-06,3.22397e-08,0.490195,0.00108172,-1.47027e-06,-7.44391e-09,0.491276,0.00107876,-1.49261e-06,-2.46428e-09,0.492353,0.00107577,-1.5e-06,1.73011e-08,0.493427,0.00107282,-1.4481e-06,-7.13552e-09,0.494499,0.0010699,-1.4695e-06,1.1241e-08,0.495567,0.001067,-1.43578e-06,-8.02637e-09,0.496633,0.0010641,-1.45986e-06,2.08645e-08,0.497695,0.00106124,-1.39726e-06,-1.58271e-08,0.498755,0.0010584,-1.44475e-06,1.26415e-08,0.499812,0.00105555,-1.40682e-06,2.48655e-08,0.500866,0.00105281,-1.33222e-06,-5.24988e-08,0.501918,0.00104999,-1.48972e-06,6.59206e-08,0.502966,0.00104721,-1.29196e-06,-3.237e-08,0.504012,0.00104453,-1.38907e-06,3.95479e-09,0.505055,0.00104176,-1.3772e-06,1.65509e-08,0.506096,0.00103905,-1.32755e-06,-1.05539e-08,0.507133,0.00103637,-1.35921e-06,2.56648e-08,0.508168,0.00103373,-1.28222e-06,-3.25007e-08,0.509201,0.00103106,-1.37972e-06,4.47336e-08,0.51023,0.00102844,-1.24552e-06,-2.72245e-08,0.511258,0.00102587,-1.32719e-06,4.55952e-09,0.512282,0.00102323,-1.31352e-06,8.98645e-09,0.513304,0.00102063,-1.28656e-06,1.90992e-08,0.514323,0.00101811,-1.22926e-06,-2.57786e-08,0.51534,0.00101557,-1.30659e-06,2.44104e-08,0.516355,0.00101303,-1.23336e-06,-1.22581e-08,0.517366,0.00101053,-1.27014e-06,2.4622e-08,0.518376,0.00100806,-1.19627e-06,-2.66253e-08,0.519383,0.00100559,-1.27615e-06,2.22744e-08,0.520387,0.00100311,-1.20932e-06,-2.8679e-09,0.521389,0.00100068,-1.21793e-06,-1.08029e-08,0.522388,0.000998211,-1.25034e-06,4.60795e-08,0.523385,0.000995849,-1.1121e-06,-5.4306e-08,0.52438,0.000993462,-1.27502e-06,5.19354e-08,0.525372,0.000991067,-1.11921e-06,-3.42262e-08,0.526362,0.000988726,-1.22189e-06,2.53646e-08,0.52735,0.000986359,-1.14579e-06,-7.62782e-09,0.528335,0.000984044,-1.16868e-06,5.14668e-09,0.529318,0.000981722,-1.15324e-06,-1.29589e-08,0.530298,0.000979377,-1.19211e-06,4.66888e-08,0.531276,0.000977133,-1.05205e-06,-5.45868e-08,0.532252,0.000974865,-1.21581e-06,5.24495e-08,0.533226,0.000972591,-1.05846e-06,-3.60019e-08,0.534198,0.000970366,-1.16647e-06,3.19537e-08,0.535167,0.000968129,-1.07061e-06,-3.2208e-08,0.536134,0.000965891,-1.16723e-06,3.72738e-08,0.537099,0.000963668,-1.05541e-06,2.32205e-09,0.538061,0.000961564,-1.04844e-06,-4.65618e-08,0.539022,0.000959328,-1.18813e-06,6.47159e-08,0.53998,0.000957146,-9.93979e-07,-3.3488e-08,0.540936,0.000955057,-1.09444e-06,9.63166e-09,0.54189,0.000952897,-1.06555e-06,-5.03871e-09,0.542842,0.000950751,-1.08066e-06,1.05232e-08,0.543792,0.000948621,-1.04909e-06,2.25503e-08,0.544739,0.000946591,-9.81444e-07,-4.11195e-08,0.545685,0.000944504,-1.1048e-06,2.27182e-08,0.546628,0.000942363,-1.03665e-06,9.85146e-09,0.54757,0.000940319,-1.00709e-06,-2.51938e-09,0.548509,0.000938297,-1.01465e-06,2.25858e-10,0.549446,0.000936269,-1.01397e-06,1.61598e-09,0.550381,0.000934246,-1.00913e-06,-6.68983e-09,0.551315,0.000932207,-1.0292e-06,2.51434e-08,0.552246,0.000930224,-9.53765e-07,-3.42793e-08,0.553175,0.000928214,-1.0566e-06,5.23688e-08,0.554102,0.000926258,-8.99497e-07,-5.59865e-08,0.555028,0.000924291,-1.06746e-06,5.23679e-08,0.555951,0.000922313,-9.10352e-07,-3.42763e-08,0.556872,0.00092039,-1.01318e-06,2.51326e-08,0.557792,0.000918439,-9.37783e-07,-6.64954e-09,0.558709,0.000916543,-9.57732e-07,1.46554e-09,0.559625,0.000914632,-9.53335e-07,7.87281e-10,0.560538,0.000912728,-9.50973e-07,-4.61466e-09,0.56145,0.000910812,-9.64817e-07,1.76713e-08,0.56236,0.000908935,-9.11804e-07,-6.46564e-09,0.563268,0.000907092,-9.312e-07,8.19121e-09,0.564174,0.000905255,-9.06627e-07,-2.62992e-08,0.565078,0.000903362,-9.85524e-07,3.74007e-08,0.565981,0.000901504,-8.73322e-07,-4.0942e-09,0.566882,0.000899745,-8.85605e-07,-2.1024e-08,0.56778,0.00089791,-9.48677e-07,2.85854e-08,0.568677,0.000896099,-8.62921e-07,-3.3713e-08,0.569573,0.000894272,-9.64059e-07,4.6662e-08,0.570466,0.000892484,-8.24073e-07,-3.37258e-08,0.571358,0.000890734,-9.25251e-07,2.86365e-08,0.572247,0.00088897,-8.39341e-07,-2.12155e-08,0.573135,0.000887227,-9.02988e-07,-3.37913e-09,0.574022,0.000885411,-9.13125e-07,3.47319e-08,0.574906,0.000883689,-8.08929e-07,-1.63394e-08,0.575789,0.000882022,-8.57947e-07,-2.8979e-08,0.57667,0.00088022,-9.44885e-07,7.26509e-08,0.57755,0.000878548,-7.26932e-07,-8.28106e-08,0.578427,0.000876845,-9.75364e-07,7.97774e-08,0.579303,0.000875134,-7.36032e-07,-5.74849e-08,0.580178,0.00087349,-9.08486e-07,3.09529e-08,0.58105,0.000871765,-8.15628e-07,-6.72206e-09,0.581921,0.000870114,-8.35794e-07,-4.06451e-09,0.582791,0.00086843,-8.47987e-07,2.29799e-08,0.583658,0.000866803,-7.79048e-07,-2.82503e-08,0.584524,0.00086516,-8.63799e-07,3.04167e-08,0.585388,0.000863524,-7.72548e-07,-3.38119e-08,0.586251,0.000861877,-8.73984e-07,4.52264e-08,0.587112,0.000860265,-7.38305e-07,-2.78842e-08,0.587972,0.000858705,-8.21958e-07,6.70567e-09,0.58883,0.000857081,-8.01841e-07,1.06161e-09,0.589686,0.000855481,-7.98656e-07,-1.09521e-08,0.590541,0.00085385,-8.31512e-07,4.27468e-08,0.591394,0.000852316,-7.03272e-07,-4.08257e-08,0.592245,0.000850787,-8.25749e-07,1.34677e-09,0.593095,0.000849139,-8.21709e-07,3.54387e-08,0.593944,0.000847602,-7.15393e-07,-2.38924e-08,0.59479,0.0008461,-7.8707e-07,5.26143e-10,0.595636,0.000844527,-7.85491e-07,2.17879e-08,0.596479,0.000843021,-7.20127e-07,-2.80733e-08,0.597322,0.000841497,-8.04347e-07,3.09005e-08,0.598162,0.000839981,-7.11646e-07,-3.5924e-08,0.599002,0.00083845,-8.19418e-07,5.3191e-08,0.599839,0.000836971,-6.59845e-07,-5.76307e-08,0.600676,0.000835478,-8.32737e-07,5.81227e-08,0.60151,0.000833987,-6.58369e-07,-5.56507e-08,0.602344,0.000832503,-8.25321e-07,4.52706e-08,0.603175,0.000830988,-6.89509e-07,-6.22236e-09,0.604006,0.000829591,-7.08176e-07,-2.03811e-08,0.604834,0.000828113,-7.6932e-07,2.8142e-08,0.605662,0.000826659,-6.84894e-07,-3.25822e-08,0.606488,0.000825191,-7.8264e-07,4.25823e-08,0.607312,0.000823754,-6.54893e-07,-1.85376e-08,0.608135,0.000822389,-7.10506e-07,-2.80365e-08,0.608957,0.000820883,-7.94616e-07,7.1079e-08,0.609777,0.000819507,-5.81379e-07,-7.74655e-08,0.610596,0.000818112,-8.13775e-07,5.9969e-08,0.611413,0.000816665,-6.33868e-07,-4.32013e-08,0.612229,0.000815267,-7.63472e-07,5.32313e-08,0.613044,0.0008139,-6.03778e-07,-5.05148e-08,0.613857,0.000812541,-7.55323e-07,2.96187e-08,0.614669,0.000811119,-6.66466e-07,-8.35545e-09,0.615479,0.000809761,-6.91533e-07,3.80301e-09,0.616288,0.00080839,-6.80124e-07,-6.85666e-09,0.617096,0.000807009,-7.00694e-07,2.36237e-08,0.617903,0.000805678,-6.29822e-07,-2.80336e-08,0.618708,0.000804334,-7.13923e-07,2.8906e-08,0.619511,0.000802993,-6.27205e-07,-2.79859e-08,0.620314,0.000801655,-7.11163e-07,2.34329e-08,0.621114,0.000800303,-6.40864e-07,-6.14108e-09,0.621914,0.000799003,-6.59287e-07,1.13151e-09,0.622712,0.000797688,-6.55893e-07,1.61507e-09,0.62351,0.000796381,-6.51048e-07,-7.59186e-09,0.624305,0.000795056,-6.73823e-07,2.87524e-08,0.6251,0.000793794,-5.87566e-07,-4.7813e-08,0.625893,0.000792476,-7.31005e-07,4.32901e-08,0.626685,0.000791144,-6.01135e-07,-6.13814e-09,0.627475,0.000789923,-6.19549e-07,-1.87376e-08,0.628264,0.000788628,-6.75762e-07,2.14837e-08,0.629052,0.000787341,-6.11311e-07,-7.59265e-09,0.629839,0.000786095,-6.34089e-07,8.88692e-09,0.630625,0.000784854,-6.07428e-07,-2.7955e-08,0.631409,0.000783555,-6.91293e-07,4.33285e-08,0.632192,0.000782302,-5.61307e-07,-2.61497e-08,0.632973,0.000781101,-6.39757e-07,1.6658e-09,0.633754,0.000779827,-6.34759e-07,1.94866e-08,0.634533,0.000778616,-5.76299e-07,-2.00076e-08,0.635311,0.000777403,-6.36322e-07,9.39091e-10,0.636088,0.000776133,-6.33505e-07,1.62512e-08,0.636863,0.000774915,-5.84751e-07,-6.33937e-09,0.637638,0.000773726,-6.03769e-07,9.10609e-09,0.638411,0.000772546,-5.76451e-07,-3.00849e-08,0.639183,0.000771303,-6.66706e-07,5.1629e-08,0.639953,0.000770125,-5.11819e-07,-5.7222e-08,0.640723,0.000768929,-6.83485e-07,5.80497e-08,0.641491,0.000767736,-5.09336e-07,-5.57674e-08,0.642259,0.000766551,-6.76638e-07,4.58105e-08,0.643024,0.000765335,-5.39206e-07,-8.26541e-09,0.643789,0.000764231,-5.64002e-07,-1.27488e-08,0.644553,0.000763065,-6.02249e-07,-3.44168e-10,0.645315,0.00076186,-6.03281e-07,1.41254e-08,0.646077,0.000760695,-5.60905e-07,3.44727e-09,0.646837,0.000759584,-5.50563e-07,-2.79144e-08,0.647596,0.000758399,-6.34307e-07,4.86057e-08,0.648354,0.000757276,-4.88489e-07,-4.72989e-08,0.64911,0.000756158,-6.30386e-07,2.13807e-08,0.649866,0.000754961,-5.66244e-07,2.13808e-08,0.65062,0.000753893,-5.02102e-07,-4.7299e-08,0.651374,0.000752746,-6.43999e-07,4.86059e-08,0.652126,0.000751604,-4.98181e-07,-2.79154e-08,0.652877,0.000750524,-5.81927e-07,3.45089e-09,0.653627,0.000749371,-5.71575e-07,1.41119e-08,0.654376,0.00074827,-5.29239e-07,-2.93748e-10,0.655123,0.00074721,-5.3012e-07,-1.29368e-08,0.65587,0.000746111,-5.68931e-07,-7.56355e-09,0.656616,0.000744951,-5.91621e-07,4.3191e-08,0.65736,0.000743897,-4.62048e-07,-4.59911e-08,0.658103,0.000742835,-6.00022e-07,2.15642e-08,0.658846,0.0007417,-5.35329e-07,1.93389e-08,0.659587,0.000740687,-4.77312e-07,-3.93152e-08,0.660327,0.000739615,-5.95258e-07,1.87126e-08,0.661066,0.00073848,-5.3912e-07,2.40695e-08,0.661804,0.000737474,-4.66912e-07,-5.53859e-08,0.662541,0.000736374,-6.33069e-07,7.82648e-08,0.663277,0.000735343,-3.98275e-07,-7.88593e-08,0.664012,0.00073431,-6.34853e-07,5.83585e-08,0.664745,0.000733215,-4.59777e-07,-3.53656e-08,0.665478,0.000732189,-5.65874e-07,2.34994e-08,0.66621,0.000731128,-4.95376e-07,9.72743e-10,0.66694,0.00073014,-4.92458e-07,-2.73903e-08,0.66767,0.000729073,-5.74629e-07,4.89839e-08,0.668398,0.000728071,-4.27677e-07,-4.93359e-08,0.669126,0.000727068,-5.75685e-07,2.91504e-08,0.669853,0.000726004,-4.88234e-07,-7.66109e-09,0.670578,0.000725004,-5.11217e-07,1.49392e-09,0.671303,0.000723986,-5.06735e-07,1.68533e-09,0.672026,0.000722978,-5.01679e-07,-8.23525e-09,0.672749,0.00072195,-5.26385e-07,3.12556e-08,0.67347,0.000720991,-4.32618e-07,-5.71825e-08,0.674191,0.000719954,-6.04166e-07,7.8265e-08,0.67491,0.00071898,-3.69371e-07,-7.70634e-08,0.675628,0.00071801,-6.00561e-07,5.11747e-08,0.676346,0.000716963,-4.47037e-07,-8.42615e-09,0.677062,0.000716044,-4.72315e-07,-1.747e-08,0.677778,0.000715046,-5.24725e-07,1.87015e-08,0.678493,0.000714053,-4.68621e-07,2.26856e-09,0.679206,0.000713123,-4.61815e-07,-2.77758e-08,0.679919,0.000712116,-5.45142e-07,4.92298e-08,0.68063,0.000711173,-3.97453e-07,-4.99339e-08,0.681341,0.000710228,-5.47255e-07,3.12967e-08,0.682051,0.000709228,-4.53365e-07,-1.56481e-08,0.68276,0.000708274,-5.00309e-07,3.12958e-08,0.683467,0.000707367,-4.06422e-07,-4.99303e-08,0.684174,0.000706405,-5.56213e-07,4.9216e-08,0.68488,0.00070544,-4.08565e-07,-2.77245e-08,0.685585,0.00070454,-4.91738e-07,2.07748e-09,0.686289,0.000703562,-4.85506e-07,1.94146e-08,0.686992,0.00070265,-4.27262e-07,-2.01314e-08,0.687695,0.000701735,-4.87656e-07,1.50616e-09,0.688396,0.000700764,-4.83137e-07,1.41067e-08,0.689096,0.00069984,-4.40817e-07,1.67168e-09,0.689795,0.000698963,-4.35802e-07,-2.07934e-08,0.690494,0.000698029,-4.98182e-07,2.18972e-08,0.691192,0.000697099,-4.32491e-07,-7.19092e-09,0.691888,0.000696212,-4.54064e-07,6.86642e-09,0.692584,0.000695325,-4.33464e-07,-2.02747e-08,0.693279,0.000694397,-4.94288e-07,1.46279e-08,0.693973,0.000693452,-4.50405e-07,2.13678e-08,0.694666,0.000692616,-3.86301e-07,-4.04945e-08,0.695358,0.000691721,-5.07785e-07,2.14009e-08,0.696049,0.00069077,-4.43582e-07,1.44955e-08,0.69674,0.000689926,-4.00096e-07,-1.97783e-08,0.697429,0.000689067,-4.5943e-07,5.01296e-09,0.698118,0.000688163,-4.44392e-07,-2.73521e-10,0.698805,0.000687273,-4.45212e-07,-3.91893e-09,0.699492,0.000686371,-4.56969e-07,1.59493e-08,0.700178,0.000685505,-4.09121e-07,-2.73351e-10,0.700863,0.000684686,-4.09941e-07,-1.4856e-08,0.701548,0.000683822,-4.54509e-07,9.25979e-11,0.702231,0.000682913,-4.54231e-07,1.44855e-08,0.702913,0.000682048,-4.10775e-07,1.56992e-09,0.703595,0.000681231,-4.06065e-07,-2.07652e-08,0.704276,0.000680357,-4.68361e-07,2.18864e-08,0.704956,0.000679486,-4.02701e-07,-7.17595e-09,0.705635,0.000678659,-4.24229e-07,6.81748e-09,0.706313,0.000677831,-4.03777e-07,-2.0094e-08,0.70699,0.000676963,-4.64059e-07,1.39538e-08,0.707667,0.000676077,-4.22197e-07,2.38835e-08,0.708343,0.000675304,-3.50547e-07,-4.98831e-08,0.709018,0.000674453,-5.00196e-07,5.64395e-08,0.709692,0.000673622,-3.30878e-07,-5.66657e-08,0.710365,0.00067279,-5.00875e-07,5.1014e-08,0.711037,0.000671942,-3.47833e-07,-2.81809e-08,0.711709,0.000671161,-4.32376e-07,2.10513e-09,0.712379,0.000670303,-4.2606e-07,1.97604e-08,0.713049,0.00066951,-3.66779e-07,-2.15422e-08,0.713718,0.000668712,-4.31406e-07,6.8038e-09,0.714387,0.000667869,-4.10994e-07,-5.67295e-09,0.715054,0.00066703,-4.28013e-07,1.5888e-08,0.715721,0.000666222,-3.80349e-07,1.72576e-09,0.716387,0.000665467,-3.75172e-07,-2.27911e-08,0.717052,0.000664648,-4.43545e-07,2.9834e-08,0.717716,0.00066385,-3.54043e-07,-3.69401e-08,0.718379,0.000663031,-4.64864e-07,5.83219e-08,0.719042,0.000662277,-2.89898e-07,-7.71382e-08,0.719704,0.000661465,-5.21313e-07,7.14171e-08,0.720365,0.000660637,-3.07061e-07,-2.97161e-08,0.721025,0.000659934,-3.96209e-07,-1.21575e-08,0.721685,0.000659105,-4.32682e-07,1.87412e-08,0.722343,0.000658296,-3.76458e-07,-3.2029e-09,0.723001,0.000657533,-3.86067e-07,-5.9296e-09,0.723659,0.000656743,-4.03856e-07,2.69213e-08,0.724315,0.000656016,-3.23092e-07,-4.21511e-08,0.724971,0.000655244,-4.49545e-07,2.24737e-08,0.725625,0.000654412,-3.82124e-07,1.18611e-08,0.726279,0.000653683,-3.46541e-07,-1.03132e-08,0.726933,0.000652959,-3.7748e-07,-3.02128e-08,0.727585,0.000652114,-4.68119e-07,7.15597e-08,0.728237,0.000651392,-2.5344e-07,-7.72119e-08,0.728888,0.000650654,-4.85075e-07,5.8474e-08,0.729538,0.000649859,-3.09654e-07,-3.74746e-08,0.730188,0.000649127,-4.22077e-07,3.18197e-08,0.730837,0.000648379,-3.26618e-07,-3.01997e-08,0.731485,0.000647635,-4.17217e-07,2.93747e-08,0.732132,0.000646888,-3.29093e-07,-2.76943e-08,0.732778,0.000646147,-4.12176e-07,2.17979e-08,0.733424,0.000645388,-3.46783e-07,1.07292e-10,0.734069,0.000644695,-3.46461e-07,-2.22271e-08,0.734713,0.000643935,-4.13142e-07,2.91963e-08,0.735357,0.000643197,-3.25553e-07,-3.49536e-08,0.736,0.000642441,-4.30414e-07,5.10133e-08,0.736642,0.000641733,-2.77374e-07,-4.98904e-08,0.737283,0.000641028,-4.27045e-07,2.93392e-08,0.737924,0.000640262,-3.39028e-07,-7.86156e-09,0.738564,0.000639561,-3.62612e-07,2.10703e-09,0.739203,0.000638842,-3.56291e-07,-5.6653e-10,0.739842,0.000638128,-3.57991e-07,1.59086e-10,0.740479,0.000637412,-3.57513e-07,-6.98321e-11,0.741116,0.000636697,-3.57723e-07,1.20214e-10,0.741753,0.000635982,-3.57362e-07,-4.10987e-10,0.742388,0.000635266,-3.58595e-07,1.5237e-09,0.743023,0.000634553,-3.54024e-07,-5.68376e-09,0.743657,0.000633828,-3.71075e-07,2.12113e-08,0.744291,0.00063315,-3.07441e-07,-1.95569e-08,0.744924,0.000632476,-3.66112e-07,-2.58816e-09,0.745556,0.000631736,-3.73877e-07,2.99096e-08,0.746187,0.000631078,-2.84148e-07,-5.74454e-08,0.746818,0.000630337,-4.56484e-07,8.06629e-08,0.747448,0.000629666,-2.14496e-07,-8.63922e-08,0.748077,0.000628978,-4.73672e-07,8.60918e-08,0.748706,0.000628289,-2.15397e-07,-7.91613e-08,0.749334,0.000627621,-4.5288e-07,5.17393e-08,0.749961,0.00062687,-2.97663e-07,-8.58662e-09,0.750588,0.000626249,-3.23422e-07,-1.73928e-08,0.751214,0.00062555,-3.75601e-07,1.85532e-08,0.751839,0.000624855,-3.19941e-07,2.78479e-09,0.752463,0.000624223,-3.11587e-07,-2.96923e-08,0.753087,0.000623511,-4.00664e-07,5.63799e-08,0.75371,0.000622879,-2.31524e-07,-7.66179e-08,0.754333,0.000622186,-4.61378e-07,7.12778e-08,0.754955,0.000621477,-2.47545e-07,-2.96794e-08,0.755576,0.000620893,-3.36583e-07,-1.21648e-08,0.756196,0.000620183,-3.73077e-07,1.87339e-08,0.756816,0.000619493,-3.16875e-07,-3.16622e-09,0.757435,0.00061885,-3.26374e-07,-6.0691e-09,0.758054,0.000618179,-3.44581e-07,2.74426e-08,0.758672,0.000617572,-2.62254e-07,-4.40968e-08,0.759289,0.000616915,-3.94544e-07,2.97352e-08,0.759906,0.000616215,-3.05338e-07,-1.52393e-08,0.760522,0.000615559,-3.51056e-07,3.12221e-08,0.761137,0.000614951,-2.5739e-07,-5.00443e-08,0.761751,0.000614286,-4.07523e-07,4.9746e-08,0.762365,0.00061362,-2.58285e-07,-2.97303e-08,0.762979,0.000613014,-3.47476e-07,9.57079e-09,0.763591,0.000612348,-3.18764e-07,-8.55287e-09,0.764203,0.000611685,-3.44422e-07,2.46407e-08,0.764815,0.00061107,-2.705e-07,-3.04053e-08,0.765426,0.000610437,-3.61716e-07,3.73759e-08,0.766036,0.000609826,-2.49589e-07,-5.94935e-08,0.766645,0.000609149,-4.28069e-07,8.13889e-08,0.767254,0.000608537,-1.83902e-07,-8.72483e-08,0.767862,0.000607907,-4.45647e-07,8.87901e-08,0.76847,0.000607282,-1.79277e-07,-8.90983e-08,0.769077,0.000606656,-4.46572e-07,8.87892e-08,0.769683,0.000606029,-1.80204e-07,-8.72446e-08,0.770289,0.000605407,-4.41938e-07,8.13752e-08,0.770894,0.000604768,-1.97812e-07,-5.94423e-08,0.771498,0.000604194,-3.76139e-07,3.71848e-08,0.772102,0.000603553,-2.64585e-07,-2.96922e-08,0.772705,0.000602935,-3.53661e-07,2.19793e-08,0.773308,0.000602293,-2.87723e-07,1.37955e-09,0.77391,0.000601722,-2.83585e-07,-2.74976e-08,0.774512,0.000601072,-3.66077e-07,4.9006e-08,0.775112,0.000600487,-2.19059e-07,-4.93171e-08,0.775712,0.000599901,-3.67011e-07,2.90531e-08,0.776312,0.000599254,-2.79851e-07,-7.29081e-09,0.776911,0.000598673,-3.01724e-07,1.10077e-10,0.777509,0.00059807,-3.01393e-07,6.85053e-09,0.778107,0.000597487,-2.80842e-07,-2.75123e-08,0.778704,0.000596843,-3.63379e-07,4.35939e-08,0.779301,0.000596247,-2.32597e-07,-2.7654e-08,0.779897,0.000595699,-3.15559e-07,7.41741e-09,0.780492,0.00059509,-2.93307e-07,-2.01562e-09,0.781087,0.000594497,-2.99354e-07,6.45059e-10,0.781681,0.000593901,-2.97418e-07,-5.64635e-10,0.782275,0.000593304,-2.99112e-07,1.61347e-09,0.782868,0.000592711,-2.94272e-07,-5.88926e-09,0.78346,0.000592105,-3.1194e-07,2.19436e-08,0.784052,0.000591546,-2.46109e-07,-2.22805e-08,0.784643,0.000590987,-3.1295e-07,7.57368e-09,0.785234,0.000590384,-2.90229e-07,-8.01428e-09,0.785824,0.00058978,-3.14272e-07,2.44834e-08,0.786414,0.000589225,-2.40822e-07,-3.03148e-08,0.787003,0.000588652,-3.31766e-07,3.7171e-08,0.787591,0.0005881,-2.20253e-07,-5.87646e-08,0.788179,0.000587483,-3.96547e-07,7.86782e-08,0.788766,0.000586926,-1.60512e-07,-7.71342e-08,0.789353,0.000586374,-3.91915e-07,5.10444e-08,0.789939,0.000585743,-2.38782e-07,-7.83422e-09,0.790524,0.000585242,-2.62284e-07,-1.97076e-08,0.791109,0.000584658,-3.21407e-07,2.70598e-08,0.791693,0.000584097,-2.40228e-07,-2.89269e-08,0.792277,0.000583529,-3.27008e-07,2.90431e-08,0.792861,0.000582963,-2.39879e-07,-2.76409e-08,0.793443,0.0005824,-3.22802e-07,2.1916e-08,0.794025,0.00058182,-2.57054e-07,-4.18368e-10,0.794607,0.000581305,-2.58309e-07,-2.02425e-08,0.795188,0.000580727,-3.19036e-07,2.17838e-08,0.795768,0.000580155,-2.53685e-07,-7.28814e-09,0.796348,0.000579625,-2.75549e-07,7.36871e-09,0.796928,0.000579096,-2.53443e-07,-2.21867e-08,0.797506,0.000578523,-3.20003e-07,2.17736e-08,0.798085,0.000577948,-2.54683e-07,-5.30296e-09,0.798662,0.000577423,-2.70592e-07,-5.61698e-10,0.799239,0.00057688,-2.72277e-07,7.54977e-09,0.799816,0.000576358,-2.49627e-07,-2.96374e-08,0.800392,0.00057577,-3.38539e-07,5.1395e-08,0.800968,0.000575247,-1.84354e-07,-5.67335e-08,0.801543,0.000574708,-3.54555e-07,5.63297e-08,0.802117,0.000574168,-1.85566e-07,-4.93759e-08,0.802691,0.000573649,-3.33693e-07,2.19646e-08,0.803264,0.000573047,-2.678e-07,2.1122e-08,0.803837,0.000572575,-2.04433e-07,-4.68482e-08,0.804409,0.000572026,-3.44978e-07,4.70613e-08,0.804981,0.000571477,-2.03794e-07,-2.21877e-08,0.805552,0.000571003,-2.70357e-07,-1.79153e-08,0.806123,0.000570408,-3.24103e-07,3.42443e-08,0.806693,0.000569863,-2.2137e-07,1.47556e-10,0.807263,0.000569421,-2.20928e-07,-3.48345e-08,0.807832,0.000568874,-3.25431e-07,1.99812e-08,0.808401,0.000568283,-2.65487e-07,1.45143e-08,0.808969,0.000567796,-2.21945e-07,-1.84338e-08,0.809536,0.000567297,-2.77246e-07,-3.83608e-10,0.810103,0.000566741,-2.78397e-07,1.99683e-08,0.81067,0.000566244,-2.18492e-07,-1.98848e-08,0.811236,0.000565747,-2.78146e-07,-3.38976e-11,0.811801,0.000565191,-2.78248e-07,2.00204e-08,0.812366,0.000564695,-2.18187e-07,-2.04429e-08,0.812931,0.000564197,-2.79516e-07,2.1467e-09,0.813495,0.000563644,-2.73076e-07,1.18561e-08,0.814058,0.000563134,-2.37507e-07,1.00334e-08,0.814621,0.000562689,-2.07407e-07,-5.19898e-08,0.815183,0.000562118,-3.63376e-07,7.87163e-08,0.815745,0.000561627,-1.27227e-07,-8.40616e-08,0.816306,0.000561121,-3.79412e-07,7.87163e-08,0.816867,0.000560598,-1.43263e-07,-5.19898e-08,0.817428,0.000560156,-2.99233e-07,1.00335e-08,0.817988,0.000559587,-2.69132e-07,1.18559e-08,0.818547,0.000559085,-2.33564e-07,2.14764e-09,0.819106,0.000558624,-2.27122e-07,-2.04464e-08,0.819664,0.000558108,-2.88461e-07,2.00334e-08,0.820222,0.000557591,-2.28361e-07,-8.24277e-11,0.820779,0.000557135,-2.28608e-07,-1.97037e-08,0.821336,0.000556618,-2.87719e-07,1.92925e-08,0.821893,0.000556101,-2.29841e-07,2.13831e-09,0.822448,0.000555647,-2.23427e-07,-2.78458e-08,0.823004,0.000555117,-3.06964e-07,4.96402e-08,0.823559,0.000554652,-1.58043e-07,-5.15058e-08,0.824113,0.000554181,-3.12561e-07,3.71737e-08,0.824667,0.000553668,-2.0104e-07,-3.75844e-08,0.82522,0.000553153,-3.13793e-07,5.35592e-08,0.825773,0.000552686,-1.53115e-07,-5.74431e-08,0.826326,0.000552207,-3.25444e-07,5.7004e-08,0.826878,0.000551728,-1.54433e-07,-5.13635e-08,0.827429,0.000551265,-3.08523e-07,2.92406e-08,0.82798,0.000550735,-2.20801e-07,-5.99424e-09,0.828531,0.000550276,-2.38784e-07,-5.26363e-09,0.829081,0.000549782,-2.54575e-07,2.70488e-08,0.82963,0.000549354,-1.73429e-07,-4.33268e-08,0.83018,0.000548878,-3.03409e-07,2.7049e-08,0.830728,0.000548352,-2.22262e-07,-5.26461e-09,0.831276,0.000547892,-2.38056e-07,-5.99057e-09,0.831824,0.000547397,-2.56027e-07,2.92269e-08,0.832371,0.000546973,-1.68347e-07,-5.13125e-08,0.832918,0.000546482,-3.22284e-07,5.68139e-08,0.833464,0.000546008,-1.51843e-07,-5.67336e-08,0.83401,0.000545534,-3.22043e-07,5.09113e-08,0.834555,0.000545043,-1.6931e-07,-2.77022e-08,0.8351,0.000544621,-2.52416e-07,2.92924e-10,0.835644,0.000544117,-2.51537e-07,2.65305e-08,0.836188,0.000543694,-1.71946e-07,-4.68105e-08,0.836732,0.00054321,-3.12377e-07,4.15021e-08,0.837275,0.000542709,-1.87871e-07,1.13355e-11,0.837817,0.000542334,-1.87837e-07,-4.15474e-08,0.838359,0.000541833,-3.12479e-07,4.69691e-08,0.838901,0.000541349,-1.71572e-07,-2.71196e-08,0.839442,0.000540925,-2.52931e-07,1.90462e-09,0.839983,0.000540425,-2.47217e-07,1.95011e-08,0.840523,0.000539989,-1.88713e-07,-2.03045e-08,0.841063,0.00053955,-2.49627e-07,2.11216e-09,0.841602,0.000539057,-2.4329e-07,1.18558e-08,0.842141,0.000538606,-2.07723e-07,1.00691e-08,0.842679,0.000538221,-1.77516e-07,-5.21324e-08,0.843217,0.00053771,-3.33913e-07,7.92513e-08,0.843755,0.00053728,-9.6159e-08,-8.60587e-08,0.844292,0.000536829,-3.54335e-07,8.61696e-08,0.844828,0.000536379,-9.58263e-08,-7.98057e-08,0.845364,0.000535948,-3.35243e-07,5.42394e-08,0.8459,0.00053544,-1.72525e-07,-1.79426e-08,0.846435,0.000535041,-2.26353e-07,1.75308e-08,0.84697,0.000534641,-1.73761e-07,-5.21806e-08,0.847505,0.000534137,-3.30302e-07,7.19824e-08,0.848038,0.000533692,-1.14355e-07,-5.69349e-08,0.848572,0.000533293,-2.8516e-07,3.65479e-08,0.849105,0.000532832,-1.75516e-07,-2.96519e-08,0.849638,0.000532392,-2.64472e-07,2.2455e-08,0.85017,0.000531931,-1.97107e-07,-5.63451e-10,0.850702,0.000531535,-1.98797e-07,-2.02011e-08,0.851233,0.000531077,-2.59401e-07,2.17634e-08,0.851764,0.000530623,-1.94111e-07,-7.24794e-09,0.852294,0.000530213,-2.15854e-07,7.22832e-09,0.852824,0.000529803,-1.94169e-07,-2.16653e-08,0.853354,0.00052935,-2.59165e-07,1.98283e-08,0.853883,0.000528891,-1.9968e-07,1.95678e-09,0.854412,0.000528497,-1.9381e-07,-2.76554e-08,0.85494,0.000528027,-2.76776e-07,4.90603e-08,0.855468,0.00052762,-1.29596e-07,-4.93764e-08,0.855995,0.000527213,-2.77725e-07,2.92361e-08,0.856522,0.000526745,-1.90016e-07,-7.96341e-09,0.857049,0.000526341,-2.13907e-07,2.61752e-09,0.857575,0.000525922,-2.06054e-07,-2.50665e-09,0.8581,0.000525502,-2.13574e-07,7.40906e-09,0.858626,0.000525097,-1.91347e-07,-2.71296e-08,0.859151,0.000524633,-2.72736e-07,4.15048e-08,0.859675,0.000524212,-1.48221e-07,-1.96802e-08,0.860199,0.000523856,-2.07262e-07,-2.23886e-08,0.860723,0.000523375,-2.74428e-07,4.96299e-08,0.861246,0.000522975,-1.25538e-07,-5.69216e-08,0.861769,0.000522553,-2.96303e-07,5.88473e-08,0.862291,0.000522137,-1.19761e-07,-5.92584e-08,0.862813,0.00052172,-2.97536e-07,5.8977e-08,0.863334,0.000521301,-1.20605e-07,-5.74403e-08,0.863855,0.000520888,-2.92926e-07,5.15751e-08,0.864376,0.000520457,-1.38201e-07,-2.96506e-08,0.864896,0.000520091,-2.27153e-07,7.42277e-09,0.865416,0.000519659,-2.04885e-07,-4.05057e-11,0.865936,0.00051925,-2.05006e-07,-7.26074e-09,0.866455,0.000518818,-2.26788e-07,2.90835e-08,0.866973,0.000518451,-1.39538e-07,-4.94686e-08,0.867492,0.000518024,-2.87944e-07,4.95814e-08,0.868009,0.000517597,-1.39199e-07,-2.96479e-08,0.868527,0.000517229,-2.28143e-07,9.40539e-09,0.869044,0.000516801,-1.99927e-07,-7.9737e-09,0.86956,0.000516378,-2.23848e-07,2.24894e-08,0.870077,0.000515997,-1.5638e-07,-2.23793e-08,0.870592,0.000515617,-2.23517e-07,7.42302e-09,0.871108,0.000515193,-2.01248e-07,-7.31283e-09,0.871623,0.000514768,-2.23187e-07,2.18283e-08,0.872137,0.000514387,-1.57702e-07,-2.03959e-08,0.872652,0.000514011,-2.1889e-07,1.50711e-10,0.873165,0.000513573,-2.18437e-07,1.97931e-08,0.873679,0.000513196,-1.59058e-07,-1.97183e-08,0.874192,0.000512819,-2.18213e-07,-5.24324e-10,0.874704,0.000512381,-2.19786e-07,2.18156e-08,0.875217,0.000512007,-1.54339e-07,-2.71336e-08,0.875728,0.000511616,-2.3574e-07,2.71141e-08,0.87624,0.000511226,-1.54398e-07,-2.17182e-08,0.876751,0.000510852,-2.19552e-07,1.54131e-10,0.877262,0.000510414,-2.1909e-07,2.11017e-08,0.877772,0.000510039,-1.55785e-07,-2.49562e-08,0.878282,0.000509652,-2.30654e-07,1.91183e-08,0.878791,0.000509248,-1.73299e-07,8.08751e-09,0.8793,0.000508926,-1.49036e-07,-5.14684e-08,0.879809,0.000508474,-3.03441e-07,7.85766e-08,0.880317,0.000508103,-6.77112e-08,-8.40242e-08,0.880825,0.000507715,-3.19784e-07,7.87063e-08,0.881333,0.000507312,-8.36649e-08,-5.19871e-08,0.88184,0.000506988,-2.39626e-07,1.00327e-08,0.882346,0.000506539,-2.09528e-07,1.18562e-08,0.882853,0.000506156,-1.73959e-07,2.14703e-09,0.883359,0.000505814,-1.67518e-07,-2.04444e-08,0.883864,0.000505418,-2.28851e-07,2.00258e-08,0.88437,0.00050502,-1.68774e-07,-5.42855e-11,0.884874,0.000504682,-1.68937e-07,-1.98087e-08,0.885379,0.000504285,-2.28363e-07,1.96842e-08,0.885883,0.000503887,-1.6931e-07,6.76342e-10,0.886387,0.000503551,-1.67281e-07,-2.23896e-08,0.88689,0.000503149,-2.3445e-07,2.92774e-08,0.887393,0.000502768,-1.46618e-07,-3.51152e-08,0.887896,0.00050237,-2.51963e-07,5.15787e-08,0.888398,0.00050202,-9.72271e-08,-5.19903e-08,0.8889,0.00050167,-2.53198e-07,3.71732e-08,0.889401,0.000501275,-1.41678e-07,-3.70978e-08,0.889902,0.00050088,-2.52972e-07,5.16132e-08,0.890403,0.000500529,-9.81321e-08,-5.01459e-08,0.890903,0.000500183,-2.4857e-07,2.9761e-08,0.891403,0.000499775,-1.59287e-07,-9.29351e-09,0.891903,0.000499428,-1.87167e-07,7.41301e-09,0.892402,0.000499076,-1.64928e-07,-2.03585e-08,0.892901,0.000498685,-2.26004e-07,1.44165e-08,0.893399,0.000498276,-1.82754e-07,2.22974e-08,0.893898,0.000497978,-1.15862e-07,-4.40013e-08,0.894395,0.000497614,-2.47866e-07,3.44985e-08,0.894893,0.000497222,-1.44371e-07,-3.43882e-08,0.89539,0.00049683,-2.47535e-07,4.34497e-08,0.895886,0.000496465,-1.17186e-07,-2.02012e-08,0.896383,0.00049617,-1.7779e-07,-2.22497e-08,0.896879,0.000495748,-2.44539e-07,4.95952e-08,0.897374,0.000495408,-9.57532e-08,-5.69217e-08,0.89787,0.000495045,-2.66518e-07,5.88823e-08,0.898364,0.000494689,-8.98713e-08,-5.93983e-08,0.898859,0.000494331,-2.68066e-07,5.95017e-08,0.899353,0.000493973,-8.95613e-08,-5.9399e-08,0.899847,0.000493616,-2.67758e-07,5.8885e-08,0.90034,0.000493257,-9.11033e-08,-5.69317e-08,0.900833,0.000492904,-2.61898e-07,4.96326e-08,0.901326,0.000492529,-1.13001e-07,-2.23893e-08,0.901819,0.000492236,-1.80169e-07,-1.968e-08,0.902311,0.000491817,-2.39209e-07,4.15047e-08,0.902802,0.000491463,-1.14694e-07,-2.71296e-08,0.903293,0.000491152,-1.96083e-07,7.409e-09,0.903784,0.000490782,-1.73856e-07,-2.50645e-09,0.904275,0.000490427,-1.81376e-07,2.61679e-09,0.904765,0.000490072,-1.73525e-07,-7.96072e-09,0.905255,0.000489701,-1.97407e-07,2.92261e-08,0.905745,0.000489394,-1.09729e-07,-4.93389e-08,0.906234,0.000489027,-2.57746e-07,4.89204e-08,0.906723,0.000488658,-1.10985e-07,-2.71333e-08,0.907211,0.000488354,-1.92385e-07,8.30861e-12,0.907699,0.00048797,-1.9236e-07,2.71001e-08,0.908187,0.000487666,-1.1106e-07,-4.88041e-08,0.908675,0.000487298,-2.57472e-07,4.89069e-08,0.909162,0.000486929,-1.10751e-07,-2.76143e-08,0.909649,0.000486625,-1.93594e-07,1.9457e-09,0.910135,0.000486244,-1.87757e-07,1.98315e-08,0.910621,0.000485928,-1.28262e-07,-2.16671e-08,0.911107,0.000485606,-1.93264e-07,7.23216e-09,0.911592,0.000485241,-1.71567e-07,-7.26152e-09,0.912077,0.000484877,-1.93352e-07,2.18139e-08,0.912562,0.000484555,-1.2791e-07,-2.03895e-08,0.913047,0.000484238,-1.89078e-07,1.39494e-10,0.913531,0.000483861,-1.8866e-07,1.98315e-08,0.914014,0.000483543,-1.29165e-07,-1.98609e-08,0.914498,0.000483225,-1.88748e-07,7.39912e-12,0.914981,0.000482847,-1.88726e-07,1.98313e-08,0.915463,0.000482529,-1.29232e-07,-1.9728e-08,0.915946,0.000482212,-1.88416e-07,-5.24035e-10,0.916428,0.000481833,-1.89988e-07,2.18241e-08,0.916909,0.000481519,-1.24516e-07,-2.71679e-08,0.917391,0.000481188,-2.06019e-07,2.72427e-08,0.917872,0.000480858,-1.24291e-07,-2.21985e-08,0.918353,0.000480543,-1.90886e-07,1.94644e-09,0.918833,0.000480167,-1.85047e-07,1.44127e-08,0.919313,0.00047984,-1.41809e-07,7.39438e-12,0.919793,0.000479556,-1.41787e-07,-1.44423e-08,0.920272,0.000479229,-1.85114e-07,-1.84291e-09,0.920751,0.000478854,-1.90642e-07,2.18139e-08,0.92123,0.000478538,-1.25201e-07,-2.58081e-08,0.921708,0.00047821,-2.02625e-07,2.18139e-08,0.922186,0.00047787,-1.37183e-07,-1.84291e-09,0.922664,0.00047759,-1.42712e-07,-1.44423e-08,0.923141,0.000477262,-1.86039e-07,7.34701e-12,0.923618,0.00047689,-1.86017e-07,1.44129e-08,0.924095,0.000476561,-1.42778e-07,1.94572e-09,0.924572,0.000476281,-1.36941e-07,-2.21958e-08,0.925048,0.000475941,-2.03528e-07,2.72327e-08,0.925523,0.000475615,-1.2183e-07,-2.71304e-08,0.925999,0.00047529,-2.03221e-07,2.16843e-08,0.926474,0.000474949,-1.38168e-07,-2.16005e-12,0.926949,0.000474672,-1.38175e-07,-2.16756e-08,0.927423,0.000474331,-2.03202e-07,2.71001e-08,0.927897,0.000474006,-1.21902e-07,-2.71201e-08,0.928371,0.000473681,-2.03262e-07,2.17757e-08,0.928845,0.00047334,-1.37935e-07,-3.78028e-10,0.929318,0.000473063,-1.39069e-07,-2.02636e-08,0.929791,0.000472724,-1.9986e-07,2.18276e-08,0.930263,0.000472389,-1.34377e-07,-7.44231e-09,0.930736,0.000472098,-1.56704e-07,7.94165e-09,0.931208,0.000471809,-1.32879e-07,-2.43243e-08,0.931679,0.00047147,-2.05851e-07,2.97508e-08,0.932151,0.000471148,-1.16599e-07,-3.50742e-08,0.932622,0.000470809,-2.21822e-07,5.09414e-08,0.933092,0.000470518,-6.89976e-08,-4.94821e-08,0.933563,0.000470232,-2.17444e-07,2.77775e-08,0.934033,0.00046988,-1.34111e-07,-2.02351e-09,0.934502,0.000469606,-1.40182e-07,-1.96835e-08,0.934972,0.000469267,-1.99232e-07,2.11529e-08,0.935441,0.000468932,-1.35774e-07,-5.32332e-09,0.93591,0.000468644,-1.51743e-07,1.40413e-10,0.936378,0.000468341,-1.51322e-07,4.76166e-09,0.936846,0.000468053,-1.37037e-07,-1.9187e-08,0.937314,0.000467721,-1.94598e-07,1.23819e-08,0.937782,0.000467369,-1.57453e-07,2.92642e-08,0.938249,0.000467142,-6.96601e-08,-6.98342e-08,0.938716,0.000466793,-2.79163e-07,7.12586e-08,0.939183,0.000466449,-6.53869e-08,-3.63863e-08,0.939649,0.000466209,-1.74546e-07,1.46818e-08,0.940115,0.000465904,-1.305e-07,-2.2341e-08,0.940581,0.000465576,-1.97523e-07,1.50774e-08,0.941046,0.000465226,-1.52291e-07,2.16359e-08,0.941511,0.000464986,-8.73832e-08,-4.20162e-08,0.941976,0.000464685,-2.13432e-07,2.72198e-08,0.942441,0.00046434,-1.31773e-07,-7.2581e-09,0.942905,0.000464055,-1.53547e-07,1.81263e-09,0.943369,0.000463753,-1.48109e-07,7.58386e-12,0.943832,0.000463457,-1.48086e-07,-1.84298e-09,0.944296,0.000463155,-1.53615e-07,7.36433e-09,0.944759,0.00046287,-1.31522e-07,-2.76143e-08,0.945221,0.000462524,-2.14365e-07,4.34883e-08,0.945684,0.000462226,-8.39003e-08,-2.71297e-08,0.946146,0.000461977,-1.65289e-07,5.42595e-09,0.946608,0.000461662,-1.49012e-07,5.42593e-09,0.947069,0.000461381,-1.32734e-07,-2.71297e-08,0.94753,0.000461034,-2.14123e-07,4.34881e-08,0.947991,0.000460736,-8.36585e-08,-2.76134e-08,0.948452,0.000460486,-1.66499e-07,7.36083e-09,0.948912,0.000460175,-1.44416e-07,-1.82993e-09,0.949372,0.000459881,-1.49906e-07,-4.11073e-11,0.949832,0.000459581,-1.50029e-07,1.99434e-09,0.950291,0.000459287,-1.44046e-07,-7.93627e-09,0.950751,0.000458975,-1.67855e-07,2.97507e-08,0.951209,0.000458728,-7.86029e-08,-5.1462e-08,0.951668,0.000458417,-2.32989e-07,5.6888e-08,0.952126,0.000458121,-6.2325e-08,-5.68806e-08,0.952584,0.000457826,-2.32967e-07,5.14251e-08,0.953042,0.000457514,-7.86914e-08,-2.96107e-08,0.953499,0.000457268,-1.67523e-07,7.41296e-09,0.953956,0.000456955,-1.45285e-07,-4.11262e-11,0.954413,0.000456665,-1.45408e-07,-7.24847e-09,0.95487,0.000456352,-1.67153e-07,2.9035e-08,0.955326,0.000456105,-8.00484e-08,-4.92869e-08,0.955782,0.000455797,-2.27909e-07,4.89032e-08,0.956238,0.000455488,-8.11994e-08,-2.71166e-08,0.956693,0.000455244,-1.62549e-07,-4.13678e-11,0.957148,0.000454919,-1.62673e-07,2.72821e-08,0.957603,0.000454675,-8.0827e-08,-4.94824e-08,0.958057,0.000454365,-2.29274e-07,5.14382e-08,0.958512,0.000454061,-7.49597e-08,-3.7061e-08,0.958965,0.0004538,-1.86143e-07,3.72013e-08,0.959419,0.000453539,-7.45389e-08,-5.21396e-08,0.959873,0.000453234,-2.30958e-07,5.21476e-08,0.960326,0.000452928,-7.45146e-08,-3.72416e-08,0.960778,0.000452667,-1.8624e-07,3.72143e-08,0.961231,0.000452407,-7.45967e-08,-5.20109e-08,0.961683,0.000452101,-2.30629e-07,5.16199e-08,0.962135,0.000451795,-7.57696e-08,-3.52595e-08,0.962587,0.000451538,-1.81548e-07,2.98133e-08,0.963038,0.000451264,-9.2108e-08,-2.43892e-08,0.963489,0.000451007,-1.65276e-07,8.13892e-09,0.96394,0.000450701,-1.40859e-07,-8.16647e-09,0.964391,0.000450394,-1.65358e-07,2.45269e-08,0.964841,0.000450137,-9.17775e-08,-3.03367e-08,0.965291,0.000449863,-1.82787e-07,3.7215e-08,0.965741,0.000449609,-7.11424e-08,-5.89188e-08,0.96619,0.00044929,-2.47899e-07,7.92509e-08,0.966639,0.000449032,-1.01462e-08,-7.92707e-08,0.967088,0.000448773,-2.47958e-07,5.90181e-08,0.967537,0.000448455,-7.0904e-08,-3.75925e-08,0.967985,0.0004482,-1.83681e-07,3.17471e-08,0.968433,0.000447928,-8.84401e-08,-2.97913e-08,0.968881,0.000447662,-1.77814e-07,2.78133e-08,0.969329,0.000447389,-9.4374e-08,-2.18572e-08,0.969776,0.000447135,-1.59946e-07,1.10134e-11,0.970223,0.000446815,-1.59913e-07,2.18132e-08,0.97067,0.000446561,-9.44732e-08,-2.76591e-08,0.971116,0.000446289,-1.7745e-07,2.92185e-08,0.971562,0.000446022,-8.97948e-08,-2.96104e-08,0.972008,0.000445753,-1.78626e-07,2.96185e-08,0.972454,0.000445485,-8.97706e-08,-2.92588e-08,0.972899,0.000445218,-1.77547e-07,2.78123e-08,0.973344,0.000444946,-9.41103e-08,-2.23856e-08,0.973789,0.000444691,-1.61267e-07,2.12559e-09,0.974233,0.000444374,-1.5489e-07,1.38833e-08,0.974678,0.000444106,-1.13241e-07,1.94591e-09,0.975122,0.000443886,-1.07403e-07,-2.16669e-08,0.975565,0.000443606,-1.72404e-07,2.5117e-08,0.976009,0.000443336,-9.70526e-08,-1.91963e-08,0.976452,0.000443085,-1.54642e-07,-7.93627e-09,0.976895,0.000442752,-1.7845e-07,5.09414e-08,0.977338,0.000442548,-2.56262e-08,-7.66201e-08,0.97778,0.000442266,-2.55486e-07,7.67249e-08,0.978222,0.000441986,-2.53118e-08,-5.14655e-08,0.978664,0.000441781,-1.79708e-07,9.92773e-09,0.979106,0.000441451,-1.49925e-07,1.17546e-08,0.979547,0.000441186,-1.14661e-07,2.65868e-09,0.979988,0.000440965,-1.06685e-07,-2.23893e-08,0.980429,0.000440684,-1.73853e-07,2.72939e-08,0.980869,0.000440419,-9.19716e-08,-2.71816e-08,0.98131,0.000440153,-1.73516e-07,2.18278e-08,0.98175,0.000439872,-1.08033e-07,-5.24833e-10,0.982189,0.000439654,-1.09607e-07,-1.97284e-08,0.982629,0.000439376,-1.68793e-07,1.98339e-08,0.983068,0.000439097,-1.09291e-07,-2.62901e-12,0.983507,0.000438879,-1.09299e-07,-1.98234e-08,0.983946,0.000438601,-1.68769e-07,1.96916e-08,0.984384,0.000438322,-1.09694e-07,6.6157e-10,0.984823,0.000438105,-1.0771e-07,-2.23379e-08,0.985261,0.000437823,-1.74723e-07,2.90855e-08,0.985698,0.00043756,-8.74669e-08,-3.43992e-08,0.986136,0.000437282,-1.90665e-07,4.89068e-08,0.986573,0.000437048,-4.39442e-08,-4.20188e-08,0.98701,0.000436834,-1.7e-07,-4.11073e-11,0.987446,0.000436494,-1.70124e-07,4.21832e-08,0.987883,0.00043628,-4.35742e-08,-4.94824e-08,0.988319,0.000436044,-1.92021e-07,3.6537e-08,0.988755,0.00043577,-8.24102e-08,-3.70611e-08,0.989191,0.000435494,-1.93593e-07,5.21026e-08,0.989626,0.000435263,-3.72855e-08,-5.21402e-08,0.990061,0.000435032,-1.93706e-07,3.7249e-08,0.990496,0.000434756,-8.19592e-08,-3.72512e-08,0.990931,0.000434481,-1.93713e-07,5.21511e-08,0.991365,0.00043425,-3.72595e-08,-5.21439e-08,0.991799,0.000434019,-1.93691e-07,3.72152e-08,0.992233,0.000433743,-8.20456e-08,-3.71123e-08,0.992667,0.000433468,-1.93382e-07,5.16292e-08,0.9931,0.000433236,-3.84947e-08,-5.01953e-08,0.993533,0.000433008,-1.89081e-07,2.99427e-08,0.993966,0.00043272,-9.92525e-08,-9.9708e-09,0.994399,0.000432491,-1.29165e-07,9.94051e-09,0.994831,0.000432263,-9.93434e-08,-2.97912e-08,0.995263,0.000431975,-1.88717e-07,4.96198e-08,0.995695,0.000431746,-3.98578e-08,-4.94785e-08,0.996127,0.000431518,-1.88293e-07,2.9085e-08,0.996558,0.000431229,-1.01038e-07,-7.25675e-09,0.996989,0.000431005,-1.22809e-07,-5.79945e-11,0.99742,0.000430759,-1.22983e-07,7.48873e-09,0.997851,0.000430536,-1.00516e-07,-2.98969e-08,0.998281,0.000430245,-1.90207e-07,5.24942e-08,0.998711,0.000430022,-3.27246e-08,-6.08706e-08,0.999141,0.000429774,-2.15336e-07,7.17788e-08,0.999571,0.000429392,0.,0.}; + + template + __device__ __forceinline__ void Lab2RGBConvert_f(const T& src, D& dst) + { + const float lThresh = 0.008856f * 903.3f; + const float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f; + + float Y, fy; + + if (src.x <= lThresh) + { + Y = src.x / 903.3f; + fy = 7.787f * Y + 16.0f / 116.0f; + } + else + { + fy = (src.x + 16.0f) / 116.0f; + Y = fy * fy * fy; + } + + float X = src.y / 500.0f + fy; + float Z = fy - src.z / 200.0f; + + if (X <= fThresh) + X = (X - 16.0f / 116.0f) / 7.787f; + else + X = X * X * X; + + if (Z <= fThresh) + Z = (Z - 16.0f / 116.0f) / 7.787f; + else + Z = Z * Z * Z; + + float B = 0.052891f * X - 0.204043f * Y + 1.151152f * Z; + float G = -0.921235f * X + 1.875991f * Y + 0.045244f * Z; + float R = 3.079933f * X - 1.537150f * Y - 0.542782f * Z; + + if (srgb) + { + B = splineInterpolate(B * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + } + + dst.x = blueIdx == 0 ? B : R; + dst.y = G; + dst.z = blueIdx == 0 ? R : B; + setAlpha(dst, ColorChannel::max()); + } + + template + __device__ __forceinline__ void Lab2RGBConvert_b(const T& src, D& dst) + { + float3 srcf, dstf; + + srcf.x = src.x * (100.f / 255.f); + srcf.y = src.y - 128; + srcf.z = src.z - 128; + + Lab2RGBConvert_f(srcf, dstf); + + dst.x = saturate_cast(dstf.x * 255.f); + dst.y = saturate_cast(dstf.y * 255.f); + dst.z = saturate_cast(dstf.z * 255.f); + setAlpha(dst, ColorChannel::max()); + } + + template struct Lab2RGB; + template + struct Lab2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + Lab2RGBConvert_b(src, dst); + + return dst; + } + __host__ __device__ __forceinline__ Lab2RGB() {} + __host__ __device__ __forceinline__ Lab2RGB(const Lab2RGB&) {} + }; + template + struct Lab2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + Lab2RGBConvert_f(src, dst); + + return dst; + } + __host__ __device__ __forceinline__ Lab2RGB() {} + __host__ __device__ __forceinline__ Lab2RGB(const Lab2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_Lab2RGB_TRAITS(name, scn, dcn, srgb, blueIdx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::Lab2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + +///////////////////////////////////// RGB <-> Luv ///////////////////////////////////// + + namespace color_detail + { + __constant__ float c_LabCbrtTab[] = {0.137931,0.0114066,0.,1.18859e-07,0.149338,0.011407,3.56578e-07,-5.79396e-07,0.160745,0.0114059,-1.38161e-06,2.16892e-06,0.172151,0.0114097,5.12516e-06,-8.0814e-06,0.183558,0.0113957,-1.9119e-05,3.01567e-05,0.194965,0.0114479,7.13509e-05,-0.000112545,0.206371,0.011253,-0.000266285,-0.000106493,0.217252,0.0104009,-0.000585765,7.32149e-05,0.22714,0.00944906,-0.00036612,1.21917e-05,0.236235,0.0087534,-0.000329545,2.01753e-05,0.244679,0.00815483,-0.000269019,1.24435e-05,0.252577,0.00765412,-0.000231689,1.05618e-05,0.26001,0.00722243,-0.000200003,8.26662e-06,0.267041,0.00684723,-0.000175203,6.76746e-06,0.27372,0.00651712,-0.000154901,5.61192e-06,0.280088,0.00622416,-0.000138065,4.67009e-06,0.286179,0.00596204,-0.000124055,3.99012e-06,0.292021,0.0057259,-0.000112085,3.36032e-06,0.297638,0.00551181,-0.000102004,2.95338e-06,0.30305,0.00531666,-9.31435e-05,2.52875e-06,0.308277,0.00513796,-8.55572e-05,2.22022e-06,0.313331,0.00497351,-7.88966e-05,1.97163e-06,0.318228,0.00482163,-7.29817e-05,1.7248e-06,0.322978,0.00468084,-6.78073e-05,1.55998e-06,0.327593,0.0045499,-6.31274e-05,1.36343e-06,0.332081,0.00442774,-5.90371e-05,1.27136e-06,0.336451,0.00431348,-5.5223e-05,1.09111e-06,0.34071,0.00420631,-5.19496e-05,1.0399e-06,0.344866,0.00410553,-4.88299e-05,9.18347e-07,0.348923,0.00401062,-4.60749e-05,8.29942e-07,0.352889,0.00392096,-4.35851e-05,7.98478e-07,0.356767,0.00383619,-4.11896e-05,6.84917e-07,0.360562,0.00375586,-3.91349e-05,6.63976e-07,0.36428,0.00367959,-3.7143e-05,5.93086e-07,0.367923,0.00360708,-3.53637e-05,5.6976e-07,0.371495,0.00353806,-3.36544e-05,4.95533e-07,0.375,0.00347224,-3.21678e-05,4.87951e-07,0.378441,0.00340937,-3.0704e-05,4.4349e-07,0.38182,0.00334929,-2.93735e-05,4.20297e-07,0.38514,0.0032918,-2.81126e-05,3.7872e-07,0.388404,0.00323671,-2.69764e-05,3.596e-07,0.391614,0.00318384,-2.58976e-05,3.5845e-07,0.394772,0.00313312,-2.48223e-05,2.92765e-07,0.397881,0.00308435,-2.3944e-05,3.18232e-07,0.400942,0.00303742,-2.29893e-05,2.82046e-07,0.403957,0.00299229,-2.21432e-05,2.52315e-07,0.406927,0.00294876,-2.13862e-05,2.58416e-07,0.409855,0.00290676,-2.0611e-05,2.33939e-07,0.412741,0.00286624,-1.99092e-05,2.36342e-07,0.415587,0.00282713,-1.92001e-05,1.916e-07,0.418396,0.00278931,-1.86253e-05,2.1915e-07,0.421167,0.00275271,-1.79679e-05,1.83498e-07,0.423901,0.00271733,-1.74174e-05,1.79343e-07,0.426602,0.00268303,-1.68794e-05,1.72013e-07,0.429268,0.00264979,-1.63633e-05,1.75686e-07,0.431901,0.00261759,-1.58363e-05,1.3852e-07,0.434503,0.00258633,-1.54207e-05,1.64304e-07,0.437074,0.00255598,-1.49278e-05,1.28136e-07,0.439616,0.00252651,-1.45434e-05,1.57618e-07,0.442128,0.0024979,-1.40705e-05,1.0566e-07,0.444612,0.00247007,-1.37535e-05,1.34998e-07,0.447068,0.00244297,-1.33485e-05,1.29207e-07,0.449498,0.00241666,-1.29609e-05,9.32347e-08,0.451902,0.00239102,-1.26812e-05,1.23703e-07,0.45428,0.00236603,-1.23101e-05,9.74072e-08,0.456634,0.0023417,-1.20179e-05,1.12518e-07,0.458964,0.002318,-1.16803e-05,7.83681e-08,0.46127,0.00229488,-1.14452e-05,1.10452e-07,0.463554,0.00227232,-1.11139e-05,7.58719e-08,0.465815,0.00225032,-1.08863e-05,9.2699e-08,0.468055,0.00222882,-1.06082e-05,8.97738e-08,0.470273,0.00220788,-1.03388e-05,5.4845e-08,0.47247,0.00218736,-1.01743e-05,1.0808e-07,0.474648,0.00216734,-9.85007e-06,4.9277e-08,0.476805,0.00214779,-9.70224e-06,8.22408e-08,0.478943,0.00212863,-9.45551e-06,6.87942e-08,0.481063,0.00210993,-9.24913e-06,5.98144e-08,0.483163,0.00209161,-9.06969e-06,7.93789e-08,0.485246,0.00207371,-8.83155e-06,3.99032e-08,0.487311,0.00205616,-8.71184e-06,8.88325e-08,0.489358,0.002039,-8.44534e-06,2.20004e-08,0.491389,0.00202218,-8.37934e-06,9.13872e-08,0.493403,0.0020057,-8.10518e-06,2.96829e-08,0.495401,0.00198957,-8.01613e-06,5.81028e-08,0.497382,0.00197372,-7.84183e-06,6.5731e-08,0.499348,0.00195823,-7.64463e-06,3.66019e-08,0.501299,0.00194305,-7.53483e-06,2.62811e-08,0.503234,0.00192806,-7.45598e-06,9.66907e-08,0.505155,0.00191344,-7.16591e-06,4.18928e-09,0.507061,0.00189912,-7.15334e-06,6.53665e-08,0.508953,0.00188501,-6.95724e-06,3.23686e-08,0.510831,0.00187119,-6.86014e-06,4.35774e-08,0.512696,0.0018576,-6.72941e-06,3.17406e-08,0.514547,0.00184424,-6.63418e-06,6.78785e-08,0.516384,0.00183117,-6.43055e-06,-5.23126e-09,0.518209,0.0018183,-6.44624e-06,7.22562e-08,0.520021,0.00180562,-6.22947e-06,1.42292e-08,0.52182,0.0017932,-6.18679e-06,4.9641e-08,0.523607,0.00178098,-6.03786e-06,2.56259e-08,0.525382,0.00176898,-5.96099e-06,2.66696e-08,0.527145,0.00175714,-5.88098e-06,4.65094e-08,0.528897,0.00174552,-5.74145e-06,2.57114e-08,0.530637,0.00173411,-5.66431e-06,2.94588e-08,0.532365,0.00172287,-5.57594e-06,3.52667e-08,0.534082,0.00171182,-5.47014e-06,8.28868e-09,0.535789,0.00170091,-5.44527e-06,5.07871e-08,0.537484,0.00169017,-5.29291e-06,2.69817e-08,0.539169,0.00167967,-5.21197e-06,2.01009e-08,0.540844,0.0016693,-5.15166e-06,1.18237e-08,0.542508,0.00165903,-5.11619e-06,5.18135e-08,0.544162,0.00164896,-4.96075e-06,1.9341e-08,0.545806,0.00163909,-4.90273e-06,-9.96867e-09,0.54744,0.00162926,-4.93263e-06,8.01382e-08,0.549064,0.00161963,-4.69222e-06,-1.25601e-08,0.550679,0.00161021,-4.7299e-06,2.97067e-08,0.552285,0.00160084,-4.64078e-06,1.29426e-08,0.553881,0.0015916,-4.60195e-06,3.77327e-08,0.555468,0.00158251,-4.48875e-06,1.49412e-08,0.557046,0.00157357,-4.44393e-06,2.17118e-08,0.558615,0.00156475,-4.3788e-06,1.74206e-08,0.560176,0.00155605,-4.32653e-06,2.78152e-08,0.561727,0.00154748,-4.24309e-06,-9.47239e-09,0.563271,0.00153896,-4.27151e-06,6.9679e-08,0.564805,0.00153063,-4.06247e-06,-3.08246e-08,0.566332,0.00152241,-4.15494e-06,5.36188e-08,0.56785,0.00151426,-3.99409e-06,-4.83594e-09,0.56936,0.00150626,-4.00859e-06,2.53293e-08,0.570863,0.00149832,-3.93261e-06,2.27286e-08,0.572357,0.00149052,-3.86442e-06,2.96541e-09,0.573844,0.0014828,-3.85552e-06,2.50147e-08,0.575323,0.00147516,-3.78048e-06,1.61842e-08,0.576794,0.00146765,-3.73193e-06,2.94582e-08,0.578258,0.00146028,-3.64355e-06,-1.48076e-08,0.579715,0.00145295,-3.68798e-06,2.97724e-08,0.581164,0.00144566,-3.59866e-06,1.49272e-08,0.582606,0.00143851,-3.55388e-06,2.97285e-08,0.584041,0.00143149,-3.46469e-06,-1.46323e-08,0.585469,0.00142451,-3.50859e-06,2.88004e-08,0.58689,0.00141758,-3.42219e-06,1.864e-08,0.588304,0.00141079,-3.36627e-06,1.58482e-08,0.589712,0.00140411,-3.31872e-06,-2.24279e-08,0.591112,0.00139741,-3.38601e-06,7.38639e-08,0.592507,0.00139085,-3.16441e-06,-3.46088e-08,0.593894,0.00138442,-3.26824e-06,4.96675e-09,0.595275,0.0013779,-3.25334e-06,7.4346e-08,0.59665,0.00137162,-3.0303e-06,-6.39319e-08,0.598019,0.00136536,-3.2221e-06,6.21725e-08,0.599381,0.00135911,-3.03558e-06,-5.94423e-09,0.600737,0.00135302,-3.05341e-06,2.12091e-08,0.602087,0.00134697,-2.98979e-06,-1.92876e-08,0.603431,0.00134094,-3.04765e-06,5.5941e-08,0.604769,0.00133501,-2.87983e-06,-2.56622e-08,0.606101,0.00132917,-2.95681e-06,4.67078e-08,0.607427,0.0013234,-2.81669e-06,-4.19592e-08,0.608748,0.00131764,-2.94257e-06,6.15243e-08,0.610062,0.00131194,-2.75799e-06,-2.53244e-08,0.611372,0.00130635,-2.83397e-06,3.97739e-08,0.612675,0.0013008,-2.71465e-06,-1.45618e-08,0.613973,0.00129533,-2.75833e-06,1.84733e-08,0.615266,0.00128986,-2.70291e-06,2.73606e-10,0.616553,0.00128446,-2.70209e-06,4.00367e-08,0.617835,0.00127918,-2.58198e-06,-4.12113e-08,0.619111,0.00127389,-2.70561e-06,6.52039e-08,0.620383,0.00126867,-2.51e-06,-4.07901e-08,0.621649,0.00126353,-2.63237e-06,3.83516e-08,0.62291,0.00125838,-2.51732e-06,6.59315e-09,0.624166,0.00125337,-2.49754e-06,-5.11939e-09,0.625416,0.00124836,-2.5129e-06,1.38846e-08,0.626662,0.00124337,-2.47124e-06,9.18514e-09,0.627903,0.00123846,-2.44369e-06,8.97952e-09,0.629139,0.0012336,-2.41675e-06,1.45012e-08,0.63037,0.00122881,-2.37325e-06,-7.37949e-09,0.631597,0.00122404,-2.39538e-06,1.50169e-08,0.632818,0.00121929,-2.35033e-06,6.91648e-09,0.634035,0.00121461,-2.32958e-06,1.69219e-08,0.635248,0.00121,-2.27882e-06,-1.49997e-08,0.636455,0.0012054,-2.32382e-06,4.30769e-08,0.637659,0.00120088,-2.19459e-06,-3.80986e-08,0.638857,0.00119638,-2.30888e-06,4.97134e-08,0.640051,0.00119191,-2.15974e-06,-4.15463e-08,0.641241,0.00118747,-2.28438e-06,5.68667e-08,0.642426,0.00118307,-2.11378e-06,-7.10641e-09,0.643607,0.00117882,-2.1351e-06,-2.8441e-08,0.644784,0.00117446,-2.22042e-06,6.12658e-08,0.645956,0.00117021,-2.03663e-06,-3.78083e-08,0.647124,0.00116602,-2.15005e-06,3.03627e-08,0.648288,0.00116181,-2.05896e-06,-2.40379e-08,0.649448,0.00115762,-2.13108e-06,6.57887e-08,0.650603,0.00115356,-1.93371e-06,-6.03028e-08,0.651755,0.00114951,-2.11462e-06,5.62134e-08,0.652902,0.00114545,-1.94598e-06,-4.53417e-08,0.654046,0.00114142,-2.082e-06,6.55489e-08,0.655185,0.00113745,-1.88536e-06,-3.80396e-08,0.656321,0.00113357,-1.99948e-06,2.70049e-08,0.657452,0.00112965,-1.91846e-06,-1.03755e-08,0.65858,0.00112578,-1.94959e-06,1.44973e-08,0.659704,0.00112192,-1.9061e-06,1.1991e-08,0.660824,0.00111815,-1.87012e-06,-2.85634e-09,0.66194,0.0011144,-1.87869e-06,-5.65782e-10,0.663053,0.00111064,-1.88039e-06,5.11947e-09,0.664162,0.0011069,-1.86503e-06,3.96924e-08,0.665267,0.00110328,-1.74595e-06,-4.46795e-08,0.666368,0.00109966,-1.87999e-06,1.98161e-08,0.667466,0.00109596,-1.82054e-06,2.502e-08,0.66856,0.00109239,-1.74548e-06,-6.86593e-10,0.669651,0.0010889,-1.74754e-06,-2.22739e-08,0.670738,0.00108534,-1.81437e-06,3.01776e-08,0.671821,0.0010818,-1.72383e-06,2.07732e-08,0.672902,0.00107841,-1.66151e-06,-5.36658e-08,0.673978,0.00107493,-1.82251e-06,7.46802e-08,0.675051,0.00107151,-1.59847e-06,-6.62411e-08,0.676121,0.00106811,-1.79719e-06,7.10748e-08,0.677188,0.00106473,-1.58397e-06,-3.92441e-08,0.678251,0.00106145,-1.7017e-06,2.62973e-08,0.679311,0.00105812,-1.62281e-06,-6.34035e-09,0.680367,0.00105486,-1.64183e-06,-9.36249e-10,0.68142,0.00105157,-1.64464e-06,1.00854e-08,0.68247,0.00104831,-1.61438e-06,2.01995e-08,0.683517,0.00104514,-1.55378e-06,-3.1279e-08,0.68456,0.00104194,-1.64762e-06,4.53114e-08,0.685601,0.00103878,-1.51169e-06,-3.07573e-08,0.686638,0.00103567,-1.60396e-06,1.81133e-08,0.687672,0.00103251,-1.54962e-06,1.79085e-08,0.688703,0.00102947,-1.49589e-06,-3.01428e-08,0.689731,0.00102639,-1.58632e-06,4.30583e-08,0.690756,0.00102334,-1.45715e-06,-2.28814e-08,0.691778,0.00102036,-1.52579e-06,-1.11373e-08,0.692797,0.00101727,-1.5592e-06,6.74305e-08,0.693812,0.00101436,-1.35691e-06,-7.97709e-08,0.694825,0.0010114,-1.59622e-06,7.28391e-08,0.695835,0.00100843,-1.37771e-06,-3.27715e-08,0.696842,0.00100558,-1.47602e-06,-1.35807e-09,0.697846,0.00100262,-1.48009e-06,3.82037e-08,0.698847,0.000999775,-1.36548e-06,-3.22474e-08,0.699846,0.000996948,-1.46223e-06,3.11809e-08,0.700841,0.000994117,-1.36868e-06,-3.28714e-08,0.701834,0.000991281,-1.4673e-06,4.07001e-08,0.702824,0.000988468,-1.3452e-06,-1.07197e-08,0.703811,0.000985746,-1.37736e-06,2.17866e-09,0.704795,0.000982998,-1.37082e-06,2.00521e-09,0.705777,0.000980262,-1.3648e-06,-1.01996e-08,0.706756,0.000977502,-1.3954e-06,3.87931e-08,0.707732,0.000974827,-1.27902e-06,-2.57632e-08,0.708706,0.000972192,-1.35631e-06,4.65513e-09,0.709676,0.000969493,-1.34235e-06,7.14257e-09,0.710645,0.00096683,-1.32092e-06,2.63791e-08,0.71161,0.000964267,-1.24178e-06,-5.30543e-08,0.712573,0.000961625,-1.40095e-06,6.66289e-08,0.713533,0.000959023,-1.20106e-06,-3.46474e-08,0.714491,0.000956517,-1.305e-06,1.23559e-08,0.715446,0.000953944,-1.26793e-06,-1.47763e-08,0.716399,0.000951364,-1.31226e-06,4.67494e-08,0.717349,0.000948879,-1.17201e-06,-5.3012e-08,0.718297,0.000946376,-1.33105e-06,4.60894e-08,0.719242,0.000943852,-1.19278e-06,-1.21366e-08,0.720185,0.00094143,-1.22919e-06,2.45673e-09,0.721125,0.000938979,-1.22182e-06,2.30966e-09,0.722063,0.000936543,-1.21489e-06,-1.16954e-08,0.722998,0.000934078,-1.24998e-06,4.44718e-08,0.723931,0.000931711,-1.11656e-06,-4.69823e-08,0.724861,0.000929337,-1.25751e-06,2.4248e-08,0.725789,0.000926895,-1.18477e-06,9.5949e-09,0.726715,0.000924554,-1.15598e-06,-3.02286e-09,0.727638,0.000922233,-1.16505e-06,2.49649e-09,0.72856,0.00091991,-1.15756e-06,-6.96321e-09,0.729478,0.000917575,-1.17845e-06,2.53564e-08,0.730395,0.000915294,-1.10238e-06,-3.48578e-08,0.731309,0.000912984,-1.20695e-06,5.44704e-08,0.732221,0.000910734,-1.04354e-06,-6.38144e-08,0.73313,0.000908455,-1.23499e-06,8.15781e-08,0.734038,0.00090623,-9.90253e-07,-8.3684e-08,0.734943,0.000903999,-1.2413e-06,7.43441e-08,0.735846,0.000901739,-1.01827e-06,-3.48787e-08,0.736746,0.000899598,-1.12291e-06,5.56596e-09,0.737645,0.000897369,-1.10621e-06,1.26148e-08,0.738541,0.000895194,-1.06837e-06,3.57935e-09,0.739435,0.000893068,-1.05763e-06,-2.69322e-08,0.740327,0.000890872,-1.13842e-06,4.45448e-08,0.741217,0.000888729,-1.00479e-06,-3.20376e-08,0.742105,0.000886623,-1.1009e-06,2.40011e-08,0.74299,0.000884493,-1.0289e-06,-4.36209e-09,0.743874,0.000882422,-1.04199e-06,-6.55268e-09,0.744755,0.000880319,-1.06164e-06,3.05728e-08,0.745634,0.000878287,-9.69926e-07,-5.61338e-08,0.746512,0.000876179,-1.13833e-06,7.4753e-08,0.747387,0.000874127,-9.14068e-07,-6.40644e-08,0.74826,0.000872106,-1.10626e-06,6.22955e-08,0.749131,0.000870081,-9.19375e-07,-6.59083e-08,0.75,0.000868044,-1.1171e-06,8.21284e-08,0.750867,0.000866056,-8.70714e-07,-8.37915e-08,0.751732,0.000864064,-1.12209e-06,7.42237e-08,0.752595,0.000862042,-8.99418e-07,-3.42894e-08,0.753456,0.00086014,-1.00229e-06,3.32955e-09,0.754315,0.000858146,-9.92297e-07,2.09712e-08,0.755173,0.000856224,-9.29384e-07,-2.76096e-08,0.756028,0.000854282,-1.01221e-06,2.98627e-08,0.756881,0.000852348,-9.22625e-07,-3.22365e-08,0.757733,0.000850406,-1.01933e-06,3.94786e-08,0.758582,0.000848485,-9.00898e-07,-6.46833e-09,0.75943,0.000846664,-9.20303e-07,-1.36052e-08,0.760275,0.000844783,-9.61119e-07,1.28447e-09,0.761119,0.000842864,-9.57266e-07,8.4674e-09,0.761961,0.000840975,-9.31864e-07,2.44506e-08,0.762801,0.000839185,-8.58512e-07,-4.6665e-08,0.763639,0.000837328,-9.98507e-07,4.30001e-08,0.764476,0.00083546,-8.69507e-07,-6.12609e-09,0.76531,0.000833703,-8.87885e-07,-1.84959e-08,0.766143,0.000831871,-9.43372e-07,2.05052e-08,0.766974,0.000830046,-8.81857e-07,-3.92026e-09,0.767803,0.000828271,-8.93618e-07,-4.82426e-09,0.768631,0.000826469,-9.0809e-07,2.32172e-08,0.769456,0.000824722,-8.38439e-07,-2.84401e-08,0.77028,0.00082296,-9.23759e-07,3.09386e-08,0.771102,0.000821205,-8.30943e-07,-3.57099e-08,0.771922,0.000819436,-9.38073e-07,5.22963e-08,0.772741,0.000817717,-7.81184e-07,-5.42658e-08,0.773558,0.000815992,-9.43981e-07,4.55579e-08,0.774373,0.000814241,-8.07308e-07,-8.75656e-09,0.775186,0.0008126,-8.33578e-07,-1.05315e-08,0.775998,0.000810901,-8.65172e-07,-8.72188e-09,0.776808,0.000809145,-8.91338e-07,4.54191e-08,0.777616,0.000807498,-7.5508e-07,-5.37454e-08,0.778423,0.000805827,-9.16317e-07,5.03532e-08,0.779228,0.000804145,-7.65257e-07,-2.84584e-08,0.780031,0.000802529,-8.50632e-07,3.87579e-09,0.780833,0.00080084,-8.39005e-07,1.29552e-08,0.781633,0.0007992,-8.00139e-07,3.90804e-09,0.782432,0.000797612,-7.88415e-07,-2.85874e-08,0.783228,0.000795949,-8.74177e-07,5.0837e-08,0.784023,0.000794353,-7.21666e-07,-5.55513e-08,0.784817,0.000792743,-8.8832e-07,5.21587e-08,0.785609,0.000791123,-7.31844e-07,-3.38744e-08,0.786399,0.000789558,-8.33467e-07,2.37342e-08,0.787188,0.000787962,-7.62264e-07,-1.45775e-09,0.787975,0.000786433,-7.66638e-07,-1.79034e-08,0.788761,0.000784846,-8.20348e-07,1.34665e-08,0.789545,0.000783246,-7.79948e-07,2.3642e-08,0.790327,0.000781757,-7.09022e-07,-4.84297e-08,0.791108,0.000780194,-8.54311e-07,5.08674e-08,0.791888,0.000778638,-7.01709e-07,-3.58303e-08,0.792666,0.000777127,-8.092e-07,3.28493e-08,0.793442,0.000775607,-7.10652e-07,-3.59624e-08,0.794217,0.000774078,-8.1854e-07,5.13959e-08,0.79499,0.000772595,-6.64352e-07,-5.04121e-08,0.795762,0.000771115,-8.15588e-07,3.10431e-08,0.796532,0.000769577,-7.22459e-07,-1.41557e-08,0.797301,0.00076809,-7.64926e-07,2.55795e-08,0.798069,0.000766636,-6.88187e-07,-2.85578e-08,0.798835,0.000765174,-7.73861e-07,2.90472e-08,0.799599,0.000763714,-6.86719e-07,-2.80262e-08,0.800362,0.000762256,-7.70798e-07,2.34531e-08,0.801123,0.000760785,-7.00438e-07,-6.18144e-09,0.801884,0.000759366,-7.18983e-07,1.27263e-09,0.802642,0.000757931,-7.15165e-07,1.09101e-09,0.803399,0.000756504,-7.11892e-07,-5.63675e-09,0.804155,0.000755064,-7.28802e-07,2.14559e-08,0.80491,0.00075367,-6.64434e-07,-2.05821e-08,0.805663,0.00075228,-7.26181e-07,1.26812e-09,0.806414,0.000750831,-7.22377e-07,1.55097e-08,0.807164,0.000749433,-6.75848e-07,-3.70216e-09,0.807913,0.00074807,-6.86954e-07,-7.0105e-10,0.80866,0.000746694,-6.89057e-07,6.5063e-09,0.809406,0.000745336,-6.69538e-07,-2.53242e-08,0.810151,0.000743921,-7.45511e-07,3.51858e-08,0.810894,0.000742535,-6.39953e-07,3.79034e-09,0.811636,0.000741267,-6.28582e-07,-5.03471e-08,0.812377,0.000739858,-7.79624e-07,7.83886e-08,0.813116,0.000738534,-5.44458e-07,-8.43935e-08,0.813854,0.000737192,-7.97638e-07,8.03714e-08,0.81459,0.000735838,-5.56524e-07,-5.82784e-08,0.815325,0.00073455,-7.31359e-07,3.35329e-08,0.816059,0.000733188,-6.3076e-07,-1.62486e-08,0.816792,0.000731878,-6.79506e-07,3.14614e-08,0.817523,0.000730613,-5.85122e-07,-4.99925e-08,0.818253,0.000729293,-7.35099e-07,4.92994e-08,0.818982,0.000727971,-5.87201e-07,-2.79959e-08,0.819709,0.000726712,-6.71189e-07,3.07959e-09,0.820435,0.000725379,-6.6195e-07,1.56777e-08,0.82116,0.000724102,-6.14917e-07,-6.18564e-09,0.821883,0.000722854,-6.33474e-07,9.06488e-09,0.822606,0.000721614,-6.06279e-07,-3.00739e-08,0.823327,0.000720311,-6.96501e-07,5.16262e-08,0.824046,0.000719073,-5.41623e-07,-5.72214e-08,0.824765,0.000717818,-7.13287e-07,5.80503e-08,0.825482,0.000716566,-5.39136e-07,-5.57703e-08,0.826198,0.00071532,-7.06447e-07,4.58215e-08,0.826912,0.000714045,-5.68983e-07,-8.30636e-09,0.827626,0.000712882,-5.93902e-07,-1.25961e-08,0.828338,0.000711656,-6.3169e-07,-9.13985e-10,0.829049,0.00071039,-6.34432e-07,1.62519e-08,0.829759,0.00070917,-5.85676e-07,-4.48904e-09,0.830468,0.000707985,-5.99143e-07,1.70418e-09,0.831175,0.000706792,-5.9403e-07,-2.32768e-09,0.831881,0.000705597,-6.01014e-07,7.60648e-09,0.832586,0.000704418,-5.78194e-07,-2.80982e-08,0.83329,0.000703177,-6.62489e-07,4.51817e-08,0.833993,0.000701988,-5.26944e-07,-3.34192e-08,0.834694,0.000700834,-6.27201e-07,2.88904e-08,0.835394,0.000699666,-5.4053e-07,-2.25378e-08,0.836093,0.000698517,-6.08143e-07,1.65589e-09,0.836791,0.000697306,-6.03176e-07,1.59142e-08,0.837488,0.000696147,-5.55433e-07,-5.70801e-09,0.838184,0.000695019,-5.72557e-07,6.91792e-09,0.838878,0.000693895,-5.51803e-07,-2.19637e-08,0.839571,0.000692725,-6.17694e-07,2.13321e-08,0.840263,0.000691554,-5.53698e-07,-3.75996e-09,0.840954,0.000690435,-5.64978e-07,-6.29219e-09,0.841644,0.000689287,-5.83855e-07,2.89287e-08,0.842333,0.000688206,-4.97068e-07,-4.98181e-08,0.843021,0.000687062,-6.46523e-07,5.11344e-08,0.843707,0.000685922,-4.9312e-07,-3.55102e-08,0.844393,0.00068483,-5.9965e-07,3.13019e-08,0.845077,0.000683724,-5.05745e-07,-3.00925e-08,0.84576,0.000682622,-5.96022e-07,2.94636e-08,0.846442,0.000681519,-5.07631e-07,-2.81572e-08,0.847123,0.000680419,-5.92103e-07,2.35606e-08,0.847803,0.000679306,-5.21421e-07,-6.48045e-09,0.848482,0.000678243,-5.40863e-07,2.36124e-09,0.849159,0.000677169,-5.33779e-07,-2.96461e-09,0.849836,0.000676092,-5.42673e-07,9.49728e-09,0.850512,0.000675035,-5.14181e-07,-3.50245e-08,0.851186,0.000673902,-6.19254e-07,7.09959e-08,0.851859,0.000672876,-4.06267e-07,-7.01453e-08,0.852532,0.000671853,-6.16703e-07,3.07714e-08,0.853203,0.000670712,-5.24388e-07,6.66423e-09,0.853873,0.000669684,-5.04396e-07,2.17629e-09,0.854542,0.000668681,-4.97867e-07,-1.53693e-08,0.855211,0.000667639,-5.43975e-07,-3.03752e-10,0.855878,0.000666551,-5.44886e-07,1.65844e-08,0.856544,0.000665511,-4.95133e-07,-6.42907e-09,0.857209,0.000664501,-5.1442e-07,9.13195e-09,0.857873,0.0006635,-4.87024e-07,-3.00987e-08,0.858536,0.000662435,-5.7732e-07,5.16584e-08,0.859198,0.000661436,-4.22345e-07,-5.73255e-08,0.859859,0.000660419,-5.94322e-07,5.84343e-08,0.860518,0.000659406,-4.19019e-07,-5.72022e-08,0.861177,0.000658396,-5.90626e-07,5.11653e-08,0.861835,0.000657368,-4.3713e-07,-2.82495e-08,0.862492,0.000656409,-5.21878e-07,2.22788e-09,0.863148,0.000655372,-5.15195e-07,1.9338e-08,0.863803,0.0006544,-4.5718e-07,-1.99754e-08,0.864457,0.000653425,-5.17107e-07,9.59024e-10,0.86511,0.000652394,-5.1423e-07,1.61393e-08,0.865762,0.000651414,-4.65812e-07,-5.91149e-09,0.866413,0.000650465,-4.83546e-07,7.50665e-09,0.867063,0.00064952,-4.61026e-07,-2.4115e-08,0.867712,0.000648526,-5.33371e-07,2.93486e-08,0.86836,0.000647547,-4.45325e-07,-3.36748e-08,0.869007,0.000646555,-5.4635e-07,4.57461e-08,0.869653,0.0006456,-4.09112e-07,-3.01002e-08,0.870298,0.000644691,-4.99412e-07,1.50501e-08,0.870942,0.000643738,-4.54262e-07,-3.01002e-08,0.871585,0.000642739,-5.44563e-07,4.57461e-08,0.872228,0.000641787,-4.07324e-07,-3.36748e-08,0.872869,0.000640871,-5.08349e-07,2.93486e-08,0.873509,0.000639943,-4.20303e-07,-2.4115e-08,0.874149,0.00063903,-4.92648e-07,7.50655e-09,0.874787,0.000638067,-4.70128e-07,-5.91126e-09,0.875425,0.000637109,-4.87862e-07,1.61385e-08,0.876062,0.000636182,-4.39447e-07,9.61961e-10,0.876697,0.000635306,-4.36561e-07,-1.99863e-08,0.877332,0.000634373,-4.9652e-07,1.93785e-08,0.877966,0.000633438,-4.38384e-07,2.07697e-09,0.878599,0.000632567,-4.32153e-07,-2.76864e-08,0.879231,0.00063162,-5.15212e-07,4.90641e-08,0.879862,0.000630737,-3.6802e-07,-4.93606e-08,0.880493,0.000629852,-5.16102e-07,2.9169e-08,0.881122,0.000628908,-4.28595e-07,-7.71083e-09,0.881751,0.000628027,-4.51727e-07,1.6744e-09,0.882378,0.000627129,-4.46704e-07,1.01317e-09,0.883005,0.000626239,-4.43665e-07,-5.72703e-09,0.883631,0.000625334,-4.60846e-07,2.1895e-08,0.884255,0.000624478,-3.95161e-07,-2.22481e-08,0.88488,0.000623621,-4.61905e-07,7.4928e-09,0.885503,0.00062272,-4.39427e-07,-7.72306e-09,0.886125,0.000621818,-4.62596e-07,2.33995e-08,0.886746,0.000620963,-3.92398e-07,-2.62704e-08,0.887367,0.000620099,-4.71209e-07,2.20775e-08,0.887987,0.000619223,-4.04976e-07,-2.43496e-09,0.888605,0.000618406,-4.12281e-07,-1.23377e-08,0.889223,0.000617544,-4.49294e-07,-7.81876e-09,0.88984,0.000616622,-4.72751e-07,4.36128e-08,0.890457,0.000615807,-3.41912e-07,-4.7423e-08,0.891072,0.000614981,-4.84181e-07,2.68698e-08,0.891687,0.000614093,-4.03572e-07,-4.51384e-10,0.8923,0.000613285,-4.04926e-07,-2.50643e-08,0.892913,0.0006124,-4.80119e-07,4.11038e-08,0.893525,0.000611563,-3.56808e-07,-2.01414e-08,0.894136,0.000610789,-4.17232e-07,-2.01426e-08,0.894747,0.000609894,-4.7766e-07,4.11073e-08,0.895356,0.000609062,-3.54338e-07,-2.50773e-08,0.895965,0.000608278,-4.2957e-07,-4.02954e-10,0.896573,0.000607418,-4.30779e-07,2.66891e-08,0.89718,0.000606636,-3.50711e-07,-4.67489e-08,0.897786,0.000605795,-4.90958e-07,4.10972e-08,0.898391,0.000604936,-3.67666e-07,1.56948e-09,0.898996,0.000604205,-3.62958e-07,-4.73751e-08,0.8996,0.000603337,-5.05083e-07,6.87214e-08,0.900202,0.000602533,-2.98919e-07,-4.86966e-08,0.900805,0.000601789,-4.45009e-07,6.85589e-09,0.901406,0.00060092,-4.24441e-07,2.1273e-08,0.902007,0.000600135,-3.60622e-07,-3.23434e-08,0.902606,0.000599317,-4.57652e-07,4.84959e-08,0.903205,0.000598547,-3.12164e-07,-4.24309e-08,0.903803,0.000597795,-4.39457e-07,2.01844e-09,0.904401,0.000596922,-4.33402e-07,3.43571e-08,0.904997,0.000596159,-3.30331e-07,-2.02374e-08,0.905593,0.000595437,-3.91043e-07,-1.30123e-08,0.906188,0.000594616,-4.3008e-07,1.26819e-08,0.906782,0.000593794,-3.92034e-07,2.18894e-08,0.907376,0.000593076,-3.26366e-07,-4.06349e-08,0.907968,0.000592301,-4.4827e-07,2.1441e-08,0.90856,0.000591469,-3.83947e-07,1.44754e-08,0.909151,0.000590744,-3.40521e-07,-1.97379e-08,0.909742,0.000590004,-3.99735e-07,4.87161e-09,0.910331,0.000589219,-3.8512e-07,2.51532e-10,0.91092,0.00058845,-3.84366e-07,-5.87776e-09,0.911508,0.000587663,-4.01999e-07,2.32595e-08,0.912096,0.000586929,-3.3222e-07,-2.75554e-08,0.912682,0.000586182,-4.14887e-07,2.73573e-08,0.913268,0.000585434,-3.32815e-07,-2.22692e-08,0.913853,0.000584702,-3.99622e-07,2.11486e-09,0.914437,0.000583909,-3.93278e-07,1.38098e-08,0.915021,0.000583164,-3.51848e-07,2.25042e-09,0.915604,0.000582467,-3.45097e-07,-2.28115e-08,0.916186,0.000581708,-4.13531e-07,2.93911e-08,0.916767,0.000580969,-3.25358e-07,-3.51481e-08,0.917348,0.000580213,-4.30803e-07,5.15967e-08,0.917928,0.000579506,-2.76012e-07,-5.20296e-08,0.918507,0.000578798,-4.32101e-07,3.73124e-08,0.919085,0.000578046,-3.20164e-07,-3.76154e-08,0.919663,0.000577293,-4.3301e-07,5.35447e-08,0.92024,0.000576587,-2.72376e-07,-5.7354e-08,0.920816,0.000575871,-4.44438e-07,5.66621e-08,0.921391,0.000575152,-2.74452e-07,-5.00851e-08,0.921966,0.000574453,-4.24707e-07,2.4469e-08,0.92254,0.000573677,-3.513e-07,1.18138e-08,0.923114,0.000573009,-3.15859e-07,-1.21195e-08,0.923686,0.000572341,-3.52217e-07,-2.29403e-08,0.924258,0.000571568,-4.21038e-07,4.4276e-08,0.924829,0.000570859,-2.8821e-07,-3.49546e-08,0.9254,0.000570178,-3.93074e-07,3.59377e-08,0.92597,0.000569499,-2.85261e-07,-4.91915e-08,0.926539,0.000568781,-4.32835e-07,4.16189e-08,0.927107,0.00056804,-3.07979e-07,1.92523e-09,0.927675,0.00056743,-3.02203e-07,-4.93198e-08,0.928242,0.000566678,-4.50162e-07,7.61447e-08,0.928809,0.000566006,-2.21728e-07,-7.6445e-08,0.929374,0.000565333,-4.51063e-07,5.08216e-08,0.929939,0.000564583,-2.98599e-07,-7.63212e-09,0.930503,0.000563963,-3.21495e-07,-2.02931e-08,0.931067,0.000563259,-3.82374e-07,2.92001e-08,0.93163,0.000562582,-2.94774e-07,-3.69025e-08,0.932192,0.000561882,-4.05482e-07,5.88053e-08,0.932754,0.000561247,-2.29066e-07,-7.91094e-08,0.933315,0.000560552,-4.66394e-07,7.88184e-08,0.933875,0.000559856,-2.29939e-07,-5.73501e-08,0.934434,0.000559224,-4.01989e-07,3.13727e-08,0.934993,0.000558514,-3.07871e-07,-8.53611e-09,0.935551,0.000557873,-3.33479e-07,2.77175e-09,0.936109,0.000557214,-3.25164e-07,-2.55091e-09,0.936666,0.000556556,-3.32817e-07,7.43188e-09,0.937222,0.000555913,-3.10521e-07,-2.71766e-08,0.937778,0.00055521,-3.92051e-07,4.167e-08,0.938333,0.000554551,-2.67041e-07,-2.02941e-08,0.938887,0.000553956,-3.27923e-07,-2.00984e-08,0.93944,0.00055324,-3.88218e-07,4.10828e-08,0.939993,0.000552587,-2.6497e-07,-2.50237e-08,0.940546,0.000551982,-3.40041e-07,-5.92583e-10,0.941097,0.0005513,-3.41819e-07,2.7394e-08,0.941648,0.000550698,-2.59637e-07,-4.93788e-08,0.942199,0.000550031,-4.07773e-07,5.09119e-08,0.942748,0.000549368,-2.55038e-07,-3.50595e-08,0.943297,0.000548753,-3.60216e-07,2.97214e-08,0.943846,0.000548122,-2.71052e-07,-2.42215e-08,0.944394,0.000547507,-3.43716e-07,7.55985e-09,0.944941,0.000546842,-3.21037e-07,-6.01796e-09,0.945487,0.000546182,-3.3909e-07,1.65119e-08,0.946033,0.000545553,-2.89555e-07,-4.2498e-10,0.946578,0.000544973,-2.9083e-07,-1.4812e-08,0.947123,0.000544347,-3.35266e-07,6.83068e-11,0.947667,0.000543676,-3.35061e-07,1.45388e-08,0.94821,0.00054305,-2.91444e-07,1.38123e-09,0.948753,0.000542471,-2.87301e-07,-2.00637e-08,0.949295,0.000541836,-3.47492e-07,1.92688e-08,0.949837,0.000541199,-2.89685e-07,2.59298e-09,0.950378,0.000540628,-2.81906e-07,-2.96407e-08,0.950918,0.000539975,-3.70829e-07,5.63652e-08,0.951458,0.000539402,-2.01733e-07,-7.66107e-08,0.951997,0.000538769,-4.31565e-07,7.12638e-08,0.952535,0.00053812,-2.17774e-07,-2.96305e-08,0.953073,0.000537595,-3.06665e-07,-1.23464e-08,0.95361,0.000536945,-3.43704e-07,1.94114e-08,0.954147,0.000536316,-2.8547e-07,-5.69451e-09,0.954683,0.000535728,-3.02554e-07,3.36666e-09,0.955219,0.000535133,-2.92454e-07,-7.77208e-09,0.955753,0.000534525,-3.1577e-07,2.77216e-08,0.956288,0.000533976,-2.32605e-07,-4.35097e-08,0.956821,0.00053338,-3.63134e-07,2.7108e-08,0.957354,0.000532735,-2.8181e-07,-5.31772e-09,0.957887,0.000532156,-2.97764e-07,-5.83718e-09,0.958419,0.000531543,-3.15275e-07,2.86664e-08,0.95895,0.000530998,-2.29276e-07,-4.9224e-08,0.959481,0.000530392,-3.76948e-07,4.90201e-08,0.960011,0.000529785,-2.29887e-07,-2.76471e-08,0.96054,0.000529243,-3.12829e-07,1.96385e-09,0.961069,0.000528623,-3.06937e-07,1.97917e-08,0.961598,0.000528068,-2.47562e-07,-2.15261e-08,0.962125,0.000527508,-3.1214e-07,6.70795e-09,0.962653,0.000526904,-2.92016e-07,-5.30573e-09,0.963179,0.000526304,-3.07934e-07,1.4515e-08,0.963705,0.000525732,-2.64389e-07,6.85048e-09,0.964231,0.000525224,-2.43837e-07,-4.19169e-08,0.964756,0.00052461,-3.69588e-07,4.1608e-08,0.96528,0.000523996,-2.44764e-07,-5.30598e-09,0.965804,0.000523491,-2.60682e-07,-2.03841e-08,0.966327,0.000522908,-3.21834e-07,2.72378e-08,0.966849,0.000522346,-2.40121e-07,-2.89625e-08,0.967371,0.000521779,-3.27008e-07,2.90075e-08,0.967893,0.000521212,-2.39986e-07,-2.74629e-08,0.968414,0.00052065,-3.22374e-07,2.12396e-08,0.968934,0.000520069,-2.58656e-07,2.10922e-09,0.969454,0.000519558,-2.52328e-07,-2.96765e-08,0.969973,0.000518964,-3.41357e-07,5.6992e-08,0.970492,0.000518452,-1.70382e-07,-7.90821e-08,0.97101,0.000517874,-4.07628e-07,8.05224e-08,0.971528,0.000517301,-1.66061e-07,-6.41937e-08,0.972045,0.000516776,-3.58642e-07,5.70429e-08,0.972561,0.00051623,-1.87513e-07,-4.47686e-08,0.973077,0.00051572,-3.21819e-07,2.82237e-09,0.973593,0.000515085,-3.13352e-07,3.34792e-08,0.974108,0.000514559,-2.12914e-07,-1.75298e-08,0.974622,0.000514081,-2.65503e-07,-2.29648e-08,0.975136,0.000513481,-3.34398e-07,4.97843e-08,0.975649,0.000512961,-1.85045e-07,-5.6963e-08,0.976162,0.00051242,-3.55934e-07,5.88585e-08,0.976674,0.000511885,-1.79359e-07,-5.92616e-08,0.977185,0.000511348,-3.57143e-07,5.89785e-08,0.977696,0.000510811,-1.80208e-07,-5.74433e-08,0.978207,0.000510278,-3.52538e-07,5.15854e-08,0.978717,0.000509728,-1.97781e-07,-2.9689e-08,0.979226,0.000509243,-2.86848e-07,7.56591e-09,0.979735,0.000508692,-2.64151e-07,-5.74649e-10,0.980244,0.000508162,-2.65875e-07,-5.26732e-09,0.980752,0.000507615,-2.81677e-07,2.16439e-08,0.981259,0.000507116,-2.16745e-07,-2.17037e-08,0.981766,0.000506618,-2.81856e-07,5.56636e-09,0.982272,0.000506071,-2.65157e-07,-5.61689e-10,0.982778,0.000505539,-2.66842e-07,-3.31963e-09,0.983283,0.000504995,-2.76801e-07,1.38402e-08,0.983788,0.000504483,-2.3528e-07,7.56339e-09,0.984292,0.000504035,-2.1259e-07,-4.40938e-08,0.984796,0.000503478,-3.44871e-07,4.96026e-08,0.985299,0.000502937,-1.96064e-07,-3.51071e-08,0.985802,0.000502439,-3.01385e-07,3.12212e-08,0.986304,0.00050193,-2.07721e-07,-3.0173e-08,0.986806,0.000501424,-2.9824e-07,2.9866e-08,0.987307,0.000500917,-2.08642e-07,-2.96865e-08,0.987808,0.000500411,-2.97702e-07,2.92753e-08,0.988308,0.000499903,-2.09876e-07,-2.78101e-08,0.988807,0.0004994,-2.93306e-07,2.23604e-08,0.989307,0.000498881,-2.26225e-07,-2.02681e-09,0.989805,0.000498422,-2.32305e-07,-1.42531e-08,0.990303,0.000497915,-2.75065e-07,-5.65232e-10,0.990801,0.000497363,-2.76761e-07,1.65141e-08,0.991298,0.000496859,-2.27218e-07,-5.88639e-09,0.991795,0.000496387,-2.44878e-07,7.0315e-09,0.992291,0.000495918,-2.23783e-07,-2.22396e-08,0.992787,0.000495404,-2.90502e-07,2.23224e-08,0.993282,0.00049489,-2.23535e-07,-7.44543e-09,0.993776,0.000494421,-2.45871e-07,7.45924e-09,0.994271,0.000493951,-2.23493e-07,-2.23915e-08,0.994764,0.000493437,-2.90668e-07,2.25021e-08,0.995257,0.000492923,-2.23161e-07,-8.01218e-09,0.99575,0.000492453,-2.47198e-07,9.54669e-09,0.996242,0.000491987,-2.18558e-07,-3.01746e-08,0.996734,0.000491459,-3.09082e-07,5.1547e-08,0.997225,0.000490996,-1.54441e-07,-5.68039e-08,0.997716,0.000490517,-3.24853e-07,5.64594e-08,0.998206,0.000490036,-1.55474e-07,-4.98245e-08,0.998696,0.000489576,-3.04948e-07,2.36292e-08,0.999186,0.000489037,-2.3406e-07,1.49121e-08,0.999674,0.000488613,-1.89324e-07,-2.3673e-08,1.00016,0.000488164,-2.60343e-07,2.01754e-08,1.00065,0.000487704,-1.99816e-07,-5.70288e-08,1.00114,0.000487133,-3.70903e-07,8.87303e-08,1.00162,0.000486657,-1.04712e-07,-5.94737e-08,1.00211,0.000486269,-2.83133e-07,2.99553e-08,1.0026,0.000485793,-1.93267e-07,-6.03474e-08,1.00308,0.000485225,-3.74309e-07,9.2225e-08,1.00357,0.000484754,-9.76345e-08,-7.0134e-08,1.00405,0.000484348,-3.08036e-07,6.91016e-08,1.00454,0.000483939,-1.00731e-07,-8.70633e-08,1.00502,0.000483476,-3.61921e-07,4.07328e-08,1.0055,0.000482875,-2.39723e-07,4.33413e-08,1.00599,0.000482525,-1.09699e-07,-9.48886e-08,1.00647,0.000482021,-3.94365e-07,9.77947e-08,1.00695,0.000481526,-1.00981e-07,-5.78713e-08,1.00743,0.00048115,-2.74595e-07,1.44814e-08,1.00791,0.000480645,-2.31151e-07,-5.42665e-11,1.00839,0.000480182,-2.31314e-07,-1.42643e-08,1.00887,0.000479677,-2.74106e-07,5.71115e-08,1.00935,0.0004793,-1.02772e-07,-9.49724e-08,1.00983,0.000478809,-3.87689e-07,8.43596e-08,1.01031,0.000478287,-1.3461e-07,-4.04755e-09,1.01079,0.000478006,-1.46753e-07,-6.81694e-08,1.01127,0.000477508,-3.51261e-07,3.83067e-08,1.01174,0.00047692,-2.36341e-07,3.41521e-08,1.01222,0.00047655,-1.33885e-07,-5.57058e-08,1.0127,0.000476115,-3.01002e-07,6.94616e-08,1.01317,0.000475721,-9.26174e-08,-1.02931e-07,1.01365,0.000475227,-4.01412e-07,1.03846e-07,1.01412,0.000474736,-8.98751e-08,-7.40321e-08,1.0146,0.000474334,-3.11971e-07,7.30735e-08,1.01507,0.00047393,-9.27508e-08,-9.90527e-08,1.01554,0.000473447,-3.89909e-07,8.47188e-08,1.01602,0.000472921,-1.35753e-07,-1.40381e-09,1.01649,0.000472645,-1.39964e-07,-7.91035e-08,1.01696,0.000472128,-3.77275e-07,7.93993e-08,1.01744,0.000471612,-1.39077e-07,-7.52607e-11,1.01791,0.000471334,-1.39302e-07,-7.90983e-08,1.01838,0.000470818,-3.76597e-07,7.80499e-08,1.01885,0.000470299,-1.42448e-07,5.31733e-09,1.01932,0.00047003,-1.26496e-07,-9.93193e-08,1.01979,0.000469479,-4.24453e-07,1.53541e-07,1.02026,0.00046909,3.617e-08,-1.57217e-07,1.02073,0.000468691,-4.35482e-07,1.177e-07,1.02119,0.000468173,-8.23808e-08,-7.51659e-08,1.02166,0.000467783,-3.07878e-07,6.37538e-08,1.02213,0.000467358,-1.16617e-07,-6.064e-08,1.0226,0.000466943,-2.98537e-07,5.9597e-08,1.02306,0.000466525,-1.19746e-07,-5.85386e-08,1.02353,0.00046611,-2.95362e-07,5.53482e-08,1.024,0.000465685,-1.29317e-07,-4.36449e-08,1.02446,0.000465296,-2.60252e-07,2.20268e-11,1.02493,0.000464775,-2.60186e-07,4.35568e-08,1.02539,0.000464386,-1.29516e-07,-5.50398e-08,1.02586,0.000463961,-2.94635e-07,5.73932e-08,1.02632,0.000463544,-1.22456e-07,-5.53236e-08,1.02678,0.000463133,-2.88426e-07,4.46921e-08,1.02725,0.000462691,-1.5435e-07,-4.23534e-09,1.02771,0.000462369,-1.67056e-07,-2.77507e-08,1.02817,0.000461952,-2.50308e-07,-3.97101e-09,1.02863,0.000461439,-2.62221e-07,4.36348e-08,1.02909,0.000461046,-1.31317e-07,-5.13589e-08,1.02955,0.000460629,-2.85394e-07,4.25913e-08,1.03001,0.000460186,-1.5762e-07,2.0285e-10,1.03047,0.000459871,-1.57011e-07,-4.34027e-08,1.03093,0.000459427,-2.87219e-07,5.41987e-08,1.03139,0.000459015,-1.24623e-07,-5.4183e-08,1.03185,0.000458604,-2.87172e-07,4.33239e-08,1.03231,0.000458159,-1.572e-07,9.65817e-11,1.03277,0.000457845,-1.56911e-07,-4.37103e-08,1.03323,0.0004574,-2.88041e-07,5.55351e-08,1.03368,0.000456991,-1.21436e-07,-5.9221e-08,1.03414,0.00045657,-2.99099e-07,6.21394e-08,1.0346,0.000456158,-1.1268e-07,-7.01275e-08,1.03505,0.000455723,-3.23063e-07,9.91614e-08,1.03551,0.000455374,-2.55788e-08,-8.80996e-08,1.03596,0.000455058,-2.89878e-07,1.48184e-08,1.03642,0.000454523,-2.45422e-07,2.88258e-08,1.03687,0.000454119,-1.58945e-07,-1.09125e-08,1.03733,0.000453768,-1.91682e-07,1.48241e-08,1.03778,0.000453429,-1.4721e-07,-4.83838e-08,1.03823,0.00045299,-2.92361e-07,5.95019e-08,1.03869,0.000452584,-1.13856e-07,-7.04146e-08,1.03914,0.000452145,-3.25099e-07,1.02947e-07,1.03959,0.000451803,-1.62583e-08,-1.02955e-07,1.04004,0.000451462,-3.25123e-07,7.04544e-08,1.04049,0.000451023,-1.1376e-07,-5.96534e-08,1.04094,0.000450616,-2.9272e-07,4.89499e-08,1.04139,0.000450178,-1.45871e-07,-1.69369e-08,1.04184,0.000449835,-1.96681e-07,1.87977e-08,1.04229,0.000449498,-1.40288e-07,-5.82539e-08,1.04274,0.000449043,-3.1505e-07,9.50087e-08,1.04319,0.000448698,-3.00238e-08,-8.33623e-08,1.04364,0.000448388,-2.80111e-07,2.20363e-11,1.04409,0.000447828,-2.80045e-07,8.32742e-08,1.04454,0.000447517,-3.02221e-08,-9.47002e-08,1.04498,0.000447173,-3.14323e-07,5.7108e-08,1.04543,0.000446716,-1.42999e-07,-1.45225e-08,1.04588,0.000446386,-1.86566e-07,9.82022e-10,1.04632,0.000446016,-1.8362e-07,1.05944e-08,1.04677,0.00044568,-1.51837e-07,-4.33597e-08,1.04721,0.000445247,-2.81916e-07,4.36352e-08,1.04766,0.000444814,-1.51011e-07,-1.19717e-08,1.0481,0.000444476,-1.86926e-07,4.25158e-09,1.04855,0.000444115,-1.74171e-07,-5.03461e-09,1.04899,0.000443751,-1.89275e-07,1.58868e-08,1.04944,0.00044342,-1.41614e-07,-5.85127e-08,1.04988,0.000442961,-3.17152e-07,9.89548e-08,1.05032,0.000442624,-2.0288e-08,-9.88878e-08,1.05076,0.000442287,-3.16951e-07,5.81779e-08,1.05121,0.000441827,-1.42418e-07,-1.46144e-08,1.05165,0.000441499,-1.86261e-07,2.79892e-10,1.05209,0.000441127,-1.85421e-07,1.34949e-08,1.05253,0.000440797,-1.44937e-07,-5.42594e-08,1.05297,0.000440344,-3.07715e-07,8.43335e-08,1.05341,0.000439982,-5.47146e-08,-4.46558e-08,1.05385,0.000439738,-1.88682e-07,-2.49193e-08,1.05429,0.000439286,-2.6344e-07,2.5124e-08,1.05473,0.000438835,-1.88068e-07,4.36328e-08,1.05517,0.000438589,-5.71699e-08,-8.04459e-08,1.05561,0.000438234,-2.98508e-07,3.97324e-08,1.05605,0.000437756,-1.79311e-07,4.07258e-08,1.05648,0.000437519,-5.71332e-08,-8.34263e-08,1.05692,0.000437155,-3.07412e-07,5.45608e-08,1.05736,0.000436704,-1.4373e-07,-1.56078e-08,1.05779,0.000436369,-1.90553e-07,7.87043e-09,1.05823,0.000436012,-1.66942e-07,-1.58739e-08,1.05867,0.00043563,-2.14563e-07,5.56251e-08,1.0591,0.000435368,-4.76881e-08,-8.74172e-08,1.05954,0.000435011,-3.0994e-07,5.56251e-08,1.05997,0.000434558,-1.43064e-07,-1.58739e-08,1.06041,0.000434224,-1.90686e-07,7.87042e-09,1.06084,0.000433866,-1.67075e-07,-1.56078e-08,1.06127,0.000433485,-2.13898e-07,5.45609e-08,1.06171,0.000433221,-5.02157e-08,-8.34263e-08,1.06214,0.00043287,-3.00495e-07,4.07258e-08,1.06257,0.000432391,-1.78317e-07,3.97325e-08,1.063,0.000432154,-5.91198e-08,-8.04464e-08,1.06344,0.000431794,-3.00459e-07,4.36347e-08,1.06387,0.000431324,-1.69555e-07,2.5117e-08,1.0643,0.000431061,-9.42041e-08,-2.48934e-08,1.06473,0.000430798,-1.68884e-07,-4.47527e-08,1.06516,0.000430326,-3.03142e-07,8.46951e-08,1.06559,0.000429973,-4.90573e-08,-5.56089e-08,1.06602,0.000429708,-2.15884e-07,1.85314e-08,1.06645,0.000429332,-1.6029e-07,-1.85166e-08,1.06688,0.000428956,-2.1584e-07,5.5535e-08,1.06731,0.000428691,-4.92347e-08,-8.44142e-08,1.06774,0.000428339,-3.02477e-07,4.37032e-08,1.06816,0.000427865,-1.71368e-07,2.88107e-08,1.06859,0.000427609,-8.49356e-08,-3.97367e-08,1.06902,0.00042732,-2.04146e-07,1.09267e-08,1.06945,0.000426945,-1.71365e-07,-3.97023e-09,1.06987,0.00042659,-1.83276e-07,4.9542e-09,1.0703,0.000426238,-1.68414e-07,-1.58466e-08,1.07073,0.000425854,-2.15953e-07,5.84321e-08,1.07115,0.000425597,-4.0657e-08,-9.86725e-08,1.07158,0.00042522,-3.36674e-07,9.78392e-08,1.072,0.00042484,-4.31568e-08,-5.42658e-08,1.07243,0.000424591,-2.05954e-07,1.45377e-11,1.07285,0.000424179,-2.0591e-07,5.42076e-08,1.07328,0.00042393,-4.32877e-08,-9.76357e-08,1.0737,0.00042355,-3.36195e-07,9.79165e-08,1.07412,0.000423172,-4.24451e-08,-5.56118e-08,1.07455,0.00042292,-2.09281e-07,5.32143e-09,1.07497,0.000422518,-1.93316e-07,3.43261e-08,1.07539,0.000422234,-9.0338e-08,-2.34165e-08,1.07581,0.000421983,-1.60588e-07,-5.98692e-08,1.07623,0.000421482,-3.40195e-07,1.43684e-07,1.07666,0.000421233,9.08574e-08,-1.5724e-07,1.07708,0.000420943,-3.80862e-07,1.27647e-07,1.0775,0.000420564,2.0791e-09,-1.1493e-07,1.07792,0.000420223,-3.4271e-07,9.36534e-08,1.07834,0.000419819,-6.17499e-08,-2.12653e-08,1.07876,0.000419632,-1.25546e-07,-8.59219e-09,1.07918,0.000419355,-1.51322e-07,-6.35752e-08,1.0796,0.000418861,-3.42048e-07,1.43684e-07,1.08002,0.000418608,8.90034e-08,-1.53532e-07,1.08043,0.000418326,-3.71593e-07,1.12817e-07,1.08085,0.000417921,-3.31414e-08,-5.93184e-08,1.08127,0.000417677,-2.11097e-07,5.24697e-09,1.08169,0.00041727,-1.95356e-07,3.83305e-08,1.0821,0.000416995,-8.03642e-08,-3.93597e-08,1.08252,0.000416716,-1.98443e-07,-1.0094e-10,1.08294,0.000416319,-1.98746e-07,3.97635e-08,1.08335,0.00041604,-7.94557e-08,-3.97437e-08,1.08377,0.000415762,-1.98687e-07,1.94215e-12,1.08419,0.000415365,-1.98681e-07,3.97359e-08,1.0846,0.000415087,-7.94732e-08,-3.97362e-08,1.08502,0.000414809,-1.98682e-07,-4.31063e-13,1.08543,0.000414411,-1.98683e-07,3.97379e-08,1.08584,0.000414133,-7.94694e-08,-3.97418e-08,1.08626,0.000413855,-1.98695e-07,2.00563e-11,1.08667,0.000413458,-1.98635e-07,3.96616e-08,1.08709,0.000413179,-7.965e-08,-3.9457e-08,1.0875,0.000412902,-1.98021e-07,-1.04281e-09,1.08791,0.000412502,-2.01149e-07,4.36282e-08,1.08832,0.000412231,-7.02648e-08,-5.42608e-08,1.08874,0.000411928,-2.33047e-07,5.42057e-08,1.08915,0.000411624,-7.04301e-08,-4.33527e-08,1.08956,0.000411353,-2.00488e-07,-4.07378e-12,1.08997,0.000410952,-2.005e-07,4.3369e-08,1.09038,0.000410681,-7.03934e-08,-5.42627e-08,1.09079,0.000410378,-2.33182e-07,5.44726e-08,1.0912,0.000410075,-6.97637e-08,-4.44186e-08,1.09161,0.000409802,-2.03019e-07,3.99235e-09,1.09202,0.000409408,-1.91042e-07,2.84491e-08,1.09243,0.000409111,-1.05695e-07,1.42043e-09,1.09284,0.000408904,-1.01434e-07,-3.41308e-08,1.09325,0.000408599,-2.03826e-07,1.58937e-08,1.09366,0.000408239,-1.56145e-07,-2.94438e-08,1.09406,0.000407838,-2.44476e-07,1.01881e-07,1.09447,0.000407655,6.11676e-08,-1.39663e-07,1.09488,0.000407358,-3.57822e-07,9.91432e-08,1.09529,0.00040694,-6.03921e-08,-1.84912e-08,1.09569,0.000406764,-1.15866e-07,-2.51785e-08,1.0961,0.000406457,-1.91401e-07,-4.03115e-12,1.09651,0.000406074,-1.91413e-07,2.51947e-08,1.09691,0.000405767,-1.15829e-07,1.84346e-08,1.09732,0.00040559,-6.05254e-08,-9.89332e-08,1.09772,0.000405172,-3.57325e-07,1.3888e-07,1.09813,0.000404874,5.93136e-08,-9.8957e-08,1.09853,0.000404696,-2.37557e-07,1.853e-08,1.09894,0.000404277,-1.81968e-07,2.48372e-08,1.09934,0.000403987,-1.07456e-07,1.33047e-09,1.09975,0.000403776,-1.03465e-07,-3.01591e-08,1.10015,0.000403479,-1.93942e-07,9.66054e-11,1.10055,0.000403091,-1.93652e-07,2.97727e-08,1.10096,0.000402793,-1.04334e-07,2.19273e-11,1.10136,0.000402585,-1.04268e-07,-2.98604e-08,1.10176,0.000402287,-1.93849e-07,2.10325e-10,1.10216,0.0004019,-1.93218e-07,2.90191e-08,1.10256,0.0004016,-1.06161e-07,2.92264e-09,1.10297,0.000401397,-9.73931e-08,-4.07096e-08,1.10337,0.00040108,-2.19522e-07,4.07067e-08,1.10377,0.000400763,-9.7402e-08,-2.90783e-09,1.10417,0.000400559,-1.06126e-07,-2.90754e-08,1.10457,0.00040026,-1.93352e-07,9.00021e-14,1.10497,0.000399873,-1.93351e-07,2.9075e-08,1.10537,0.000399574,-1.06126e-07,2.90902e-09,1.10577,0.00039937,-9.73992e-08,-4.07111e-08,1.10617,0.000399053,-2.19533e-07,4.07262e-08,1.10657,0.000398736,-9.73541e-08,-2.98424e-09,1.10697,0.000398533,-1.06307e-07,-2.87892e-08,1.10736,0.000398234,-1.92674e-07,-1.06824e-09,1.10776,0.000397845,-1.95879e-07,3.30622e-08,1.10816,0.000397552,-9.66926e-08,-1.19712e-08,1.10856,0.000397323,-1.32606e-07,1.48225e-08,1.10895,0.000397102,-8.81387e-08,-4.73187e-08,1.10935,0.000396784,-2.30095e-07,5.52429e-08,1.10975,0.00039649,-6.4366e-08,-5.44437e-08,1.11014,0.000396198,-2.27697e-07,4.33226e-08,1.11054,0.000395872,-9.77293e-08,3.62656e-10,1.11094,0.000395678,-9.66414e-08,-4.47732e-08,1.11133,0.00039535,-2.30961e-07,5.95208e-08,1.11173,0.000395067,-5.23985e-08,-7.41008e-08,1.11212,0.00039474,-2.74701e-07,1.17673e-07,1.11252,0.000394543,7.83181e-08,-1.58172e-07,1.11291,0.000394225,-3.96199e-07,1.57389e-07,1.1133,0.000393905,7.59679e-08,-1.13756e-07,1.1137,0.000393716,-2.653e-07,5.92165e-08,1.11409,0.000393363,-8.76507e-08,-3.90074e-09,1.11449,0.000393176,-9.93529e-08,-4.36136e-08,1.11488,0.000392846,-2.30194e-07,5.91457e-08,1.11527,0.000392563,-5.27564e-08,-7.376e-08,1.11566,0.000392237,-2.74037e-07,1.16685e-07,1.11606,0.000392039,7.60189e-08,-1.54562e-07,1.11645,0.000391727,-3.87667e-07,1.43935e-07,1.11684,0.000391384,4.4137e-08,-6.35487e-08,1.11723,0.000391281,-1.46509e-07,-8.94896e-09,1.11762,0.000390961,-1.73356e-07,-1.98647e-08,1.11801,0.000390555,-2.3295e-07,8.8408e-08,1.1184,0.000390354,3.22736e-08,-9.53486e-08,1.11879,0.000390133,-2.53772e-07,5.45677e-08,1.11918,0.000389789,-9.0069e-08,-3.71296e-09,1.11957,0.000389598,-1.01208e-07,-3.97159e-08,1.11996,0.000389276,-2.20355e-07,4.33671e-08,1.12035,0.000388966,-9.02542e-08,-1.45431e-08,1.12074,0.000388741,-1.33883e-07,1.48052e-08,1.12113,0.000388518,-8.94678e-08,-4.46778e-08,1.12152,0.000388205,-2.23501e-07,4.46966e-08,1.12191,0.000387892,-8.94114e-08,-1.48992e-08,1.12229,0.000387669,-1.34109e-07,1.49003e-08,1.12268,0.000387445,-8.94082e-08,-4.47019e-08,1.12307,0.000387132,-2.23514e-07,4.4698e-08,1.12345,0.000386819,-8.942e-08,-1.48806e-08,1.12384,0.000386596,-1.34062e-07,1.48245e-08,1.12423,0.000386372,-8.95885e-08,-4.44172e-08,1.12461,0.00038606,-2.2284e-07,4.36351e-08,1.125,0.000385745,-9.19348e-08,-1.09139e-08,1.12539,0.000385528,-1.24677e-07,2.05584e-11,1.12577,0.000385279,-1.24615e-07,1.08317e-08,1.12616,0.000385062,-9.21198e-08,-4.33473e-08,1.12654,0.000384748,-2.22162e-07,4.33481e-08,1.12693,0.000384434,-9.21174e-08,-1.08356e-08,1.12731,0.000384217,-1.24624e-07,-5.50907e-12,1.12769,0.000383968,-1.24641e-07,1.08577e-08,1.12808,0.000383751,-9.20679e-08,-4.34252e-08,1.12846,0.000383437,-2.22343e-07,4.36337e-08,1.12884,0.000383123,-9.14422e-08,-1.19005e-08,1.12923,0.000382904,-1.27144e-07,3.96813e-09,1.12961,0.000382662,-1.15239e-07,-3.97207e-09,1.12999,0.000382419,-1.27155e-07,1.19201e-08,1.13038,0.000382201,-9.1395e-08,-4.37085e-08,1.13076,0.000381887,-2.2252e-07,4.37046e-08,1.13114,0.000381573,-9.14068e-08,-1.19005e-08,1.13152,0.000381355,-1.27108e-07,3.89734e-09,1.1319,0.000381112,-1.15416e-07,-3.68887e-09,1.13228,0.00038087,-1.26483e-07,1.08582e-08,1.13266,0.00038065,-9.39083e-08,-3.97438e-08,1.13304,0.000380343,-2.1314e-07,2.89076e-08,1.13342,0.000380003,-1.26417e-07,4.33225e-08,1.1338,0.00037988,3.55072e-09,-8.29883e-08,1.13418,0.000379638,-2.45414e-07,5.0212e-08,1.13456,0.000379298,-9.47781e-08,1.34964e-09,1.13494,0.000379113,-9.07292e-08,-5.56105e-08,1.13532,0.000378764,-2.57561e-07,1.01883e-07,1.1357,0.000378555,4.80889e-08,-1.13504e-07,1.13608,0.000378311,-2.92423e-07,1.13713e-07,1.13646,0.000378067,4.87176e-08,-1.02931e-07,1.13683,0.000377856,-2.60076e-07,5.95923e-08,1.13721,0.000377514,-8.12988e-08,-1.62288e-08,1.13759,0.000377303,-1.29985e-07,5.32278e-09,1.13797,0.000377059,-1.14017e-07,-5.06237e-09,1.13834,0.000376816,-1.29204e-07,1.49267e-08,1.13872,0.000376602,-8.44237e-08,-5.46444e-08,1.1391,0.000376269,-2.48357e-07,8.44417e-08,1.13947,0.000376026,4.96815e-09,-4.47039e-08,1.13985,0.000375902,-1.29143e-07,-2.48355e-08,1.14023,0.000375569,-2.0365e-07,2.48368e-08,1.1406,0.000375236,-1.2914e-07,4.46977e-08,1.14098,0.000375112,4.95341e-09,-8.44184e-08,1.14135,0.000374869,-2.48302e-07,5.45572e-08,1.14173,0.000374536,-8.463e-08,-1.46013e-08,1.1421,0.000374323,-1.28434e-07,3.8478e-09,1.14247,0.000374077,-1.1689e-07,-7.89941e-10,1.14285,0.000373841,-1.1926e-07,-6.88042e-10,1.14322,0.0003736,-1.21324e-07,3.54213e-09,1.1436,0.000373368,-1.10698e-07,-1.34805e-08,1.14397,0.000373107,-1.51139e-07,5.03798e-08,1.14434,0.000372767,0.,0.}; + + template + __device__ __forceinline__ void RGB2LuvConvert_f(const T& src, D& dst) + { + const float _d = 1.f / (0.950456f + 15 + 1.088754f * 3); + const float _un = 13 * (4 * 0.950456f * _d); + const float _vn = 13 * (9 * _d); + + float B = blueIdx == 0 ? src.x : src.z; + float G = src.y; + float R = blueIdx == 0 ? src.z : src.x; + + if (srgb) + { + B = splineInterpolate(B * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R * GAMMA_TAB_SIZE, c_sRGBGammaTab, GAMMA_TAB_SIZE); + } + + float X = R * 0.412453f + G * 0.357580f + B * 0.180423f; + float Y = R * 0.212671f + G * 0.715160f + B * 0.072169f; + float Z = R * 0.019334f + G * 0.119193f + B * 0.950227f; + + float L = splineInterpolate(Y * (LAB_CBRT_TAB_SIZE / 1.5f), c_LabCbrtTab, LAB_CBRT_TAB_SIZE); + L = 116.f * L - 16.f; + + const float d = (4 * 13) / ::fmaxf(X + 15 * Y + 3 * Z, numeric_limits::epsilon()); + float u = L * (X * d - _un); + float v = L * ((9 * 0.25f) * Y * d - _vn); + + dst.x = L; + dst.y = u; + dst.z = v; + } + + template + __device__ __forceinline__ void RGB2LuvConvert_b(const T& src, D& dst) + { + float3 srcf, dstf; + + srcf.x = src.x * (1.f / 255.f); + srcf.y = src.y * (1.f / 255.f); + srcf.z = src.z * (1.f / 255.f); + + RGB2LuvConvert_f(srcf, dstf); + + dst.x = saturate_cast(dstf.x * 2.55f); + dst.y = saturate_cast(dstf.y * 0.72033898305084743f + 96.525423728813564f); + dst.z = saturate_cast(dstf.z * 0.9732824427480916f + 136.259541984732824f); + } + + template struct RGB2Luv; + template + struct RGB2Luv + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + RGB2LuvConvert_b(src, dst); + + return dst; + } + __host__ __device__ __forceinline__ RGB2Luv() {} + __host__ __device__ __forceinline__ RGB2Luv(const RGB2Luv&) {} + }; + template + struct RGB2Luv + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + RGB2LuvConvert_f(src, dst); + + return dst; + } + __host__ __device__ __forceinline__ RGB2Luv() {} + __host__ __device__ __forceinline__ RGB2Luv(const RGB2Luv&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_RGB2Luv_TRAITS(name, scn, dcn, srgb, blueIdx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::RGB2Luv functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + namespace color_detail + { + template + __device__ __forceinline__ void Luv2RGBConvert_f(const T& src, D& dst) + { + const float _d = 1.f / (0.950456f + 15 + 1.088754f * 3); + const float _un = 4 * 0.950456f * _d; + const float _vn = 9 * _d; + + float L = src.x; + float u = src.y; + float v = src.z; + + float Y = (L + 16.f) * (1.f / 116.f); + Y = Y * Y * Y; + + float d = (1.f / 13.f) / L; + u = u * d + _un; + v = v * d + _vn; + + float iv = 1.f / v; + float X = 2.25f * u * Y * iv; + float Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv; + + float B = 0.055648f * X - 0.204043f * Y + 1.057311f * Z; + float G = -0.969256f * X + 1.875991f * Y + 0.041556f * Z; + float R = 3.240479f * X - 1.537150f * Y - 0.498535f * Z; + + if (srgb) + { + B = splineInterpolate(B * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + G = splineInterpolate(G * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + R = splineInterpolate(R * GAMMA_TAB_SIZE, c_sRGBInvGammaTab, GAMMA_TAB_SIZE); + } + + dst.x = blueIdx == 0 ? B : R; + dst.y = G; + dst.z = blueIdx == 0 ? R : B; + setAlpha(dst, ColorChannel::max()); + } + + template + __device__ __forceinline__ void Luv2RGBConvert_b(const T& src, D& dst) + { + float3 srcf, dstf; + + srcf.x = src.x * (100.f / 255.f); + srcf.y = src.y * 1.388235294117647f - 134.f; + srcf.z = src.z * 1.027450980392157f - 140.f; + + Luv2RGBConvert_f(srcf, dstf); + + dst.x = saturate_cast(dstf.x * 255.f); + dst.y = saturate_cast(dstf.y * 255.f); + dst.z = saturate_cast(dstf.z * 255.f); + setAlpha(dst, ColorChannel::max()); + } + + template struct Luv2RGB; + template + struct Luv2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + Luv2RGBConvert_b(src, dst); + + return dst; + } + __host__ __device__ __forceinline__ Luv2RGB() {} + __host__ __device__ __forceinline__ Luv2RGB(const Luv2RGB&) {} + }; + template + struct Luv2RGB + : unary_function::vec_type, typename TypeVec::vec_type> + { + __device__ __forceinline__ typename TypeVec::vec_type operator ()(const typename TypeVec::vec_type& src) const + { + typename TypeVec::vec_type dst; + + Luv2RGBConvert_f(src, dst); + + return dst; + } + __host__ __device__ __forceinline__ Luv2RGB() {} + __host__ __device__ __forceinline__ Luv2RGB(const Luv2RGB&) {} + }; + } + +#define OPENCV_CUDA_IMPLEMENT_Luv2RGB_TRAITS(name, scn, dcn, srgb, blueIdx) \ + template struct name ## _traits \ + { \ + typedef ::cv::cuda::device::color_detail::Luv2RGB functor_type; \ + static __host__ __device__ __forceinline__ functor_type create_functor() \ + { \ + return functor_type(); \ + } \ + }; + + #undef CV_DESCALE + +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_COLOR_DETAIL_HPP__ diff --git a/include/opencv2/core/cuda/detail/reduce.hpp b/include/opencv2/core/cuda/detail/reduce.hpp new file mode 100644 index 0000000..0c35eab --- /dev/null +++ b/include/opencv2/core/cuda/detail/reduce.hpp @@ -0,0 +1,365 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_REDUCE_DETAIL_HPP__ +#define __OPENCV_CUDA_REDUCE_DETAIL_HPP__ + +#include +#include "../warp.hpp" +#include "../warp_shuffle.hpp" + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + namespace reduce_detail + { + template struct GetType; + template struct GetType + { + typedef T type; + }; + template struct GetType + { + typedef T type; + }; + template struct GetType + { + typedef T type; + }; + + template + struct For + { + template + static __device__ void loadToSmem(const PointerTuple& smem, const ValTuple& val, unsigned int tid) + { + thrust::get(smem)[tid] = thrust::get(val); + + For::loadToSmem(smem, val, tid); + } + template + static __device__ void loadFromSmem(const PointerTuple& smem, const ValTuple& val, unsigned int tid) + { + thrust::get(val) = thrust::get(smem)[tid]; + + For::loadFromSmem(smem, val, tid); + } + + template + static __device__ void merge(const PointerTuple& smem, const ValTuple& val, unsigned int tid, unsigned int delta, const OpTuple& op) + { + typename GetType::type>::type reg = thrust::get(smem)[tid + delta]; + thrust::get(smem)[tid] = thrust::get(val) = thrust::get(op)(thrust::get(val), reg); + + For::merge(smem, val, tid, delta, op); + } + template + static __device__ void mergeShfl(const ValTuple& val, unsigned int delta, unsigned int width, const OpTuple& op) + { + typename GetType::type>::type reg = shfl_down(thrust::get(val), delta, width); + thrust::get(val) = thrust::get(op)(thrust::get(val), reg); + + For::mergeShfl(val, delta, width, op); + } + }; + template + struct For + { + template + static __device__ void loadToSmem(const PointerTuple&, const ValTuple&, unsigned int) + { + } + template + static __device__ void loadFromSmem(const PointerTuple&, const ValTuple&, unsigned int) + { + } + + template + static __device__ void merge(const PointerTuple&, const ValTuple&, unsigned int, unsigned int, const OpTuple&) + { + } + template + static __device__ void mergeShfl(const ValTuple&, unsigned int, unsigned int, const OpTuple&) + { + } + }; + + template + __device__ __forceinline__ void loadToSmem(volatile T* smem, T& val, unsigned int tid) + { + smem[tid] = val; + } + template + __device__ __forceinline__ void loadFromSmem(volatile T* smem, T& val, unsigned int tid) + { + val = smem[tid]; + } + template + __device__ __forceinline__ void loadToSmem(const thrust::tuple& smem, + const thrust::tuple& val, + unsigned int tid) + { + For<0, thrust::tuple_size >::value>::loadToSmem(smem, val, tid); + } + template + __device__ __forceinline__ void loadFromSmem(const thrust::tuple& smem, + const thrust::tuple& val, + unsigned int tid) + { + For<0, thrust::tuple_size >::value>::loadFromSmem(smem, val, tid); + } + + template + __device__ __forceinline__ void merge(volatile T* smem, T& val, unsigned int tid, unsigned int delta, const Op& op) + { + T reg = smem[tid + delta]; + smem[tid] = val = op(val, reg); + } + template + __device__ __forceinline__ void mergeShfl(T& val, unsigned int delta, unsigned int width, const Op& op) + { + T reg = shfl_down(val, delta, width); + val = op(val, reg); + } + template + __device__ __forceinline__ void merge(const thrust::tuple& smem, + const thrust::tuple& val, + unsigned int tid, + unsigned int delta, + const thrust::tuple& op) + { + For<0, thrust::tuple_size >::value>::merge(smem, val, tid, delta, op); + } + template + __device__ __forceinline__ void mergeShfl(const thrust::tuple& val, + unsigned int delta, + unsigned int width, + const thrust::tuple& op) + { + For<0, thrust::tuple_size >::value>::mergeShfl(val, delta, width, op); + } + + template struct Generic + { + template + static __device__ void reduce(Pointer smem, Reference val, unsigned int tid, Op op) + { + loadToSmem(smem, val, tid); + if (N >= 32) + __syncthreads(); + + if (N >= 2048) + { + if (tid < 1024) + merge(smem, val, tid, 1024, op); + + __syncthreads(); + } + if (N >= 1024) + { + if (tid < 512) + merge(smem, val, tid, 512, op); + + __syncthreads(); + } + if (N >= 512) + { + if (tid < 256) + merge(smem, val, tid, 256, op); + + __syncthreads(); + } + if (N >= 256) + { + if (tid < 128) + merge(smem, val, tid, 128, op); + + __syncthreads(); + } + if (N >= 128) + { + if (tid < 64) + merge(smem, val, tid, 64, op); + + __syncthreads(); + } + if (N >= 64) + { + if (tid < 32) + merge(smem, val, tid, 32, op); + } + + if (tid < 16) + { + merge(smem, val, tid, 16, op); + merge(smem, val, tid, 8, op); + merge(smem, val, tid, 4, op); + merge(smem, val, tid, 2, op); + merge(smem, val, tid, 1, op); + } + } + }; + + template + struct Unroll + { + static __device__ void loopShfl(Reference val, Op op, unsigned int N) + { + mergeShfl(val, I, N, op); + Unroll::loopShfl(val, op, N); + } + static __device__ void loop(Pointer smem, Reference val, unsigned int tid, Op op) + { + merge(smem, val, tid, I, op); + Unroll::loop(smem, val, tid, op); + } + }; + template + struct Unroll<0, Pointer, Reference, Op> + { + static __device__ void loopShfl(Reference, Op, unsigned int) + { + } + static __device__ void loop(Pointer, Reference, unsigned int, Op) + { + } + }; + + template struct WarpOptimized + { + template + static __device__ void reduce(Pointer smem, Reference val, unsigned int tid, Op op) + { + #if __CUDA_ARCH__ >= 300 + (void) smem; + (void) tid; + + Unroll::loopShfl(val, op, N); + #else + loadToSmem(smem, val, tid); + + if (tid < N / 2) + Unroll::loop(smem, val, tid, op); + #endif + } + }; + + template struct GenericOptimized32 + { + enum { M = N / 32 }; + + template + static __device__ void reduce(Pointer smem, Reference val, unsigned int tid, Op op) + { + const unsigned int laneId = Warp::laneId(); + + #if __CUDA_ARCH__ >= 300 + Unroll<16, Pointer, Reference, Op>::loopShfl(val, op, warpSize); + + if (laneId == 0) + loadToSmem(smem, val, tid / 32); + #else + loadToSmem(smem, val, tid); + + if (laneId < 16) + Unroll<16, Pointer, Reference, Op>::loop(smem, val, tid, op); + + __syncthreads(); + + if (laneId == 0) + loadToSmem(smem, val, tid / 32); + #endif + + __syncthreads(); + + loadFromSmem(smem, val, tid); + + if (tid < 32) + { + #if __CUDA_ARCH__ >= 300 + Unroll::loopShfl(val, op, M); + #else + Unroll::loop(smem, val, tid, op); + #endif + } + } + }; + + template struct StaticIf; + template struct StaticIf + { + typedef T1 type; + }; + template struct StaticIf + { + typedef T2 type; + }; + + template struct IsPowerOf2 + { + enum { value = ((N != 0) && !(N & (N - 1))) }; + }; + + template struct Dispatcher + { + typedef typename StaticIf< + (N <= 32) && IsPowerOf2::value, + WarpOptimized, + typename StaticIf< + (N <= 1024) && IsPowerOf2::value, + GenericOptimized32, + Generic + >::type + >::type reductor; + }; + } +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_REDUCE_DETAIL_HPP__ diff --git a/include/opencv2/core/cuda/detail/reduce_key_val.hpp b/include/opencv2/core/cuda/detail/reduce_key_val.hpp new file mode 100644 index 0000000..bab85d7 --- /dev/null +++ b/include/opencv2/core/cuda/detail/reduce_key_val.hpp @@ -0,0 +1,502 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_PRED_VAL_REDUCE_DETAIL_HPP__ +#define __OPENCV_CUDA_PRED_VAL_REDUCE_DETAIL_HPP__ + +#include +#include "../warp.hpp" +#include "../warp_shuffle.hpp" + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + namespace reduce_key_val_detail + { + template struct GetType; + template struct GetType + { + typedef T type; + }; + template struct GetType + { + typedef T type; + }; + template struct GetType + { + typedef T type; + }; + + template + struct For + { + template + static __device__ void loadToSmem(const PointerTuple& smem, const ReferenceTuple& data, unsigned int tid) + { + thrust::get(smem)[tid] = thrust::get(data); + + For::loadToSmem(smem, data, tid); + } + template + static __device__ void loadFromSmem(const PointerTuple& smem, const ReferenceTuple& data, unsigned int tid) + { + thrust::get(data) = thrust::get(smem)[tid]; + + For::loadFromSmem(smem, data, tid); + } + + template + static __device__ void copyShfl(const ReferenceTuple& val, unsigned int delta, int width) + { + thrust::get(val) = shfl_down(thrust::get(val), delta, width); + + For::copyShfl(val, delta, width); + } + template + static __device__ void copy(const PointerTuple& svals, const ReferenceTuple& val, unsigned int tid, unsigned int delta) + { + thrust::get(svals)[tid] = thrust::get(val) = thrust::get(svals)[tid + delta]; + + For::copy(svals, val, tid, delta); + } + + template + static __device__ void mergeShfl(const KeyReferenceTuple& key, const ValReferenceTuple& val, const CmpTuple& cmp, unsigned int delta, int width) + { + typename GetType::type>::type reg = shfl_down(thrust::get(key), delta, width); + + if (thrust::get(cmp)(reg, thrust::get(key))) + { + thrust::get(key) = reg; + thrust::get(val) = shfl_down(thrust::get(val), delta, width); + } + + For::mergeShfl(key, val, cmp, delta, width); + } + template + static __device__ void merge(const KeyPointerTuple& skeys, const KeyReferenceTuple& key, + const ValPointerTuple& svals, const ValReferenceTuple& val, + const CmpTuple& cmp, + unsigned int tid, unsigned int delta) + { + typename GetType::type>::type reg = thrust::get(skeys)[tid + delta]; + + if (thrust::get(cmp)(reg, thrust::get(key))) + { + thrust::get(skeys)[tid] = thrust::get(key) = reg; + thrust::get(svals)[tid] = thrust::get(val) = thrust::get(svals)[tid + delta]; + } + + For::merge(skeys, key, svals, val, cmp, tid, delta); + } + }; + template + struct For + { + template + static __device__ void loadToSmem(const PointerTuple&, const ReferenceTuple&, unsigned int) + { + } + template + static __device__ void loadFromSmem(const PointerTuple&, const ReferenceTuple&, unsigned int) + { + } + + template + static __device__ void copyShfl(const ReferenceTuple&, unsigned int, int) + { + } + template + static __device__ void copy(const PointerTuple&, const ReferenceTuple&, unsigned int, unsigned int) + { + } + + template + static __device__ void mergeShfl(const KeyReferenceTuple&, const ValReferenceTuple&, const CmpTuple&, unsigned int, int) + { + } + template + static __device__ void merge(const KeyPointerTuple&, const KeyReferenceTuple&, + const ValPointerTuple&, const ValReferenceTuple&, + const CmpTuple&, + unsigned int, unsigned int) + { + } + }; + + ////////////////////////////////////////////////////// + // loadToSmem + + template + __device__ __forceinline__ void loadToSmem(volatile T* smem, T& data, unsigned int tid) + { + smem[tid] = data; + } + template + __device__ __forceinline__ void loadFromSmem(volatile T* smem, T& data, unsigned int tid) + { + data = smem[tid]; + } + template + __device__ __forceinline__ void loadToSmem(const thrust::tuple& smem, + const thrust::tuple& data, + unsigned int tid) + { + For<0, thrust::tuple_size >::value>::loadToSmem(smem, data, tid); + } + template + __device__ __forceinline__ void loadFromSmem(const thrust::tuple& smem, + const thrust::tuple& data, + unsigned int tid) + { + For<0, thrust::tuple_size >::value>::loadFromSmem(smem, data, tid); + } + + ////////////////////////////////////////////////////// + // copyVals + + template + __device__ __forceinline__ void copyValsShfl(V& val, unsigned int delta, int width) + { + val = shfl_down(val, delta, width); + } + template + __device__ __forceinline__ void copyVals(volatile V* svals, V& val, unsigned int tid, unsigned int delta) + { + svals[tid] = val = svals[tid + delta]; + } + template + __device__ __forceinline__ void copyValsShfl(const thrust::tuple& val, + unsigned int delta, + int width) + { + For<0, thrust::tuple_size >::value>::copyShfl(val, delta, width); + } + template + __device__ __forceinline__ void copyVals(const thrust::tuple& svals, + const thrust::tuple& val, + unsigned int tid, unsigned int delta) + { + For<0, thrust::tuple_size >::value>::copy(svals, val, tid, delta); + } + + ////////////////////////////////////////////////////// + // merge + + template + __device__ __forceinline__ void mergeShfl(K& key, V& val, const Cmp& cmp, unsigned int delta, int width) + { + K reg = shfl_down(key, delta, width); + + if (cmp(reg, key)) + { + key = reg; + copyValsShfl(val, delta, width); + } + } + template + __device__ __forceinline__ void merge(volatile K* skeys, K& key, volatile V* svals, V& val, const Cmp& cmp, unsigned int tid, unsigned int delta) + { + K reg = skeys[tid + delta]; + + if (cmp(reg, key)) + { + skeys[tid] = key = reg; + copyVals(svals, val, tid, delta); + } + } + template + __device__ __forceinline__ void mergeShfl(K& key, + const thrust::tuple& val, + const Cmp& cmp, + unsigned int delta, int width) + { + K reg = shfl_down(key, delta, width); + + if (cmp(reg, key)) + { + key = reg; + copyValsShfl(val, delta, width); + } + } + template + __device__ __forceinline__ void merge(volatile K* skeys, K& key, + const thrust::tuple& svals, + const thrust::tuple& val, + const Cmp& cmp, unsigned int tid, unsigned int delta) + { + K reg = skeys[tid + delta]; + + if (cmp(reg, key)) + { + skeys[tid] = key = reg; + copyVals(svals, val, tid, delta); + } + } + template + __device__ __forceinline__ void mergeShfl(const thrust::tuple& key, + const thrust::tuple& val, + const thrust::tuple& cmp, + unsigned int delta, int width) + { + For<0, thrust::tuple_size >::value>::mergeShfl(key, val, cmp, delta, width); + } + template + __device__ __forceinline__ void merge(const thrust::tuple& skeys, + const thrust::tuple& key, + const thrust::tuple& svals, + const thrust::tuple& val, + const thrust::tuple& cmp, + unsigned int tid, unsigned int delta) + { + For<0, thrust::tuple_size >::value>::merge(skeys, key, svals, val, cmp, tid, delta); + } + + ////////////////////////////////////////////////////// + // Generic + + template struct Generic + { + template + static __device__ void reduce(KP skeys, KR key, VP svals, VR val, unsigned int tid, Cmp cmp) + { + loadToSmem(skeys, key, tid); + loadValsToSmem(svals, val, tid); + if (N >= 32) + __syncthreads(); + + if (N >= 2048) + { + if (tid < 1024) + merge(skeys, key, svals, val, cmp, tid, 1024); + + __syncthreads(); + } + if (N >= 1024) + { + if (tid < 512) + merge(skeys, key, svals, val, cmp, tid, 512); + + __syncthreads(); + } + if (N >= 512) + { + if (tid < 256) + merge(skeys, key, svals, val, cmp, tid, 256); + + __syncthreads(); + } + if (N >= 256) + { + if (tid < 128) + merge(skeys, key, svals, val, cmp, tid, 128); + + __syncthreads(); + } + if (N >= 128) + { + if (tid < 64) + merge(skeys, key, svals, val, cmp, tid, 64); + + __syncthreads(); + } + if (N >= 64) + { + if (tid < 32) + merge(skeys, key, svals, val, cmp, tid, 32); + } + + if (tid < 16) + { + merge(skeys, key, svals, val, cmp, tid, 16); + merge(skeys, key, svals, val, cmp, tid, 8); + merge(skeys, key, svals, val, cmp, tid, 4); + merge(skeys, key, svals, val, cmp, tid, 2); + merge(skeys, key, svals, val, cmp, tid, 1); + } + } + }; + + template + struct Unroll + { + static __device__ void loopShfl(KR key, VR val, Cmp cmp, unsigned int N) + { + mergeShfl(key, val, cmp, I, N); + Unroll::loopShfl(key, val, cmp, N); + } + static __device__ void loop(KP skeys, KR key, VP svals, VR val, unsigned int tid, Cmp cmp) + { + merge(skeys, key, svals, val, cmp, tid, I); + Unroll::loop(skeys, key, svals, val, tid, cmp); + } + }; + template + struct Unroll<0, KP, KR, VP, VR, Cmp> + { + static __device__ void loopShfl(KR, VR, Cmp, unsigned int) + { + } + static __device__ void loop(KP, KR, VP, VR, unsigned int, Cmp) + { + } + }; + + template struct WarpOptimized + { + template + static __device__ void reduce(KP skeys, KR key, VP svals, VR val, unsigned int tid, Cmp cmp) + { + #if 0 // __CUDA_ARCH__ >= 300 + (void) skeys; + (void) svals; + (void) tid; + + Unroll::loopShfl(key, val, cmp, N); + #else + loadToSmem(skeys, key, tid); + loadToSmem(svals, val, tid); + + if (tid < N / 2) + Unroll::loop(skeys, key, svals, val, tid, cmp); + #endif + } + }; + + template struct GenericOptimized32 + { + enum { M = N / 32 }; + + template + static __device__ void reduce(KP skeys, KR key, VP svals, VR val, unsigned int tid, Cmp cmp) + { + const unsigned int laneId = Warp::laneId(); + + #if 0 // __CUDA_ARCH__ >= 300 + Unroll<16, KP, KR, VP, VR, Cmp>::loopShfl(key, val, cmp, warpSize); + + if (laneId == 0) + { + loadToSmem(skeys, key, tid / 32); + loadToSmem(svals, val, tid / 32); + } + #else + loadToSmem(skeys, key, tid); + loadToSmem(svals, val, tid); + + if (laneId < 16) + Unroll<16, KP, KR, VP, VR, Cmp>::loop(skeys, key, svals, val, tid, cmp); + + __syncthreads(); + + if (laneId == 0) + { + loadToSmem(skeys, key, tid / 32); + loadToSmem(svals, val, tid / 32); + } + #endif + + __syncthreads(); + + loadFromSmem(skeys, key, tid); + + if (tid < 32) + { + #if 0 // __CUDA_ARCH__ >= 300 + loadFromSmem(svals, val, tid); + + Unroll::loopShfl(key, val, cmp, M); + #else + Unroll::loop(skeys, key, svals, val, tid, cmp); + #endif + } + } + }; + + template struct StaticIf; + template struct StaticIf + { + typedef T1 type; + }; + template struct StaticIf + { + typedef T2 type; + }; + + template struct IsPowerOf2 + { + enum { value = ((N != 0) && !(N & (N - 1))) }; + }; + + template struct Dispatcher + { + typedef typename StaticIf< + (N <= 32) && IsPowerOf2::value, + WarpOptimized, + typename StaticIf< + (N <= 1024) && IsPowerOf2::value, + GenericOptimized32, + Generic + >::type + >::type reductor; + }; + } +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_PRED_VAL_REDUCE_DETAIL_HPP__ diff --git a/include/opencv2/core/cuda/detail/transform_detail.hpp b/include/opencv2/core/cuda/detail/transform_detail.hpp new file mode 100644 index 0000000..96031c8 --- /dev/null +++ b/include/opencv2/core/cuda/detail/transform_detail.hpp @@ -0,0 +1,399 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_TRANSFORM_DETAIL_HPP__ +#define __OPENCV_CUDA_TRANSFORM_DETAIL_HPP__ + +#include "../common.hpp" +#include "../vec_traits.hpp" +#include "../functional.hpp" + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + namespace transform_detail + { + //! Read Write Traits + + template struct UnaryReadWriteTraits + { + typedef typename TypeVec::vec_type read_type; + typedef typename TypeVec::vec_type write_type; + }; + + template struct BinaryReadWriteTraits + { + typedef typename TypeVec::vec_type read_type1; + typedef typename TypeVec::vec_type read_type2; + typedef typename TypeVec::vec_type write_type; + }; + + //! Transform kernels + + template struct OpUnroller; + template <> struct OpUnroller<1> + { + template + static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, UnOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src.x); + } + + template + static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, BinOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src1.x, src2.x); + } + }; + template <> struct OpUnroller<2> + { + template + static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, UnOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src.y); + } + + template + static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, BinOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src1.x, src2.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src1.y, src2.y); + } + }; + template <> struct OpUnroller<3> + { + template + static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, const UnOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src.y); + if (mask(y, x_shifted + 2)) + dst.z = op(src.z); + } + + template + static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, const BinOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src1.x, src2.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src1.y, src2.y); + if (mask(y, x_shifted + 2)) + dst.z = op(src1.z, src2.z); + } + }; + template <> struct OpUnroller<4> + { + template + static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, const UnOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src.y); + if (mask(y, x_shifted + 2)) + dst.z = op(src.z); + if (mask(y, x_shifted + 3)) + dst.w = op(src.w); + } + + template + static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, const BinOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.x = op(src1.x, src2.x); + if (mask(y, x_shifted + 1)) + dst.y = op(src1.y, src2.y); + if (mask(y, x_shifted + 2)) + dst.z = op(src1.z, src2.z); + if (mask(y, x_shifted + 3)) + dst.w = op(src1.w, src2.w); + } + }; + template <> struct OpUnroller<8> + { + template + static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, const UnOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.a0 = op(src.a0); + if (mask(y, x_shifted + 1)) + dst.a1 = op(src.a1); + if (mask(y, x_shifted + 2)) + dst.a2 = op(src.a2); + if (mask(y, x_shifted + 3)) + dst.a3 = op(src.a3); + if (mask(y, x_shifted + 4)) + dst.a4 = op(src.a4); + if (mask(y, x_shifted + 5)) + dst.a5 = op(src.a5); + if (mask(y, x_shifted + 6)) + dst.a6 = op(src.a6); + if (mask(y, x_shifted + 7)) + dst.a7 = op(src.a7); + } + + template + static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, const BinOp& op, int x_shifted, int y) + { + if (mask(y, x_shifted)) + dst.a0 = op(src1.a0, src2.a0); + if (mask(y, x_shifted + 1)) + dst.a1 = op(src1.a1, src2.a1); + if (mask(y, x_shifted + 2)) + dst.a2 = op(src1.a2, src2.a2); + if (mask(y, x_shifted + 3)) + dst.a3 = op(src1.a3, src2.a3); + if (mask(y, x_shifted + 4)) + dst.a4 = op(src1.a4, src2.a4); + if (mask(y, x_shifted + 5)) + dst.a5 = op(src1.a5, src2.a5); + if (mask(y, x_shifted + 6)) + dst.a6 = op(src1.a6, src2.a6); + if (mask(y, x_shifted + 7)) + dst.a7 = op(src1.a7, src2.a7); + } + }; + + template + static __global__ void transformSmart(const PtrStepSz src_, PtrStep dst_, const Mask mask, const UnOp op) + { + typedef TransformFunctorTraits ft; + typedef typename UnaryReadWriteTraits::read_type read_type; + typedef typename UnaryReadWriteTraits::write_type write_type; + + const int x = threadIdx.x + blockIdx.x * blockDim.x; + const int y = threadIdx.y + blockIdx.y * blockDim.y; + const int x_shifted = x * ft::smart_shift; + + if (y < src_.rows) + { + const T* src = src_.ptr(y); + D* dst = dst_.ptr(y); + + if (x_shifted + ft::smart_shift - 1 < src_.cols) + { + const read_type src_n_el = ((const read_type*)src)[x]; + write_type dst_n_el = ((const write_type*)dst)[x]; + + OpUnroller::unroll(src_n_el, dst_n_el, mask, op, x_shifted, y); + + ((write_type*)dst)[x] = dst_n_el; + } + else + { + for (int real_x = x_shifted; real_x < src_.cols; ++real_x) + { + if (mask(y, real_x)) + dst[real_x] = op(src[real_x]); + } + } + } + } + + template + __global__ static void transformSimple(const PtrStepSz src, PtrStep dst, const Mask mask, const UnOp op) + { + const int x = blockDim.x * blockIdx.x + threadIdx.x; + const int y = blockDim.y * blockIdx.y + threadIdx.y; + + if (x < src.cols && y < src.rows && mask(y, x)) + { + dst.ptr(y)[x] = op(src.ptr(y)[x]); + } + } + + template + static __global__ void transformSmart(const PtrStepSz src1_, const PtrStep src2_, PtrStep dst_, + const Mask mask, const BinOp op) + { + typedef TransformFunctorTraits ft; + typedef typename BinaryReadWriteTraits::read_type1 read_type1; + typedef typename BinaryReadWriteTraits::read_type2 read_type2; + typedef typename BinaryReadWriteTraits::write_type write_type; + + const int x = threadIdx.x + blockIdx.x * blockDim.x; + const int y = threadIdx.y + blockIdx.y * blockDim.y; + const int x_shifted = x * ft::smart_shift; + + if (y < src1_.rows) + { + const T1* src1 = src1_.ptr(y); + const T2* src2 = src2_.ptr(y); + D* dst = dst_.ptr(y); + + if (x_shifted + ft::smart_shift - 1 < src1_.cols) + { + const read_type1 src1_n_el = ((const read_type1*)src1)[x]; + const read_type2 src2_n_el = ((const read_type2*)src2)[x]; + write_type dst_n_el = ((const write_type*)dst)[x]; + + OpUnroller::unroll(src1_n_el, src2_n_el, dst_n_el, mask, op, x_shifted, y); + + ((write_type*)dst)[x] = dst_n_el; + } + else + { + for (int real_x = x_shifted; real_x < src1_.cols; ++real_x) + { + if (mask(y, real_x)) + dst[real_x] = op(src1[real_x], src2[real_x]); + } + } + } + } + + template + static __global__ void transformSimple(const PtrStepSz src1, const PtrStep src2, PtrStep dst, + const Mask mask, const BinOp op) + { + const int x = blockDim.x * blockIdx.x + threadIdx.x; + const int y = blockDim.y * blockIdx.y + threadIdx.y; + + if (x < src1.cols && y < src1.rows && mask(y, x)) + { + const T1 src1_data = src1.ptr(y)[x]; + const T2 src2_data = src2.ptr(y)[x]; + dst.ptr(y)[x] = op(src1_data, src2_data); + } + } + + template struct TransformDispatcher; + template<> struct TransformDispatcher + { + template + static void call(PtrStepSz src, PtrStepSz dst, UnOp op, Mask mask, cudaStream_t stream) + { + typedef TransformFunctorTraits ft; + + const dim3 threads(ft::simple_block_dim_x, ft::simple_block_dim_y, 1); + const dim3 grid(divUp(src.cols, threads.x), divUp(src.rows, threads.y), 1); + + transformSimple<<>>(src, dst, mask, op); + cudaSafeCall( cudaGetLastError() ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + + template + static void call(PtrStepSz src1, PtrStepSz src2, PtrStepSz dst, BinOp op, Mask mask, cudaStream_t stream) + { + typedef TransformFunctorTraits ft; + + const dim3 threads(ft::simple_block_dim_x, ft::simple_block_dim_y, 1); + const dim3 grid(divUp(src1.cols, threads.x), divUp(src1.rows, threads.y), 1); + + transformSimple<<>>(src1, src2, dst, mask, op); + cudaSafeCall( cudaGetLastError() ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + }; + template<> struct TransformDispatcher + { + template + static void call(PtrStepSz src, PtrStepSz dst, UnOp op, Mask mask, cudaStream_t stream) + { + typedef TransformFunctorTraits ft; + + CV_StaticAssert(ft::smart_shift != 1, ""); + + if (!isAligned(src.data, ft::smart_shift * sizeof(T)) || !isAligned(src.step, ft::smart_shift * sizeof(T)) || + !isAligned(dst.data, ft::smart_shift * sizeof(D)) || !isAligned(dst.step, ft::smart_shift * sizeof(D))) + { + TransformDispatcher::call(src, dst, op, mask, stream); + return; + } + + const dim3 threads(ft::smart_block_dim_x, ft::smart_block_dim_y, 1); + const dim3 grid(divUp(src.cols, threads.x * ft::smart_shift), divUp(src.rows, threads.y), 1); + + transformSmart<<>>(src, dst, mask, op); + cudaSafeCall( cudaGetLastError() ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + + template + static void call(PtrStepSz src1, PtrStepSz src2, PtrStepSz dst, BinOp op, Mask mask, cudaStream_t stream) + { + typedef TransformFunctorTraits ft; + + CV_StaticAssert(ft::smart_shift != 1, ""); + + if (!isAligned(src1.data, ft::smart_shift * sizeof(T1)) || !isAligned(src1.step, ft::smart_shift * sizeof(T1)) || + !isAligned(src2.data, ft::smart_shift * sizeof(T2)) || !isAligned(src2.step, ft::smart_shift * sizeof(T2)) || + !isAligned(dst.data, ft::smart_shift * sizeof(D)) || !isAligned(dst.step, ft::smart_shift * sizeof(D))) + { + TransformDispatcher::call(src1, src2, dst, op, mask, stream); + return; + } + + const dim3 threads(ft::smart_block_dim_x, ft::smart_block_dim_y, 1); + const dim3 grid(divUp(src1.cols, threads.x * ft::smart_shift), divUp(src1.rows, threads.y), 1); + + transformSmart<<>>(src1, src2, dst, mask, op); + cudaSafeCall( cudaGetLastError() ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + }; + } // namespace transform_detail +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_TRANSFORM_DETAIL_HPP__ diff --git a/include/opencv2/core/cuda/detail/type_traits_detail.hpp b/include/opencv2/core/cuda/detail/type_traits_detail.hpp new file mode 100644 index 0000000..3463c78 --- /dev/null +++ b/include/opencv2/core/cuda/detail/type_traits_detail.hpp @@ -0,0 +1,191 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_TYPE_TRAITS_DETAIL_HPP__ +#define __OPENCV_CUDA_TYPE_TRAITS_DETAIL_HPP__ + +#include "../common.hpp" +#include "../vec_traits.hpp" + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + namespace type_traits_detail + { + template struct Select { typedef T1 type; }; + template struct Select { typedef T2 type; }; + + template struct IsSignedIntergral { enum {value = 0}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + template <> struct IsSignedIntergral { enum {value = 1}; }; + + template struct IsUnsignedIntegral { enum {value = 0}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + template <> struct IsUnsignedIntegral { enum {value = 1}; }; + + template struct IsIntegral { enum {value = IsSignedIntergral::value || IsUnsignedIntegral::value}; }; + template <> struct IsIntegral { enum {value = 1}; }; + template <> struct IsIntegral { enum {value = 1}; }; + + template struct IsFloat { enum {value = 0}; }; + template <> struct IsFloat { enum {value = 1}; }; + template <> struct IsFloat { enum {value = 1}; }; + + template struct IsVec { enum {value = 0}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + template <> struct IsVec { enum {value = 1}; }; + + template struct AddParameterType { typedef const U& type; }; + template struct AddParameterType { typedef U& type; }; + template <> struct AddParameterType { typedef void type; }; + + template struct ReferenceTraits + { + enum { value = false }; + typedef U type; + }; + template struct ReferenceTraits + { + enum { value = true }; + typedef U type; + }; + + template struct PointerTraits + { + enum { value = false }; + typedef void type; + }; + template struct PointerTraits + { + enum { value = true }; + typedef U type; + }; + template struct PointerTraits + { + enum { value = true }; + typedef U type; + }; + + template struct UnConst + { + typedef U type; + enum { value = 0 }; + }; + template struct UnConst + { + typedef U type; + enum { value = 1 }; + }; + template struct UnConst + { + typedef U& type; + enum { value = 1 }; + }; + + template struct UnVolatile + { + typedef U type; + enum { value = 0 }; + }; + template struct UnVolatile + { + typedef U type; + enum { value = 1 }; + }; + template struct UnVolatile + { + typedef U& type; + enum { value = 1 }; + }; + } // namespace type_traits_detail +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_TYPE_TRAITS_DETAIL_HPP__ diff --git a/include/opencv2/core/cuda/detail/vec_distance_detail.hpp b/include/opencv2/core/cuda/detail/vec_distance_detail.hpp new file mode 100644 index 0000000..9ca85a5 --- /dev/null +++ b/include/opencv2/core/cuda/detail/vec_distance_detail.hpp @@ -0,0 +1,121 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_VEC_DISTANCE_DETAIL_HPP__ +#define __OPENCV_CUDA_VEC_DISTANCE_DETAIL_HPP__ + +#include "../datamov_utils.hpp" + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + namespace vec_distance_detail + { + template struct UnrollVecDiffCached + { + template + static __device__ void calcCheck(const T1* vecCached, const T2* vecGlob, int len, Dist& dist, int ind) + { + if (ind < len) + { + T1 val1 = *vecCached++; + + T2 val2; + ForceGlob::Load(vecGlob, ind, val2); + + dist.reduceIter(val1, val2); + + UnrollVecDiffCached::calcCheck(vecCached, vecGlob, len, dist, ind + THREAD_DIM); + } + } + + template + static __device__ void calcWithoutCheck(const T1* vecCached, const T2* vecGlob, Dist& dist) + { + T1 val1 = *vecCached++; + + T2 val2; + ForceGlob::Load(vecGlob, 0, val2); + vecGlob += THREAD_DIM; + + dist.reduceIter(val1, val2); + + UnrollVecDiffCached::calcWithoutCheck(vecCached, vecGlob, dist); + } + }; + template struct UnrollVecDiffCached + { + template + static __device__ __forceinline__ void calcCheck(const T1*, const T2*, int, Dist&, int) + { + } + + template + static __device__ __forceinline__ void calcWithoutCheck(const T1*, const T2*, Dist&) + { + } + }; + + template struct VecDiffCachedCalculator; + template struct VecDiffCachedCalculator + { + template + static __device__ __forceinline__ void calc(const T1* vecCached, const T2* vecGlob, int len, Dist& dist, int tid) + { + UnrollVecDiffCached::calcCheck(vecCached, vecGlob, len, dist, tid); + } + }; + template struct VecDiffCachedCalculator + { + template + static __device__ __forceinline__ void calc(const T1* vecCached, const T2* vecGlob, int len, Dist& dist, int tid) + { + UnrollVecDiffCached::calcWithoutCheck(vecCached, vecGlob + tid, dist); + } + }; + } // namespace vec_distance_detail +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_VEC_DISTANCE_DETAIL_HPP__ diff --git a/include/opencv2/core/cuda/dynamic_smem.hpp b/include/opencv2/core/cuda/dynamic_smem.hpp new file mode 100644 index 0000000..3488463 --- /dev/null +++ b/include/opencv2/core/cuda/dynamic_smem.hpp @@ -0,0 +1,88 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_DYNAMIC_SMEM_HPP__ +#define __OPENCV_CUDA_DYNAMIC_SMEM_HPP__ + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template struct DynamicSharedMem + { + __device__ __forceinline__ operator T*() + { + extern __shared__ int __smem[]; + return (T*)__smem; + } + + __device__ __forceinline__ operator const T*() const + { + extern __shared__ int __smem[]; + return (T*)__smem; + } + }; + + // specialize for double to avoid unaligned memory access compile errors + template<> struct DynamicSharedMem + { + __device__ __forceinline__ operator double*() + { + extern __shared__ double __smem_d[]; + return (double*)__smem_d; + } + + __device__ __forceinline__ operator const double*() const + { + extern __shared__ double __smem_d[]; + return (double*)__smem_d; + } + }; +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_DYNAMIC_SMEM_HPP__ diff --git a/include/opencv2/core/cuda/emulation.hpp b/include/opencv2/core/cuda/emulation.hpp new file mode 100644 index 0000000..d346865 --- /dev/null +++ b/include/opencv2/core/cuda/emulation.hpp @@ -0,0 +1,269 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef OPENCV_CUDA_EMULATION_HPP_ +#define OPENCV_CUDA_EMULATION_HPP_ + +#include "common.hpp" +#include "warp_reduce.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + struct Emulation + { + + static __device__ __forceinline__ int syncthreadsOr(int pred) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 200) + // just campilation stab + return 0; +#else + return __syncthreads_or(pred); +#endif + } + + template + static __forceinline__ __device__ int Ballot(int predicate) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ >= 200) + return __ballot(predicate); +#else + __shared__ volatile int cta_buffer[CTA_SIZE]; + + int tid = threadIdx.x; + cta_buffer[tid] = predicate ? (1 << (tid & 31)) : 0; + return warp_reduce(cta_buffer); +#endif + } + + struct smem + { + enum { TAG_MASK = (1U << ( (sizeof(unsigned int) << 3) - 5U)) - 1U }; + + template + static __device__ __forceinline__ T atomicInc(T* address, T val) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) + T count; + unsigned int tag = threadIdx.x << ( (sizeof(unsigned int) << 3) - 5U); + do + { + count = *address & TAG_MASK; + count = tag | (count + 1); + *address = count; + } while (*address != count); + + return (count & TAG_MASK) - 1; +#else + return ::atomicInc(address, val); +#endif + } + + template + static __device__ __forceinline__ T atomicAdd(T* address, T val) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) + T count; + unsigned int tag = threadIdx.x << ( (sizeof(unsigned int) << 3) - 5U); + do + { + count = *address & TAG_MASK; + count = tag | (count + val); + *address = count; + } while (*address != count); + + return (count & TAG_MASK) - val; +#else + return ::atomicAdd(address, val); +#endif + } + + template + static __device__ __forceinline__ T atomicMin(T* address, T val) + { +#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120) + T count = ::min(*address, val); + do + { + *address = count; + } while (*address > count); + + return count; +#else + return ::atomicMin(address, val); +#endif + } + }; // struct cmem + + struct glob + { + static __device__ __forceinline__ int atomicAdd(int* address, int val) + { + return ::atomicAdd(address, val); + } + static __device__ __forceinline__ unsigned int atomicAdd(unsigned int* address, unsigned int val) + { + return ::atomicAdd(address, val); + } + static __device__ __forceinline__ float atomicAdd(float* address, float val) + { + #if __CUDA_ARCH__ >= 200 + return ::atomicAdd(address, val); + #else + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(val + __int_as_float(assumed))); + } while (assumed != old); + return __int_as_float(old); + #endif + } + static __device__ __forceinline__ double atomicAdd(double* address, double val) + { + #if __CUDA_ARCH__ >= 130 + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(val + __longlong_as_double(assumed))); + } while (assumed != old); + return __longlong_as_double(old); + #else + (void) address; + (void) val; + return 0.0; + #endif + } + + static __device__ __forceinline__ int atomicMin(int* address, int val) + { + return ::atomicMin(address, val); + } + static __device__ __forceinline__ float atomicMin(float* address, float val) + { + #if __CUDA_ARCH__ >= 120 + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(::fminf(val, __int_as_float(assumed)))); + } while (assumed != old); + return __int_as_float(old); + #else + (void) address; + (void) val; + return 0.0f; + #endif + } + static __device__ __forceinline__ double atomicMin(double* address, double val) + { + #if __CUDA_ARCH__ >= 130 + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(::fmin(val, __longlong_as_double(assumed)))); + } while (assumed != old); + return __longlong_as_double(old); + #else + (void) address; + (void) val; + return 0.0; + #endif + } + + static __device__ __forceinline__ int atomicMax(int* address, int val) + { + return ::atomicMax(address, val); + } + static __device__ __forceinline__ float atomicMax(float* address, float val) + { + #if __CUDA_ARCH__ >= 120 + int* address_as_i = (int*) address; + int old = *address_as_i, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_i, assumed, + __float_as_int(::fmaxf(val, __int_as_float(assumed)))); + } while (assumed != old); + return __int_as_float(old); + #else + (void) address; + (void) val; + return 0.0f; + #endif + } + static __device__ __forceinline__ double atomicMax(double* address, double val) + { + #if __CUDA_ARCH__ >= 130 + unsigned long long int* address_as_ull = (unsigned long long int*) address; + unsigned long long int old = *address_as_ull, assumed; + do { + assumed = old; + old = ::atomicCAS(address_as_ull, assumed, + __double_as_longlong(::fmax(val, __longlong_as_double(assumed)))); + } while (assumed != old); + return __longlong_as_double(old); + #else + (void) address; + (void) val; + return 0.0; + #endif + } + }; + }; //struct Emulation +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif /* OPENCV_CUDA_EMULATION_HPP_ */ diff --git a/include/opencv2/core/cuda/filters.hpp b/include/opencv2/core/cuda/filters.hpp new file mode 100644 index 0000000..9adc00c --- /dev/null +++ b/include/opencv2/core/cuda/filters.hpp @@ -0,0 +1,286 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_FILTERS_HPP__ +#define __OPENCV_CUDA_FILTERS_HPP__ + +#include "saturate_cast.hpp" +#include "vec_traits.hpp" +#include "vec_math.hpp" +#include "type_traits.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template struct PointFilter + { + typedef typename Ptr2D::elem_type elem_type; + typedef float index_type; + + explicit __host__ __device__ __forceinline__ PointFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f) + : src(src_) + { + (void)fx; + (void)fy; + } + + __device__ __forceinline__ elem_type operator ()(float y, float x) const + { + return src(__float2int_rz(y), __float2int_rz(x)); + } + + Ptr2D src; + }; + + template struct LinearFilter + { + typedef typename Ptr2D::elem_type elem_type; + typedef float index_type; + + explicit __host__ __device__ __forceinline__ LinearFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f) + : src(src_) + { + (void)fx; + (void)fy; + } + __device__ __forceinline__ elem_type operator ()(float y, float x) const + { + typedef typename TypeVec::cn>::vec_type work_type; + + work_type out = VecTraits::all(0); + + const int x1 = __float2int_rd(x); + const int y1 = __float2int_rd(y); + const int x2 = x1 + 1; + const int y2 = y1 + 1; + + elem_type src_reg = src(y1, x1); + out = out + src_reg * ((x2 - x) * (y2 - y)); + + src_reg = src(y1, x2); + out = out + src_reg * ((x - x1) * (y2 - y)); + + src_reg = src(y2, x1); + out = out + src_reg * ((x2 - x) * (y - y1)); + + src_reg = src(y2, x2); + out = out + src_reg * ((x - x1) * (y - y1)); + + return saturate_cast(out); + } + + Ptr2D src; + }; + + template struct CubicFilter + { + typedef typename Ptr2D::elem_type elem_type; + typedef float index_type; + typedef typename TypeVec::cn>::vec_type work_type; + + explicit __host__ __device__ __forceinline__ CubicFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f) + : src(src_) + { + (void)fx; + (void)fy; + } + + static __device__ __forceinline__ float bicubicCoeff(float x_) + { + float x = fabsf(x_); + if (x <= 1.0f) + { + return x * x * (1.5f * x - 2.5f) + 1.0f; + } + else if (x < 2.0f) + { + return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f; + } + else + { + return 0.0f; + } + } + + __device__ elem_type operator ()(float y, float x) const + { + const float xmin = ::ceilf(x - 2.0f); + const float xmax = ::floorf(x + 2.0f); + + const float ymin = ::ceilf(y - 2.0f); + const float ymax = ::floorf(y + 2.0f); + + work_type sum = VecTraits::all(0); + float wsum = 0.0f; + + for (float cy = ymin; cy <= ymax; cy += 1.0f) + { + for (float cx = xmin; cx <= xmax; cx += 1.0f) + { + const float w = bicubicCoeff(x - cx) * bicubicCoeff(y - cy); + sum = sum + w * src(__float2int_rd(cy), __float2int_rd(cx)); + wsum += w; + } + } + + work_type res = (!wsum)? VecTraits::all(0) : sum / wsum; + + return saturate_cast(res); + } + + Ptr2D src; + }; + // for integer scaling + template struct IntegerAreaFilter + { + typedef typename Ptr2D::elem_type elem_type; + typedef float index_type; + + explicit __host__ __device__ __forceinline__ IntegerAreaFilter(const Ptr2D& src_, float scale_x_, float scale_y_) + : src(src_), scale_x(scale_x_), scale_y(scale_y_), scale(1.f / (scale_x * scale_y)) {} + + __device__ __forceinline__ elem_type operator ()(float y, float x) const + { + float fsx1 = x * scale_x; + float fsx2 = fsx1 + scale_x; + + int sx1 = __float2int_ru(fsx1); + int sx2 = __float2int_rd(fsx2); + + float fsy1 = y * scale_y; + float fsy2 = fsy1 + scale_y; + + int sy1 = __float2int_ru(fsy1); + int sy2 = __float2int_rd(fsy2); + + typedef typename TypeVec::cn>::vec_type work_type; + work_type out = VecTraits::all(0.f); + + for(int dy = sy1; dy < sy2; ++dy) + for(int dx = sx1; dx < sx2; ++dx) + { + out = out + src(dy, dx) * scale; + } + + return saturate_cast(out); + } + + Ptr2D src; + float scale_x, scale_y ,scale; + }; + + template struct AreaFilter + { + typedef typename Ptr2D::elem_type elem_type; + typedef float index_type; + + explicit __host__ __device__ __forceinline__ AreaFilter(const Ptr2D& src_, float scale_x_, float scale_y_) + : src(src_), scale_x(scale_x_), scale_y(scale_y_){} + + __device__ __forceinline__ elem_type operator ()(float y, float x) const + { + float fsx1 = x * scale_x; + float fsx2 = fsx1 + scale_x; + + int sx1 = __float2int_ru(fsx1); + int sx2 = __float2int_rd(fsx2); + + float fsy1 = y * scale_y; + float fsy2 = fsy1 + scale_y; + + int sy1 = __float2int_ru(fsy1); + int sy2 = __float2int_rd(fsy2); + + float scale = 1.f / (fminf(scale_x, src.width - fsx1) * fminf(scale_y, src.height - fsy1)); + + typedef typename TypeVec::cn>::vec_type work_type; + work_type out = VecTraits::all(0.f); + + for (int dy = sy1; dy < sy2; ++dy) + { + for (int dx = sx1; dx < sx2; ++dx) + out = out + src(dy, dx) * scale; + + if (sx1 > fsx1) + out = out + src(dy, (sx1 -1) ) * ((sx1 - fsx1) * scale); + + if (sx2 < fsx2) + out = out + src(dy, sx2) * ((fsx2 -sx2) * scale); + } + + if (sy1 > fsy1) + for (int dx = sx1; dx < sx2; ++dx) + out = out + src( (sy1 - 1) , dx) * ((sy1 -fsy1) * scale); + + if (sy2 < fsy2) + for (int dx = sx1; dx < sx2; ++dx) + out = out + src(sy2, dx) * ((fsy2 -sy2) * scale); + + if ((sy1 > fsy1) && (sx1 > fsx1)) + out = out + src( (sy1 - 1) , (sx1 - 1)) * ((sy1 -fsy1) * (sx1 -fsx1) * scale); + + if ((sy1 > fsy1) && (sx2 < fsx2)) + out = out + src( (sy1 - 1) , sx2) * ((sy1 -fsy1) * (fsx2 -sx2) * scale); + + if ((sy2 < fsy2) && (sx2 < fsx2)) + out = out + src(sy2, sx2) * ((fsy2 -sy2) * (fsx2 -sx2) * scale); + + if ((sy2 < fsy2) && (sx1 > fsx1)) + out = out + src(sy2, (sx1 - 1)) * ((fsy2 -sy2) * (sx1 -fsx1) * scale); + + return saturate_cast(out); + } + + Ptr2D src; + float scale_x, scale_y; + int width, haight; + }; +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_FILTERS_HPP__ diff --git a/include/opencv2/core/cuda/funcattrib.hpp b/include/opencv2/core/cuda/funcattrib.hpp new file mode 100644 index 0000000..fbb236b --- /dev/null +++ b/include/opencv2/core/cuda/funcattrib.hpp @@ -0,0 +1,79 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_DEVICE_FUNCATTRIB_HPP_ +#define __OPENCV_CUDA_DEVICE_FUNCATTRIB_HPP_ + +#include + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template + void printFuncAttrib(Func& func) + { + + cudaFuncAttributes attrs; + cudaFuncGetAttributes(&attrs, func); + + printf("=== Function stats ===\n"); + printf("Name: \n"); + printf("sharedSizeBytes = %d\n", attrs.sharedSizeBytes); + printf("constSizeBytes = %d\n", attrs.constSizeBytes); + printf("localSizeBytes = %d\n", attrs.localSizeBytes); + printf("maxThreadsPerBlock = %d\n", attrs.maxThreadsPerBlock); + printf("numRegs = %d\n", attrs.numRegs); + printf("ptxVersion = %d\n", attrs.ptxVersion); + printf("binaryVersion = %d\n", attrs.binaryVersion); + printf("\n"); + fflush(stdout); + } +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif /* __OPENCV_CUDA_DEVICE_FUNCATTRIB_HPP_ */ diff --git a/include/opencv2/core/cuda/functional.hpp b/include/opencv2/core/cuda/functional.hpp new file mode 100644 index 0000000..ed3943d --- /dev/null +++ b/include/opencv2/core/cuda/functional.hpp @@ -0,0 +1,797 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_FUNCTIONAL_HPP__ +#define __OPENCV_CUDA_FUNCTIONAL_HPP__ + +#include +#include "saturate_cast.hpp" +#include "vec_traits.hpp" +#include "type_traits.hpp" +#include "device_functions.h" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + // Function Objects + template struct unary_function : public std::unary_function {}; + template struct binary_function : public std::binary_function {}; + + // Arithmetic Operations + template struct plus : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a + b; + } + __host__ __device__ __forceinline__ plus() {} + __host__ __device__ __forceinline__ plus(const plus&) {} + }; + + template struct minus : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a - b; + } + __host__ __device__ __forceinline__ minus() {} + __host__ __device__ __forceinline__ minus(const minus&) {} + }; + + template struct multiplies : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a * b; + } + __host__ __device__ __forceinline__ multiplies() {} + __host__ __device__ __forceinline__ multiplies(const multiplies&) {} + }; + + template struct divides : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a / b; + } + __host__ __device__ __forceinline__ divides() {} + __host__ __device__ __forceinline__ divides(const divides&) {} + }; + + template struct modulus : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a % b; + } + __host__ __device__ __forceinline__ modulus() {} + __host__ __device__ __forceinline__ modulus(const modulus&) {} + }; + + template struct negate : unary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a) const + { + return -a; + } + __host__ __device__ __forceinline__ negate() {} + __host__ __device__ __forceinline__ negate(const negate&) {} + }; + + // Comparison Operations + template struct equal_to : binary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a == b; + } + __host__ __device__ __forceinline__ equal_to() {} + __host__ __device__ __forceinline__ equal_to(const equal_to&) {} + }; + + template struct not_equal_to : binary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a != b; + } + __host__ __device__ __forceinline__ not_equal_to() {} + __host__ __device__ __forceinline__ not_equal_to(const not_equal_to&) {} + }; + + template struct greater : binary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a > b; + } + __host__ __device__ __forceinline__ greater() {} + __host__ __device__ __forceinline__ greater(const greater&) {} + }; + + template struct less : binary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a < b; + } + __host__ __device__ __forceinline__ less() {} + __host__ __device__ __forceinline__ less(const less&) {} + }; + + template struct greater_equal : binary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a >= b; + } + __host__ __device__ __forceinline__ greater_equal() {} + __host__ __device__ __forceinline__ greater_equal(const greater_equal&) {} + }; + + template struct less_equal : binary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a <= b; + } + __host__ __device__ __forceinline__ less_equal() {} + __host__ __device__ __forceinline__ less_equal(const less_equal&) {} + }; + + // Logical Operations + template struct logical_and : binary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a && b; + } + __host__ __device__ __forceinline__ logical_and() {} + __host__ __device__ __forceinline__ logical_and(const logical_and&) {} + }; + + template struct logical_or : binary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a || b; + } + __host__ __device__ __forceinline__ logical_or() {} + __host__ __device__ __forceinline__ logical_or(const logical_or&) {} + }; + + template struct logical_not : unary_function + { + __device__ __forceinline__ bool operator ()(typename TypeTraits::ParameterType a) const + { + return !a; + } + __host__ __device__ __forceinline__ logical_not() {} + __host__ __device__ __forceinline__ logical_not(const logical_not&) {} + }; + + // Bitwise Operations + template struct bit_and : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a & b; + } + __host__ __device__ __forceinline__ bit_and() {} + __host__ __device__ __forceinline__ bit_and(const bit_and&) {} + }; + + template struct bit_or : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a | b; + } + __host__ __device__ __forceinline__ bit_or() {} + __host__ __device__ __forceinline__ bit_or(const bit_or&) {} + }; + + template struct bit_xor : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType a, + typename TypeTraits::ParameterType b) const + { + return a ^ b; + } + __host__ __device__ __forceinline__ bit_xor() {} + __host__ __device__ __forceinline__ bit_xor(const bit_xor&) {} + }; + + template struct bit_not : unary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType v) const + { + return ~v; + } + __host__ __device__ __forceinline__ bit_not() {} + __host__ __device__ __forceinline__ bit_not(const bit_not&) {} + }; + + // Generalized Identity Operations + template struct identity : unary_function + { + __device__ __forceinline__ typename TypeTraits::ParameterType operator()(typename TypeTraits::ParameterType x) const + { + return x; + } + __host__ __device__ __forceinline__ identity() {} + __host__ __device__ __forceinline__ identity(const identity&) {} + }; + + template struct project1st : binary_function + { + __device__ __forceinline__ typename TypeTraits::ParameterType operator()(typename TypeTraits::ParameterType lhs, typename TypeTraits::ParameterType rhs) const + { + return lhs; + } + __host__ __device__ __forceinline__ project1st() {} + __host__ __device__ __forceinline__ project1st(const project1st&) {} + }; + + template struct project2nd : binary_function + { + __device__ __forceinline__ typename TypeTraits::ParameterType operator()(typename TypeTraits::ParameterType lhs, typename TypeTraits::ParameterType rhs) const + { + return rhs; + } + __host__ __device__ __forceinline__ project2nd() {} + __host__ __device__ __forceinline__ project2nd(const project2nd&) {} + }; + + // Min/Max Operations + +#define OPENCV_CUDA_IMPLEMENT_MINMAX(name, type, op) \ + template <> struct name : binary_function \ + { \ + __device__ __forceinline__ type operator()(type lhs, type rhs) const {return op(lhs, rhs);} \ + __host__ __device__ __forceinline__ name() {}\ + __host__ __device__ __forceinline__ name(const name&) {}\ + }; + + template struct maximum : binary_function + { + __device__ __forceinline__ T operator()(typename TypeTraits::ParameterType lhs, typename TypeTraits::ParameterType rhs) const + { + return max(lhs, rhs); + } + __host__ __device__ __forceinline__ maximum() {} + __host__ __device__ __forceinline__ maximum(const maximum&) {} + }; + + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, uchar, ::max) + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, schar, ::max) + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, char, ::max) + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, ushort, ::max) + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, short, ::max) + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, int, ::max) + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, uint, ::max) + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, float, ::fmax) + OPENCV_CUDA_IMPLEMENT_MINMAX(maximum, double, ::fmax) + + template struct minimum : binary_function + { + __device__ __forceinline__ T operator()(typename TypeTraits::ParameterType lhs, typename TypeTraits::ParameterType rhs) const + { + return min(lhs, rhs); + } + __host__ __device__ __forceinline__ minimum() {} + __host__ __device__ __forceinline__ minimum(const minimum&) {} + }; + + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, uchar, ::min) + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, schar, ::min) + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, char, ::min) + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, ushort, ::min) + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, short, ::min) + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, int, ::min) + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, uint, ::min) + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, float, ::fmin) + OPENCV_CUDA_IMPLEMENT_MINMAX(minimum, double, ::fmin) + +#undef OPENCV_CUDA_IMPLEMENT_MINMAX + + // Math functions + + template struct abs_func : unary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType x) const + { + return abs(x); + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ unsigned char operator ()(unsigned char x) const + { + return x; + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ signed char operator ()(signed char x) const + { + return ::abs((int)x); + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ char operator ()(char x) const + { + return ::abs((int)x); + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ unsigned short operator ()(unsigned short x) const + { + return x; + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ short operator ()(short x) const + { + return ::abs((int)x); + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ unsigned int operator ()(unsigned int x) const + { + return x; + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ int operator ()(int x) const + { + return ::abs(x); + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ float operator ()(float x) const + { + return ::fabsf(x); + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + template <> struct abs_func : unary_function + { + __device__ __forceinline__ double operator ()(double x) const + { + return ::fabs(x); + } + + __host__ __device__ __forceinline__ abs_func() {} + __host__ __device__ __forceinline__ abs_func(const abs_func&) {} + }; + +#define OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(name, func) \ + template struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ float operator ()(typename TypeTraits::ParameterType v) const \ + { \ + return func ## f(v); \ + } \ + __host__ __device__ __forceinline__ name ## _func() {} \ + __host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \ + }; \ + template <> struct name ## _func : unary_function \ + { \ + __device__ __forceinline__ double operator ()(double v) const \ + { \ + return func(v); \ + } \ + __host__ __device__ __forceinline__ name ## _func() {} \ + __host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \ + }; + +#define OPENCV_CUDA_IMPLEMENT_BIN_FUNCTOR(name, func) \ + template struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ float operator ()(typename TypeTraits::ParameterType v1, typename TypeTraits::ParameterType v2) const \ + { \ + return func ## f(v1, v2); \ + } \ + __host__ __device__ __forceinline__ name ## _func() {} \ + __host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \ + }; \ + template <> struct name ## _func : binary_function \ + { \ + __device__ __forceinline__ double operator ()(double v1, double v2) const \ + { \ + return func(v1, v2); \ + } \ + __host__ __device__ __forceinline__ name ## _func() {} \ + __host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \ + }; + + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(sqrt, ::sqrt) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(exp, ::exp) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(exp2, ::exp2) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(exp10, ::exp10) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(log, ::log) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(log2, ::log2) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(log10, ::log10) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(sin, ::sin) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(cos, ::cos) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(tan, ::tan) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(asin, ::asin) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(acos, ::acos) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(atan, ::atan) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(sinh, ::sinh) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(cosh, ::cosh) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(tanh, ::tanh) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(asinh, ::asinh) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(acosh, ::acosh) + OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR(atanh, ::atanh) + + OPENCV_CUDA_IMPLEMENT_BIN_FUNCTOR(hypot, ::hypot) + OPENCV_CUDA_IMPLEMENT_BIN_FUNCTOR(atan2, ::atan2) + OPENCV_CUDA_IMPLEMENT_BIN_FUNCTOR(pow, ::pow) + + #undef OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR + #undef OPENCV_CUDA_IMPLEMENT_UN_FUNCTOR_NO_DOUBLE + #undef OPENCV_CUDA_IMPLEMENT_BIN_FUNCTOR + + template struct hypot_sqr_func : binary_function + { + __device__ __forceinline__ T operator ()(typename TypeTraits::ParameterType src1, typename TypeTraits::ParameterType src2) const + { + return src1 * src1 + src2 * src2; + } + __host__ __device__ __forceinline__ hypot_sqr_func() {} + __host__ __device__ __forceinline__ hypot_sqr_func(const hypot_sqr_func&) {} + }; + + // Saturate Cast Functor + template struct saturate_cast_func : unary_function + { + __device__ __forceinline__ D operator ()(typename TypeTraits::ParameterType v) const + { + return saturate_cast(v); + } + __host__ __device__ __forceinline__ saturate_cast_func() {} + __host__ __device__ __forceinline__ saturate_cast_func(const saturate_cast_func&) {} + }; + + // Threshold Functors + template struct thresh_binary_func : unary_function + { + __host__ __device__ __forceinline__ thresh_binary_func(T thresh_, T maxVal_) : thresh(thresh_), maxVal(maxVal_) {} + + __device__ __forceinline__ T operator()(typename TypeTraits::ParameterType src) const + { + return (src > thresh) * maxVal; + } + + __host__ __device__ __forceinline__ thresh_binary_func() {} + __host__ __device__ __forceinline__ thresh_binary_func(const thresh_binary_func& other) + : thresh(other.thresh), maxVal(other.maxVal) {} + + T thresh; + T maxVal; + }; + + template struct thresh_binary_inv_func : unary_function + { + __host__ __device__ __forceinline__ thresh_binary_inv_func(T thresh_, T maxVal_) : thresh(thresh_), maxVal(maxVal_) {} + + __device__ __forceinline__ T operator()(typename TypeTraits::ParameterType src) const + { + return (src <= thresh) * maxVal; + } + + __host__ __device__ __forceinline__ thresh_binary_inv_func() {} + __host__ __device__ __forceinline__ thresh_binary_inv_func(const thresh_binary_inv_func& other) + : thresh(other.thresh), maxVal(other.maxVal) {} + + T thresh; + T maxVal; + }; + + template struct thresh_trunc_func : unary_function + { + explicit __host__ __device__ __forceinline__ thresh_trunc_func(T thresh_, T maxVal_ = 0) : thresh(thresh_) {(void)maxVal_;} + + __device__ __forceinline__ T operator()(typename TypeTraits::ParameterType src) const + { + return minimum()(src, thresh); + } + + __host__ __device__ __forceinline__ thresh_trunc_func() {} + __host__ __device__ __forceinline__ thresh_trunc_func(const thresh_trunc_func& other) + : thresh(other.thresh) {} + + T thresh; + }; + + template struct thresh_to_zero_func : unary_function + { + explicit __host__ __device__ __forceinline__ thresh_to_zero_func(T thresh_, T maxVal_ = 0) : thresh(thresh_) {(void)maxVal_;} + + __device__ __forceinline__ T operator()(typename TypeTraits::ParameterType src) const + { + return (src > thresh) * src; + } + + __host__ __device__ __forceinline__ thresh_to_zero_func() {} + __host__ __device__ __forceinline__ thresh_to_zero_func(const thresh_to_zero_func& other) + : thresh(other.thresh) {} + + T thresh; + }; + + template struct thresh_to_zero_inv_func : unary_function + { + explicit __host__ __device__ __forceinline__ thresh_to_zero_inv_func(T thresh_, T maxVal_ = 0) : thresh(thresh_) {(void)maxVal_;} + + __device__ __forceinline__ T operator()(typename TypeTraits::ParameterType src) const + { + return (src <= thresh) * src; + } + + __host__ __device__ __forceinline__ thresh_to_zero_inv_func() {} + __host__ __device__ __forceinline__ thresh_to_zero_inv_func(const thresh_to_zero_inv_func& other) + : thresh(other.thresh) {} + + T thresh; + }; + + // Function Object Adaptors + template struct unary_negate : unary_function + { + explicit __host__ __device__ __forceinline__ unary_negate(const Predicate& p) : pred(p) {} + + __device__ __forceinline__ bool operator()(typename TypeTraits::ParameterType x) const + { + return !pred(x); + } + + __host__ __device__ __forceinline__ unary_negate() {} + __host__ __device__ __forceinline__ unary_negate(const unary_negate& other) : pred(other.pred) {} + + Predicate pred; + }; + + template __host__ __device__ __forceinline__ unary_negate not1(const Predicate& pred) + { + return unary_negate(pred); + } + + template struct binary_negate : binary_function + { + explicit __host__ __device__ __forceinline__ binary_negate(const Predicate& p) : pred(p) {} + + __device__ __forceinline__ bool operator()(typename TypeTraits::ParameterType x, + typename TypeTraits::ParameterType y) const + { + return !pred(x,y); + } + + __host__ __device__ __forceinline__ binary_negate() {} + __host__ __device__ __forceinline__ binary_negate(const binary_negate& other) : pred(other.pred) {} + + Predicate pred; + }; + + template __host__ __device__ __forceinline__ binary_negate not2(const BinaryPredicate& pred) + { + return binary_negate(pred); + } + + template struct binder1st : unary_function + { + __host__ __device__ __forceinline__ binder1st(const Op& op_, const typename Op::first_argument_type& arg1_) : op(op_), arg1(arg1_) {} + + __device__ __forceinline__ typename Op::result_type operator ()(typename TypeTraits::ParameterType a) const + { + return op(arg1, a); + } + + __host__ __device__ __forceinline__ binder1st() {} + __host__ __device__ __forceinline__ binder1st(const binder1st& other) : op(other.op), arg1(other.arg1) {} + + Op op; + typename Op::first_argument_type arg1; + }; + + template __host__ __device__ __forceinline__ binder1st bind1st(const Op& op, const T& x) + { + return binder1st(op, typename Op::first_argument_type(x)); + } + + template struct binder2nd : unary_function + { + __host__ __device__ __forceinline__ binder2nd(const Op& op_, const typename Op::second_argument_type& arg2_) : op(op_), arg2(arg2_) {} + + __forceinline__ __device__ typename Op::result_type operator ()(typename TypeTraits::ParameterType a) const + { + return op(a, arg2); + } + + __host__ __device__ __forceinline__ binder2nd() {} + __host__ __device__ __forceinline__ binder2nd(const binder2nd& other) : op(other.op), arg2(other.arg2) {} + + Op op; + typename Op::second_argument_type arg2; + }; + + template __host__ __device__ __forceinline__ binder2nd bind2nd(const Op& op, const T& x) + { + return binder2nd(op, typename Op::second_argument_type(x)); + } + + // Functor Traits + template struct IsUnaryFunction + { + typedef char Yes; + struct No {Yes a[2];}; + + template static Yes check(unary_function); + static No check(...); + + static F makeF(); + + enum { value = (sizeof(check(makeF())) == sizeof(Yes)) }; + }; + + template struct IsBinaryFunction + { + typedef char Yes; + struct No {Yes a[2];}; + + template static Yes check(binary_function); + static No check(...); + + static F makeF(); + + enum { value = (sizeof(check(makeF())) == sizeof(Yes)) }; + }; + + namespace functional_detail + { + template struct UnOpShift { enum { shift = 1 }; }; + template struct UnOpShift { enum { shift = 4 }; }; + template struct UnOpShift { enum { shift = 2 }; }; + + template struct DefaultUnaryShift + { + enum { shift = UnOpShift::shift }; + }; + + template struct BinOpShift { enum { shift = 1 }; }; + template struct BinOpShift { enum { shift = 4 }; }; + template struct BinOpShift { enum { shift = 2 }; }; + + template struct DefaultBinaryShift + { + enum { shift = BinOpShift::shift }; + }; + + template ::value> struct ShiftDispatcher; + template struct ShiftDispatcher + { + enum { shift = DefaultUnaryShift::shift }; + }; + template struct ShiftDispatcher + { + enum { shift = DefaultBinaryShift::shift }; + }; + } + + template struct DefaultTransformShift + { + enum { shift = functional_detail::ShiftDispatcher::shift }; + }; + + template struct DefaultTransformFunctorTraits + { + enum { simple_block_dim_x = 16 }; + enum { simple_block_dim_y = 16 }; + + enum { smart_block_dim_x = 16 }; + enum { smart_block_dim_y = 16 }; + enum { smart_shift = DefaultTransformShift::shift }; + }; + + template struct TransformFunctorTraits : DefaultTransformFunctorTraits {}; + +#define OPENCV_CUDA_TRANSFORM_FUNCTOR_TRAITS(type) \ + template <> struct TransformFunctorTraits< type > : DefaultTransformFunctorTraits< type > +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_FUNCTIONAL_HPP__ diff --git a/include/opencv2/core/cuda/limits.hpp b/include/opencv2/core/cuda/limits.hpp new file mode 100644 index 0000000..b98bdf2 --- /dev/null +++ b/include/opencv2/core/cuda/limits.hpp @@ -0,0 +1,128 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_LIMITS_HPP__ +#define __OPENCV_CUDA_LIMITS_HPP__ + +#include +#include +#include "common.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ +template struct numeric_limits; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static bool min() { return false; } + __device__ __forceinline__ static bool max() { return true; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static signed char min() { return SCHAR_MIN; } + __device__ __forceinline__ static signed char max() { return SCHAR_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static unsigned char min() { return 0; } + __device__ __forceinline__ static unsigned char max() { return UCHAR_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static short min() { return SHRT_MIN; } + __device__ __forceinline__ static short max() { return SHRT_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static unsigned short min() { return 0; } + __device__ __forceinline__ static unsigned short max() { return USHRT_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static int min() { return INT_MIN; } + __device__ __forceinline__ static int max() { return INT_MAX; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static unsigned int min() { return 0; } + __device__ __forceinline__ static unsigned int max() { return UINT_MAX; } + static const bool is_signed = false; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static float min() { return FLT_MIN; } + __device__ __forceinline__ static float max() { return FLT_MAX; } + __device__ __forceinline__ static float epsilon() { return FLT_EPSILON; } + static const bool is_signed = true; +}; + +template <> struct numeric_limits +{ + __device__ __forceinline__ static double min() { return DBL_MIN; } + __device__ __forceinline__ static double max() { return DBL_MAX; } + __device__ __forceinline__ static double epsilon() { return DBL_EPSILON; } + static const bool is_signed = true; +}; +}}} // namespace cv { namespace cuda { namespace cudev { + +//! @endcond + +#endif // __OPENCV_CUDA_LIMITS_HPP__ diff --git a/include/opencv2/core/cuda/reduce.hpp b/include/opencv2/core/cuda/reduce.hpp new file mode 100644 index 0000000..3133c9a --- /dev/null +++ b/include/opencv2/core/cuda/reduce.hpp @@ -0,0 +1,205 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_REDUCE_HPP__ +#define __OPENCV_CUDA_REDUCE_HPP__ + +#include +#include "detail/reduce.hpp" +#include "detail/reduce_key_val.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template + __device__ __forceinline__ void reduce(volatile T* smem, T& val, unsigned int tid, const Op& op) + { + reduce_detail::Dispatcher::reductor::template reduce(smem, val, tid, op); + } + template + __device__ __forceinline__ void reduce(const thrust::tuple& smem, + const thrust::tuple& val, + unsigned int tid, + const thrust::tuple& op) + { + reduce_detail::Dispatcher::reductor::template reduce< + const thrust::tuple&, + const thrust::tuple&, + const thrust::tuple&>(smem, val, tid, op); + } + + template + __device__ __forceinline__ void reduceKeyVal(volatile K* skeys, K& key, volatile V* svals, V& val, unsigned int tid, const Cmp& cmp) + { + reduce_key_val_detail::Dispatcher::reductor::template reduce(skeys, key, svals, val, tid, cmp); + } + template + __device__ __forceinline__ void reduceKeyVal(volatile K* skeys, K& key, + const thrust::tuple& svals, + const thrust::tuple& val, + unsigned int tid, const Cmp& cmp) + { + reduce_key_val_detail::Dispatcher::reductor::template reduce&, + const thrust::tuple&, + const Cmp&>(skeys, key, svals, val, tid, cmp); + } + template + __device__ __forceinline__ void reduceKeyVal(const thrust::tuple& skeys, + const thrust::tuple& key, + const thrust::tuple& svals, + const thrust::tuple& val, + unsigned int tid, + const thrust::tuple& cmp) + { + reduce_key_val_detail::Dispatcher::reductor::template reduce< + const thrust::tuple&, + const thrust::tuple&, + const thrust::tuple&, + const thrust::tuple&, + const thrust::tuple& + >(skeys, key, svals, val, tid, cmp); + } + + // smem_tuple + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0) + { + return thrust::make_tuple((volatile T0*) t0); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1, T2* t2) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7, T8* t8) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7, (volatile T8*) t8); + } + + template + __device__ __forceinline__ + thrust::tuple + smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7, T8* t8, T9* t9) + { + return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7, (volatile T8*) t8, (volatile T9*) t9); + } +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_UTILITY_HPP__ diff --git a/include/opencv2/core/cuda/saturate_cast.hpp b/include/opencv2/core/cuda/saturate_cast.hpp new file mode 100644 index 0000000..e7633c7 --- /dev/null +++ b/include/opencv2/core/cuda/saturate_cast.hpp @@ -0,0 +1,292 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_SATURATE_CAST_HPP__ +#define __OPENCV_CUDA_SATURATE_CAST_HPP__ + +#include "common.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template __device__ __forceinline__ _Tp saturate_cast(uchar v) { return _Tp(v); } + template __device__ __forceinline__ _Tp saturate_cast(schar v) { return _Tp(v); } + template __device__ __forceinline__ _Tp saturate_cast(ushort v) { return _Tp(v); } + template __device__ __forceinline__ _Tp saturate_cast(short v) { return _Tp(v); } + template __device__ __forceinline__ _Tp saturate_cast(uint v) { return _Tp(v); } + template __device__ __forceinline__ _Tp saturate_cast(int v) { return _Tp(v); } + template __device__ __forceinline__ _Tp saturate_cast(float v) { return _Tp(v); } + template __device__ __forceinline__ _Tp saturate_cast(double v) { return _Tp(v); } + + template<> __device__ __forceinline__ uchar saturate_cast(schar v) + { + uint res = 0; + int vi = v; + asm("cvt.sat.u8.s8 %0, %1;" : "=r"(res) : "r"(vi)); + return res; + } + template<> __device__ __forceinline__ uchar saturate_cast(short v) + { + uint res = 0; + asm("cvt.sat.u8.s16 %0, %1;" : "=r"(res) : "h"(v)); + return res; + } + template<> __device__ __forceinline__ uchar saturate_cast(ushort v) + { + uint res = 0; + asm("cvt.sat.u8.u16 %0, %1;" : "=r"(res) : "h"(v)); + return res; + } + template<> __device__ __forceinline__ uchar saturate_cast(int v) + { + uint res = 0; + asm("cvt.sat.u8.s32 %0, %1;" : "=r"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ uchar saturate_cast(uint v) + { + uint res = 0; + asm("cvt.sat.u8.u32 %0, %1;" : "=r"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ uchar saturate_cast(float v) + { + uint res = 0; + asm("cvt.rni.sat.u8.f32 %0, %1;" : "=r"(res) : "f"(v)); + return res; + } + template<> __device__ __forceinline__ uchar saturate_cast(double v) + { + #if __CUDA_ARCH__ >= 130 + uint res = 0; + asm("cvt.rni.sat.u8.f64 %0, %1;" : "=r"(res) : "d"(v)); + return res; + #else + return saturate_cast((float)v); + #endif + } + + template<> __device__ __forceinline__ schar saturate_cast(uchar v) + { + uint res = 0; + uint vi = v; + asm("cvt.sat.s8.u8 %0, %1;" : "=r"(res) : "r"(vi)); + return res; + } + template<> __device__ __forceinline__ schar saturate_cast(short v) + { + uint res = 0; + asm("cvt.sat.s8.s16 %0, %1;" : "=r"(res) : "h"(v)); + return res; + } + template<> __device__ __forceinline__ schar saturate_cast(ushort v) + { + uint res = 0; + asm("cvt.sat.s8.u16 %0, %1;" : "=r"(res) : "h"(v)); + return res; + } + template<> __device__ __forceinline__ schar saturate_cast(int v) + { + uint res = 0; + asm("cvt.sat.s8.s32 %0, %1;" : "=r"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ schar saturate_cast(uint v) + { + uint res = 0; + asm("cvt.sat.s8.u32 %0, %1;" : "=r"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ schar saturate_cast(float v) + { + uint res = 0; + asm("cvt.rni.sat.s8.f32 %0, %1;" : "=r"(res) : "f"(v)); + return res; + } + template<> __device__ __forceinline__ schar saturate_cast(double v) + { + #if __CUDA_ARCH__ >= 130 + uint res = 0; + asm("cvt.rni.sat.s8.f64 %0, %1;" : "=r"(res) : "d"(v)); + return res; + #else + return saturate_cast((float)v); + #endif + } + + template<> __device__ __forceinline__ ushort saturate_cast(schar v) + { + ushort res = 0; + int vi = v; + asm("cvt.sat.u16.s8 %0, %1;" : "=h"(res) : "r"(vi)); + return res; + } + template<> __device__ __forceinline__ ushort saturate_cast(short v) + { + ushort res = 0; + asm("cvt.sat.u16.s16 %0, %1;" : "=h"(res) : "h"(v)); + return res; + } + template<> __device__ __forceinline__ ushort saturate_cast(int v) + { + ushort res = 0; + asm("cvt.sat.u16.s32 %0, %1;" : "=h"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ ushort saturate_cast(uint v) + { + ushort res = 0; + asm("cvt.sat.u16.u32 %0, %1;" : "=h"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ ushort saturate_cast(float v) + { + ushort res = 0; + asm("cvt.rni.sat.u16.f32 %0, %1;" : "=h"(res) : "f"(v)); + return res; + } + template<> __device__ __forceinline__ ushort saturate_cast(double v) + { + #if __CUDA_ARCH__ >= 130 + ushort res = 0; + asm("cvt.rni.sat.u16.f64 %0, %1;" : "=h"(res) : "d"(v)); + return res; + #else + return saturate_cast((float)v); + #endif + } + + template<> __device__ __forceinline__ short saturate_cast(ushort v) + { + short res = 0; + asm("cvt.sat.s16.u16 %0, %1;" : "=h"(res) : "h"(v)); + return res; + } + template<> __device__ __forceinline__ short saturate_cast(int v) + { + short res = 0; + asm("cvt.sat.s16.s32 %0, %1;" : "=h"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ short saturate_cast(uint v) + { + short res = 0; + asm("cvt.sat.s16.u32 %0, %1;" : "=h"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ short saturate_cast(float v) + { + short res = 0; + asm("cvt.rni.sat.s16.f32 %0, %1;" : "=h"(res) : "f"(v)); + return res; + } + template<> __device__ __forceinline__ short saturate_cast(double v) + { + #if __CUDA_ARCH__ >= 130 + short res = 0; + asm("cvt.rni.sat.s16.f64 %0, %1;" : "=h"(res) : "d"(v)); + return res; + #else + return saturate_cast((float)v); + #endif + } + + template<> __device__ __forceinline__ int saturate_cast(uint v) + { + int res = 0; + asm("cvt.sat.s32.u32 %0, %1;" : "=r"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ int saturate_cast(float v) + { + return __float2int_rn(v); + } + template<> __device__ __forceinline__ int saturate_cast(double v) + { + #if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 130 + return __double2int_rn(v); + #else + return saturate_cast((float)v); + #endif + } + + template<> __device__ __forceinline__ uint saturate_cast(schar v) + { + uint res = 0; + int vi = v; + asm("cvt.sat.u32.s8 %0, %1;" : "=r"(res) : "r"(vi)); + return res; + } + template<> __device__ __forceinline__ uint saturate_cast(short v) + { + uint res = 0; + asm("cvt.sat.u32.s16 %0, %1;" : "=r"(res) : "h"(v)); + return res; + } + template<> __device__ __forceinline__ uint saturate_cast(int v) + { + uint res = 0; + asm("cvt.sat.u32.s32 %0, %1;" : "=r"(res) : "r"(v)); + return res; + } + template<> __device__ __forceinline__ uint saturate_cast(float v) + { + return __float2uint_rn(v); + } + template<> __device__ __forceinline__ uint saturate_cast(double v) + { + #if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 130 + return __double2uint_rn(v); + #else + return saturate_cast((float)v); + #endif + } +}}} + +//! @endcond + +#endif /* __OPENCV_CUDA_SATURATE_CAST_HPP__ */ diff --git a/include/opencv2/core/cuda/scan.hpp b/include/opencv2/core/cuda/scan.hpp new file mode 100644 index 0000000..687abb5 --- /dev/null +++ b/include/opencv2/core/cuda/scan.hpp @@ -0,0 +1,258 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_SCAN_HPP__ +#define __OPENCV_CUDA_SCAN_HPP__ + +#include "opencv2/core/cuda/common.hpp" +#include "opencv2/core/cuda/utility.hpp" +#include "opencv2/core/cuda/warp.hpp" +#include "opencv2/core/cuda/warp_shuffle.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + enum ScanKind { EXCLUSIVE = 0, INCLUSIVE = 1 }; + + template struct WarpScan + { + __device__ __forceinline__ WarpScan() {} + __device__ __forceinline__ WarpScan(const WarpScan& other) { (void)other; } + + __device__ __forceinline__ T operator()( volatile T *ptr , const unsigned int idx) + { + const unsigned int lane = idx & 31; + F op; + + if ( lane >= 1) ptr [idx ] = op(ptr [idx - 1], ptr [idx]); + if ( lane >= 2) ptr [idx ] = op(ptr [idx - 2], ptr [idx]); + if ( lane >= 4) ptr [idx ] = op(ptr [idx - 4], ptr [idx]); + if ( lane >= 8) ptr [idx ] = op(ptr [idx - 8], ptr [idx]); + if ( lane >= 16) ptr [idx ] = op(ptr [idx - 16], ptr [idx]); + + if( Kind == INCLUSIVE ) + return ptr [idx]; + else + return (lane > 0) ? ptr [idx - 1] : 0; + } + + __device__ __forceinline__ unsigned int index(const unsigned int tid) + { + return tid; + } + + __device__ __forceinline__ void init(volatile T *ptr){} + + static const int warp_offset = 0; + + typedef WarpScan merge; + }; + + template struct WarpScanNoComp + { + __device__ __forceinline__ WarpScanNoComp() {} + __device__ __forceinline__ WarpScanNoComp(const WarpScanNoComp& other) { (void)other; } + + __device__ __forceinline__ T operator()( volatile T *ptr , const unsigned int idx) + { + const unsigned int lane = threadIdx.x & 31; + F op; + + ptr [idx ] = op(ptr [idx - 1], ptr [idx]); + ptr [idx ] = op(ptr [idx - 2], ptr [idx]); + ptr [idx ] = op(ptr [idx - 4], ptr [idx]); + ptr [idx ] = op(ptr [idx - 8], ptr [idx]); + ptr [idx ] = op(ptr [idx - 16], ptr [idx]); + + if( Kind == INCLUSIVE ) + return ptr [idx]; + else + return (lane > 0) ? ptr [idx - 1] : 0; + } + + __device__ __forceinline__ unsigned int index(const unsigned int tid) + { + return (tid >> warp_log) * warp_smem_stride + 16 + (tid & warp_mask); + } + + __device__ __forceinline__ void init(volatile T *ptr) + { + ptr[threadIdx.x] = 0; + } + + static const int warp_smem_stride = 32 + 16 + 1; + static const int warp_offset = 16; + static const int warp_log = 5; + static const int warp_mask = 31; + + typedef WarpScanNoComp merge; + }; + + template struct BlockScan + { + __device__ __forceinline__ BlockScan() {} + __device__ __forceinline__ BlockScan(const BlockScan& other) { (void)other; } + + __device__ __forceinline__ T operator()(volatile T *ptr) + { + const unsigned int tid = threadIdx.x; + const unsigned int lane = tid & warp_mask; + const unsigned int warp = tid >> warp_log; + + Sc scan; + typename Sc::merge merge_scan; + const unsigned int idx = scan.index(tid); + + T val = scan(ptr, idx); + __syncthreads (); + + if( warp == 0) + scan.init(ptr); + __syncthreads (); + + if( lane == 31 ) + ptr [scan.warp_offset + warp ] = (Kind == INCLUSIVE) ? val : ptr [idx]; + __syncthreads (); + + if( warp == 0 ) + merge_scan(ptr, idx); + __syncthreads(); + + if ( warp > 0) + val = ptr [scan.warp_offset + warp - 1] + val; + __syncthreads (); + + ptr[idx] = val; + __syncthreads (); + + return val ; + } + + static const int warp_log = 5; + static const int warp_mask = 31; + }; + + template + __device__ T warpScanInclusive(T idata, volatile T* s_Data, unsigned int tid) + { + #if __CUDA_ARCH__ >= 300 + const unsigned int laneId = cv::cuda::device::Warp::laneId(); + + // scan on shuffl functions + #pragma unroll + for (int i = 1; i <= (OPENCV_CUDA_WARP_SIZE / 2); i *= 2) + { + const T n = cv::cuda::device::shfl_up(idata, i); + if (laneId >= i) + idata += n; + } + + return idata; + #else + unsigned int pos = 2 * tid - (tid & (OPENCV_CUDA_WARP_SIZE - 1)); + s_Data[pos] = 0; + pos += OPENCV_CUDA_WARP_SIZE; + s_Data[pos] = idata; + + s_Data[pos] += s_Data[pos - 1]; + s_Data[pos] += s_Data[pos - 2]; + s_Data[pos] += s_Data[pos - 4]; + s_Data[pos] += s_Data[pos - 8]; + s_Data[pos] += s_Data[pos - 16]; + + return s_Data[pos]; + #endif + } + + template + __device__ __forceinline__ T warpScanExclusive(T idata, volatile T* s_Data, unsigned int tid) + { + return warpScanInclusive(idata, s_Data, tid) - idata; + } + + template + __device__ T blockScanInclusive(T idata, volatile T* s_Data, unsigned int tid) + { + if (tiNumScanThreads > OPENCV_CUDA_WARP_SIZE) + { + //Bottom-level inclusive warp scan + T warpResult = warpScanInclusive(idata, s_Data, tid); + + //Save top elements of each warp for exclusive warp scan + //sync to wait for warp scans to complete (because s_Data is being overwritten) + __syncthreads(); + if ((tid & (OPENCV_CUDA_WARP_SIZE - 1)) == (OPENCV_CUDA_WARP_SIZE - 1)) + { + s_Data[tid >> OPENCV_CUDA_LOG_WARP_SIZE] = warpResult; + } + + //wait for warp scans to complete + __syncthreads(); + + if (tid < (tiNumScanThreads / OPENCV_CUDA_WARP_SIZE) ) + { + //grab top warp elements + T val = s_Data[tid]; + //calculate exclusive scan and write back to shared memory + s_Data[tid] = warpScanExclusive(val, s_Data, tid); + } + + //return updated warp scans with exclusive scan results + __syncthreads(); + + return warpResult + s_Data[tid >> OPENCV_CUDA_LOG_WARP_SIZE]; + } + else + { + return warpScanInclusive(idata, s_Data, tid); + } + } +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_SCAN_HPP__ diff --git a/include/opencv2/core/cuda/simd_functions.hpp b/include/opencv2/core/cuda/simd_functions.hpp new file mode 100644 index 0000000..b9e0041 --- /dev/null +++ b/include/opencv2/core/cuda/simd_functions.hpp @@ -0,0 +1,869 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +/* + * Copyright (c) 2013 NVIDIA Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OPENCV_CUDA_SIMD_FUNCTIONS_HPP__ +#define __OPENCV_CUDA_SIMD_FUNCTIONS_HPP__ + +#include "common.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + // 2 + + static __device__ __forceinline__ unsigned int vadd2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vadd2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vadd.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = a ^ b; // sum bits + r = a + b; // actual sum + s = s ^ r; // determine carry-ins for each bit position + s = s & 0x00010000; // carry-in to high word (= carry-out from low word) + r = r - s; // subtract out carry-out from low word + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsub2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vsub2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vsub.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = a ^ b; // sum bits + r = a - b; // actual sum + s = s ^ r; // determine carry-ins for each bit position + s = s & 0x00010000; // borrow to high word + r = r + s; // compensate for borrow from low word + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vabsdiff2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vabsdiff2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vabsdiff.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t, u, v; + s = a & 0x0000ffff; // extract low halfword + r = b & 0x0000ffff; // extract low halfword + u = ::max(r, s); // maximum of low halfwords + v = ::min(r, s); // minimum of low halfwords + s = a & 0xffff0000; // extract high halfword + r = b & 0xffff0000; // extract high halfword + t = ::max(r, s); // maximum of high halfwords + s = ::min(r, s); // minimum of high halfwords + r = u | t; // maximum of both halfwords + s = v | s; // minimum of both halfwords + r = r - s; // |a - b| = max(a,b) - min(a,b); + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vavg2(unsigned int a, unsigned int b) + { + unsigned int r, s; + + // HAKMEM #23: a + b = 2 * (a & b) + (a ^ b) ==> + // (a + b) / 2 = (a & b) + ((a ^ b) >> 1) + s = a ^ b; + r = a & b; + s = s & 0xfffefffe; // ensure shift doesn't cross halfword boundaries + s = s >> 1; + s = r + s; + + return s; + } + + static __device__ __forceinline__ unsigned int vavrg2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vavrg2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // HAKMEM #23: a + b = 2 * (a | b) - (a ^ b) ==> + // (a + b + 1) / 2 = (a | b) - ((a ^ b) >> 1) + unsigned int s; + s = a ^ b; + r = a | b; + s = s & 0xfffefffe; // ensure shift doesn't cross half-word boundaries + s = s >> 1; + r = r - s; + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vseteq2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.eq %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + unsigned int c; + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x8000 + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r & ~c; // msb = 1, if r was 0x0000 + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpeq2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vseteq2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x8000 + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r & ~c; // msb = 1, if r was 0x0000 + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetge2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.ge %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg2(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpge2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetge2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg2(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetgt2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.gt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg2(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80008000; // msbs = carry-outs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpgt2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetgt2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg2(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80008000; // msbs = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetle2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.le %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg2(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmple2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetle2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg2(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetlt2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset2.u32.u32.lt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg2(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmplt2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetlt2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg2(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80008000; // msb = carry-outs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetne2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm ("vset2.u32.u32.ne %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + unsigned int c; + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r | c; // msb = 1, if r was not 0x0000 + c = c & 0x80008000; // extract msbs + r = c >> 15; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpne2(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetne2(a, b); + c = r << 16; // convert bool + r = c - r; // into mask + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x0000 if a == b + c = r | 0x80008000; // set msbs, to catch carry out + c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000 + c = r | c; // msb = 1, if r was not 0x0000 + c = c & 0x80008000; // extract msbs + r = c >> 15; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vmax2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vmax2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vmax.u32.u32.u32 %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t, u; + r = a & 0x0000ffff; // extract low halfword + s = b & 0x0000ffff; // extract low halfword + t = ::max(r, s); // maximum of low halfwords + r = a & 0xffff0000; // extract high halfword + s = b & 0xffff0000; // extract high halfword + u = ::max(r, s); // maximum of high halfwords + r = t | u; // combine halfword maximums + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vmin2(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vmin2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vmin.u32.u32.u32 %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t, u; + r = a & 0x0000ffff; // extract low halfword + s = b & 0x0000ffff; // extract low halfword + t = ::min(r, s); // minimum of low halfwords + r = a & 0xffff0000; // extract high halfword + s = b & 0xffff0000; // extract high halfword + u = ::min(r, s); // minimum of high halfwords + r = t | u; // combine halfword minimums + #endif + + return r; + } + + // 4 + + static __device__ __forceinline__ unsigned int vadd4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vadd4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vadd.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vadd.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t; + s = a ^ b; // sum bits + r = a & 0x7f7f7f7f; // clear msbs + t = b & 0x7f7f7f7f; // clear msbs + s = s & 0x80808080; // msb sum bits + r = r + t; // add without msbs, record carry-out in msbs + r = r ^ s; // sum of msb sum and carry-in bits, w/o carry-out + #endif /* __CUDA_ARCH__ >= 300 */ + + return r; + } + + static __device__ __forceinline__ unsigned int vsub4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vsub4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vsub.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vsub.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s, t; + s = a ^ ~b; // inverted sum bits + r = a | 0x80808080; // set msbs + t = b & 0x7f7f7f7f; // clear msbs + s = s & 0x80808080; // inverted msb sum bits + r = r - t; // subtract w/o msbs, record inverted borrows in msb + r = r ^ s; // combine inverted msb sum bits and borrows + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vavg4(unsigned int a, unsigned int b) + { + unsigned int r, s; + + // HAKMEM #23: a + b = 2 * (a & b) + (a ^ b) ==> + // (a + b) / 2 = (a & b) + ((a ^ b) >> 1) + s = a ^ b; + r = a & b; + s = s & 0xfefefefe; // ensure following shift doesn't cross byte boundaries + s = s >> 1; + s = r + s; + + return s; + } + + static __device__ __forceinline__ unsigned int vavrg4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vavrg4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // HAKMEM #23: a + b = 2 * (a | b) - (a ^ b) ==> + // (a + b + 1) / 2 = (a | b) - ((a ^ b) >> 1) + unsigned int c; + c = a ^ b; + r = a | b; + c = c & 0xfefefefe; // ensure following shift doesn't cross byte boundaries + c = c >> 1; + r = r - c; + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vseteq4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.eq %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + unsigned int c; + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + r = r ^ c; // extract msbs, msb = 1 if r < 0x80 + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r & ~c; // msb = 1, if r was 0x00 + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpeq4(unsigned int a, unsigned int b) + { + unsigned int r, t; + + #if __CUDA_ARCH__ >= 300 + r = vseteq4(a, b); + t = r << 8; // convert bool + r = t - r; // to mask + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + t = a ^ b; // 0x00 if a == b + r = t | 0x80808080; // set msbs, to catch carry out + t = t ^ r; // extract msbs, msb = 1 if t < 0x80 + r = r - 0x01010101; // msb = 0, if t was 0x00 or 0x80 + r = t & ~r; // msb = 1, if t was 0x00 + t = r >> 7; // build mask + t = r - t; // from + r = t | r; // msbs + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetle4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.le %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg4(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmple4(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetle4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask + #else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavrg4(a, b); // (b + ~a + 1) / 2 = (b - a) / 2 + c = c & 0x80808080; // msbs = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetlt4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.lt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg4(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmplt4(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetlt4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask + #else + asm("not.b32 %0, %0;" : "+r"(a)); + c = vavg4(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down] + c = c & 0x80808080; // msbs = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetge4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.ge %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavrg4(a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpge4(unsigned int a, unsigned int b) + { + unsigned int r, s; + + #if __CUDA_ARCH__ >= 300 + r = vsetge4(a, b); + s = r << 8; // convert bool + r = s - r; // to mask + #else + asm ("not.b32 %0,%0;" : "+r"(b)); + r = vavrg4 (a, b); // (a + ~b + 1) / 2 = (a - b) / 2 + r = r & 0x80808080; // msb = carry-outs + s = r >> 7; // build mask + s = r - s; // from + r = s | r; // msbs + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetgt4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.gt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int c; + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg4(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpgt4(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetgt4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask + #else + asm("not.b32 %0, %0;" : "+r"(b)); + c = vavg4(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down] + c = c & 0x80808080; // msb = carry-outs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vsetne4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vset4.u32.u32.ne %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + unsigned int c; + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r | c; // msb = 1, if r was not 0x00 + c = c & 0x80808080; // extract msbs + r = c >> 7; // convert to bool + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vcmpne4(unsigned int a, unsigned int b) + { + unsigned int r, c; + + #if __CUDA_ARCH__ >= 300 + r = vsetne4(a, b); + c = r << 8; // convert bool + r = c - r; // to mask + #else + // inspired by Alan Mycroft's null-byte detection algorithm: + // null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080)) + r = a ^ b; // 0x00 if a == b + c = r | 0x80808080; // set msbs, to catch carry out + c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80 + c = r | c; // msb = 1, if r was not 0x00 + c = c & 0x80808080; // extract msbs + r = c >> 7; // convert + r = c - r; // msbs to + r = c | r; // mask + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vabsdiff4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vabsdiff4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vabsdiff.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vabsdiff.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = vcmpge4(a, b); // mask = 0xff if a >= b + r = a ^ b; // + s = (r & s) ^ b; // select a when a >= b, else select b => max(a,b) + r = s ^ r; // select a when b >= a, else select b => min(a,b) + r = s - r; // |a - b| = max(a,b) - min(a,b); + #endif + + return r; + } + + static __device__ __forceinline__ unsigned int vmax4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vmax4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vmax.u32.u32.u32 %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmax.u32.u32.u32 %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = vcmpge4(a, b); // mask = 0xff if a >= b + r = a & s; // select a when b >= a + s = b & ~s; // select b when b < a + r = r | s; // combine byte selections + #endif + + return r; // byte-wise unsigned maximum + } + + static __device__ __forceinline__ unsigned int vmin4(unsigned int a, unsigned int b) + { + unsigned int r = 0; + + #if __CUDA_ARCH__ >= 300 + asm("vmin4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #elif __CUDA_ARCH__ >= 200 + asm("vmin.u32.u32.u32 %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + asm("vmin.u32.u32.u32 %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r)); + #else + unsigned int s; + s = vcmpge4(b, a); // mask = 0xff if a >= b + r = a & s; // select a when b >= a + s = b & ~s; // select b when b < a + r = r | s; // combine byte selections + #endif + + return r; + } +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_SIMD_FUNCTIONS_HPP__ diff --git a/include/opencv2/core/cuda/transform.hpp b/include/opencv2/core/cuda/transform.hpp new file mode 100644 index 0000000..08a313d --- /dev/null +++ b/include/opencv2/core/cuda/transform.hpp @@ -0,0 +1,75 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_TRANSFORM_HPP__ +#define __OPENCV_CUDA_TRANSFORM_HPP__ + +#include "common.hpp" +#include "utility.hpp" +#include "detail/transform_detail.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template + static inline void transform(PtrStepSz src, PtrStepSz dst, UnOp op, const Mask& mask, cudaStream_t stream) + { + typedef TransformFunctorTraits ft; + transform_detail::TransformDispatcher::cn == 1 && VecTraits::cn == 1 && ft::smart_shift != 1>::call(src, dst, op, mask, stream); + } + + template + static inline void transform(PtrStepSz src1, PtrStepSz src2, PtrStepSz dst, BinOp op, const Mask& mask, cudaStream_t stream) + { + typedef TransformFunctorTraits ft; + transform_detail::TransformDispatcher::cn == 1 && VecTraits::cn == 1 && VecTraits::cn == 1 && ft::smart_shift != 1>::call(src1, src2, dst, op, mask, stream); + } +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_TRANSFORM_HPP__ diff --git a/include/opencv2/core/cuda/type_traits.hpp b/include/opencv2/core/cuda/type_traits.hpp new file mode 100644 index 0000000..f2471eb --- /dev/null +++ b/include/opencv2/core/cuda/type_traits.hpp @@ -0,0 +1,90 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_TYPE_TRAITS_HPP__ +#define __OPENCV_CUDA_TYPE_TRAITS_HPP__ + +#include "detail/type_traits_detail.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template struct IsSimpleParameter + { + enum {value = type_traits_detail::IsIntegral::value || type_traits_detail::IsFloat::value || + type_traits_detail::PointerTraits::type>::value}; + }; + + template struct TypeTraits + { + typedef typename type_traits_detail::UnConst::type NonConstType; + typedef typename type_traits_detail::UnVolatile::type NonVolatileType; + typedef typename type_traits_detail::UnVolatile::type>::type UnqualifiedType; + typedef typename type_traits_detail::PointerTraits::type PointeeType; + typedef typename type_traits_detail::ReferenceTraits::type ReferredType; + + enum { isConst = type_traits_detail::UnConst::value }; + enum { isVolatile = type_traits_detail::UnVolatile::value }; + + enum { isReference = type_traits_detail::ReferenceTraits::value }; + enum { isPointer = type_traits_detail::PointerTraits::type>::value }; + + enum { isUnsignedInt = type_traits_detail::IsUnsignedIntegral::value }; + enum { isSignedInt = type_traits_detail::IsSignedIntergral::value }; + enum { isIntegral = type_traits_detail::IsIntegral::value }; + enum { isFloat = type_traits_detail::IsFloat::value }; + enum { isArith = isIntegral || isFloat }; + enum { isVec = type_traits_detail::IsVec::value }; + + typedef typename type_traits_detail::Select::value, + T, typename type_traits_detail::AddParameterType::type>::type ParameterType; + }; +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_TYPE_TRAITS_HPP__ diff --git a/include/opencv2/core/cuda/utility.hpp b/include/opencv2/core/cuda/utility.hpp new file mode 100644 index 0000000..ed60471 --- /dev/null +++ b/include/opencv2/core/cuda/utility.hpp @@ -0,0 +1,221 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_UTILITY_HPP__ +#define __OPENCV_CUDA_UTILITY_HPP__ + +#include "saturate_cast.hpp" +#include "datamov_utils.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + #define OPENCV_CUDA_LOG_WARP_SIZE (5) + #define OPENCV_CUDA_WARP_SIZE (1 << OPENCV_CUDA_LOG_WARP_SIZE) + #define OPENCV_CUDA_LOG_MEM_BANKS ((__CUDA_ARCH__ >= 200) ? 5 : 4) // 32 banks on fermi, 16 on tesla + #define OPENCV_CUDA_MEM_BANKS (1 << OPENCV_CUDA_LOG_MEM_BANKS) + + /////////////////////////////////////////////////////////////////////////////// + // swap + + template void __device__ __host__ __forceinline__ swap(T& a, T& b) + { + const T temp = a; + a = b; + b = temp; + } + + /////////////////////////////////////////////////////////////////////////////// + // Mask Reader + + struct SingleMask + { + explicit __host__ __device__ __forceinline__ SingleMask(PtrStepb mask_) : mask(mask_) {} + __host__ __device__ __forceinline__ SingleMask(const SingleMask& mask_): mask(mask_.mask){} + + __device__ __forceinline__ bool operator()(int y, int x) const + { + return mask.ptr(y)[x] != 0; + } + + PtrStepb mask; + }; + + struct SingleMaskChannels + { + __host__ __device__ __forceinline__ SingleMaskChannels(PtrStepb mask_, int channels_) + : mask(mask_), channels(channels_) {} + __host__ __device__ __forceinline__ SingleMaskChannels(const SingleMaskChannels& mask_) + :mask(mask_.mask), channels(mask_.channels){} + + __device__ __forceinline__ bool operator()(int y, int x) const + { + return mask.ptr(y)[x / channels] != 0; + } + + PtrStepb mask; + int channels; + }; + + struct MaskCollection + { + explicit __host__ __device__ __forceinline__ MaskCollection(PtrStepb* maskCollection_) + : maskCollection(maskCollection_) {} + + __device__ __forceinline__ MaskCollection(const MaskCollection& masks_) + : maskCollection(masks_.maskCollection), curMask(masks_.curMask){} + + __device__ __forceinline__ void next() + { + curMask = *maskCollection++; + } + __device__ __forceinline__ void setMask(int z) + { + curMask = maskCollection[z]; + } + + __device__ __forceinline__ bool operator()(int y, int x) const + { + uchar val; + return curMask.data == 0 || (ForceGlob::Load(curMask.ptr(y), x, val), (val != 0)); + } + + const PtrStepb* maskCollection; + PtrStepb curMask; + }; + + struct WithOutMask + { + __host__ __device__ __forceinline__ WithOutMask(){} + __host__ __device__ __forceinline__ WithOutMask(const WithOutMask&){} + + __device__ __forceinline__ void next() const + { + } + __device__ __forceinline__ void setMask(int) const + { + } + + __device__ __forceinline__ bool operator()(int, int) const + { + return true; + } + + __device__ __forceinline__ bool operator()(int, int, int) const + { + return true; + } + + static __device__ __forceinline__ bool check(int, int) + { + return true; + } + + static __device__ __forceinline__ bool check(int, int, int) + { + return true; + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // Solve linear system + + // solve 2x2 linear system Ax=b + template __device__ __forceinline__ bool solve2x2(const T A[2][2], const T b[2], T x[2]) + { + T det = A[0][0] * A[1][1] - A[1][0] * A[0][1]; + + if (det != 0) + { + double invdet = 1.0 / det; + + x[0] = saturate_cast(invdet * (b[0] * A[1][1] - b[1] * A[0][1])); + + x[1] = saturate_cast(invdet * (A[0][0] * b[1] - A[1][0] * b[0])); + + return true; + } + + return false; + } + + // solve 3x3 linear system Ax=b + template __device__ __forceinline__ bool solve3x3(const T A[3][3], const T b[3], T x[3]) + { + T det = A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) + - A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) + + A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]); + + if (det != 0) + { + double invdet = 1.0 / det; + + x[0] = saturate_cast(invdet * + (b[0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) - + A[0][1] * (b[1] * A[2][2] - A[1][2] * b[2] ) + + A[0][2] * (b[1] * A[2][1] - A[1][1] * b[2] ))); + + x[1] = saturate_cast(invdet * + (A[0][0] * (b[1] * A[2][2] - A[1][2] * b[2] ) - + b[0] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) + + A[0][2] * (A[1][0] * b[2] - b[1] * A[2][0]))); + + x[2] = saturate_cast(invdet * + (A[0][0] * (A[1][1] * b[2] - b[1] * A[2][1]) - + A[0][1] * (A[1][0] * b[2] - b[1] * A[2][0]) + + b[0] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]))); + + return true; + } + + return false; + } +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_UTILITY_HPP__ diff --git a/include/opencv2/core/cuda/vec_distance.hpp b/include/opencv2/core/cuda/vec_distance.hpp new file mode 100644 index 0000000..013b747 --- /dev/null +++ b/include/opencv2/core/cuda/vec_distance.hpp @@ -0,0 +1,232 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_VEC_DISTANCE_HPP__ +#define __OPENCV_CUDA_VEC_DISTANCE_HPP__ + +#include "reduce.hpp" +#include "functional.hpp" +#include "detail/vec_distance_detail.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template struct L1Dist + { + typedef int value_type; + typedef int result_type; + + __device__ __forceinline__ L1Dist() : mySum(0) {} + + __device__ __forceinline__ void reduceIter(int val1, int val2) + { + mySum = __sad(val1, val2, mySum); + } + + template __device__ __forceinline__ void reduceAll(int* smem, int tid) + { + reduce(smem, mySum, tid, plus()); + } + + __device__ __forceinline__ operator int() const + { + return mySum; + } + + int mySum; + }; + template <> struct L1Dist + { + typedef float value_type; + typedef float result_type; + + __device__ __forceinline__ L1Dist() : mySum(0.0f) {} + + __device__ __forceinline__ void reduceIter(float val1, float val2) + { + mySum += ::fabs(val1 - val2); + } + + template __device__ __forceinline__ void reduceAll(float* smem, int tid) + { + reduce(smem, mySum, tid, plus()); + } + + __device__ __forceinline__ operator float() const + { + return mySum; + } + + float mySum; + }; + + struct L2Dist + { + typedef float value_type; + typedef float result_type; + + __device__ __forceinline__ L2Dist() : mySum(0.0f) {} + + __device__ __forceinline__ void reduceIter(float val1, float val2) + { + float reg = val1 - val2; + mySum += reg * reg; + } + + template __device__ __forceinline__ void reduceAll(float* smem, int tid) + { + reduce(smem, mySum, tid, plus()); + } + + __device__ __forceinline__ operator float() const + { + return sqrtf(mySum); + } + + float mySum; + }; + + struct HammingDist + { + typedef int value_type; + typedef int result_type; + + __device__ __forceinline__ HammingDist() : mySum(0) {} + + __device__ __forceinline__ void reduceIter(int val1, int val2) + { + mySum += __popc(val1 ^ val2); + } + + template __device__ __forceinline__ void reduceAll(int* smem, int tid) + { + reduce(smem, mySum, tid, plus()); + } + + __device__ __forceinline__ operator int() const + { + return mySum; + } + + int mySum; + }; + + // calc distance between two vectors in global memory + template + __device__ void calcVecDiffGlobal(const T1* vec1, const T2* vec2, int len, Dist& dist, typename Dist::result_type* smem, int tid) + { + for (int i = tid; i < len; i += THREAD_DIM) + { + T1 val1; + ForceGlob::Load(vec1, i, val1); + + T2 val2; + ForceGlob::Load(vec2, i, val2); + + dist.reduceIter(val1, val2); + } + + dist.reduceAll(smem, tid); + } + + // calc distance between two vectors, first vector is cached in register or shared memory, second vector is in global memory + template + __device__ __forceinline__ void calcVecDiffCached(const T1* vecCached, const T2* vecGlob, int len, Dist& dist, typename Dist::result_type* smem, int tid) + { + vec_distance_detail::VecDiffCachedCalculator::calc(vecCached, vecGlob, len, dist, tid); + + dist.reduceAll(smem, tid); + } + + // calc distance between two vectors in global memory + template struct VecDiffGlobal + { + explicit __device__ __forceinline__ VecDiffGlobal(const T1* vec1_, int = 0, void* = 0, int = 0, int = 0) + { + vec1 = vec1_; + } + + template + __device__ __forceinline__ void calc(const T2* vec2, int len, Dist& dist, typename Dist::result_type* smem, int tid) const + { + calcVecDiffGlobal(vec1, vec2, len, dist, smem, tid); + } + + const T1* vec1; + }; + + // calc distance between two vectors, first vector is cached in register memory, second vector is in global memory + template struct VecDiffCachedRegister + { + template __device__ __forceinline__ VecDiffCachedRegister(const T1* vec1, int len, U* smem, int glob_tid, int tid) + { + if (glob_tid < len) + smem[glob_tid] = vec1[glob_tid]; + __syncthreads(); + + U* vec1ValsPtr = vec1Vals; + + #pragma unroll + for (int i = tid; i < MAX_LEN; i += THREAD_DIM) + *vec1ValsPtr++ = smem[i]; + + __syncthreads(); + } + + template + __device__ __forceinline__ void calc(const T2* vec2, int len, Dist& dist, typename Dist::result_type* smem, int tid) const + { + calcVecDiffCached(vec1Vals, vec2, len, dist, smem, tid); + } + + U vec1Vals[MAX_LEN / THREAD_DIM]; + }; +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_VEC_DISTANCE_HPP__ diff --git a/include/opencv2/core/cuda/vec_math.hpp b/include/opencv2/core/cuda/vec_math.hpp new file mode 100644 index 0000000..8595fb8 --- /dev/null +++ b/include/opencv2/core/cuda/vec_math.hpp @@ -0,0 +1,930 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_VECMATH_HPP__ +#define __OPENCV_CUDA_VECMATH_HPP__ + +#include "vec_traits.hpp" +#include "saturate_cast.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + +// saturate_cast + +namespace vec_math_detail +{ + template struct SatCastHelper; + template struct SatCastHelper<1, VecD> + { + template static __device__ __forceinline__ VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x)); + } + }; + template struct SatCastHelper<2, VecD> + { + template static __device__ __forceinline__ VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y)); + } + }; + template struct SatCastHelper<3, VecD> + { + template static __device__ __forceinline__ VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y), saturate_cast(v.z)); + } + }; + template struct SatCastHelper<4, VecD> + { + template static __device__ __forceinline__ VecD cast(const VecS& v) + { + typedef typename VecTraits::elem_type D; + return VecTraits::make(saturate_cast(v.x), saturate_cast(v.y), saturate_cast(v.z), saturate_cast(v.w)); + } + }; + + template static __device__ __forceinline__ VecD saturate_cast_helper(const VecS& v) + { + return SatCastHelper::cn, VecD>::cast(v); + } +} + +template static __device__ __forceinline__ T saturate_cast(const uchar1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const char1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const ushort1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const short1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const uint1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const int1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const float1& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const double1& v) {return vec_math_detail::saturate_cast_helper(v);} + +template static __device__ __forceinline__ T saturate_cast(const uchar2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const char2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const ushort2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const short2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const uint2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const int2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const float2& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const double2& v) {return vec_math_detail::saturate_cast_helper(v);} + +template static __device__ __forceinline__ T saturate_cast(const uchar3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const char3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const ushort3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const short3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const uint3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const int3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const float3& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const double3& v) {return vec_math_detail::saturate_cast_helper(v);} + +template static __device__ __forceinline__ T saturate_cast(const uchar4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const char4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const ushort4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const short4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const uint4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const int4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const float4& v) {return vec_math_detail::saturate_cast_helper(v);} +template static __device__ __forceinline__ T saturate_cast(const double4& v) {return vec_math_detail::saturate_cast_helper(v);} + +// unary operators + +#define CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(op, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a) \ + { \ + return VecTraits::make(op (a.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y), op (a.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a) \ + { \ + return VecTraits::make(op (a.x), op (a.y), op (a.z), op (a.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(-, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(!, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_OP(~, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_VEC_UNARY_OP + +// unary functions + +#define CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(func_name, func, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a) \ + { \ + return VecTraits::make(func (a.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y), func (a.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a) \ + { \ + return VecTraits::make(func (a.x), func (a.y), func (a.z), func (a.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, char, char) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, short, short) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::abs, int, int) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, /*::abs*/, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::fabsf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(abs, ::fabs, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrtf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sqrt, ::sqrt, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::expf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp, ::exp, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp2, ::exp2, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(exp10, ::exp10, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::logf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log, ::log, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log2, ::log2, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10f, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(log10, ::log10, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sinf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sin, ::sin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cosf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cos, ::cos, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tanf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tan, ::tan, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asinf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asin, ::asin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acosf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acos, ::acos, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atanf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atan, ::atan, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(sinh, ::sinh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::coshf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(cosh, ::cosh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(tanh, ::tanh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(asinh, ::asinh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acoshf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(acosh, ::acosh, double, double) + +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, char, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, short, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, int, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanhf, float, float) +CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC(atanh, ::atanh, double, double) + +#undef CV_CUDEV_IMPLEMENT_VEC_UNARY_FUNC + +// binary operators (vec & vec) + +#define CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(op, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a, const input_type ## 1 & b) \ + { \ + return VecTraits::make(a.x op b.x); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a, const input_type ## 2 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a, const input_type ## 3 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y, a.z op b.z); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a, const input_type ## 4 & b) \ + { \ + return VecTraits::make(a.x op b.x, a.y op b.y, a.z op b.z, a.w op b.w); \ + } + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(+, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(-, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(*, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, uchar, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, char, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, ushort, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, short, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(/, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(==, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(!=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(>=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(<=, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&&, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, char, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, ushort, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, short, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, int, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, uint, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, float, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(||, double, uchar) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(&, uint, uint) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(|, uint, uint) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_OP(^, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_VEC_BINARY_OP + +// binary operators (vec & scalar) + +#define CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(op, input_type, scalar_type, output_type) \ + __device__ __forceinline__ output_type ## 1 operator op(const input_type ## 1 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s); \ + } \ + __device__ __forceinline__ output_type ## 1 operator op(scalar_type s, const input_type ## 1 & b) \ + { \ + return VecTraits::make(s op b.x); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(const input_type ## 2 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s); \ + } \ + __device__ __forceinline__ output_type ## 2 operator op(scalar_type s, const input_type ## 2 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(const input_type ## 3 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s, a.z op s); \ + } \ + __device__ __forceinline__ output_type ## 3 operator op(scalar_type s, const input_type ## 3 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y, s op b.z); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(const input_type ## 4 & a, scalar_type s) \ + { \ + return VecTraits::make(a.x op s, a.y op s, a.z op s, a.w op s); \ + } \ + __device__ __forceinline__ output_type ## 4 operator op(scalar_type s, const input_type ## 4 & b) \ + { \ + return VecTraits::make(s op b.x, s op b.y, s op b.z, s op b.w); \ + } + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(+, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(-, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(*, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(/, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(==, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(!=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(>=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(<=, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&&, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, char, char, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, ushort, ushort, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, short, short, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, int, int, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, uint, uint, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, float, float, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(||, double, double, uchar) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(&, uint, uint, uint) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(|, uint, uint, uint) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP(^, uint, uint, uint) + +#undef CV_CUDEV_IMPLEMENT_SCALAR_BINARY_OP + +// binary function (vec & vec) + +#define CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(func_name, func, input_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a, const input_type ## 1 & b) \ + { \ + return VecTraits::make(func (a.x, b.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a, const input_type ## 2 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a, const input_type ## 3 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y), func (a.z, b.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a, const input_type ## 4 & b) \ + { \ + return VecTraits::make(func (a.x, b.x), func (a.y, b.y), func (a.z, b.z), func (a.w, b.w)); \ + } + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::max, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::fmaxf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(max, ::fmax, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, uchar, uchar) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, char, char) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, ushort, ushort) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, short, short) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, uint, uint) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::min, int, int) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::fminf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(min, ::fmin, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, char, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, short, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, uint, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, int, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypotf, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(hypot, ::hypot, double, double) + +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, uchar, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, char, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, ushort, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, short, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, uint, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, int, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2f, float, float) +CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC(atan2, ::atan2, double, double) + +#undef CV_CUDEV_IMPLEMENT_VEC_BINARY_FUNC + +// binary function (vec & scalar) + +#define CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(func_name, func, input_type, scalar_type, output_type) \ + __device__ __forceinline__ output_type ## 1 func_name(const input_type ## 1 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 1 func_name(scalar_type s, const input_type ## 1 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(const input_type ## 2 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 2 func_name(scalar_type s, const input_type ## 2 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(const input_type ## 3 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s), func ((output_type) a.z, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 3 func_name(scalar_type s, const input_type ## 3 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y), func ((output_type) s, (output_type) b.z)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(const input_type ## 4 & a, scalar_type s) \ + { \ + return VecTraits::make(func ((output_type) a.x, (output_type) s), func ((output_type) a.y, (output_type) s), func ((output_type) a.z, (output_type) s), func ((output_type) a.w, (output_type) s)); \ + } \ + __device__ __forceinline__ output_type ## 4 func_name(scalar_type s, const input_type ## 4 & b) \ + { \ + return VecTraits::make(func ((output_type) s, (output_type) b.x), func ((output_type) s, (output_type) b.y), func ((output_type) s, (output_type) b.z), func ((output_type) s, (output_type) b.w)); \ + } + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::max, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmaxf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(max, ::fmax, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, uchar, uchar, uchar) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, char, char, char) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, ushort, ushort, ushort) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, short, short, short) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, uint, uint, uint) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::min, int, int, int) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fminf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(min, ::fmin, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypotf, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(hypot, ::hypot, double, double, double) + +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, uchar, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, uchar, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, char, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, char, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, ushort, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, ushort, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, short, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, short, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, uint, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, uint, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, int, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, int, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2f, float, float, float) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, float, double, double) +CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC(atan2, ::atan2, double, double, double) + +#undef CV_CUDEV_IMPLEMENT_SCALAR_BINARY_FUNC + +}}} // namespace cv { namespace cuda { namespace device + +//! @endcond + +#endif // __OPENCV_CUDA_VECMATH_HPP__ diff --git a/include/opencv2/core/cuda/vec_traits.hpp b/include/opencv2/core/cuda/vec_traits.hpp new file mode 100644 index 0000000..905e37f --- /dev/null +++ b/include/opencv2/core/cuda/vec_traits.hpp @@ -0,0 +1,288 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_VEC_TRAITS_HPP__ +#define __OPENCV_CUDA_VEC_TRAITS_HPP__ + +#include "common.hpp" + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template struct TypeVec; + + struct __align__(8) uchar8 + { + uchar a0, a1, a2, a3, a4, a5, a6, a7; + }; + static __host__ __device__ __forceinline__ uchar8 make_uchar8(uchar a0, uchar a1, uchar a2, uchar a3, uchar a4, uchar a5, uchar a6, uchar a7) + { + uchar8 val = {a0, a1, a2, a3, a4, a5, a6, a7}; + return val; + } + struct __align__(8) char8 + { + schar a0, a1, a2, a3, a4, a5, a6, a7; + }; + static __host__ __device__ __forceinline__ char8 make_char8(schar a0, schar a1, schar a2, schar a3, schar a4, schar a5, schar a6, schar a7) + { + char8 val = {a0, a1, a2, a3, a4, a5, a6, a7}; + return val; + } + struct __align__(16) ushort8 + { + ushort a0, a1, a2, a3, a4, a5, a6, a7; + }; + static __host__ __device__ __forceinline__ ushort8 make_ushort8(ushort a0, ushort a1, ushort a2, ushort a3, ushort a4, ushort a5, ushort a6, ushort a7) + { + ushort8 val = {a0, a1, a2, a3, a4, a5, a6, a7}; + return val; + } + struct __align__(16) short8 + { + short a0, a1, a2, a3, a4, a5, a6, a7; + }; + static __host__ __device__ __forceinline__ short8 make_short8(short a0, short a1, short a2, short a3, short a4, short a5, short a6, short a7) + { + short8 val = {a0, a1, a2, a3, a4, a5, a6, a7}; + return val; + } + struct __align__(32) uint8 + { + uint a0, a1, a2, a3, a4, a5, a6, a7; + }; + static __host__ __device__ __forceinline__ uint8 make_uint8(uint a0, uint a1, uint a2, uint a3, uint a4, uint a5, uint a6, uint a7) + { + uint8 val = {a0, a1, a2, a3, a4, a5, a6, a7}; + return val; + } + struct __align__(32) int8 + { + int a0, a1, a2, a3, a4, a5, a6, a7; + }; + static __host__ __device__ __forceinline__ int8 make_int8(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) + { + int8 val = {a0, a1, a2, a3, a4, a5, a6, a7}; + return val; + } + struct __align__(32) float8 + { + float a0, a1, a2, a3, a4, a5, a6, a7; + }; + static __host__ __device__ __forceinline__ float8 make_float8(float a0, float a1, float a2, float a3, float a4, float a5, float a6, float a7) + { + float8 val = {a0, a1, a2, a3, a4, a5, a6, a7}; + return val; + } + struct double8 + { + double a0, a1, a2, a3, a4, a5, a6, a7; + }; + static __host__ __device__ __forceinline__ double8 make_double8(double a0, double a1, double a2, double a3, double a4, double a5, double a6, double a7) + { + double8 val = {a0, a1, a2, a3, a4, a5, a6, a7}; + return val; + } + +#define OPENCV_CUDA_IMPLEMENT_TYPE_VEC(type) \ + template<> struct TypeVec { typedef type vec_type; }; \ + template<> struct TypeVec { typedef type ## 1 vec_type; }; \ + template<> struct TypeVec { typedef type ## 2 vec_type; }; \ + template<> struct TypeVec { typedef type ## 2 vec_type; }; \ + template<> struct TypeVec { typedef type ## 3 vec_type; }; \ + template<> struct TypeVec { typedef type ## 3 vec_type; }; \ + template<> struct TypeVec { typedef type ## 4 vec_type; }; \ + template<> struct TypeVec { typedef type ## 4 vec_type; }; \ + template<> struct TypeVec { typedef type ## 8 vec_type; }; \ + template<> struct TypeVec { typedef type ## 8 vec_type; }; + + OPENCV_CUDA_IMPLEMENT_TYPE_VEC(uchar) + OPENCV_CUDA_IMPLEMENT_TYPE_VEC(char) + OPENCV_CUDA_IMPLEMENT_TYPE_VEC(ushort) + OPENCV_CUDA_IMPLEMENT_TYPE_VEC(short) + OPENCV_CUDA_IMPLEMENT_TYPE_VEC(int) + OPENCV_CUDA_IMPLEMENT_TYPE_VEC(uint) + OPENCV_CUDA_IMPLEMENT_TYPE_VEC(float) + OPENCV_CUDA_IMPLEMENT_TYPE_VEC(double) + + #undef OPENCV_CUDA_IMPLEMENT_TYPE_VEC + + template<> struct TypeVec { typedef schar vec_type; }; + template<> struct TypeVec { typedef char2 vec_type; }; + template<> struct TypeVec { typedef char3 vec_type; }; + template<> struct TypeVec { typedef char4 vec_type; }; + template<> struct TypeVec { typedef char8 vec_type; }; + + template<> struct TypeVec { typedef uchar vec_type; }; + template<> struct TypeVec { typedef uchar2 vec_type; }; + template<> struct TypeVec { typedef uchar3 vec_type; }; + template<> struct TypeVec { typedef uchar4 vec_type; }; + template<> struct TypeVec { typedef uchar8 vec_type; }; + + template struct VecTraits; + +#define OPENCV_CUDA_IMPLEMENT_VEC_TRAITS(type) \ + template<> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=1}; \ + static __device__ __host__ __forceinline__ type all(type v) {return v;} \ + static __device__ __host__ __forceinline__ type make(type x) {return x;} \ + static __device__ __host__ __forceinline__ type make(const type* v) {return *v;} \ + }; \ + template<> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=1}; \ + static __device__ __host__ __forceinline__ type ## 1 all(type v) {return make_ ## type ## 1(v);} \ + static __device__ __host__ __forceinline__ type ## 1 make(type x) {return make_ ## type ## 1(x);} \ + static __device__ __host__ __forceinline__ type ## 1 make(const type* v) {return make_ ## type ## 1(*v);} \ + }; \ + template<> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=2}; \ + static __device__ __host__ __forceinline__ type ## 2 all(type v) {return make_ ## type ## 2(v, v);} \ + static __device__ __host__ __forceinline__ type ## 2 make(type x, type y) {return make_ ## type ## 2(x, y);} \ + static __device__ __host__ __forceinline__ type ## 2 make(const type* v) {return make_ ## type ## 2(v[0], v[1]);} \ + }; \ + template<> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=3}; \ + static __device__ __host__ __forceinline__ type ## 3 all(type v) {return make_ ## type ## 3(v, v, v);} \ + static __device__ __host__ __forceinline__ type ## 3 make(type x, type y, type z) {return make_ ## type ## 3(x, y, z);} \ + static __device__ __host__ __forceinline__ type ## 3 make(const type* v) {return make_ ## type ## 3(v[0], v[1], v[2]);} \ + }; \ + template<> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=4}; \ + static __device__ __host__ __forceinline__ type ## 4 all(type v) {return make_ ## type ## 4(v, v, v, v);} \ + static __device__ __host__ __forceinline__ type ## 4 make(type x, type y, type z, type w) {return make_ ## type ## 4(x, y, z, w);} \ + static __device__ __host__ __forceinline__ type ## 4 make(const type* v) {return make_ ## type ## 4(v[0], v[1], v[2], v[3]);} \ + }; \ + template<> struct VecTraits \ + { \ + typedef type elem_type; \ + enum {cn=8}; \ + static __device__ __host__ __forceinline__ type ## 8 all(type v) {return make_ ## type ## 8(v, v, v, v, v, v, v, v);} \ + static __device__ __host__ __forceinline__ type ## 8 make(type a0, type a1, type a2, type a3, type a4, type a5, type a6, type a7) {return make_ ## type ## 8(a0, a1, a2, a3, a4, a5, a6, a7);} \ + static __device__ __host__ __forceinline__ type ## 8 make(const type* v) {return make_ ## type ## 8(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);} \ + }; + + OPENCV_CUDA_IMPLEMENT_VEC_TRAITS(uchar) + OPENCV_CUDA_IMPLEMENT_VEC_TRAITS(ushort) + OPENCV_CUDA_IMPLEMENT_VEC_TRAITS(short) + OPENCV_CUDA_IMPLEMENT_VEC_TRAITS(int) + OPENCV_CUDA_IMPLEMENT_VEC_TRAITS(uint) + OPENCV_CUDA_IMPLEMENT_VEC_TRAITS(float) + OPENCV_CUDA_IMPLEMENT_VEC_TRAITS(double) + + #undef OPENCV_CUDA_IMPLEMENT_VEC_TRAITS + + template<> struct VecTraits + { + typedef char elem_type; + enum {cn=1}; + static __device__ __host__ __forceinline__ char all(char v) {return v;} + static __device__ __host__ __forceinline__ char make(char x) {return x;} + static __device__ __host__ __forceinline__ char make(const char* x) {return *x;} + }; + template<> struct VecTraits + { + typedef schar elem_type; + enum {cn=1}; + static __device__ __host__ __forceinline__ schar all(schar v) {return v;} + static __device__ __host__ __forceinline__ schar make(schar x) {return x;} + static __device__ __host__ __forceinline__ schar make(const schar* x) {return *x;} + }; + template<> struct VecTraits + { + typedef schar elem_type; + enum {cn=1}; + static __device__ __host__ __forceinline__ char1 all(schar v) {return make_char1(v);} + static __device__ __host__ __forceinline__ char1 make(schar x) {return make_char1(x);} + static __device__ __host__ __forceinline__ char1 make(const schar* v) {return make_char1(v[0]);} + }; + template<> struct VecTraits + { + typedef schar elem_type; + enum {cn=2}; + static __device__ __host__ __forceinline__ char2 all(schar v) {return make_char2(v, v);} + static __device__ __host__ __forceinline__ char2 make(schar x, schar y) {return make_char2(x, y);} + static __device__ __host__ __forceinline__ char2 make(const schar* v) {return make_char2(v[0], v[1]);} + }; + template<> struct VecTraits + { + typedef schar elem_type; + enum {cn=3}; + static __device__ __host__ __forceinline__ char3 all(schar v) {return make_char3(v, v, v);} + static __device__ __host__ __forceinline__ char3 make(schar x, schar y, schar z) {return make_char3(x, y, z);} + static __device__ __host__ __forceinline__ char3 make(const schar* v) {return make_char3(v[0], v[1], v[2]);} + }; + template<> struct VecTraits + { + typedef schar elem_type; + enum {cn=4}; + static __device__ __host__ __forceinline__ char4 all(schar v) {return make_char4(v, v, v, v);} + static __device__ __host__ __forceinline__ char4 make(schar x, schar y, schar z, schar w) {return make_char4(x, y, z, w);} + static __device__ __host__ __forceinline__ char4 make(const schar* v) {return make_char4(v[0], v[1], v[2], v[3]);} + }; + template<> struct VecTraits + { + typedef schar elem_type; + enum {cn=8}; + static __device__ __host__ __forceinline__ char8 all(schar v) {return make_char8(v, v, v, v, v, v, v, v);} + static __device__ __host__ __forceinline__ char8 make(schar a0, schar a1, schar a2, schar a3, schar a4, schar a5, schar a6, schar a7) {return make_char8(a0, a1, a2, a3, a4, a5, a6, a7);} + static __device__ __host__ __forceinline__ char8 make(const schar* v) {return make_char8(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);} + }; +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif // __OPENCV_CUDA_VEC_TRAITS_HPP__ diff --git a/include/opencv2/core/cuda/warp.hpp b/include/opencv2/core/cuda/warp.hpp new file mode 100644 index 0000000..d93afe7 --- /dev/null +++ b/include/opencv2/core/cuda/warp.hpp @@ -0,0 +1,139 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_DEVICE_WARP_HPP__ +#define __OPENCV_CUDA_DEVICE_WARP_HPP__ + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + struct Warp + { + enum + { + LOG_WARP_SIZE = 5, + WARP_SIZE = 1 << LOG_WARP_SIZE, + STRIDE = WARP_SIZE + }; + + /** \brief Returns the warp lane ID of the calling thread. */ + static __device__ __forceinline__ unsigned int laneId() + { + unsigned int ret; + asm("mov.u32 %0, %laneid;" : "=r"(ret) ); + return ret; + } + + template + static __device__ __forceinline__ void fill(It beg, It end, const T& value) + { + for(It t = beg + laneId(); t < end; t += STRIDE) + *t = value; + } + + template + static __device__ __forceinline__ OutIt copy(InIt beg, InIt end, OutIt out) + { + for(InIt t = beg + laneId(); t < end; t += STRIDE, out += STRIDE) + *out = *t; + return out; + } + + template + static __device__ __forceinline__ OutIt transform(InIt beg, InIt end, OutIt out, UnOp op) + { + for(InIt t = beg + laneId(); t < end; t += STRIDE, out += STRIDE) + *out = op(*t); + return out; + } + + template + static __device__ __forceinline__ OutIt transform(InIt1 beg1, InIt1 end1, InIt2 beg2, OutIt out, BinOp op) + { + unsigned int lane = laneId(); + + InIt1 t1 = beg1 + lane; + InIt2 t2 = beg2 + lane; + for(; t1 < end1; t1 += STRIDE, t2 += STRIDE, out += STRIDE) + *out = op(*t1, *t2); + return out; + } + + template + static __device__ __forceinline__ T reduce(volatile T *ptr, BinOp op) + { + const unsigned int lane = laneId(); + + if (lane < 16) + { + T partial = ptr[lane]; + + ptr[lane] = partial = op(partial, ptr[lane + 16]); + ptr[lane] = partial = op(partial, ptr[lane + 8]); + ptr[lane] = partial = op(partial, ptr[lane + 4]); + ptr[lane] = partial = op(partial, ptr[lane + 2]); + ptr[lane] = partial = op(partial, ptr[lane + 1]); + } + + return *ptr; + } + + template + static __device__ __forceinline__ void yota(OutIt beg, OutIt end, T value) + { + unsigned int lane = laneId(); + value += lane; + + for(OutIt t = beg + lane; t < end; t += STRIDE, value += STRIDE) + *t = value; + } + }; +}}} // namespace cv { namespace cuda { namespace cudev + +//! @endcond + +#endif /* __OPENCV_CUDA_DEVICE_WARP_HPP__ */ diff --git a/include/opencv2/core/cuda/warp_reduce.hpp b/include/opencv2/core/cuda/warp_reduce.hpp new file mode 100644 index 0000000..530303d --- /dev/null +++ b/include/opencv2/core/cuda/warp_reduce.hpp @@ -0,0 +1,76 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef OPENCV_CUDA_WARP_REDUCE_HPP__ +#define OPENCV_CUDA_WARP_REDUCE_HPP__ + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template + __device__ __forceinline__ T warp_reduce(volatile T *ptr , const unsigned int tid = threadIdx.x) + { + const unsigned int lane = tid & 31; // index of thread in warp (0..31) + + if (lane < 16) + { + T partial = ptr[tid]; + + ptr[tid] = partial = partial + ptr[tid + 16]; + ptr[tid] = partial = partial + ptr[tid + 8]; + ptr[tid] = partial = partial + ptr[tid + 4]; + ptr[tid] = partial = partial + ptr[tid + 2]; + ptr[tid] = partial = partial + ptr[tid + 1]; + } + + return ptr[tid - lane]; + } +}}} // namespace cv { namespace cuda { namespace cudev { + +//! @endcond + +#endif /* OPENCV_CUDA_WARP_REDUCE_HPP__ */ diff --git a/include/opencv2/core/cuda/warp_shuffle.hpp b/include/opencv2/core/cuda/warp_shuffle.hpp new file mode 100644 index 0000000..5cf42ec --- /dev/null +++ b/include/opencv2/core/cuda/warp_shuffle.hpp @@ -0,0 +1,153 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CUDA_WARP_SHUFFLE_HPP__ +#define __OPENCV_CUDA_WARP_SHUFFLE_HPP__ + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +namespace cv { namespace cuda { namespace device +{ + template + __device__ __forceinline__ T shfl(T val, int srcLane, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + return __shfl(val, srcLane, width); + #else + return T(); + #endif + } + __device__ __forceinline__ unsigned int shfl(unsigned int val, int srcLane, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + return (unsigned int) __shfl((int) val, srcLane, width); + #else + return 0; + #endif + } + __device__ __forceinline__ double shfl(double val, int srcLane, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + int lo = __double2loint(val); + int hi = __double2hiint(val); + + lo = __shfl(lo, srcLane, width); + hi = __shfl(hi, srcLane, width); + + return __hiloint2double(hi, lo); + #else + return 0.0; + #endif + } + + template + __device__ __forceinline__ T shfl_down(T val, unsigned int delta, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + return __shfl_down(val, delta, width); + #else + return T(); + #endif + } + __device__ __forceinline__ unsigned int shfl_down(unsigned int val, unsigned int delta, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + return (unsigned int) __shfl_down((int) val, delta, width); + #else + return 0; + #endif + } + __device__ __forceinline__ double shfl_down(double val, unsigned int delta, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + int lo = __double2loint(val); + int hi = __double2hiint(val); + + lo = __shfl_down(lo, delta, width); + hi = __shfl_down(hi, delta, width); + + return __hiloint2double(hi, lo); + #else + return 0.0; + #endif + } + + template + __device__ __forceinline__ T shfl_up(T val, unsigned int delta, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + return __shfl_up(val, delta, width); + #else + return T(); + #endif + } + __device__ __forceinline__ unsigned int shfl_up(unsigned int val, unsigned int delta, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + return (unsigned int) __shfl_up((int) val, delta, width); + #else + return 0; + #endif + } + __device__ __forceinline__ double shfl_up(double val, unsigned int delta, int width = warpSize) + { + #if __CUDA_ARCH__ >= 300 + int lo = __double2loint(val); + int hi = __double2hiint(val); + + lo = __shfl_up(lo, delta, width); + hi = __shfl_up(hi, delta, width); + + return __hiloint2double(hi, lo); + #else + return 0.0; + #endif + } +}}} + +//! @endcond + +#endif // __OPENCV_CUDA_WARP_SHUFFLE_HPP__ diff --git a/include/opencv2/core/cuda_stream_accessor.hpp b/include/opencv2/core/cuda_stream_accessor.hpp new file mode 100644 index 0000000..dd6589b --- /dev/null +++ b/include/opencv2/core/cuda_stream_accessor.hpp @@ -0,0 +1,87 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CUDA_STREAM_ACCESSOR_HPP__ +#define __OPENCV_CORE_CUDA_STREAM_ACCESSOR_HPP__ + +#ifndef __cplusplus +# error cuda_stream_accessor.hpp header must be compiled as C++ +#endif + +/** @file cuda_stream_accessor.hpp + * This is only header file that depends on CUDA Runtime API. All other headers are independent. + */ + +#include +#include "opencv2/core/cvdef.h" + +namespace cv +{ + namespace cuda + { + +//! @addtogroup cudacore_struct +//! @{ + + class Stream; + class Event; + + /** @brief Class that enables getting cudaStream_t from cuda::Stream + */ + struct StreamAccessor + { + CV_EXPORTS static cudaStream_t getStream(const Stream& stream); + }; + + /** @brief Class that enables getting cudaEvent_t from cuda::Event + */ + struct EventAccessor + { + CV_EXPORTS static cudaEvent_t getEvent(const Event& event); + }; + +//! @} + + } +} + +#endif /* __OPENCV_CORE_CUDA_STREAM_ACCESSOR_HPP__ */ diff --git a/include/opencv2/core/cuda_types.hpp b/include/opencv2/core/cuda_types.hpp new file mode 100644 index 0000000..8df816e --- /dev/null +++ b/include/opencv2/core/cuda_types.hpp @@ -0,0 +1,135 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CUDA_TYPES_HPP__ +#define __OPENCV_CORE_CUDA_TYPES_HPP__ + +#ifndef __cplusplus +# error cuda_types.hpp header must be compiled as C++ +#endif + +/** @file + * @deprecated Use @ref cudev instead. + */ + +//! @cond IGNORED + +#ifdef __CUDACC__ + #define __CV_CUDA_HOST_DEVICE__ __host__ __device__ __forceinline__ +#else + #define __CV_CUDA_HOST_DEVICE__ +#endif + +namespace cv +{ + namespace cuda + { + + // Simple lightweight structures that encapsulates information about an image on device. + // It is intended to pass to nvcc-compiled code. GpuMat depends on headers that nvcc can't compile + + template struct DevPtr + { + typedef T elem_type; + typedef int index_type; + + enum { elem_size = sizeof(elem_type) }; + + T* data; + + __CV_CUDA_HOST_DEVICE__ DevPtr() : data(0) {} + __CV_CUDA_HOST_DEVICE__ DevPtr(T* data_) : data(data_) {} + + __CV_CUDA_HOST_DEVICE__ size_t elemSize() const { return elem_size; } + __CV_CUDA_HOST_DEVICE__ operator T*() { return data; } + __CV_CUDA_HOST_DEVICE__ operator const T*() const { return data; } + }; + + template struct PtrSz : public DevPtr + { + __CV_CUDA_HOST_DEVICE__ PtrSz() : size(0) {} + __CV_CUDA_HOST_DEVICE__ PtrSz(T* data_, size_t size_) : DevPtr(data_), size(size_) {} + + size_t size; + }; + + template struct PtrStep : public DevPtr + { + __CV_CUDA_HOST_DEVICE__ PtrStep() : step(0) {} + __CV_CUDA_HOST_DEVICE__ PtrStep(T* data_, size_t step_) : DevPtr(data_), step(step_) {} + + size_t step; + + __CV_CUDA_HOST_DEVICE__ T* ptr(int y = 0) { return ( T*)( ( char*)DevPtr::data + y * step); } + __CV_CUDA_HOST_DEVICE__ const T* ptr(int y = 0) const { return (const T*)( (const char*)DevPtr::data + y * step); } + + __CV_CUDA_HOST_DEVICE__ T& operator ()(int y, int x) { return ptr(y)[x]; } + __CV_CUDA_HOST_DEVICE__ const T& operator ()(int y, int x) const { return ptr(y)[x]; } + }; + + template struct PtrStepSz : public PtrStep + { + __CV_CUDA_HOST_DEVICE__ PtrStepSz() : cols(0), rows(0) {} + __CV_CUDA_HOST_DEVICE__ PtrStepSz(int rows_, int cols_, T* data_, size_t step_) + : PtrStep(data_, step_), cols(cols_), rows(rows_) {} + + template + explicit PtrStepSz(const PtrStepSz& d) : PtrStep((T*)d.data, d.step), cols(d.cols), rows(d.rows){} + + int cols; + int rows; + }; + + typedef PtrStepSz PtrStepSzb; + typedef PtrStepSz PtrStepSzf; + typedef PtrStepSz PtrStepSzi; + + typedef PtrStep PtrStepb; + typedef PtrStep PtrStepf; + typedef PtrStep PtrStepi; + + } +} + +//! @endcond + +#endif /* __OPENCV_CORE_CUDA_TYPES_HPP__ */ diff --git a/include/opencv2/core/cvdef.h b/include/opencv2/core/cvdef.h new file mode 100644 index 0000000..1d933b5 --- /dev/null +++ b/include/opencv2/core/cvdef.h @@ -0,0 +1,231 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CVDEF_H__ +#define __OPENCV_CORE_CVDEF_H__ + +#if !defined _CRT_SECURE_NO_DEPRECATE && defined _MSC_VER && _MSC_VER > 1300 +# define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio warnings */ +#endif + +// undef problematic defines sometimes defined by system headers (windows.h in particular) +#undef small +#undef min +#undef max +#undef abs +#undef Complex + +#include "opencv2/hal/defs.h" + +#ifdef __OPENCV_BUILD +# define DISABLE_OPENCV_24_COMPATIBILITY +#endif + +#if (defined WIN32 || defined _WIN32 || defined WINCE || defined __CYGWIN__) && defined CVAPI_EXPORTS +# define CV_EXPORTS __declspec(dllexport) +#elif defined __GNUC__ && __GNUC__ >= 4 +# define CV_EXPORTS __attribute__ ((visibility ("default"))) +#else +# define CV_EXPORTS +#endif + +#ifndef CV_EXTERN_C +# ifdef __cplusplus +# define CV_EXTERN_C extern "C" +# else +# define CV_EXTERN_C +# endif +#endif + +/* special informative macros for wrapper generators */ +#define CV_EXPORTS_W CV_EXPORTS +#define CV_EXPORTS_W_SIMPLE CV_EXPORTS +#define CV_EXPORTS_AS(synonym) CV_EXPORTS +#define CV_EXPORTS_W_MAP CV_EXPORTS +#define CV_IN_OUT +#define CV_OUT +#define CV_PROP +#define CV_PROP_RW +#define CV_WRAP +#define CV_WRAP_AS(synonym) + +/****************************************************************************************\ +* Matrix type (Mat) * +\****************************************************************************************/ + +#define CV_CN_MAX 512 +#define CV_CN_SHIFT 3 +#define CV_DEPTH_MAX (1 << CV_CN_SHIFT) + +#define CV_8U 0 +#define CV_8S 1 +#define CV_16U 2 +#define CV_16S 3 +#define CV_32S 4 +#define CV_32F 5 +#define CV_64F 6 +#define CV_USRTYPE1 7 + +#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1) +#define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK) + +#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT)) +#define CV_MAKE_TYPE CV_MAKETYPE + +#define CV_8UC1 CV_MAKETYPE(CV_8U,1) +#define CV_8UC2 CV_MAKETYPE(CV_8U,2) +#define CV_8UC3 CV_MAKETYPE(CV_8U,3) +#define CV_8UC4 CV_MAKETYPE(CV_8U,4) +#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n)) + +#define CV_8SC1 CV_MAKETYPE(CV_8S,1) +#define CV_8SC2 CV_MAKETYPE(CV_8S,2) +#define CV_8SC3 CV_MAKETYPE(CV_8S,3) +#define CV_8SC4 CV_MAKETYPE(CV_8S,4) +#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n)) + +#define CV_16UC1 CV_MAKETYPE(CV_16U,1) +#define CV_16UC2 CV_MAKETYPE(CV_16U,2) +#define CV_16UC3 CV_MAKETYPE(CV_16U,3) +#define CV_16UC4 CV_MAKETYPE(CV_16U,4) +#define CV_16UC(n) CV_MAKETYPE(CV_16U,(n)) + +#define CV_16SC1 CV_MAKETYPE(CV_16S,1) +#define CV_16SC2 CV_MAKETYPE(CV_16S,2) +#define CV_16SC3 CV_MAKETYPE(CV_16S,3) +#define CV_16SC4 CV_MAKETYPE(CV_16S,4) +#define CV_16SC(n) CV_MAKETYPE(CV_16S,(n)) + +#define CV_32SC1 CV_MAKETYPE(CV_32S,1) +#define CV_32SC2 CV_MAKETYPE(CV_32S,2) +#define CV_32SC3 CV_MAKETYPE(CV_32S,3) +#define CV_32SC4 CV_MAKETYPE(CV_32S,4) +#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n)) + +#define CV_32FC1 CV_MAKETYPE(CV_32F,1) +#define CV_32FC2 CV_MAKETYPE(CV_32F,2) +#define CV_32FC3 CV_MAKETYPE(CV_32F,3) +#define CV_32FC4 CV_MAKETYPE(CV_32F,4) +#define CV_32FC(n) CV_MAKETYPE(CV_32F,(n)) + +#define CV_64FC1 CV_MAKETYPE(CV_64F,1) +#define CV_64FC2 CV_MAKETYPE(CV_64F,2) +#define CV_64FC3 CV_MAKETYPE(CV_64F,3) +#define CV_64FC4 CV_MAKETYPE(CV_64F,4) +#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n)) + +#define CV_MAT_CN_MASK ((CV_CN_MAX - 1) << CV_CN_SHIFT) +#define CV_MAT_CN(flags) ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1) +#define CV_MAT_TYPE_MASK (CV_DEPTH_MAX*CV_CN_MAX - 1) +#define CV_MAT_TYPE(flags) ((flags) & CV_MAT_TYPE_MASK) +#define CV_MAT_CONT_FLAG_SHIFT 14 +#define CV_MAT_CONT_FLAG (1 << CV_MAT_CONT_FLAG_SHIFT) +#define CV_IS_MAT_CONT(flags) ((flags) & CV_MAT_CONT_FLAG) +#define CV_IS_CONT_MAT CV_IS_MAT_CONT +#define CV_SUBMAT_FLAG_SHIFT 15 +#define CV_SUBMAT_FLAG (1 << CV_SUBMAT_FLAG_SHIFT) +#define CV_IS_SUBMAT(flags) ((flags) & CV_MAT_SUBMAT_FLAG) + +/* Size of each channel item, + 0x124489 = 1000 0100 0100 0010 0010 0001 0001 ~ array of sizeof(arr_type_elem) */ +#define CV_ELEM_SIZE1(type) \ + ((((sizeof(size_t)<<28)|0x8442211) >> CV_MAT_DEPTH(type)*4) & 15) + +/* 0x3a50 = 11 10 10 01 01 00 00 ~ array of log2(sizeof(arr_type_elem)) */ +#define CV_ELEM_SIZE(type) \ + (CV_MAT_CN(type) << ((((sizeof(size_t)/4+1)*16384|0x3a50) >> CV_MAT_DEPTH(type)*2) & 3)) + +#ifndef MIN +# define MIN(a,b) ((a) > (b) ? (b) : (a)) +#endif + +#ifndef MAX +# define MAX(a,b) ((a) < (b) ? (b) : (a)) +#endif + +/****************************************************************************************\ +* exchange-add operation for atomic operations on reference counters * +\****************************************************************************************/ + +#if defined __INTEL_COMPILER && !(defined WIN32 || defined _WIN32) + // atomic increment on the linux version of the Intel(tm) compiler +# define CV_XADD(addr, delta) (int)_InterlockedExchangeAdd(const_cast(reinterpret_cast(addr)), delta) +#elif defined __GNUC__ +# if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ && !defined(__CUDACC__) +# ifdef __ATOMIC_ACQ_REL +# define CV_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), delta, __ATOMIC_ACQ_REL) +# else +# define CV_XADD(addr, delta) __atomic_fetch_add((_Atomic(int)*)(addr), delta, 4) +# endif +# else +# if defined __ATOMIC_ACQ_REL && !defined __clang__ + // version for gcc >= 4.7 +# define CV_XADD(addr, delta) (int)__atomic_fetch_add((unsigned*)(addr), (unsigned)(delta), __ATOMIC_ACQ_REL) +# else +# define CV_XADD(addr, delta) (int)__sync_fetch_and_add((unsigned*)(addr), (unsigned)(delta)) +# endif +# endif +#elif defined _MSC_VER && !defined RC_INVOKED +# include +# define CV_XADD(addr, delta) (int)_InterlockedExchangeAdd((long volatile*)addr, delta) +#else + CV_INLINE CV_XADD(int* addr, int delta) { int tmp = *addr; *addr += delta; return tmp; } +#endif + + +/****************************************************************************************\ +* CV_NORETURN attribute * +\****************************************************************************************/ + +#ifndef CV_NORETURN +# if defined(__GNUC__) +# define CV_NORETURN __attribute__((__noreturn__)) +# elif defined(_MSC_VER) && (_MSC_VER >= 1300) +# define CV_NORETURN __declspec(noreturn) +# else +# define CV_NORETURN /* nothing by default */ +# endif +#endif + +#endif // __OPENCV_CORE_CVDEF_H__ diff --git a/include/opencv2/core/cvstd.hpp b/include/opencv2/core/cvstd.hpp new file mode 100644 index 0000000..a229f53 --- /dev/null +++ b/include/opencv2/core/cvstd.hpp @@ -0,0 +1,1059 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CVSTD_HPP__ +#define __OPENCV_CORE_CVSTD_HPP__ + +#ifndef __cplusplus +# error cvstd.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/cvdef.h" + +#include +#include +#include + +#ifndef OPENCV_NOSTL +# include +#endif + +// import useful primitives from stl +#ifndef OPENCV_NOSTL_TRANSITIONAL +# include +# include +# include //for abs(int) +# include + +namespace cv +{ + using std::min; + using std::max; + using std::abs; + using std::swap; + using std::sqrt; + using std::exp; + using std::pow; + using std::log; +} + +namespace std +{ + static inline uchar abs(uchar a) { return a; } + static inline ushort abs(ushort a) { return a; } + static inline unsigned abs(unsigned a) { return a; } + static inline uint64 abs(uint64 a) { return a; } +} + +#else +namespace cv +{ + template static inline T min(T a, T b) { return a < b ? a : b; } + template static inline T max(T a, T b) { return a > b ? a : b; } + template static inline T abs(T a) { return a < 0 ? -a : a; } + template static inline void swap(T& a, T& b) { T tmp = a; a = b; b = tmp; } + + template<> inline uchar abs(uchar a) { return a; } + template<> inline ushort abs(ushort a) { return a; } + template<> inline unsigned abs(unsigned a) { return a; } + template<> inline uint64 abs(uint64 a) { return a; } +} +#endif + +namespace cv { + +//! @addtogroup core_utils +//! @{ + +//////////////////////////// memory management functions //////////////////////////// + +/** @brief Allocates an aligned memory buffer. + +The function allocates the buffer of the specified size and returns it. When the buffer size is 16 +bytes or more, the returned buffer is aligned to 16 bytes. +@param bufSize Allocated buffer size. + */ +CV_EXPORTS void* fastMalloc(size_t bufSize); + +/** @brief Deallocates a memory buffer. + +The function deallocates the buffer allocated with fastMalloc . If NULL pointer is passed, the +function does nothing. C version of the function clears the pointer *pptr* to avoid problems with +double memory deallocation. +@param ptr Pointer to the allocated buffer. + */ +CV_EXPORTS void fastFree(void* ptr); + +/*! + The STL-compilant memory Allocator based on cv::fastMalloc() and cv::fastFree() +*/ +template class Allocator +{ +public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + template class rebind { typedef Allocator other; }; + + explicit Allocator() {} + ~Allocator() {} + explicit Allocator(Allocator const&) {} + template + explicit Allocator(Allocator const&) {} + + // address + pointer address(reference r) { return &r; } + const_pointer address(const_reference r) { return &r; } + + pointer allocate(size_type count, const void* =0) { return reinterpret_cast(fastMalloc(count * sizeof (_Tp))); } + void deallocate(pointer p, size_type) { fastFree(p); } + + void construct(pointer p, const _Tp& v) { new(static_cast(p)) _Tp(v); } + void destroy(pointer p) { p->~_Tp(); } + + size_type max_size() const { return cv::max(static_cast<_Tp>(-1)/sizeof(_Tp), 1); } +}; + +//! @} core_utils + +//! @cond IGNORED + +namespace detail +{ + +// Metafunction to avoid taking a reference to void. +template +struct RefOrVoid { typedef T& type; }; + +template<> +struct RefOrVoid{ typedef void type; }; + +template<> +struct RefOrVoid{ typedef const void type; }; + +template<> +struct RefOrVoid{ typedef volatile void type; }; + +template<> +struct RefOrVoid{ typedef const volatile void type; }; + +// This class would be private to Ptr, if it didn't have to be a non-template. +struct PtrOwner; + +} + +template +struct DefaultDeleter +{ + void operator () (Y* p) const; +}; + +//! @endcond + +//! @addtogroup core_basic +//! @{ + +/** @brief Template class for smart pointers with shared ownership + +A Ptr\ pretends to be a pointer to an object of type T. Unlike an ordinary pointer, however, the +object will be automatically cleaned up once all Ptr instances pointing to it are destroyed. + +Ptr is similar to boost::shared_ptr that is part of the Boost library +() and std::shared_ptr from +the [C++11](http://en.wikipedia.org/wiki/C++11) standard. + +This class provides the following advantages: +- Default constructor, copy constructor, and assignment operator for an arbitrary C++ class or C + structure. For some objects, like files, windows, mutexes, sockets, and others, a copy + constructor or an assignment operator are difficult to define. For some other objects, like + complex classifiers in OpenCV, copy constructors are absent and not easy to implement. Finally, + some of complex OpenCV and your own data structures may be written in C. However, copy + constructors and default constructors can simplify programming a lot. Besides, they are often + required (for example, by STL containers). By using a Ptr to such an object instead of the + object itself, you automatically get all of the necessary constructors and the assignment + operator. +- *O(1)* complexity of the above-mentioned operations. While some structures, like std::vector, + provide a copy constructor and an assignment operator, the operations may take a considerable + amount of time if the data structures are large. But if the structures are put into a Ptr, the + overhead is small and independent of the data size. +- Automatic and customizable cleanup, even for C structures. See the example below with FILE\*. +- Heterogeneous collections of objects. The standard STL and most other C++ and OpenCV containers + can store only objects of the same type and the same size. The classical solution to store + objects of different types in the same container is to store pointers to the base class (Base\*) + instead but then you lose the automatic memory management. Again, by using Ptr\ instead + of raw pointers, you can solve the problem. + +A Ptr is said to *own* a pointer - that is, for each Ptr there is a pointer that will be deleted +once all Ptr instances that own it are destroyed. The owned pointer may be null, in which case +nothing is deleted. Each Ptr also *stores* a pointer. The stored pointer is the pointer the Ptr +pretends to be; that is, the one you get when you use Ptr::get or the conversion to T\*. It's +usually the same as the owned pointer, but if you use casts or the general shared-ownership +constructor, the two may diverge: the Ptr will still own the original pointer, but will itself point +to something else. + +The owned pointer is treated as a black box. The only thing Ptr needs to know about it is how to +delete it. This knowledge is encapsulated in the *deleter* - an auxiliary object that is associated +with the owned pointer and shared between all Ptr instances that own it. The default deleter is an +instance of DefaultDeleter, which uses the standard C++ delete operator; as such it will work with +any pointer allocated with the standard new operator. + +However, if the pointer must be deleted in a different way, you must specify a custom deleter upon +Ptr construction. A deleter is simply a callable object that accepts the pointer as its sole +argument. For example, if you want to wrap FILE, you may do so as follows: +@code + Ptr f(fopen("myfile.txt", "w"), fclose); + if(!f) throw ...; + fprintf(f, ....); + ... + // the file will be closed automatically by f's destructor. +@endcode +Alternatively, if you want all pointers of a particular type to be deleted the same way, you can +specialize DefaultDeleter::operator() for that type, like this: +@code + namespace cv { + template<> void DefaultDeleter::operator ()(FILE * obj) const + { + fclose(obj); + } + } +@endcode +For convenience, the following types from the OpenCV C API already have such a specialization that +calls the appropriate release function: +- CvCapture +- CvFileStorage +- CvHaarClassifierCascade +- CvMat +- CvMatND +- CvMemStorage +- CvSparseMat +- CvVideoWriter +- IplImage +@note The shared ownership mechanism is implemented with reference counting. As such, cyclic +ownership (e.g. when object a contains a Ptr to object b, which contains a Ptr to object a) will +lead to all involved objects never being cleaned up. Avoid such situations. +@note It is safe to concurrently read (but not write) a Ptr instance from multiple threads and +therefore it is normally safe to use it in multi-threaded applications. The same is true for Mat and +other C++ OpenCV classes that use internal reference counts. +*/ +template +struct Ptr +{ + /** Generic programming support. */ + typedef T element_type; + + /** The default constructor creates a null Ptr - one that owns and stores a null pointer. + */ + Ptr(); + + /** + If p is null, these are equivalent to the default constructor. + Otherwise, these constructors assume ownership of p - that is, the created Ptr owns and stores p + and assumes it is the sole owner of it. Don't use them if p is already owned by another Ptr, or + else p will get deleted twice. + With the first constructor, DefaultDeleter\() becomes the associated deleter (so p will + eventually be deleted with the standard delete operator). Y must be a complete type at the point + of invocation. + With the second constructor, d becomes the associated deleter. + Y\* must be convertible to T\*. + @param p Pointer to own. + @note It is often easier to use makePtr instead. + */ + template +#ifdef DISABLE_OPENCV_24_COMPATIBILITY + explicit +#endif + Ptr(Y* p); + + /** @overload + @param d Deleter to use for the owned pointer. + @param p Pointer to own. + */ + template + Ptr(Y* p, D d); + + /** + These constructors create a Ptr that shares ownership with another Ptr - that is, own the same + pointer as o. + With the first two, the same pointer is stored, as well; for the second, Y\* must be convertible + to T\*. + With the third, p is stored, and Y may be any type. This constructor allows to have completely + unrelated owned and stored pointers, and should be used with care to avoid confusion. A relatively + benign use is to create a non-owning Ptr, like this: + @code + ptr = Ptr(Ptr(), dont_delete_me); // owns nothing; will not delete the pointer. + @endcode + @param o Ptr to share ownership with. + */ + Ptr(const Ptr& o); + + /** @overload + @param o Ptr to share ownership with. + */ + template + Ptr(const Ptr& o); + + /** @overload + @param o Ptr to share ownership with. + @param p Pointer to store. + */ + template + Ptr(const Ptr& o, T* p); + + /** The destructor is equivalent to calling Ptr::release. */ + ~Ptr(); + + /** + Assignment replaces the current Ptr instance with one that owns and stores same pointers as o and + then destroys the old instance. + @param o Ptr to share ownership with. + */ + Ptr& operator = (const Ptr& o); + + /** @overload */ + template + Ptr& operator = (const Ptr& o); + + /** If no other Ptr instance owns the owned pointer, deletes it with the associated deleter. Then sets + both the owned and the stored pointers to NULL. + */ + void release(); + + /** + `ptr.reset(...)` is equivalent to `ptr = Ptr(...)`. + @param p Pointer to own. + */ + template + void reset(Y* p); + + /** @overload + @param d Deleter to use for the owned pointer. + @param p Pointer to own. + */ + template + void reset(Y* p, D d); + + /** + Swaps the owned and stored pointers (and deleters, if any) of this and o. + @param o Ptr to swap with. + */ + void swap(Ptr& o); + + /** Returns the stored pointer. */ + T* get() const; + + /** Ordinary pointer emulation. */ + typename detail::RefOrVoid::type operator * () const; + + /** Ordinary pointer emulation. */ + T* operator -> () const; + + /** Equivalent to get(). */ + operator T* () const; + + /** ptr.empty() is equivalent to `!ptr.get()`. */ + bool empty() const; + + /** Returns a Ptr that owns the same pointer as this, and stores the same + pointer as this, except converted via static_cast to Y*. + */ + template + Ptr staticCast() const; + + /** Ditto for const_cast. */ + template + Ptr constCast() const; + + /** Ditto for dynamic_cast. */ + template + Ptr dynamicCast() const; + +private: + detail::PtrOwner* owner; + T* stored; + + template + friend struct Ptr; // have to do this for the cross-type copy constructor +}; + +/** Equivalent to ptr1.swap(ptr2). Provided to help write generic algorithms. */ +template +void swap(Ptr& ptr1, Ptr& ptr2); + +/** Return whether ptr1.get() and ptr2.get() are equal and not equal, respectively. */ +template +bool operator == (const Ptr& ptr1, const Ptr& ptr2); +template +bool operator != (const Ptr& ptr1, const Ptr& ptr2); + +/** `makePtr(...)` is equivalent to `Ptr(new T(...))`. It is shorter than the latter, and it's +marginally safer than using a constructor or Ptr::reset, since it ensures that the owned pointer +is new and thus not owned by any other Ptr instance. +Unfortunately, perfect forwarding is impossible to implement in C++03, and so makePtr is limited +to constructors of T that have up to 10 arguments, none of which are non-const references. + */ +template +Ptr makePtr(); +/** @overload */ +template +Ptr makePtr(const A1& a1); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9); +/** @overload */ +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10); + +//////////////////////////////// string class //////////////////////////////// + +class CV_EXPORTS FileNode; //for string constructor from FileNode + +class CV_EXPORTS String +{ +public: + typedef char value_type; + typedef char& reference; + typedef const char& const_reference; + typedef char* pointer; + typedef const char* const_pointer; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef char* iterator; + typedef const char* const_iterator; + + static const size_t npos = size_t(-1); + + explicit String(); + String(const String& str); + String(const String& str, size_t pos, size_t len = npos); + String(const char* s); + String(const char* s, size_t n); + String(size_t n, char c); + String(const char* first, const char* last); + template String(Iterator first, Iterator last); + explicit String(const FileNode& fn); + ~String(); + + String& operator=(const String& str); + String& operator=(const char* s); + String& operator=(char c); + + String& operator+=(const String& str); + String& operator+=(const char* s); + String& operator+=(char c); + + size_t size() const; + size_t length() const; + + char operator[](size_t idx) const; + char operator[](int idx) const; + + const char* begin() const; + const char* end() const; + + const char* c_str() const; + + bool empty() const; + void clear(); + + int compare(const char* s) const; + int compare(const String& str) const; + + void swap(String& str); + String substr(size_t pos = 0, size_t len = npos) const; + + size_t find(const char* s, size_t pos, size_t n) const; + size_t find(char c, size_t pos = 0) const; + size_t find(const String& str, size_t pos = 0) const; + size_t find(const char* s, size_t pos = 0) const; + + size_t rfind(const char* s, size_t pos, size_t n) const; + size_t rfind(char c, size_t pos = npos) const; + size_t rfind(const String& str, size_t pos = npos) const; + size_t rfind(const char* s, size_t pos = npos) const; + + size_t find_first_of(const char* s, size_t pos, size_t n) const; + size_t find_first_of(char c, size_t pos = 0) const; + size_t find_first_of(const String& str, size_t pos = 0) const; + size_t find_first_of(const char* s, size_t pos = 0) const; + + size_t find_last_of(const char* s, size_t pos, size_t n) const; + size_t find_last_of(char c, size_t pos = npos) const; + size_t find_last_of(const String& str, size_t pos = npos) const; + size_t find_last_of(const char* s, size_t pos = npos) const; + + friend String operator+ (const String& lhs, const String& rhs); + friend String operator+ (const String& lhs, const char* rhs); + friend String operator+ (const char* lhs, const String& rhs); + friend String operator+ (const String& lhs, char rhs); + friend String operator+ (char lhs, const String& rhs); + + String toLowerCase() const; + +#ifndef OPENCV_NOSTL + String(const std::string& str); + String(const std::string& str, size_t pos, size_t len = npos); + String& operator=(const std::string& str); + String& operator+=(const std::string& str); + operator std::string() const; + + friend String operator+ (const String& lhs, const std::string& rhs); + friend String operator+ (const std::string& lhs, const String& rhs); +#endif + +private: + char* cstr_; + size_t len_; + + char* allocate(size_t len); // len without trailing 0 + void deallocate(); +}; + +//! @} core_basic + +////////////////////////// cv::String implementation ///////////////////////// + +//! @cond IGNORED + +inline +String::String() + : cstr_(0), len_(0) +{} + +inline +String::String(const String& str) + : cstr_(str.cstr_), len_(str.len_) +{ + if (cstr_) + CV_XADD(((int*)cstr_)-1, 1); +} + +inline +String::String(const String& str, size_t pos, size_t len) + : cstr_(0), len_(0) +{ + pos = min(pos, str.len_); + len = min(str.len_ - pos, len); + if (!len) return; + if (len == str.len_) + { + CV_XADD(((int*)str.cstr_)-1, 1); + cstr_ = str.cstr_; + len_ = str.len_; + return; + } + memcpy(allocate(len), str.cstr_ + pos, len); +} + +inline +String::String(const char* s) + : cstr_(0), len_(0) +{ + if (!s) return; + size_t len = strlen(s); + memcpy(allocate(len), s, len); +} + +inline +String::String(const char* s, size_t n) + : cstr_(0), len_(0) +{ + if (!n) return; + memcpy(allocate(n), s, n); +} + +inline +String::String(size_t n, char c) + : cstr_(0), len_(0) +{ + memset(allocate(n), c, n); +} + +inline +String::String(const char* first, const char* last) + : cstr_(0), len_(0) +{ + size_t len = (size_t)(last - first); + memcpy(allocate(len), first, len); +} + +template inline +String::String(Iterator first, Iterator last) + : cstr_(0), len_(0) +{ + size_t len = (size_t)(last - first); + char* str = allocate(len); + while (first != last) + { + *str++ = *first; + ++first; + } +} + +inline +String::~String() +{ + deallocate(); +} + +inline +String& String::operator=(const String& str) +{ + if (&str == this) return *this; + + deallocate(); + if (str.cstr_) CV_XADD(((int*)str.cstr_)-1, 1); + cstr_ = str.cstr_; + len_ = str.len_; + return *this; +} + +inline +String& String::operator=(const char* s) +{ + deallocate(); + if (!s) return *this; + size_t len = strlen(s); + memcpy(allocate(len), s, len); + return *this; +} + +inline +String& String::operator=(char c) +{ + deallocate(); + allocate(1)[0] = c; + return *this; +} + +inline +String& String::operator+=(const String& str) +{ + *this = *this + str; + return *this; +} + +inline +String& String::operator+=(const char* s) +{ + *this = *this + s; + return *this; +} + +inline +String& String::operator+=(char c) +{ + *this = *this + c; + return *this; +} + +inline +size_t String::size() const +{ + return len_; +} + +inline +size_t String::length() const +{ + return len_; +} + +inline +char String::operator[](size_t idx) const +{ + return cstr_[idx]; +} + +inline +char String::operator[](int idx) const +{ + return cstr_[idx]; +} + +inline +const char* String::begin() const +{ + return cstr_; +} + +inline +const char* String::end() const +{ + return len_ ? cstr_ + 1 : 0; +} + +inline +bool String::empty() const +{ + return len_ == 0; +} + +inline +const char* String::c_str() const +{ + return cstr_ ? cstr_ : ""; +} + +inline +void String::swap(String& str) +{ + cv::swap(cstr_, str.cstr_); + cv::swap(len_, str.len_); +} + +inline +void String::clear() +{ + deallocate(); +} + +inline +int String::compare(const char* s) const +{ + if (cstr_ == s) return 0; + return strcmp(c_str(), s); +} + +inline +int String::compare(const String& str) const +{ + if (cstr_ == str.cstr_) return 0; + return strcmp(c_str(), str.c_str()); +} + +inline +String String::substr(size_t pos, size_t len) const +{ + return String(*this, pos, len); +} + +inline +size_t String::find(const char* s, size_t pos, size_t n) const +{ + if (n == 0 || pos + n > len_) return npos; + const char* lmax = cstr_ + len_ - n; + for (const char* i = cstr_ + pos; i <= lmax; ++i) + { + size_t j = 0; + while (j < n && s[j] == i[j]) ++j; + if (j == n) return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::find(char c, size_t pos) const +{ + return find(&c, pos, 1); +} + +inline +size_t String::find(const String& str, size_t pos) const +{ + return find(str.c_str(), pos, str.len_); +} + +inline +size_t String::find(const char* s, size_t pos) const +{ + if (pos >= len_ || !s[0]) return npos; + const char* lmax = cstr_ + len_; + for (const char* i = cstr_ + pos; i < lmax; ++i) + { + size_t j = 0; + while (s[j] && s[j] == i[j]) + { if(i + j >= lmax) return npos; + ++j; + } + if (!s[j]) return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::rfind(const char* s, size_t pos, size_t n) const +{ + if (n > len_) return npos; + if (pos > len_ - n) pos = len_ - n; + for (const char* i = cstr_ + pos; i >= cstr_; --i) + { + size_t j = 0; + while (j < n && s[j] == i[j]) ++j; + if (j == n) return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::rfind(char c, size_t pos) const +{ + return rfind(&c, pos, 1); +} + +inline +size_t String::rfind(const String& str, size_t pos) const +{ + return rfind(str.c_str(), pos, str.len_); +} + +inline +size_t String::rfind(const char* s, size_t pos) const +{ + return rfind(s, pos, strlen(s)); +} + +inline +size_t String::find_first_of(const char* s, size_t pos, size_t n) const +{ + if (n == 0 || pos + n > len_) return npos; + const char* lmax = cstr_ + len_; + for (const char* i = cstr_ + pos; i < lmax; ++i) + { + for (size_t j = 0; j < n; ++j) + if (s[j] == *i) + return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::find_first_of(char c, size_t pos) const +{ + return find_first_of(&c, pos, 1); +} + +inline +size_t String::find_first_of(const String& str, size_t pos) const +{ + return find_first_of(str.c_str(), pos, str.len_); +} + +inline +size_t String::find_first_of(const char* s, size_t pos) const +{ + if (pos >= len_ || !s[0]) return npos; + const char* lmax = cstr_ + len_; + for (const char* i = cstr_ + pos; i < lmax; ++i) + { + for (size_t j = 0; s[j]; ++j) + if (s[j] == *i) + return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::find_last_of(const char* s, size_t pos, size_t n) const +{ + if (pos >= len_) pos = len_ - 1; + for (const char* i = cstr_ + pos; i >= cstr_; --i) + { + for (size_t j = 0; j < n; ++j) + if (s[j] == *i) + return (size_t)(i - cstr_); + } + return npos; +} + +inline +size_t String::find_last_of(char c, size_t pos) const +{ + return find_last_of(&c, pos, 1); +} + +inline +size_t String::find_last_of(const String& str, size_t pos) const +{ + return find_last_of(str.c_str(), pos, str.len_); +} + +inline +size_t String::find_last_of(const char* s, size_t pos) const +{ + if (pos >= len_) pos = len_ - 1; + for (const char* i = cstr_ + pos; i >= cstr_; --i) + { + for (size_t j = 0; s[j]; ++j) + if (s[j] == *i) + return (size_t)(i - cstr_); + } + return npos; +} + +inline +String String::toLowerCase() const +{ + String res(cstr_, len_); + + for (size_t i = 0; i < len_; ++i) + res.cstr_[i] = (char) ::tolower(cstr_[i]); + + return res; +} + +//! @endcond + +// ************************* cv::String non-member functions ************************* + +//! @relates cv::String +//! @{ + +inline +String operator + (const String& lhs, const String& rhs) +{ + String s; + s.allocate(lhs.len_ + rhs.len_); + memcpy(s.cstr_, lhs.cstr_, lhs.len_); + memcpy(s.cstr_ + lhs.len_, rhs.cstr_, rhs.len_); + return s; +} + +inline +String operator + (const String& lhs, const char* rhs) +{ + String s; + size_t rhslen = strlen(rhs); + s.allocate(lhs.len_ + rhslen); + memcpy(s.cstr_, lhs.cstr_, lhs.len_); + memcpy(s.cstr_ + lhs.len_, rhs, rhslen); + return s; +} + +inline +String operator + (const char* lhs, const String& rhs) +{ + String s; + size_t lhslen = strlen(lhs); + s.allocate(lhslen + rhs.len_); + memcpy(s.cstr_, lhs, lhslen); + memcpy(s.cstr_ + lhslen, rhs.cstr_, rhs.len_); + return s; +} + +inline +String operator + (const String& lhs, char rhs) +{ + String s; + s.allocate(lhs.len_ + 1); + memcpy(s.cstr_, lhs.cstr_, lhs.len_); + s.cstr_[lhs.len_] = rhs; + return s; +} + +inline +String operator + (char lhs, const String& rhs) +{ + String s; + s.allocate(rhs.len_ + 1); + s.cstr_[0] = lhs; + memcpy(s.cstr_ + 1, rhs.cstr_, rhs.len_); + return s; +} + +static inline bool operator== (const String& lhs, const String& rhs) { return 0 == lhs.compare(rhs); } +static inline bool operator== (const char* lhs, const String& rhs) { return 0 == rhs.compare(lhs); } +static inline bool operator== (const String& lhs, const char* rhs) { return 0 == lhs.compare(rhs); } +static inline bool operator!= (const String& lhs, const String& rhs) { return 0 != lhs.compare(rhs); } +static inline bool operator!= (const char* lhs, const String& rhs) { return 0 != rhs.compare(lhs); } +static inline bool operator!= (const String& lhs, const char* rhs) { return 0 != lhs.compare(rhs); } +static inline bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } +static inline bool operator< (const char* lhs, const String& rhs) { return rhs.compare(lhs) > 0; } +static inline bool operator< (const String& lhs, const char* rhs) { return lhs.compare(rhs) < 0; } +static inline bool operator<= (const String& lhs, const String& rhs) { return lhs.compare(rhs) <= 0; } +static inline bool operator<= (const char* lhs, const String& rhs) { return rhs.compare(lhs) >= 0; } +static inline bool operator<= (const String& lhs, const char* rhs) { return lhs.compare(rhs) <= 0; } +static inline bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } +static inline bool operator> (const char* lhs, const String& rhs) { return rhs.compare(lhs) < 0; } +static inline bool operator> (const String& lhs, const char* rhs) { return lhs.compare(rhs) > 0; } +static inline bool operator>= (const String& lhs, const String& rhs) { return lhs.compare(rhs) >= 0; } +static inline bool operator>= (const char* lhs, const String& rhs) { return rhs.compare(lhs) <= 0; } +static inline bool operator>= (const String& lhs, const char* rhs) { return lhs.compare(rhs) >= 0; } + +//! @} relates cv::String + +} // cv + +#ifndef OPENCV_NOSTL_TRANSITIONAL +namespace std +{ + static inline void swap(cv::String& a, cv::String& b) { a.swap(b); } +} +#else +namespace cv +{ + template<> inline + void swap(cv::String& a, cv::String& b) + { + a.swap(b); + } +} +#endif + +#include "opencv2/core/ptr.inl.hpp" + +#endif //__OPENCV_CORE_CVSTD_HPP__ diff --git a/include/opencv2/core/cvstd.inl.hpp b/include/opencv2/core/cvstd.inl.hpp new file mode 100644 index 0000000..03bac37 --- /dev/null +++ b/include/opencv2/core/cvstd.inl.hpp @@ -0,0 +1,267 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_CVSTDINL_HPP__ +#define __OPENCV_CORE_CVSTDINL_HPP__ + +#ifndef OPENCV_NOSTL +# include +# include +#endif + +//! @cond IGNORED + +namespace cv +{ +#ifndef OPENCV_NOSTL + +template class DataType< std::complex<_Tp> > +{ +public: + typedef std::complex<_Tp> value_type; + typedef value_type work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) }; + + typedef Vec vec_type; +}; + +inline +String::String(const std::string& str) + : cstr_(0), len_(0) +{ + if (!str.empty()) + { + size_t len = str.size(); + memcpy(allocate(len), str.c_str(), len); + } +} + +inline +String::String(const std::string& str, size_t pos, size_t len) + : cstr_(0), len_(0) +{ + size_t strlen = str.size(); + pos = max(pos, strlen); + len = min(strlen - pos, len); + if (!len) return; + memcpy(allocate(len), str.c_str() + pos, len); +} + +inline +String& String::operator = (const std::string& str) +{ + deallocate(); + if (!str.empty()) + { + size_t len = str.size(); + memcpy(allocate(len), str.c_str(), len); + } + return *this; +} + +inline +String& String::operator += (const std::string& str) +{ + *this = *this + str; + return *this; +} + +inline +String::operator std::string() const +{ + return std::string(cstr_, len_); +} + +inline +String operator + (const String& lhs, const std::string& rhs) +{ + String s; + size_t rhslen = rhs.size(); + s.allocate(lhs.len_ + rhslen); + memcpy(s.cstr_, lhs.cstr_, lhs.len_); + memcpy(s.cstr_ + lhs.len_, rhs.c_str(), rhslen); + return s; +} + +inline +String operator + (const std::string& lhs, const String& rhs) +{ + String s; + size_t lhslen = lhs.size(); + s.allocate(lhslen + rhs.len_); + memcpy(s.cstr_, lhs.c_str(), lhslen); + memcpy(s.cstr_ + lhslen, rhs.cstr_, rhs.len_); + return s; +} + +inline +FileNode::operator std::string() const +{ + String value; + read(*this, value, value); + return value; +} + +template<> inline +void operator >> (const FileNode& n, std::string& value) +{ + String val; + read(n, val, val); + value = val; +} + +template<> inline +FileStorage& operator << (FileStorage& fs, const std::string& value) +{ + return fs << cv::String(value); +} + +static inline +std::ostream& operator << (std::ostream& os, const String& str) +{ + return os << str.c_str(); +} + +static inline +std::ostream& operator << (std::ostream& out, Ptr fmtd) +{ + fmtd->reset(); + for(const char* str = fmtd->next(); str; str = fmtd->next()) + out << str; + return out; +} + +static inline +std::ostream& operator << (std::ostream& out, const Mat& mtx) +{ + return out << Formatter::get()->format(mtx); +} + +template static inline +std::ostream& operator << (std::ostream& out, const std::vector >& vec) +{ + return out << Formatter::get()->format(Mat(vec)); +} + + +template static inline +std::ostream& operator << (std::ostream& out, const std::vector >& vec) +{ + return out << Formatter::get()->format(Mat(vec)); +} + + +template static inline +std::ostream& operator << (std::ostream& out, const Matx<_Tp, m, n>& matx) +{ + return out << Formatter::get()->format(Mat(matx)); +} + +template static inline +std::ostream& operator << (std::ostream& out, const Point_<_Tp>& p) +{ + out << "[" << p.x << ", " << p.y << "]"; + return out; +} + +template static inline +std::ostream& operator << (std::ostream& out, const Point3_<_Tp>& p) +{ + out << "[" << p.x << ", " << p.y << ", " << p.z << "]"; + return out; +} + +template static inline +std::ostream& operator << (std::ostream& out, const Vec<_Tp, n>& vec) +{ + out << "["; +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable: 4127 ) +#endif + if(Vec<_Tp, n>::depth < CV_32F) +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + { + for (int i = 0; i < n - 1; ++i) { + out << (int)vec[i] << ", "; + } + out << (int)vec[n-1] << "]"; + } + else + { + for (int i = 0; i < n - 1; ++i) { + out << vec[i] << ", "; + } + out << vec[n-1] << "]"; + } + + return out; +} + +template static inline +std::ostream& operator << (std::ostream& out, const Size_<_Tp>& size) +{ + return out << "[" << size.width << " x " << size.height << "]"; +} + +template static inline +std::ostream& operator << (std::ostream& out, const Rect_<_Tp>& rect) +{ + return out << "[" << rect.width << " x " << rect.height << " from (" << rect.x << ", " << rect.y << ")]"; +} + + +#endif // OPENCV_NOSTL +} // cv + +//! @endcond + +#endif // __OPENCV_CORE_CVSTDINL_HPP__ diff --git a/include/opencv2/core/directx.hpp b/include/opencv2/core/directx.hpp new file mode 100644 index 0000000..837548e --- /dev/null +++ b/include/opencv2/core/directx.hpp @@ -0,0 +1,105 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors as is and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the copyright holders or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_DIRECTX_HPP__ +#define __OPENCV_CORE_DIRECTX_HPP__ + +#include "mat.hpp" +#include "ocl.hpp" + +#if !defined(__d3d11_h__) +struct ID3D11Device; +struct ID3D11Texture2D; +#endif + +#if !defined(__d3d10_h__) +struct ID3D10Device; +struct ID3D10Texture2D; +#endif + +#if !defined(_D3D9_H_) +struct IDirect3DDevice9; +struct IDirect3DDevice9Ex; +struct IDirect3DSurface9; +#endif + + +namespace cv { namespace directx { + +namespace ocl { +using namespace cv::ocl; + +//! @addtogroup core_directx +//! @{ + +// TODO static functions in the Context class +CV_EXPORTS Context& initializeContextFromD3D11Device(ID3D11Device* pD3D11Device); +CV_EXPORTS Context& initializeContextFromD3D10Device(ID3D10Device* pD3D10Device); +CV_EXPORTS Context& initializeContextFromDirect3DDevice9Ex(IDirect3DDevice9Ex* pDirect3DDevice9Ex); +CV_EXPORTS Context& initializeContextFromDirect3DDevice9(IDirect3DDevice9* pDirect3DDevice9); + +//! @} + +} // namespace cv::directx::ocl + +//! @addtogroup core_directx +//! @{ + +CV_EXPORTS void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D); +CV_EXPORTS void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst); + +CV_EXPORTS void convertToD3D10Texture2D(InputArray src, ID3D10Texture2D* pD3D10Texture2D); +CV_EXPORTS void convertFromD3D10Texture2D(ID3D10Texture2D* pD3D10Texture2D, OutputArray dst); + +CV_EXPORTS void convertToDirect3DSurface9(InputArray src, IDirect3DSurface9* pDirect3DSurface9, void* surfaceSharedHandle = NULL); +CV_EXPORTS void convertFromDirect3DSurface9(IDirect3DSurface9* pDirect3DSurface9, OutputArray dst, void* surfaceSharedHandle = NULL); + +// Get OpenCV type from DirectX type, return -1 if there is no equivalent +CV_EXPORTS int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT); // enum DXGI_FORMAT for D3D10/D3D11 + +// Get OpenCV type from DirectX type, return -1 if there is no equivalent +CV_EXPORTS int getTypeFromD3DFORMAT(const int iD3DFORMAT); // enum D3DTYPE for D3D9 + +//! @} + +} } // namespace cv::directx + +#endif // __OPENCV_CORE_DIRECTX_HPP__ diff --git a/include/opencv2/core/eigen.hpp b/include/opencv2/core/eigen.hpp new file mode 100644 index 0000000..44df04c --- /dev/null +++ b/include/opencv2/core/eigen.hpp @@ -0,0 +1,280 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + +#ifndef __OPENCV_CORE_EIGEN_HPP__ +#define __OPENCV_CORE_EIGEN_HPP__ + +#include "opencv2/core.hpp" + +#if defined _MSC_VER && _MSC_VER >= 1200 +#pragma warning( disable: 4714 ) //__forceinline is not inlined +#pragma warning( disable: 4127 ) //conditional expression is constant +#pragma warning( disable: 4244 ) //conversion from '__int64' to 'int', possible loss of data +#endif + +namespace cv +{ + +//! @addtogroup core_eigen +//! @{ + +template static inline +void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst ) +{ + if( !(src.Flags & Eigen::RowMajorBit) ) + { + Mat _src(src.cols(), src.rows(), DataType<_Tp>::type, + (void*)src.data(), src.stride()*sizeof(_Tp)); + transpose(_src, dst); + } + else + { + Mat _src(src.rows(), src.cols(), DataType<_Tp>::type, + (void*)src.data(), src.stride()*sizeof(_Tp)); + _src.copyTo(dst); + } +} + +// Matx case +template static inline +void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, + Matx<_Tp, _rows, _cols>& dst ) +{ + if( !(src.Flags & Eigen::RowMajorBit) ) + { + dst = Matx<_Tp, _cols, _rows>(static_cast(src.data())).t(); + } + else + { + dst = Matx<_Tp, _rows, _cols>(static_cast(src.data())); + } +} + +template static inline +void cv2eigen( const Mat& src, + Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst ) +{ + CV_DbgAssert(src.rows == _rows && src.cols == _cols); + if( !(dst.Flags & Eigen::RowMajorBit) ) + { + const Mat _dst(src.cols, src.rows, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + if( src.type() == _dst.type() ) + transpose(src, _dst); + else if( src.cols == src.rows ) + { + src.convertTo(_dst, _dst.type()); + transpose(_dst, _dst); + } + else + Mat(src.t()).convertTo(_dst, _dst.type()); + } + else + { + const Mat _dst(src.rows, src.cols, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + src.convertTo(_dst, _dst.type()); + } +} + +// Matx case +template static inline +void cv2eigen( const Matx<_Tp, _rows, _cols>& src, + Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst ) +{ + if( !(dst.Flags & Eigen::RowMajorBit) ) + { + const Mat _dst(_cols, _rows, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + transpose(src, _dst); + } + else + { + const Mat _dst(_rows, _cols, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + Mat(src).copyTo(_dst); + } +} + +template static inline +void cv2eigen( const Mat& src, + Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst ) +{ + dst.resize(src.rows, src.cols); + if( !(dst.Flags & Eigen::RowMajorBit) ) + { + const Mat _dst(src.cols, src.rows, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + if( src.type() == _dst.type() ) + transpose(src, _dst); + else if( src.cols == src.rows ) + { + src.convertTo(_dst, _dst.type()); + transpose(_dst, _dst); + } + else + Mat(src.t()).convertTo(_dst, _dst.type()); + } + else + { + const Mat _dst(src.rows, src.cols, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + src.convertTo(_dst, _dst.type()); + } +} + +// Matx case +template static inline +void cv2eigen( const Matx<_Tp, _rows, _cols>& src, + Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst ) +{ + dst.resize(_rows, _cols); + if( !(dst.Flags & Eigen::RowMajorBit) ) + { + const Mat _dst(_cols, _rows, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + transpose(src, _dst); + } + else + { + const Mat _dst(_rows, _cols, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + Mat(src).copyTo(_dst); + } +} + +template static inline +void cv2eigen( const Mat& src, + Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst ) +{ + CV_Assert(src.cols == 1); + dst.resize(src.rows); + + if( !(dst.Flags & Eigen::RowMajorBit) ) + { + const Mat _dst(src.cols, src.rows, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + if( src.type() == _dst.type() ) + transpose(src, _dst); + else + Mat(src.t()).convertTo(_dst, _dst.type()); + } + else + { + const Mat _dst(src.rows, src.cols, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + src.convertTo(_dst, _dst.type()); + } +} + +// Matx case +template static inline +void cv2eigen( const Matx<_Tp, _rows, 1>& src, + Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst ) +{ + dst.resize(_rows); + + if( !(dst.Flags & Eigen::RowMajorBit) ) + { + const Mat _dst(1, _rows, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + transpose(src, _dst); + } + else + { + const Mat _dst(_rows, 1, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + src.copyTo(_dst); + } +} + + +template static inline +void cv2eigen( const Mat& src, + Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst ) +{ + CV_Assert(src.rows == 1); + dst.resize(src.cols); + if( !(dst.Flags & Eigen::RowMajorBit) ) + { + const Mat _dst(src.cols, src.rows, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + if( src.type() == _dst.type() ) + transpose(src, _dst); + else + Mat(src.t()).convertTo(_dst, _dst.type()); + } + else + { + const Mat _dst(src.rows, src.cols, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + src.convertTo(_dst, _dst.type()); + } +} + +//Matx +template static inline +void cv2eigen( const Matx<_Tp, 1, _cols>& src, + Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst ) +{ + dst.resize(_cols); + if( !(dst.Flags & Eigen::RowMajorBit) ) + { + const Mat _dst(_cols, 1, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + transpose(src, _dst); + } + else + { + const Mat _dst(1, _cols, DataType<_Tp>::type, + dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); + Mat(src).copyTo(_dst); + } +} + +//! @} + +} // cv + +#endif diff --git a/include/opencv2/core/ippasync.hpp b/include/opencv2/core/ippasync.hpp new file mode 100644 index 0000000..4de8611 --- /dev/null +++ b/include/opencv2/core/ippasync.hpp @@ -0,0 +1,195 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_IPPASYNC_HPP__ +#define __OPENCV_CORE_IPPASYNC_HPP__ + +#ifdef HAVE_IPP_A + +#include "opencv2/core.hpp" +#include +#include + +namespace cv +{ + +namespace hpp +{ + +/** @addtogroup core_ipp +This section describes conversion between OpenCV and [Intel® IPP Asynchronous +C/C++](http://software.intel.com/en-us/intel-ipp-preview) library. [Getting Started +Guide](http://registrationcenter.intel.com/irc_nas/3727/ipp_async_get_started.htm) help you to +install the library, configure header and library build paths. + */ +//! @{ + + //! convert OpenCV data type to hppDataType + inline int toHppType(const int cvType) + { + int depth = CV_MAT_DEPTH(cvType); + int hppType = depth == CV_8U ? HPP_DATA_TYPE_8U : + depth == CV_16U ? HPP_DATA_TYPE_16U : + depth == CV_16S ? HPP_DATA_TYPE_16S : + depth == CV_32S ? HPP_DATA_TYPE_32S : + depth == CV_32F ? HPP_DATA_TYPE_32F : + depth == CV_64F ? HPP_DATA_TYPE_64F : -1; + CV_Assert( hppType >= 0 ); + return hppType; + } + + //! convert hppDataType to OpenCV data type + inline int toCvType(const int hppType) + { + int cvType = hppType == HPP_DATA_TYPE_8U ? CV_8U : + hppType == HPP_DATA_TYPE_16U ? CV_16U : + hppType == HPP_DATA_TYPE_16S ? CV_16S : + hppType == HPP_DATA_TYPE_32S ? CV_32S : + hppType == HPP_DATA_TYPE_32F ? CV_32F : + hppType == HPP_DATA_TYPE_64F ? CV_64F : -1; + CV_Assert( cvType >= 0 ); + return cvType; + } + + /** @brief Convert hppiMatrix to Mat. + + This function allocates and initializes new matrix (if needed) that has the same size and type as + input matrix. Supports CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F. + @param src input hppiMatrix. + @param dst output matrix. + @param accel accelerator instance (see hpp::getHpp for the list of acceleration framework types). + @param cn number of channels. + */ + inline void copyHppToMat(hppiMatrix* src, Mat& dst, hppAccel accel, int cn) + { + hppDataType type; + hpp32u width, height; + hppStatus sts; + + if (src == NULL) + return dst.release(); + + sts = hppiInquireMatrix(src, &type, &width, &height); + + CV_Assert( sts == HPP_STATUS_NO_ERROR); + + int matType = CV_MAKETYPE(toCvType(type), cn); + + CV_Assert(width%cn == 0); + + width /= cn; + + dst.create((int)height, (int)width, (int)matType); + + size_t newSize = (size_t)(height*(hpp32u)(dst.step)); + + sts = hppiGetMatrixData(accel,src,(hpp32u)(dst.step),dst.data,&newSize); + + CV_Assert( sts == HPP_STATUS_NO_ERROR); + } + + /** @brief Create Mat from hppiMatrix. + + This function allocates and initializes the Mat that has the same size and type as input matrix. + Supports CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F. + @param src input hppiMatrix. + @param accel accelerator instance (see hpp::getHpp for the list of acceleration framework types). + @param cn number of channels. + @sa howToUseIPPAconversion, hpp::copyHppToMat, hpp::getHpp. + */ + inline Mat getMat(hppiMatrix* src, hppAccel accel, int cn) + { + Mat dst; + copyHppToMat(src, dst, accel, cn); + return dst; + } + + /** @brief Create hppiMatrix from Mat. + + This function allocates and initializes the hppiMatrix that has the same size and type as input + matrix, returns the hppiMatrix*. + + If you want to use zero-copy for GPU you should to have 4KB aligned matrix data. See details + [hppiCreateSharedMatrix](http://software.intel.com/ru-ru/node/501697). + + Supports CV_8U, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F. + + @note The hppiMatrix pointer to the image buffer in system memory refers to the src.data. Control + the lifetime of the matrix and don't change its data, if there is no special need. + @param src input matrix. + @param accel accelerator instance. Supports type: + - **HPP_ACCEL_TYPE_CPU** - accelerated by optimized CPU instructions. + - **HPP_ACCEL_TYPE_GPU** - accelerated by GPU programmable units or fixed-function + accelerators. + - **HPP_ACCEL_TYPE_ANY** - any acceleration or no acceleration available. + @sa howToUseIPPAconversion, hpp::getMat + */ + inline hppiMatrix* getHpp(const Mat& src, hppAccel accel) + { + int htype = toHppType(src.type()); + int cn = src.channels(); + + CV_Assert(src.data); + hppAccelType accelType = hppQueryAccelType(accel); + + if (accelType!=HPP_ACCEL_TYPE_CPU) + { + hpp32u pitch, size; + hppQueryMatrixAllocParams(accel, src.cols*cn, src.rows, htype, &pitch, &size); + if (pitch!=0 && size!=0) + if ((int)(src.data)%4096==0 && pitch==(hpp32u)(src.step)) + { + return hppiCreateSharedMatrix(htype, src.cols*cn, src.rows, src.data, pitch, size); + } + } + + return hppiCreateMatrix(htype, src.cols*cn, src.rows, src.data, (hpp32s)(src.step));; + } + +//! @} +}} + +#endif + +#endif diff --git a/include/opencv2/core/mat.hpp b/include/opencv2/core/mat.hpp new file mode 100644 index 0000000..45f3cef --- /dev/null +++ b/include/opencv2/core/mat.hpp @@ -0,0 +1,3398 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_MAT_HPP__ +#define __OPENCV_CORE_MAT_HPP__ + +#ifndef __cplusplus +# error mat.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/matx.hpp" +#include "opencv2/core/types.hpp" + +#include "opencv2/core/bufferpool.hpp" + +namespace cv +{ + +//! @addtogroup core_basic +//! @{ + +enum { ACCESS_READ=1<<24, ACCESS_WRITE=1<<25, + ACCESS_RW=3<<24, ACCESS_MASK=ACCESS_RW, ACCESS_FAST=1<<26 }; + +class CV_EXPORTS _OutputArray; + +//////////////////////// Input/Output Array Arguments ///////////////////////////////// + +/** @brief This is the proxy class for passing read-only input arrays into OpenCV functions. + +It is defined as: +@code + typedef const _InputArray& InputArray; +@endcode +where _InputArray is a class that can be constructed from `Mat`, `Mat_`, `Matx`, +`std::vector`, `std::vector >` or `std::vector`. It can also be constructed +from a matrix expression. + +Since this is mostly implementation-level class, and its interface may change in future versions, we +do not describe it in details. There are a few key things, though, that should be kept in mind: + +- When you see in the reference manual or in OpenCV source code a function that takes + InputArray, it means that you can actually pass `Mat`, `Matx`, `vector` etc. (see above the + complete list). +- Optional input arguments: If some of the input arrays may be empty, pass cv::noArray() (or + simply cv::Mat() as you probably did before). +- The class is designed solely for passing parameters. That is, normally you *should not* + declare class members, local and global variables of this type. +- If you want to design your own function or a class method that can operate of arrays of + multiple types, you can use InputArray (or OutputArray) for the respective parameters. Inside + a function you should use _InputArray::getMat() method to construct a matrix header for the + array (without copying data). _InputArray::kind() can be used to distinguish Mat from + `vector<>` etc., but normally it is not needed. + +Here is how you can use a function that takes InputArray : +@code + std::vector vec; + // points or a circle + for( int i = 0; i < 30; i++ ) + vec.push_back(Point2f((float)(100 + 30*cos(i*CV_PI*2/5)), + (float)(100 - 30*sin(i*CV_PI*2/5)))); + cv::transform(vec, vec, cv::Matx23f(0.707, -0.707, 10, 0.707, 0.707, 20)); +@endcode +That is, we form an STL vector containing points, and apply in-place affine transformation to the +vector using the 2x3 matrix created inline as `Matx` instance. + +Here is how such a function can be implemented (for simplicity, we implement a very specific case of +it, according to the assertion statement inside) : +@code + void myAffineTransform(InputArray _src, OutputArray _dst, InputArray _m) + { + // get Mat headers for input arrays. This is O(1) operation, + // unless _src and/or _m are matrix expressions. + Mat src = _src.getMat(), m = _m.getMat(); + CV_Assert( src.type() == CV_32FC2 && m.type() == CV_32F && m.size() == Size(3, 2) ); + + // [re]create the output array so that it has the proper size and type. + // In case of Mat it calls Mat::create, in case of STL vector it calls vector::resize. + _dst.create(src.size(), src.type()); + Mat dst = _dst.getMat(); + + for( int i = 0; i < src.rows; i++ ) + for( int j = 0; j < src.cols; j++ ) + { + Point2f pt = src.at(i, j); + dst.at(i, j) = Point2f(m.at(0, 0)*pt.x + + m.at(0, 1)*pt.y + + m.at(0, 2), + m.at(1, 0)*pt.x + + m.at(1, 1)*pt.y + + m.at(1, 2)); + } + } +@endcode +There is another related type, InputArrayOfArrays, which is currently defined as a synonym for +InputArray: +@code + typedef InputArray InputArrayOfArrays; +@endcode +It denotes function arguments that are either vectors of vectors or vectors of matrices. A separate +synonym is needed to generate Python/Java etc. wrappers properly. At the function implementation +level their use is similar, but _InputArray::getMat(idx) should be used to get header for the +idx-th component of the outer vector and _InputArray::size().area() should be used to find the +number of components (vectors/matrices) of the outer vector. + */ +class CV_EXPORTS _InputArray +{ +public: + enum { + KIND_SHIFT = 16, + FIXED_TYPE = 0x8000 << KIND_SHIFT, + FIXED_SIZE = 0x4000 << KIND_SHIFT, + KIND_MASK = 31 << KIND_SHIFT, + + NONE = 0 << KIND_SHIFT, + MAT = 1 << KIND_SHIFT, + MATX = 2 << KIND_SHIFT, + STD_VECTOR = 3 << KIND_SHIFT, + STD_VECTOR_VECTOR = 4 << KIND_SHIFT, + STD_VECTOR_MAT = 5 << KIND_SHIFT, + EXPR = 6 << KIND_SHIFT, + OPENGL_BUFFER = 7 << KIND_SHIFT, + CUDA_HOST_MEM = 8 << KIND_SHIFT, + CUDA_GPU_MAT = 9 << KIND_SHIFT, + UMAT =10 << KIND_SHIFT, + STD_VECTOR_UMAT =11 << KIND_SHIFT, + STD_BOOL_VECTOR =12 << KIND_SHIFT + }; + + _InputArray(); + _InputArray(int _flags, void* _obj); + _InputArray(const Mat& m); + _InputArray(const MatExpr& expr); + _InputArray(const std::vector& vec); + template _InputArray(const Mat_<_Tp>& m); + template _InputArray(const std::vector<_Tp>& vec); + _InputArray(const std::vector& vec); + template _InputArray(const std::vector >& vec); + template _InputArray(const std::vector >& vec); + template _InputArray(const _Tp* vec, int n); + template _InputArray(const Matx<_Tp, m, n>& matx); + _InputArray(const double& val); + _InputArray(const cuda::GpuMat& d_mat); + _InputArray(const ogl::Buffer& buf); + _InputArray(const cuda::HostMem& cuda_mem); + template _InputArray(const cudev::GpuMat_<_Tp>& m); + _InputArray(const UMat& um); + _InputArray(const std::vector& umv); + + Mat getMat(int idx=-1) const; + Mat getMat_(int idx=-1) const; + UMat getUMat(int idx=-1) const; + void getMatVector(std::vector& mv) const; + void getUMatVector(std::vector& umv) const; + cuda::GpuMat getGpuMat() const; + ogl::Buffer getOGlBuffer() const; + + int getFlags() const; + void* getObj() const; + Size getSz() const; + + int kind() const; + int dims(int i=-1) const; + int cols(int i=-1) const; + int rows(int i=-1) const; + Size size(int i=-1) const; + int sizend(int* sz, int i=-1) const; + bool sameSize(const _InputArray& arr) const; + size_t total(int i=-1) const; + int type(int i=-1) const; + int depth(int i=-1) const; + int channels(int i=-1) const; + bool isContinuous(int i=-1) const; + bool isSubmatrix(int i=-1) const; + bool empty() const; + void copyTo(const _OutputArray& arr) const; + void copyTo(const _OutputArray& arr, const _InputArray & mask) const; + size_t offset(int i=-1) const; + size_t step(int i=-1) const; + bool isMat() const; + bool isUMat() const; + bool isMatVector() const; + bool isUMatVector() const; + bool isMatx() const; + + ~_InputArray(); + +protected: + int flags; + void* obj; + Size sz; + + void init(int _flags, const void* _obj); + void init(int _flags, const void* _obj, Size _sz); +}; + + +/** @brief This type is very similar to InputArray except that it is used for input/output and output function +parameters. + +Just like with InputArray, OpenCV users should not care about OutputArray, they just pass `Mat`, +`vector` etc. to the functions. The same limitation as for `InputArray`: *Do not explicitly +create OutputArray instances* applies here too. + +If you want to make your function polymorphic (i.e. accept different arrays as output parameters), +it is also not very difficult. Take the sample above as the reference. Note that +_OutputArray::create() needs to be called before _OutputArray::getMat(). This way you guarantee +that the output array is properly allocated. + +Optional output parameters. If you do not need certain output array to be computed and returned to +you, pass cv::noArray(), just like you would in the case of optional input array. At the +implementation level, use _OutputArray::needed() to check if certain output array needs to be +computed or not. + +There are several synonyms for OutputArray that are used to assist automatic Python/Java/... wrapper +generators: +@code + typedef OutputArray OutputArrayOfArrays; + typedef OutputArray InputOutputArray; + typedef OutputArray InputOutputArrayOfArrays; +@endcode + */ +class CV_EXPORTS _OutputArray : public _InputArray +{ +public: + enum + { + DEPTH_MASK_8U = 1 << CV_8U, + DEPTH_MASK_8S = 1 << CV_8S, + DEPTH_MASK_16U = 1 << CV_16U, + DEPTH_MASK_16S = 1 << CV_16S, + DEPTH_MASK_32S = 1 << CV_32S, + DEPTH_MASK_32F = 1 << CV_32F, + DEPTH_MASK_64F = 1 << CV_64F, + DEPTH_MASK_ALL = (DEPTH_MASK_64F<<1)-1, + DEPTH_MASK_ALL_BUT_8S = DEPTH_MASK_ALL & ~DEPTH_MASK_8S, + DEPTH_MASK_FLT = DEPTH_MASK_32F + DEPTH_MASK_64F + }; + + _OutputArray(); + _OutputArray(int _flags, void* _obj); + _OutputArray(Mat& m); + _OutputArray(std::vector& vec); + _OutputArray(cuda::GpuMat& d_mat); + _OutputArray(ogl::Buffer& buf); + _OutputArray(cuda::HostMem& cuda_mem); + template _OutputArray(cudev::GpuMat_<_Tp>& m); + template _OutputArray(std::vector<_Tp>& vec); + _OutputArray(std::vector& vec); + template _OutputArray(std::vector >& vec); + template _OutputArray(std::vector >& vec); + template _OutputArray(Mat_<_Tp>& m); + template _OutputArray(_Tp* vec, int n); + template _OutputArray(Matx<_Tp, m, n>& matx); + _OutputArray(UMat& m); + _OutputArray(std::vector& vec); + + _OutputArray(const Mat& m); + _OutputArray(const std::vector& vec); + _OutputArray(const cuda::GpuMat& d_mat); + _OutputArray(const ogl::Buffer& buf); + _OutputArray(const cuda::HostMem& cuda_mem); + template _OutputArray(const cudev::GpuMat_<_Tp>& m); + template _OutputArray(const std::vector<_Tp>& vec); + template _OutputArray(const std::vector >& vec); + template _OutputArray(const std::vector >& vec); + template _OutputArray(const Mat_<_Tp>& m); + template _OutputArray(const _Tp* vec, int n); + template _OutputArray(const Matx<_Tp, m, n>& matx); + _OutputArray(const UMat& m); + _OutputArray(const std::vector& vec); + + bool fixedSize() const; + bool fixedType() const; + bool needed() const; + Mat& getMatRef(int i=-1) const; + UMat& getUMatRef(int i=-1) const; + cuda::GpuMat& getGpuMatRef() const; + ogl::Buffer& getOGlBufferRef() const; + cuda::HostMem& getHostMemRef() const; + void create(Size sz, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0) const; + void createSameSize(const _InputArray& arr, int mtype) const; + void release() const; + void clear() const; + void setTo(const _InputArray& value, const _InputArray & mask = _InputArray()) const; + + void assign(const UMat& u) const; + void assign(const Mat& m) const; +}; + + +class CV_EXPORTS _InputOutputArray : public _OutputArray +{ +public: + _InputOutputArray(); + _InputOutputArray(int _flags, void* _obj); + _InputOutputArray(Mat& m); + _InputOutputArray(std::vector& vec); + _InputOutputArray(cuda::GpuMat& d_mat); + _InputOutputArray(ogl::Buffer& buf); + _InputOutputArray(cuda::HostMem& cuda_mem); + template _InputOutputArray(cudev::GpuMat_<_Tp>& m); + template _InputOutputArray(std::vector<_Tp>& vec); + _InputOutputArray(std::vector& vec); + template _InputOutputArray(std::vector >& vec); + template _InputOutputArray(std::vector >& vec); + template _InputOutputArray(Mat_<_Tp>& m); + template _InputOutputArray(_Tp* vec, int n); + template _InputOutputArray(Matx<_Tp, m, n>& matx); + _InputOutputArray(UMat& m); + _InputOutputArray(std::vector& vec); + + _InputOutputArray(const Mat& m); + _InputOutputArray(const std::vector& vec); + _InputOutputArray(const cuda::GpuMat& d_mat); + _InputOutputArray(const ogl::Buffer& buf); + _InputOutputArray(const cuda::HostMem& cuda_mem); + template _InputOutputArray(const cudev::GpuMat_<_Tp>& m); + template _InputOutputArray(const std::vector<_Tp>& vec); + template _InputOutputArray(const std::vector >& vec); + template _InputOutputArray(const std::vector >& vec); + template _InputOutputArray(const Mat_<_Tp>& m); + template _InputOutputArray(const _Tp* vec, int n); + template _InputOutputArray(const Matx<_Tp, m, n>& matx); + _InputOutputArray(const UMat& m); + _InputOutputArray(const std::vector& vec); +}; + +typedef const _InputArray& InputArray; +typedef InputArray InputArrayOfArrays; +typedef const _OutputArray& OutputArray; +typedef OutputArray OutputArrayOfArrays; +typedef const _InputOutputArray& InputOutputArray; +typedef InputOutputArray InputOutputArrayOfArrays; + +CV_EXPORTS InputOutputArray noArray(); + +/////////////////////////////////// MatAllocator ////////////////////////////////////// + +//! Usage flags for allocator +enum UMatUsageFlags +{ + USAGE_DEFAULT = 0, + + // buffer allocation policy is platform and usage specific + USAGE_ALLOCATE_HOST_MEMORY = 1 << 0, + USAGE_ALLOCATE_DEVICE_MEMORY = 1 << 1, + USAGE_ALLOCATE_SHARED_MEMORY = 1 << 2, // It is not equal to: USAGE_ALLOCATE_HOST_MEMORY | USAGE_ALLOCATE_DEVICE_MEMORY + + __UMAT_USAGE_FLAGS_32BIT = 0x7fffffff // Binary compatibility hint +}; + +struct CV_EXPORTS UMatData; + +/** @brief Custom array allocator +*/ +class CV_EXPORTS MatAllocator +{ +public: + MatAllocator() {} + virtual ~MatAllocator() {} + + // let's comment it off for now to detect and fix all the uses of allocator + //virtual void allocate(int dims, const int* sizes, int type, int*& refcount, + // uchar*& datastart, uchar*& data, size_t* step) = 0; + //virtual void deallocate(int* refcount, uchar* datastart, uchar* data) = 0; + virtual UMatData* allocate(int dims, const int* sizes, int type, + void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const = 0; + virtual bool allocate(UMatData* data, int accessflags, UMatUsageFlags usageFlags) const = 0; + virtual void deallocate(UMatData* data) const = 0; + virtual void map(UMatData* data, int accessflags) const; + virtual void unmap(UMatData* data) const; + virtual void download(UMatData* data, void* dst, int dims, const size_t sz[], + const size_t srcofs[], const size_t srcstep[], + const size_t dststep[]) const; + virtual void upload(UMatData* data, const void* src, int dims, const size_t sz[], + const size_t dstofs[], const size_t dststep[], + const size_t srcstep[]) const; + virtual void copy(UMatData* srcdata, UMatData* dstdata, int dims, const size_t sz[], + const size_t srcofs[], const size_t srcstep[], + const size_t dstofs[], const size_t dststep[], bool sync) const; + + // default implementation returns DummyBufferPoolController + virtual BufferPoolController* getBufferPoolController(const char* id = NULL) const; +}; + + +//////////////////////////////// MatCommaInitializer ////////////////////////////////// + +/** @brief Comma-separated Matrix Initializer + + The class instances are usually not created explicitly. + Instead, they are created on "matrix << firstValue" operator. + + The sample below initializes 2x2 rotation matrix: + + \code + double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180); + Mat R = (Mat_(2,2) << a, -b, b, a); + \endcode +*/ +template class MatCommaInitializer_ +{ +public: + //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat + MatCommaInitializer_(Mat_<_Tp>* _m); + //! the operator that takes the next value and put it to the matrix + template MatCommaInitializer_<_Tp>& operator , (T2 v); + //! another form of conversion operator + operator Mat_<_Tp>() const; +protected: + MatIterator_<_Tp> it; +}; + + +/////////////////////////////////////// Mat /////////////////////////////////////////// + +// note that umatdata might be allocated together +// with the matrix data, not as a separate object. +// therefore, it does not have constructor or destructor; +// it should be explicitly initialized using init(). +struct CV_EXPORTS UMatData +{ + enum { COPY_ON_MAP=1, HOST_COPY_OBSOLETE=2, + DEVICE_COPY_OBSOLETE=4, TEMP_UMAT=8, TEMP_COPIED_UMAT=24, + USER_ALLOCATED=32, DEVICE_MEM_MAPPED=64}; + UMatData(const MatAllocator* allocator); + ~UMatData(); + + // provide atomic access to the structure + void lock(); + void unlock(); + + bool hostCopyObsolete() const; + bool deviceCopyObsolete() const; + bool deviceMemMapped() const; + bool copyOnMap() const; + bool tempUMat() const; + bool tempCopiedUMat() const; + void markHostCopyObsolete(bool flag); + void markDeviceCopyObsolete(bool flag); + void markDeviceMemMapped(bool flag); + + const MatAllocator* prevAllocator; + const MatAllocator* currAllocator; + int urefcount; + int refcount; + uchar* data; + uchar* origdata; + size_t size; + + int flags; + void* handle; + void* userdata; + int allocatorFlags_; +}; + + +struct CV_EXPORTS UMatDataAutoLock +{ + explicit UMatDataAutoLock(UMatData* u); + ~UMatDataAutoLock(); + UMatData* u; +}; + + +struct CV_EXPORTS MatSize +{ + explicit MatSize(int* _p); + Size operator()() const; + const int& operator[](int i) const; + int& operator[](int i); + operator const int*() const; + bool operator == (const MatSize& sz) const; + bool operator != (const MatSize& sz) const; + + int* p; +}; + +struct CV_EXPORTS MatStep +{ + MatStep(); + explicit MatStep(size_t s); + const size_t& operator[](int i) const; + size_t& operator[](int i); + operator size_t() const; + MatStep& operator = (size_t s); + + size_t* p; + size_t buf[2]; +protected: + MatStep& operator = (const MatStep&); +}; + +/** @example cout_mat.cpp +An example demonstrating the serial out capabilities of cv::Mat +*/ + + /** @brief n-dimensional dense array class + +The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It +can be used to store real or complex-valued vectors and matrices, grayscale or color images, voxel +volumes, vector fields, point clouds, tensors, histograms (though, very high-dimensional histograms +may be better stored in a SparseMat ). The data layout of the array `M` is defined by the array +`M.step[]`, so that the address of element \f$(i_0,...,i_{M.dims-1})\f$, where \f$0\leq i_k= M.step[i+1]` (in fact, `M.step[i] >= M.step[i+1]*M.size[i+1]` ). This means +that 2-dimensional matrices are stored row-by-row, 3-dimensional matrices are stored plane-by-plane, +and so on. M.step[M.dims-1] is minimal and always equal to the element size M.elemSize() . + +So, the data layout in Mat is fully compatible with CvMat, IplImage, and CvMatND types from OpenCV +1.x. It is also compatible with the majority of dense array types from the standard toolkits and +SDKs, such as Numpy (ndarray), Win32 (independent device bitmaps), and others, that is, with any +array that uses *steps* (or *strides*) to compute the position of a pixel. Due to this +compatibility, it is possible to make a Mat header for user-allocated data and process it in-place +using OpenCV functions. + +There are many different ways to create a Mat object. The most popular options are listed below: + +- Use the create(nrows, ncols, type) method or the similar Mat(nrows, ncols, type[, fillValue]) +constructor. A new array of the specified size and type is allocated. type has the same meaning as +in the cvCreateMat method. For example, CV_8UC1 means a 8-bit single-channel array, CV_32FC2 +means a 2-channel (complex) floating-point array, and so on. +@code + // make a 7x7 complex matrix filled with 1+3j. + Mat M(7,7,CV_32FC2,Scalar(1,3)); + // and now turn M to a 100x60 15-channel 8-bit matrix. + // The old content will be deallocated + M.create(100,60,CV_8UC(15)); +@endcode +As noted in the introduction to this chapter, create() allocates only a new array when the shape +or type of the current array are different from the specified ones. + +- Create a multi-dimensional array: +@code + // create a 100x100x100 8-bit array + int sz[] = {100, 100, 100}; + Mat bigCube(3, sz, CV_8U, Scalar::all(0)); +@endcode +It passes the number of dimensions =1 to the Mat constructor but the created array will be +2-dimensional with the number of columns set to 1. So, Mat::dims is always \>= 2 (can also be 0 +when the array is empty). + +- Use a copy constructor or assignment operator where there can be an array or expression on the +right side (see below). As noted in the introduction, the array assignment is an O(1) operation +because it only copies the header and increases the reference counter. The Mat::clone() method can +be used to get a full (deep) copy of the array when you need it. + +- Construct a header for a part of another array. It can be a single row, single column, several +rows, several columns, rectangular region in the array (called a *minor* in algebra) or a +diagonal. Such operations are also O(1) because the new header references the same data. You can +actually modify a part of the array using this feature, for example: +@code + // add the 5-th row, multiplied by 3 to the 3rd row + M.row(3) = M.row(3) + M.row(5)*3; + // now copy the 7-th column to the 1-st column + // M.col(1) = M.col(7); // this will not work + Mat M1 = M.col(1); + M.col(7).copyTo(M1); + // create a new 320x240 image + Mat img(Size(320,240),CV_8UC3); + // select a ROI + Mat roi(img, Rect(10,10,100,100)); + // fill the ROI with (0,255,0) (which is green in RGB space); + // the original 320x240 image will be modified + roi = Scalar(0,255,0); +@endcode +Due to the additional datastart and dataend members, it is possible to compute a relative +sub-array position in the main *container* array using locateROI(): +@code + Mat A = Mat::eye(10, 10, CV_32S); + // extracts A columns, 1 (inclusive) to 3 (exclusive). + Mat B = A(Range::all(), Range(1, 3)); + // extracts B rows, 5 (inclusive) to 9 (exclusive). + // that is, C \~ A(Range(5, 9), Range(1, 3)) + Mat C = B(Range(5, 9), Range::all()); + Size size; Point ofs; + C.locateROI(size, ofs); + // size will be (width=10,height=10) and the ofs will be (x=1, y=5) +@endcode +As in case of whole matrices, if you need a deep copy, use the `clone()` method of the extracted +sub-matrices. + +- Make a header for user-allocated data. It can be useful to do the following: + -# Process "foreign" data using OpenCV (for example, when you implement a DirectShow\* filter or + a processing module for gstreamer, and so on). For example: + @code + void process_video_frame(const unsigned char* pixels, + int width, int height, int step) + { + Mat img(height, width, CV_8UC3, pixels, step); + GaussianBlur(img, img, Size(7,7), 1.5, 1.5); + } + @endcode + -# Quickly initialize small matrices and/or get a super-fast element access. + @code + double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}}; + Mat M = Mat(3, 3, CV_64F, m).inv(); + @endcode + . + Partial yet very common cases of this *user-allocated data* case are conversions from CvMat and + IplImage to Mat. For this purpose, there is function cv::cvarrToMat taking pointers to CvMat or + IplImage and the optional flag indicating whether to copy the data or not. + @snippet samples/cpp/image.cpp iplimage + +- Use MATLAB-style array initializers, zeros(), ones(), eye(), for example: +@code + // create a double-precision identity martix and add it to M. + M += Mat::eye(M.rows, M.cols, CV_64F); +@endcode + +- Use a comma-separated initializer: +@code + // create a 3x3 double-precision identity matrix + Mat M = (Mat_(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1); +@endcode +With this approach, you first call a constructor of the Mat class with the proper parameters, and +then you just put `<< operator` followed by comma-separated values that can be constants, +variables, expressions, and so on. Also, note the extra parentheses required to avoid compilation +errors. + +Once the array is created, it is automatically managed via a reference-counting mechanism. If the +array header is built on top of user-allocated data, you should handle the data by yourself. The +array data is deallocated when no one points to it. If you want to release the data pointed by a +array header before the array destructor is called, use Mat::release(). + +The next important thing to learn about the array class is element access. This manual already +described how to compute an address of each array element. Normally, you are not required to use the +formula directly in the code. If you know the array element type (which can be retrieved using the +method Mat::type() ), you can access the element \f$M_{ij}\f$ of a 2-dimensional array as: +@code + M.at(i,j) += 1.f; +@endcode +assuming that `M` is a double-precision floating-point array. There are several variants of the method +at for a different number of dimensions. + +If you need to process a whole row of a 2D array, the most efficient way is to get the pointer to +the row first, and then just use the plain C operator [] : +@code + // compute sum of positive matrix elements + // (assuming that M isa double-precision matrix) + double sum=0; + for(int i = 0; i < M.rows; i++) + { + const double* Mi = M.ptr(i); + for(int j = 0; j < M.cols; j++) + sum += std::max(Mi[j], 0.); + } +@endcode +Some operations, like the one above, do not actually depend on the array shape. They just process +elements of an array one by one (or elements from multiple arrays that have the same coordinates, +for example, array addition). Such operations are called *element-wise*. It makes sense to check +whether all the input/output arrays are continuous, namely, have no gaps at the end of each row. If +yes, process them as a long single row: +@code + // compute the sum of positive matrix elements, optimized variant + double sum=0; + int cols = M.cols, rows = M.rows; + if(M.isContinuous()) + { + cols *= rows; + rows = 1; + } + for(int i = 0; i < rows; i++) + { + const double* Mi = M.ptr(i); + for(int j = 0; j < cols; j++) + sum += std::max(Mi[j], 0.); + } +@endcode +In case of the continuous matrix, the outer loop body is executed just once. So, the overhead is +smaller, which is especially noticeable in case of small matrices. + +Finally, there are STL-style iterators that are smart enough to skip gaps between successive rows: +@code + // compute sum of positive matrix elements, iterator-based variant + double sum=0; + MatConstIterator_ it = M.begin(), it_end = M.end(); + for(; it != it_end; ++it) + sum += std::max(*it, 0.); +@endcode +The matrix iterators are random-access iterators, so they can be passed to any STL algorithm, +including std::sort(). +*/ +class CV_EXPORTS Mat +{ +public: + /** + These are various constructors that form a matrix. As noted in the AutomaticAllocation, often + the default constructor is enough, and the proper matrix will be allocated by an OpenCV function. + The constructed matrix can further be assigned to another matrix or matrix expression or can be + allocated with Mat::create . In the former case, the old content is de-referenced. + */ + Mat(); + + /** @overload + @param rows Number of rows in a 2D array. + @param cols Number of columns in a 2D array. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + */ + Mat(int rows, int cols, int type); + + /** @overload + @param size 2D array size: Size(cols, rows) . In the Size() constructor, the number of rows and the + number of columns go in the reverse order. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + */ + Mat(Size size, int type); + + /** @overload + @param rows Number of rows in a 2D array. + @param cols Number of columns in a 2D array. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param s An optional value to initialize each matrix element with. To set all the matrix elements to + the particular value after the construction, use the assignment operator + Mat::operator=(const Scalar& value) . + */ + Mat(int rows, int cols, int type, const Scalar& s); + + /** @overload + @param size 2D array size: Size(cols, rows) . In the Size() constructor, the number of rows and the + number of columns go in the reverse order. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param s An optional value to initialize each matrix element with. To set all the matrix elements to + the particular value after the construction, use the assignment operator + Mat::operator=(const Scalar& value) . + */ + Mat(Size size, int type, const Scalar& s); + + /** @overload + @param ndims Array dimensionality. + @param sizes Array of integers specifying an n-dimensional array shape. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + */ + Mat(int ndims, const int* sizes, int type); + + /** @overload + @param ndims Array dimensionality. + @param sizes Array of integers specifying an n-dimensional array shape. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param s An optional value to initialize each matrix element with. To set all the matrix elements to + the particular value after the construction, use the assignment operator + Mat::operator=(const Scalar& value) . + */ + Mat(int ndims, const int* sizes, int type, const Scalar& s); + + /** @overload + @param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied + by these constructors. Instead, the header pointing to m data or its sub-array is constructed and + associated with it. The reference counter, if any, is incremented. So, when you modify the matrix + formed using such a constructor, you also modify the corresponding elements of m . If you want to + have an independent copy of the sub-array, use Mat::clone() . + */ + Mat(const Mat& m); + + /** @overload + @param rows Number of rows in a 2D array. + @param cols Number of columns in a 2D array. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param data Pointer to the user data. Matrix constructors that take data and step parameters do not + allocate matrix data. Instead, they just initialize the matrix header that points to the specified + data, which means that no data is copied. This operation is very efficient and can be used to + process external data using OpenCV functions. The external data is not automatically deallocated, so + you should take care of it. + @param step Number of bytes each matrix row occupies. The value should include the padding bytes at + the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed + and the actual step is calculated as cols*elemSize(). See Mat::elemSize. + */ + Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP); + + /** @overload + @param size 2D array size: Size(cols, rows) . In the Size() constructor, the number of rows and the + number of columns go in the reverse order. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param data Pointer to the user data. Matrix constructors that take data and step parameters do not + allocate matrix data. Instead, they just initialize the matrix header that points to the specified + data, which means that no data is copied. This operation is very efficient and can be used to + process external data using OpenCV functions. The external data is not automatically deallocated, so + you should take care of it. + @param step Number of bytes each matrix row occupies. The value should include the padding bytes at + the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed + and the actual step is calculated as cols*elemSize(). See Mat::elemSize. + */ + Mat(Size size, int type, void* data, size_t step=AUTO_STEP); + + /** @overload + @param ndims Array dimensionality. + @param sizes Array of integers specifying an n-dimensional array shape. + @param type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or + CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices. + @param data Pointer to the user data. Matrix constructors that take data and step parameters do not + allocate matrix data. Instead, they just initialize the matrix header that points to the specified + data, which means that no data is copied. This operation is very efficient and can be used to + process external data using OpenCV functions. The external data is not automatically deallocated, so + you should take care of it. + @param steps Array of ndims-1 steps in case of a multi-dimensional array (the last step is always + set to the element size). If not specified, the matrix is assumed to be continuous. + */ + Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0); + + /** @overload + @param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied + by these constructors. Instead, the header pointing to m data or its sub-array is constructed and + associated with it. The reference counter, if any, is incremented. So, when you modify the matrix + formed using such a constructor, you also modify the corresponding elements of m . If you want to + have an independent copy of the sub-array, use Mat::clone() . + @param rowRange Range of the m rows to take. As usual, the range start is inclusive and the range + end is exclusive. Use Range::all() to take all the rows. + @param colRange Range of the m columns to take. Use Range::all() to take all the columns. + */ + Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all()); + + /** @overload + @param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied + by these constructors. Instead, the header pointing to m data or its sub-array is constructed and + associated with it. The reference counter, if any, is incremented. So, when you modify the matrix + formed using such a constructor, you also modify the corresponding elements of m . If you want to + have an independent copy of the sub-array, use Mat::clone() . + @param roi Region of interest. + */ + Mat(const Mat& m, const Rect& roi); + + /** @overload + @param m Array that (as a whole or partly) is assigned to the constructed matrix. No data is copied + by these constructors. Instead, the header pointing to m data or its sub-array is constructed and + associated with it. The reference counter, if any, is incremented. So, when you modify the matrix + formed using such a constructor, you also modify the corresponding elements of m . If you want to + have an independent copy of the sub-array, use Mat::clone() . + @param ranges Array of selected ranges of m along each dimensionality. + */ + Mat(const Mat& m, const Range* ranges); + + /** @overload + @param vec STL vector whose elements form the matrix. The matrix has a single column and the number + of rows equal to the number of vector elements. Type of the matrix matches the type of vector + elements. The constructor can handle arbitrary types, for which there is a properly declared + DataType . This means that the vector elements must be primitive numbers or uni-type numerical + tuples of numbers. Mixed-type structures are not supported. The corresponding constructor is + explicit. Since STL vectors are not automatically converted to Mat instances, you should write + Mat(vec) explicitly. Unless you copy the data into the matrix ( copyData=true ), no new elements + will be added to the vector because it can potentially yield vector data reallocation, and, thus, + the matrix data pointer will be invalid. + @param copyData Flag to specify whether the underlying data of the STL vector should be copied + to (true) or shared with (false) the newly constructed matrix. When the data is copied, the + allocated buffer is managed using Mat reference counting mechanism. While the data is shared, + the reference counter is NULL, and you should not deallocate the data until the matrix is not + destructed. + */ + template explicit Mat(const std::vector<_Tp>& vec, bool copyData=false); + + /** @overload + */ + template explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true); + + /** @overload + */ + template explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true); + + /** @overload + */ + template explicit Mat(const Point_<_Tp>& pt, bool copyData=true); + + /** @overload + */ + template explicit Mat(const Point3_<_Tp>& pt, bool copyData=true); + + /** @overload + */ + template explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer); + + //! download data from GpuMat + explicit Mat(const cuda::GpuMat& m); + + //! destructor - calls release() + ~Mat(); + + /** @brief assignment operators + + These are available assignment operators. Since they all are very different, make sure to read the + operator parameters description. + @param m Assigned, right-hand-side matrix. Matrix assignment is an O(1) operation. This means that + no data is copied but the data is shared and the reference counter, if any, is incremented. Before + assigning new data, the old data is de-referenced via Mat::release . + */ + Mat& operator = (const Mat& m); + + /** @overload + @param expr Assigned matrix expression object. As opposite to the first form of the assignment + operation, the second form can reuse already allocated matrix if it has the right size and type to + fit the matrix expression result. It is automatically handled by the real function that the matrix + expressions is expanded to. For example, C=A+B is expanded to add(A, B, C), and add takes care of + automatic C reallocation. + */ + Mat& operator = (const MatExpr& expr); + + //! retrieve UMat from Mat + UMat getUMat(int accessFlags, UMatUsageFlags usageFlags = USAGE_DEFAULT) const; + + /** @brief Creates a matrix header for the specified matrix row. + + The method makes a new header for the specified matrix row and returns it. This is an O(1) + operation, regardless of the matrix size. The underlying data of the new matrix is shared with the + original matrix. Here is the example of one of the classical basic matrix processing operations, + axpy, used by LU and many other algorithms: + @code + inline void matrix_axpy(Mat& A, int i, int j, double alpha) + { + A.row(i) += A.row(j)*alpha; + } + @endcode + @note In the current implementation, the following code does not work as expected: + @code + Mat A; + ... + A.row(i) = A.row(j); // will not work + @endcode + This happens because A.row(i) forms a temporary header that is further assigned to another header. + Remember that each of these operations is O(1), that is, no data is copied. Thus, the above + assignment is not true if you may have expected the j-th row to be copied to the i-th row. To + achieve that, you should either turn this simple assignment into an expression or use the + Mat::copyTo method: + @code + Mat A; + ... + // works, but looks a bit obscure. + A.row(i) = A.row(j) + 0; + // this is a bit longer, but the recommended method. + A.row(j).copyTo(A.row(i)); + @endcode + @param y A 0-based row index. + */ + Mat row(int y) const; + + /** @brief Creates a matrix header for the specified matrix column. + + The method makes a new header for the specified matrix column and returns it. This is an O(1) + operation, regardless of the matrix size. The underlying data of the new matrix is shared with the + original matrix. See also the Mat::row description. + @param x A 0-based column index. + */ + Mat col(int x) const; + + /** @brief Creates a matrix header for the specified row span. + + The method makes a new header for the specified row span of the matrix. Similarly to Mat::row and + Mat::col , this is an O(1) operation. + @param startrow An inclusive 0-based start index of the row span. + @param endrow An exclusive 0-based ending index of the row span. + */ + Mat rowRange(int startrow, int endrow) const; + + /** @overload + @param r Range structure containing both the start and the end indices. + */ + Mat rowRange(const Range& r) const; + + /** @brief Creates a matrix header for the specified column span. + + The method makes a new header for the specified column span of the matrix. Similarly to Mat::row and + Mat::col , this is an O(1) operation. + @param startcol An inclusive 0-based start index of the column span. + @param endcol An exclusive 0-based ending index of the column span. + */ + Mat colRange(int startcol, int endcol) const; + + /** @overload + @param r Range structure containing both the start and the end indices. + */ + Mat colRange(const Range& r) const; + + /** @brief Extracts a diagonal from a matrix + + The method makes a new header for the specified matrix diagonal. The new matrix is represented as a + single-column matrix. Similarly to Mat::row and Mat::col, this is an O(1) operation. + @param d index of the diagonal, with the following values: + - `d=0` is the main diagonal. + - `d>0` is a diagonal from the lower half. For example, d=1 means the diagonal is set + immediately below the main one. + - `d<0` is a diagonal from the upper half. For example, d=-1 means the diagonal is set + immediately above the main one. + */ + Mat diag(int d=0) const; + + /** @brief creates a diagonal matrix + + The method makes a new header for the specified matrix diagonal. The new matrix is represented as a + single-column matrix. Similarly to Mat::row and Mat::col, this is an O(1) operation. + @param d Single-column matrix that forms a diagonal matrix + */ + static Mat diag(const Mat& d); + + /** @brief Creates a full copy of the array and the underlying data. + + The method creates a full copy of the array. The original step[] is not taken into account. So, the + array copy is a continuous array occupying total()*elemSize() bytes. + */ + Mat clone() const; + + /** @brief Copies the matrix to another one. + + The method copies the matrix data to another matrix. Before copying the data, the method invokes : + @code + m.create(this->size(), this->type()); + @endcode + so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the + function does not handle the case of a partial overlap between the source and the destination + matrices. + + When the operation mask is specified, if the Mat::create call shown above reallocates the matrix, + the newly allocated matrix is initialized with all zeros before copying the data. + @param m Destination matrix. If it does not have a proper size or type before the operation, it is + reallocated. + */ + void copyTo( OutputArray m ) const; + + /** @overload + @param m Destination matrix. If it does not have a proper size or type before the operation, it is + reallocated. + @param mask Operation mask. Its non-zero elements indicate which matrix elements need to be copied. + */ + void copyTo( OutputArray m, InputArray mask ) const; + + /** @brief Converts an array to another data type with optional scaling. + + The method converts source pixel values to the target data type. saturate_cast\<\> is applied at + the end to avoid possible overflows: + + \f[m(x,y) = saturate \_ cast( \alpha (*this)(x,y) + \beta )\f] + @param m output matrix; if it does not have a proper size or type before the operation, it is + reallocated. + @param rtype desired output matrix type or, rather, the depth since the number of channels are the + same as the input has; if rtype is negative, the output matrix will have the same type as the input. + @param alpha optional scale factor. + @param beta optional delta added to the scaled values. + */ + void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; + + /** @brief Provides a functional form of convertTo. + + This is an internally used method called by the @ref MatrixExpressions engine. + @param m Destination array. + @param type Desired destination array depth (or -1 if it should be the same as the source type). + */ + void assignTo( Mat& m, int type=-1 ) const; + + /** @brief Sets all or some of the array elements to the specified value. + @param s Assigned scalar converted to the actual array type. + */ + Mat& operator = (const Scalar& s); + + /** @brief Sets all or some of the array elements to the specified value. + + This is an advanced variant of the Mat::operator=(const Scalar& s) operator. + @param value Assigned scalar converted to the actual array type. + @param mask Operation mask of the same size as \*this. + */ + Mat& setTo(InputArray value, InputArray mask=noArray()); + + /** @brief Changes the shape and/or the number of channels of a 2D matrix without copying the data. + + The method makes a new matrix header for \*this elements. The new matrix may have a different size + and/or different number of channels. Any combination is possible if: + - No extra elements are included into the new matrix and no elements are excluded. Consequently, + the product rows\*cols\*channels() must stay the same after the transformation. + - No data is copied. That is, this is an O(1) operation. Consequently, if you change the number of + rows, or the operation changes the indices of elements row in some other way, the matrix must be + continuous. See Mat::isContinuous . + + For example, if there is a set of 3D points stored as an STL vector, and you want to represent the + points as a 3xN matrix, do the following: + @code + std::vector vec; + ... + Mat pointMat = Mat(vec). // convert vector to Mat, O(1) operation + reshape(1). // make Nx3 1-channel matrix out of Nx1 3-channel. + // Also, an O(1) operation + t(); // finally, transpose the Nx3 matrix. + // This involves copying all the elements + @endcode + @param cn New number of channels. If the parameter is 0, the number of channels remains the same. + @param rows New number of rows. If the parameter is 0, the number of rows remains the same. + */ + Mat reshape(int cn, int rows=0) const; + + /** @overload */ + Mat reshape(int cn, int newndims, const int* newsz) const; + + /** @brief Transposes a matrix. + + The method performs matrix transposition by means of matrix expressions. It does not perform the + actual transposition but returns a temporary matrix transposition object that can be further used as + a part of more complex matrix expressions or can be assigned to a matrix: + @code + Mat A1 = A + Mat::eye(A.size(), A.type())*lambda; + Mat C = A1.t()*A1; // compute (A + lambda*I)^t * (A + lamda*I) + @endcode + */ + MatExpr t() const; + + /** @brief Inverses a matrix. + + The method performs a matrix inversion by means of matrix expressions. This means that a temporary + matrix inversion object is returned by the method and can be used further as a part of more complex + matrix expressions or can be assigned to a matrix. + @param method Matrix inversion method. One of cv::DecompTypes + */ + MatExpr inv(int method=DECOMP_LU) const; + + /** @brief Performs an element-wise multiplication or division of the two matrices. + + The method returns a temporary object encoding per-element array multiplication, with optional + scale. Note that this is not a matrix multiplication that corresponds to a simpler "\*" operator. + + Example: + @code + Mat C = A.mul(5/B); // equivalent to divide(A, B, C, 5) + @endcode + @param m Another array of the same type and the same size as \*this, or a matrix expression. + @param scale Optional scale factor. + */ + MatExpr mul(InputArray m, double scale=1) const; + + /** @brief Computes a cross-product of two 3-element vectors. + + The method computes a cross-product of two 3-element vectors. The vectors must be 3-element + floating-point vectors of the same shape and size. The result is another 3-element vector of the + same shape and type as operands. + @param m Another cross-product operand. + */ + Mat cross(InputArray m) const; + + /** @brief Computes a dot-product of two vectors. + + The method computes a dot-product of two matrices. If the matrices are not single-column or + single-row vectors, the top-to-bottom left-to-right scan ordering is used to treat them as 1D + vectors. The vectors must have the same size and type. If the matrices have more than one channel, + the dot products from all the channels are summed together. + @param m another dot-product operand. + */ + double dot(InputArray m) const; + + /** @brief Returns a zero array of the specified size and type. + + The method returns a Matlab-style zero array initializer. It can be used to quickly form a constant + array as a function parameter, part of a matrix expression, or as a matrix initializer. : + @code + Mat A; + A = Mat::zeros(3, 3, CV_32F); + @endcode + In the example above, a new matrix is allocated only if A is not a 3x3 floating-point matrix. + Otherwise, the existing matrix A is filled with zeros. + @param rows Number of rows. + @param cols Number of columns. + @param type Created matrix type. + */ + static MatExpr zeros(int rows, int cols, int type); + + /** @overload + @param size Alternative to the matrix size specification Size(cols, rows) . + @param type Created matrix type. + */ + static MatExpr zeros(Size size, int type); + + /** @overload + @param ndims Array dimensionality. + @param sz Array of integers specifying the array shape. + @param type Created matrix type. + */ + static MatExpr zeros(int ndims, const int* sz, int type); + + /** @brief Returns an array of all 1's of the specified size and type. + + The method returns a Matlab-style 1's array initializer, similarly to Mat::zeros. Note that using + this method you can initialize an array with an arbitrary value, using the following Matlab idiom: + @code + Mat A = Mat::ones(100, 100, CV_8U)*3; // make 100x100 matrix filled with 3. + @endcode + The above operation does not form a 100x100 matrix of 1's and then multiply it by 3. Instead, it + just remembers the scale factor (3 in this case) and use it when actually invoking the matrix + initializer. + @param rows Number of rows. + @param cols Number of columns. + @param type Created matrix type. + */ + static MatExpr ones(int rows, int cols, int type); + + /** @overload + @param size Alternative to the matrix size specification Size(cols, rows) . + @param type Created matrix type. + */ + static MatExpr ones(Size size, int type); + + /** @overload + @param ndims Array dimensionality. + @param sz Array of integers specifying the array shape. + @param type Created matrix type. + */ + static MatExpr ones(int ndims, const int* sz, int type); + + /** @brief Returns an identity matrix of the specified size and type. + + The method returns a Matlab-style identity matrix initializer, similarly to Mat::zeros. Similarly to + Mat::ones, you can use a scale operation to create a scaled identity matrix efficiently: + @code + // make a 4x4 diagonal matrix with 0.1's on the diagonal. + Mat A = Mat::eye(4, 4, CV_32F)*0.1; + @endcode + @param rows Number of rows. + @param cols Number of columns. + @param type Created matrix type. + */ + static MatExpr eye(int rows, int cols, int type); + + /** @overload + @param size Alternative matrix size specification as Size(cols, rows) . + @param type Created matrix type. + */ + static MatExpr eye(Size size, int type); + + /** @brief Allocates new array data if needed. + + This is one of the key Mat methods. Most new-style OpenCV functions and methods that produce arrays + call this method for each output array. The method uses the following algorithm: + + -# If the current array shape and the type match the new ones, return immediately. Otherwise, + de-reference the previous data by calling Mat::release. + -# Initialize the new header. + -# Allocate the new data of total()\*elemSize() bytes. + -# Allocate the new, associated with the data, reference counter and set it to 1. + + Such a scheme makes the memory management robust and efficient at the same time and helps avoid + extra typing for you. This means that usually there is no need to explicitly allocate output arrays. + That is, instead of writing: + @code + Mat color; + ... + Mat gray(color.rows, color.cols, color.depth()); + cvtColor(color, gray, COLOR_BGR2GRAY); + @endcode + you can simply write: + @code + Mat color; + ... + Mat gray; + cvtColor(color, gray, COLOR_BGR2GRAY); + @endcode + because cvtColor, as well as the most of OpenCV functions, calls Mat::create() for the output array + internally. + @param rows New number of rows. + @param cols New number of columns. + @param type New matrix type. + */ + void create(int rows, int cols, int type); + + /** @overload + @param size Alternative new matrix size specification: Size(cols, rows) + @param type New matrix type. + */ + void create(Size size, int type); + + /** @overload + @param ndims New array dimensionality. + @param sizes Array of integers specifying a new array shape. + @param type New matrix type. + */ + void create(int ndims, const int* sizes, int type); + + /** @brief Increments the reference counter. + + The method increments the reference counter associated with the matrix data. If the matrix header + points to an external data set (see Mat::Mat ), the reference counter is NULL, and the method has no + effect in this case. Normally, to avoid memory leaks, the method should not be called explicitly. It + is called implicitly by the matrix assignment operator. The reference counter increment is an atomic + operation on the platforms that support it. Thus, it is safe to operate on the same matrices + asynchronously in different threads. + */ + void addref(); + + /** @brief Decrements the reference counter and deallocates the matrix if needed. + + The method decrements the reference counter associated with the matrix data. When the reference + counter reaches 0, the matrix data is deallocated and the data and the reference counter pointers + are set to NULL's. If the matrix header points to an external data set (see Mat::Mat ), the + reference counter is NULL, and the method has no effect in this case. + + This method can be called manually to force the matrix data deallocation. But since this method is + automatically called in the destructor, or by any other method that changes the data pointer, it is + usually not needed. The reference counter decrement and check for 0 is an atomic operation on the + platforms that support it. Thus, it is safe to operate on the same matrices asynchronously in + different threads. + */ + void release(); + + //! deallocates the matrix data + void deallocate(); + //! internal use function; properly re-allocates _size, _step arrays + void copySize(const Mat& m); + + /** @brief Reserves space for the certain number of rows. + + The method reserves space for sz rows. If the matrix already has enough space to store sz rows, + nothing happens. If the matrix is reallocated, the first Mat::rows rows are preserved. The method + emulates the corresponding method of the STL vector class. + @param sz Number of rows. + */ + void reserve(size_t sz); + + /** @brief Changes the number of matrix rows. + + The methods change the number of matrix rows. If the matrix is reallocated, the first + min(Mat::rows, sz) rows are preserved. The methods emulate the corresponding methods of the STL + vector class. + @param sz New number of rows. + */ + void resize(size_t sz); + + /** @overload + @param sz New number of rows. + @param s Value assigned to the newly added elements. + */ + void resize(size_t sz, const Scalar& s); + + //! internal function + void push_back_(const void* elem); + + /** @brief Adds elements to the bottom of the matrix. + + The methods add one or more elements to the bottom of the matrix. They emulate the corresponding + method of the STL vector class. When elem is Mat , its type and the number of columns must be the + same as in the container matrix. + @param elem Added element(s). + */ + template void push_back(const _Tp& elem); + + /** @overload + @param elem Added element(s). + */ + template void push_back(const Mat_<_Tp>& elem); + + /** @overload + @param m Added line(s). + */ + void push_back(const Mat& m); + + /** @brief Removes elements from the bottom of the matrix. + + The method removes one or more rows from the bottom of the matrix. + @param nelems Number of removed rows. If it is greater than the total number of rows, an exception + is thrown. + */ + void pop_back(size_t nelems=1); + + /** @brief Locates the matrix header within a parent matrix. + + After you extracted a submatrix from a matrix using Mat::row, Mat::col, Mat::rowRange, + Mat::colRange, and others, the resultant submatrix points just to the part of the original big + matrix. However, each submatrix contains information (represented by datastart and dataend + fields) that helps reconstruct the original matrix size and the position of the extracted + submatrix within the original matrix. The method locateROI does exactly that. + @param wholeSize Output parameter that contains the size of the whole matrix containing *this* + as a part. + @param ofs Output parameter that contains an offset of *this* inside the whole matrix. + */ + void locateROI( Size& wholeSize, Point& ofs ) const; + + /** @brief Adjusts a submatrix size and position within the parent matrix. + + The method is complimentary to Mat::locateROI . The typical use of these functions is to determine + the submatrix position within the parent matrix and then shift the position somehow. Typically, it + can be required for filtering operations when pixels outside of the ROI should be taken into + account. When all the method parameters are positive, the ROI needs to grow in all directions by the + specified amount, for example: + @code + A.adjustROI(2, 2, 2, 2); + @endcode + In this example, the matrix size is increased by 4 elements in each direction. The matrix is shifted + by 2 elements to the left and 2 elements up, which brings in all the necessary pixels for the + filtering with the 5x5 kernel. + + adjustROI forces the adjusted ROI to be inside of the parent matrix that is boundaries of the + adjusted ROI are constrained by boundaries of the parent matrix. For example, if the submatrix A is + located in the first row of a parent matrix and you called A.adjustROI(2, 2, 2, 2) then A will not + be increased in the upward direction. + + The function is used internally by the OpenCV filtering functions, like filter2D , morphological + operations, and so on. + @param dtop Shift of the top submatrix boundary upwards. + @param dbottom Shift of the bottom submatrix boundary downwards. + @param dleft Shift of the left submatrix boundary to the left. + @param dright Shift of the right submatrix boundary to the right. + @sa copyMakeBorder + */ + Mat& adjustROI( int dtop, int dbottom, int dleft, int dright ); + + /** @brief Extracts a rectangular submatrix. + + The operators make a new header for the specified sub-array of \*this . They are the most + generalized forms of Mat::row, Mat::col, Mat::rowRange, and Mat::colRange . For example, + `A(Range(0, 10), Range::all())` is equivalent to `A.rowRange(0, 10)`. Similarly to all of the above, + the operators are O(1) operations, that is, no matrix data is copied. + @param rowRange Start and end row of the extracted submatrix. The upper boundary is not included. To + select all the rows, use Range::all(). + @param colRange Start and end column of the extracted submatrix. The upper boundary is not included. + To select all the columns, use Range::all(). + */ + Mat operator()( Range rowRange, Range colRange ) const; + + /** @overload + @param roi Extracted submatrix specified as a rectangle. + */ + Mat operator()( const Rect& roi ) const; + + /** @overload + @param ranges Array of selected ranges along each array dimension. + */ + Mat operator()( const Range* ranges ) const; + + // //! converts header to CvMat; no data is copied + // operator CvMat() const; + // //! converts header to CvMatND; no data is copied + // operator CvMatND() const; + // //! converts header to IplImage; no data is copied + // operator IplImage() const; + + template operator std::vector<_Tp>() const; + template operator Vec<_Tp, n>() const; + template operator Matx<_Tp, m, n>() const; + + /** @brief Reports whether the matrix is continuous or not. + + The method returns true if the matrix elements are stored continuously without gaps at the end of + each row. Otherwise, it returns false. Obviously, 1x1 or 1xN matrices are always continuous. + Matrices created with Mat::create are always continuous. But if you extract a part of the matrix + using Mat::col, Mat::diag, and so on, or constructed a matrix header for externally allocated data, + such matrices may no longer have this property. + + The continuity flag is stored as a bit in the Mat::flags field and is computed automatically when + you construct a matrix header. Thus, the continuity check is a very fast operation, though + theoretically it could be done as follows: + @code + // alternative implementation of Mat::isContinuous() + bool myCheckMatContinuity(const Mat& m) + { + //return (m.flags & Mat::CONTINUOUS_FLAG) != 0; + return m.rows == 1 || m.step == m.cols*m.elemSize(); + } + @endcode + The method is used in quite a few of OpenCV functions. The point is that element-wise operations + (such as arithmetic and logical operations, math functions, alpha blending, color space + transformations, and others) do not depend on the image geometry. Thus, if all the input and output + arrays are continuous, the functions can process them as very long single-row vectors. The example + below illustrates how an alpha-blending function can be implemented: + @code + template + void alphaBlendRGBA(const Mat& src1, const Mat& src2, Mat& dst) + { + const float alpha_scale = (float)std::numeric_limits::max(), + inv_scale = 1.f/alpha_scale; + + CV_Assert( src1.type() == src2.type() && + src1.type() == CV_MAKETYPE(DataType::depth, 4) && + src1.size() == src2.size()); + Size size = src1.size(); + dst.create(size, src1.type()); + + // here is the idiom: check the arrays for continuity and, + // if this is the case, + // treat the arrays as 1D vectors + if( src1.isContinuous() && src2.isContinuous() && dst.isContinuous() ) + { + size.width *= size.height; + size.height = 1; + } + size.width *= 4; + + for( int i = 0; i < size.height; i++ ) + { + // when the arrays are continuous, + // the outer loop is executed only once + const T* ptr1 = src1.ptr(i); + const T* ptr2 = src2.ptr(i); + T* dptr = dst.ptr(i); + + for( int j = 0; j < size.width; j += 4 ) + { + float alpha = ptr1[j+3]*inv_scale, beta = ptr2[j+3]*inv_scale; + dptr[j] = saturate_cast(ptr1[j]*alpha + ptr2[j]*beta); + dptr[j+1] = saturate_cast(ptr1[j+1]*alpha + ptr2[j+1]*beta); + dptr[j+2] = saturate_cast(ptr1[j+2]*alpha + ptr2[j+2]*beta); + dptr[j+3] = saturate_cast((1 - (1-alpha)*(1-beta))*alpha_scale); + } + } + } + @endcode + This approach, while being very simple, can boost the performance of a simple element-operation by + 10-20 percents, especially if the image is rather small and the operation is quite simple. + + Another OpenCV idiom in this function, a call of Mat::create for the destination array, that + allocates the destination array unless it already has the proper size and type. And while the newly + allocated arrays are always continuous, you still need to check the destination array because + Mat::create does not always allocate a new matrix. + */ + bool isContinuous() const; + + //! returns true if the matrix is a submatrix of another matrix + bool isSubmatrix() const; + + /** @brief Returns the matrix element size in bytes. + + The method returns the matrix element size in bytes. For example, if the matrix type is CV_16SC3 , + the method returns 3\*sizeof(short) or 6. + */ + size_t elemSize() const; + + /** @brief Returns the size of each matrix element channel in bytes. + + The method returns the matrix element channel size in bytes, that is, it ignores the number of + channels. For example, if the matrix type is CV_16SC3 , the method returns sizeof(short) or 2. + */ + size_t elemSize1() const; + + /** @brief Returns the type of a matrix element. + + The method returns a matrix element type. This is an identifier compatible with the CvMat type + system, like CV_16SC3 or 16-bit signed 3-channel array, and so on. + */ + int type() const; + + /** @brief Returns the depth of a matrix element. + + The method returns the identifier of the matrix element depth (the type of each individual channel). + For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of + matrix types contains the following values: + - CV_8U - 8-bit unsigned integers ( 0..255 ) + - CV_8S - 8-bit signed integers ( -128..127 ) + - CV_16U - 16-bit unsigned integers ( 0..65535 ) + - CV_16S - 16-bit signed integers ( -32768..32767 ) + - CV_32S - 32-bit signed integers ( -2147483648..2147483647 ) + - CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN ) + - CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN ) + */ + int depth() const; + + /** @brief Returns the number of matrix channels. + + The method returns the number of matrix channels. + */ + int channels() const; + + /** @brief Returns a normalized step. + + The method returns a matrix step divided by Mat::elemSize1() . It can be useful to quickly access an + arbitrary matrix element. + */ + size_t step1(int i=0) const; + + /** @brief Returns true if the array has no elements. + + The method returns true if Mat::total() is 0 or if Mat::data is NULL. Because of pop_back() and + resize() methods `M.total() == 0` does not imply that `M.data == NULL`. + */ + bool empty() const; + + /** @brief Returns the total number of array elements. + + The method returns the number of array elements (a number of pixels if the array represents an + image). + */ + size_t total() const; + + //! returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise + int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const; + + /** @brief Returns a pointer to the specified matrix row. + + The methods return `uchar*` or typed pointer to the specified matrix row. See the sample in + Mat::isContinuous to know how to use these methods. + @param i0 A 0-based row index. + */ + uchar* ptr(int i0=0); + /** @overload */ + const uchar* ptr(int i0=0) const; + + /** @overload */ + uchar* ptr(int i0, int i1); + /** @overload */ + const uchar* ptr(int i0, int i1) const; + + /** @overload */ + uchar* ptr(int i0, int i1, int i2); + /** @overload */ + const uchar* ptr(int i0, int i1, int i2) const; + + /** @overload */ + uchar* ptr(const int* idx); + /** @overload */ + const uchar* ptr(const int* idx) const; + /** @overload */ + template uchar* ptr(const Vec& idx); + /** @overload */ + template const uchar* ptr(const Vec& idx) const; + + /** @overload */ + template _Tp* ptr(int i0=0); + /** @overload */ + template const _Tp* ptr(int i0=0) const; + /** @overload */ + template _Tp* ptr(int i0, int i1); + /** @overload */ + template const _Tp* ptr(int i0, int i1) const; + /** @overload */ + template _Tp* ptr(int i0, int i1, int i2); + /** @overload */ + template const _Tp* ptr(int i0, int i1, int i2) const; + /** @overload */ + template _Tp* ptr(const int* idx); + /** @overload */ + template const _Tp* ptr(const int* idx) const; + /** @overload */ + template _Tp* ptr(const Vec& idx); + /** @overload */ + template const _Tp* ptr(const Vec& idx) const; + + /** @brief Returns a reference to the specified array element. + + The template methods return a reference to the specified array element. For the sake of higher + performance, the index range checks are only performed in the Debug configuration. + + Note that the variants with a single index (i) can be used to access elements of single-row or + single-column 2-dimensional arrays. That is, if, for example, A is a 1 x N floating-point matrix and + B is an M x 1 integer matrix, you can simply write `A.at(k+4)` and `B.at(2*i+1)` + instead of `A.at(0,k+4)` and `B.at(2*i+1,0)`, respectively. + + The example below initializes a Hilbert matrix: + @code + Mat H(100, 100, CV_64F); + for(int i = 0; i < H.rows; i++) + for(int j = 0; j < H.cols; j++) + H.at(i,j)=1./(i+j+1); + @endcode + @param i0 Index along the dimension 0 + */ + template _Tp& at(int i0=0); + /** @overload + @param i0 Index along the dimension 0 + */ + template const _Tp& at(int i0=0) const; + /** @overload + @param i0 Index along the dimension 0 + @param i1 Index along the dimension 1 + */ + template _Tp& at(int i0, int i1); + /** @overload + @param i0 Index along the dimension 0 + @param i1 Index along the dimension 1 + */ + template const _Tp& at(int i0, int i1) const; + + /** @overload + @param i0 Index along the dimension 0 + @param i1 Index along the dimension 1 + @param i2 Index along the dimension 2 + */ + template _Tp& at(int i0, int i1, int i2); + /** @overload + @param i0 Index along the dimension 0 + @param i1 Index along the dimension 1 + @param i2 Index along the dimension 2 + */ + template const _Tp& at(int i0, int i1, int i2) const; + + /** @overload + @param idx Array of Mat::dims indices. + */ + template _Tp& at(const int* idx); + /** @overload + @param idx Array of Mat::dims indices. + */ + template const _Tp& at(const int* idx) const; + + /** @overload */ + template _Tp& at(const Vec& idx); + /** @overload */ + template const _Tp& at(const Vec& idx) const; + + /** @overload + special versions for 2D arrays (especially convenient for referencing image pixels) + @param pt Element position specified as Point(j,i) . + */ + template _Tp& at(Point pt); + /** @overload + special versions for 2D arrays (especially convenient for referencing image pixels) + @param pt Element position specified as Point(j,i) . + */ + template const _Tp& at(Point pt) const; + + /** @brief Returns the matrix iterator and sets it to the first matrix element. + + The methods return the matrix read-only or read-write iterators. The use of matrix iterators is very + similar to the use of bi-directional STL iterators. In the example below, the alpha blending + function is rewritten using the matrix iterators: + @code + template + void alphaBlendRGBA(const Mat& src1, const Mat& src2, Mat& dst) + { + typedef Vec VT; + + const float alpha_scale = (float)std::numeric_limits::max(), + inv_scale = 1.f/alpha_scale; + + CV_Assert( src1.type() == src2.type() && + src1.type() == DataType::type && + src1.size() == src2.size()); + Size size = src1.size(); + dst.create(size, src1.type()); + + MatConstIterator_ it1 = src1.begin(), it1_end = src1.end(); + MatConstIterator_ it2 = src2.begin(); + MatIterator_ dst_it = dst.begin(); + + for( ; it1 != it1_end; ++it1, ++it2, ++dst_it ) + { + VT pix1 = *it1, pix2 = *it2; + float alpha = pix1[3]*inv_scale, beta = pix2[3]*inv_scale; + *dst_it = VT(saturate_cast(pix1[0]*alpha + pix2[0]*beta), + saturate_cast(pix1[1]*alpha + pix2[1]*beta), + saturate_cast(pix1[2]*alpha + pix2[2]*beta), + saturate_cast((1 - (1-alpha)*(1-beta))*alpha_scale)); + } + } + @endcode + */ + template MatIterator_<_Tp> begin(); + template MatConstIterator_<_Tp> begin() const; + + /** @brief Returns the matrix iterator and sets it to the after-last matrix element. + + The methods return the matrix read-only or read-write iterators, set to the point following the last + matrix element. + */ + template MatIterator_<_Tp> end(); + template MatConstIterator_<_Tp> end() const; + + /** @brief Invoke with arguments functor, and runs the functor over all matrix element. + + The methos runs operation in parallel. Operation is passed by arguments. Operation have to be a + function pointer, a function object or a lambda(C++11). + + All of below operation is equal. Put 0xFF to first channel of all matrix elements: + @code + Mat image(1920, 1080, CV_8UC3); + typedef cv::Point3_ Pixel; + + // first. raw pointer access. + for (int r = 0; r < image.rows; ++r) { + Pixel* ptr = image.ptr(0, r); + const Pixel* ptr_end = ptr + image.cols; + for (; ptr != ptr_end; ++ptr) { + ptr->x = 255; + } + } + + // Using MatIterator. (Simple but there are a Iterator's overhead) + for (Pixel &p : cv::Mat_(image)) { + p.x = 255; + } + + // Parallel execution with function object. + struct Operator { + void operator ()(Pixel &pixel, const int * position) { + pixel.x = 255; + } + }; + image.forEach(Operator()); + + // Parallel execution using C++11 lambda. + image.forEach([](Pixel &p, const int * position) -> void { + p.x = 255; + }); + @endcode + position parameter is index of current pixel: + @code + // Creating 3D matrix (255 x 255 x 255) typed uint8_t, + // and initialize all elements by the value which equals elements position. + // i.e. pixels (x,y,z) = (1,2,3) is (b,g,r) = (1,2,3). + + int sizes[] = { 255, 255, 255 }; + typedef cv::Point3_ Pixel; + + Mat_ image = Mat::zeros(3, sizes, CV_8UC3); + + image.forEachWithPosition([&](Pixel& pixel, const int position[]) -> void{ + pixel.x = position[0]; + pixel.y = position[1]; + pixel.z = position[2]; + }); + @endcode + */ + template void forEach(const Functor& operation); + /** @overload */ + template void forEach(const Functor& operation) const; + + enum { MAGIC_VAL = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG }; + enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 }; + + /*! includes several bit-fields: + - the magic signature + - continuity flag + - depth + - number of channels + */ + int flags; + //! the matrix dimensionality, >= 2 + int dims; + //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions + int rows, cols; + //! pointer to the data + uchar* data; + + //! helper fields used in locateROI and adjustROI + const uchar* datastart; + const uchar* dataend; + const uchar* datalimit; + + //! custom allocator + MatAllocator* allocator; + //! and the standard allocator + static MatAllocator* getStdAllocator(); + + //! interaction with UMat + UMatData* u; + + MatSize size; + MatStep step; + +protected: + template void forEach_impl(const Functor& operation); +}; + + +///////////////////////////////// Mat_<_Tp> //////////////////////////////////// + +/** @brief Template matrix class derived from Mat + +@code + template class Mat_ : public Mat + { + public: + // ... some specific methods + // and + // no new extra fields + }; +@endcode +The class `Mat_<_Tp>` is a *thin* template wrapper on top of the Mat class. It does not have any +extra data fields. Nor this class nor Mat has any virtual methods. Thus, references or pointers to +these two classes can be freely but carefully converted one to another. For example: +@code + // create a 100x100 8-bit matrix + Mat M(100,100,CV_8U); + // this will be compiled fine. no any data conversion will be done. + Mat_& M1 = (Mat_&)M; + // the program is likely to crash at the statement below + M1(99,99) = 1.f; +@endcode +While Mat is sufficient in most cases, Mat_ can be more convenient if you use a lot of element +access operations and if you know matrix type at the compilation time. Note that +`Mat::at(int y,int x)` and `Mat_::operator()(int y,int x)` do absolutely the same +and run at the same speed, but the latter is certainly shorter: +@code + Mat_ M(20,20); + for(int i = 0; i < M.rows; i++) + for(int j = 0; j < M.cols; j++) + M(i,j) = 1./(i+j+1); + Mat E, V; + eigen(M,E,V); + cout << E.at(0,0)/E.at(M.rows-1,0); +@endcode +To use Mat_ for multi-channel images/matrices, pass Vec as a Mat_ parameter: +@code + // allocate a 320x240 color image and fill it with green (in RGB space) + Mat_ img(240, 320, Vec3b(0,255,0)); + // now draw a diagonal white line + for(int i = 0; i < 100; i++) + img(i,i)=Vec3b(255,255,255); + // and now scramble the 2nd (red) channel of each pixel + for(int i = 0; i < img.rows; i++) + for(int j = 0; j < img.cols; j++) + img(i,j)[2] ^= (uchar)(i ^ j); +@endcode + */ +template class Mat_ : public Mat +{ +public: + typedef _Tp value_type; + typedef typename DataType<_Tp>::channel_type channel_type; + typedef MatIterator_<_Tp> iterator; + typedef MatConstIterator_<_Tp> const_iterator; + + //! default constructor + Mat_(); + //! equivalent to Mat(_rows, _cols, DataType<_Tp>::type) + Mat_(int _rows, int _cols); + //! constructor that sets each matrix element to specified value + Mat_(int _rows, int _cols, const _Tp& value); + //! equivalent to Mat(_size, DataType<_Tp>::type) + explicit Mat_(Size _size); + //! constructor that sets each matrix element to specified value + Mat_(Size _size, const _Tp& value); + //! n-dim array constructor + Mat_(int _ndims, const int* _sizes); + //! n-dim array constructor that sets each matrix element to specified value + Mat_(int _ndims, const int* _sizes, const _Tp& value); + //! copy/conversion contructor. If m is of different type, it's converted + Mat_(const Mat& m); + //! copy constructor + Mat_(const Mat_& m); + //! constructs a matrix on top of user-allocated data. step is in bytes(!!!), regardless of the type + Mat_(int _rows, int _cols, _Tp* _data, size_t _step=AUTO_STEP); + //! constructs n-dim matrix on top of user-allocated data. steps are in bytes(!!!), regardless of the type + Mat_(int _ndims, const int* _sizes, _Tp* _data, const size_t* _steps=0); + //! selects a submatrix + Mat_(const Mat_& m, const Range& rowRange, const Range& colRange=Range::all()); + //! selects a submatrix + Mat_(const Mat_& m, const Rect& roi); + //! selects a submatrix, n-dim version + Mat_(const Mat_& m, const Range* ranges); + //! from a matrix expression + explicit Mat_(const MatExpr& e); + //! makes a matrix out of Vec, std::vector, Point_ or Point3_. The matrix will have a single column + explicit Mat_(const std::vector<_Tp>& vec, bool copyData=false); + template explicit Mat_(const Vec::channel_type, n>& vec, bool copyData=true); + template explicit Mat_(const Matx::channel_type, m, n>& mtx, bool copyData=true); + explicit Mat_(const Point_::channel_type>& pt, bool copyData=true); + explicit Mat_(const Point3_::channel_type>& pt, bool copyData=true); + explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer); + + Mat_& operator = (const Mat& m); + Mat_& operator = (const Mat_& m); + //! set all the elements to s. + Mat_& operator = (const _Tp& s); + //! assign a matrix expression + Mat_& operator = (const MatExpr& e); + + //! iterators; they are smart enough to skip gaps in the end of rows + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + //! template methods for for operation over all matrix elements. + // the operations take care of skipping gaps in the end of rows (if any) + template void forEach(const Functor& operation); + template void forEach(const Functor& operation) const; + + //! equivalent to Mat::create(_rows, _cols, DataType<_Tp>::type) + void create(int _rows, int _cols); + //! equivalent to Mat::create(_size, DataType<_Tp>::type) + void create(Size _size); + //! equivalent to Mat::create(_ndims, _sizes, DatType<_Tp>::type) + void create(int _ndims, const int* _sizes); + //! cross-product + Mat_ cross(const Mat_& m) const; + //! data type conversion + template operator Mat_() const; + //! overridden forms of Mat::row() etc. + Mat_ row(int y) const; + Mat_ col(int x) const; + Mat_ diag(int d=0) const; + Mat_ clone() const; + + //! overridden forms of Mat::elemSize() etc. + size_t elemSize() const; + size_t elemSize1() const; + int type() const; + int depth() const; + int channels() const; + size_t step1(int i=0) const; + //! returns step()/sizeof(_Tp) + size_t stepT(int i=0) const; + + //! overridden forms of Mat::zeros() etc. Data type is omitted, of course + static MatExpr zeros(int rows, int cols); + static MatExpr zeros(Size size); + static MatExpr zeros(int _ndims, const int* _sizes); + static MatExpr ones(int rows, int cols); + static MatExpr ones(Size size); + static MatExpr ones(int _ndims, const int* _sizes); + static MatExpr eye(int rows, int cols); + static MatExpr eye(Size size); + + //! some more overriden methods + Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright ); + Mat_ operator()( const Range& rowRange, const Range& colRange ) const; + Mat_ operator()( const Rect& roi ) const; + Mat_ operator()( const Range* ranges ) const; + + //! more convenient forms of row and element access operators + _Tp* operator [](int y); + const _Tp* operator [](int y) const; + + //! returns reference to the specified element + _Tp& operator ()(const int* idx); + //! returns read-only reference to the specified element + const _Tp& operator ()(const int* idx) const; + + //! returns reference to the specified element + template _Tp& operator ()(const Vec& idx); + //! returns read-only reference to the specified element + template const _Tp& operator ()(const Vec& idx) const; + + //! returns reference to the specified element (1D case) + _Tp& operator ()(int idx0); + //! returns read-only reference to the specified element (1D case) + const _Tp& operator ()(int idx0) const; + //! returns reference to the specified element (2D case) + _Tp& operator ()(int idx0, int idx1); + //! returns read-only reference to the specified element (2D case) + const _Tp& operator ()(int idx0, int idx1) const; + //! returns reference to the specified element (3D case) + _Tp& operator ()(int idx0, int idx1, int idx2); + //! returns read-only reference to the specified element (3D case) + const _Tp& operator ()(int idx0, int idx1, int idx2) const; + + _Tp& operator ()(Point pt); + const _Tp& operator ()(Point pt) const; + + //! conversion to vector. + operator std::vector<_Tp>() const; + //! conversion to Vec + template operator Vec::channel_type, n>() const; + //! conversion to Matx + template operator Matx::channel_type, m, n>() const; +}; + +typedef Mat_ Mat1b; +typedef Mat_ Mat2b; +typedef Mat_ Mat3b; +typedef Mat_ Mat4b; + +typedef Mat_ Mat1s; +typedef Mat_ Mat2s; +typedef Mat_ Mat3s; +typedef Mat_ Mat4s; + +typedef Mat_ Mat1w; +typedef Mat_ Mat2w; +typedef Mat_ Mat3w; +typedef Mat_ Mat4w; + +typedef Mat_ Mat1i; +typedef Mat_ Mat2i; +typedef Mat_ Mat3i; +typedef Mat_ Mat4i; + +typedef Mat_ Mat1f; +typedef Mat_ Mat2f; +typedef Mat_ Mat3f; +typedef Mat_ Mat4f; + +typedef Mat_ Mat1d; +typedef Mat_ Mat2d; +typedef Mat_ Mat3d; +typedef Mat_ Mat4d; + +/** @todo document */ +class CV_EXPORTS UMat +{ +public: + //! default constructor + UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT); + //! constructs 2D matrix of the specified size and type + // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) + UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + UMat(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + //! constucts 2D matrix and fills it with the specified value _s. + UMat(int rows, int cols, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT); + UMat(Size size, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT); + + //! constructs n-dimensional matrix + UMat(int ndims, const int* sizes, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + UMat(int ndims, const int* sizes, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT); + + //! copy constructor + UMat(const UMat& m); + + //! creates a matrix header for a part of the bigger matrix + UMat(const UMat& m, const Range& rowRange, const Range& colRange=Range::all()); + UMat(const UMat& m, const Rect& roi); + UMat(const UMat& m, const Range* ranges); + //! builds matrix from std::vector with or without copying the data + template explicit UMat(const std::vector<_Tp>& vec, bool copyData=false); + //! builds matrix from cv::Vec; the data is copied by default + template explicit UMat(const Vec<_Tp, n>& vec, bool copyData=true); + //! builds matrix from cv::Matx; the data is copied by default + template explicit UMat(const Matx<_Tp, m, n>& mtx, bool copyData=true); + //! builds matrix from a 2D point + template explicit UMat(const Point_<_Tp>& pt, bool copyData=true); + //! builds matrix from a 3D point + template explicit UMat(const Point3_<_Tp>& pt, bool copyData=true); + //! builds matrix from comma initializer + template explicit UMat(const MatCommaInitializer_<_Tp>& commaInitializer); + + //! destructor - calls release() + ~UMat(); + //! assignment operators + UMat& operator = (const UMat& m); + + Mat getMat(int flags) const; + + //! returns a new matrix header for the specified row + UMat row(int y) const; + //! returns a new matrix header for the specified column + UMat col(int x) const; + //! ... for the specified row span + UMat rowRange(int startrow, int endrow) const; + UMat rowRange(const Range& r) const; + //! ... for the specified column span + UMat colRange(int startcol, int endcol) const; + UMat colRange(const Range& r) const; + //! ... for the specified diagonal + // (d=0 - the main diagonal, + // >0 - a diagonal from the lower half, + // <0 - a diagonal from the upper half) + UMat diag(int d=0) const; + //! constructs a square diagonal matrix which main diagonal is vector "d" + static UMat diag(const UMat& d); + + //! returns deep copy of the matrix, i.e. the data is copied + UMat clone() const; + //! copies the matrix content to "m". + // It calls m.create(this->size(), this->type()). + void copyTo( OutputArray m ) const; + //! copies those matrix elements to "m" that are marked with non-zero mask elements. + void copyTo( OutputArray m, InputArray mask ) const; + //! converts matrix to another datatype with optional scalng. See cvConvertScale. + void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; + + void assignTo( UMat& m, int type=-1 ) const; + + //! sets every matrix element to s + UMat& operator = (const Scalar& s); + //! sets some of the matrix elements to s, according to the mask + UMat& setTo(InputArray value, InputArray mask=noArray()); + //! creates alternative matrix header for the same data, with different + // number of channels and/or different number of rows. see cvReshape. + UMat reshape(int cn, int rows=0) const; + UMat reshape(int cn, int newndims, const int* newsz) const; + + //! matrix transposition by means of matrix expressions + UMat t() const; + //! matrix inversion by means of matrix expressions + UMat inv(int method=DECOMP_LU) const; + //! per-element matrix multiplication by means of matrix expressions + UMat mul(InputArray m, double scale=1) const; + + //! computes dot-product + double dot(InputArray m) const; + + //! Matlab-style matrix initialization + static UMat zeros(int rows, int cols, int type); + static UMat zeros(Size size, int type); + static UMat zeros(int ndims, const int* sz, int type); + static UMat ones(int rows, int cols, int type); + static UMat ones(Size size, int type); + static UMat ones(int ndims, const int* sz, int type); + static UMat eye(int rows, int cols, int type); + static UMat eye(Size size, int type); + + //! allocates new matrix data unless the matrix already has specified size and type. + // previous data is unreferenced if needed. + void create(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + void create(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + void create(int ndims, const int* sizes, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT); + + //! increases the reference counter; use with care to avoid memleaks + void addref(); + //! decreases reference counter; + // deallocates the data when reference counter reaches 0. + void release(); + + //! deallocates the matrix data + void deallocate(); + //! internal use function; properly re-allocates _size, _step arrays + void copySize(const UMat& m); + + //! locates matrix header within a parent matrix. See below + void locateROI( Size& wholeSize, Point& ofs ) const; + //! moves/resizes the current matrix ROI inside the parent matrix. + UMat& adjustROI( int dtop, int dbottom, int dleft, int dright ); + //! extracts a rectangular sub-matrix + // (this is a generalized form of row, rowRange etc.) + UMat operator()( Range rowRange, Range colRange ) const; + UMat operator()( const Rect& roi ) const; + UMat operator()( const Range* ranges ) const; + + //! returns true iff the matrix data is continuous + // (i.e. when there are no gaps between successive rows). + // similar to CV_IS_MAT_CONT(cvmat->type) + bool isContinuous() const; + + //! returns true if the matrix is a submatrix of another matrix + bool isSubmatrix() const; + + //! returns element size in bytes, + // similar to CV_ELEM_SIZE(cvmat->type) + size_t elemSize() const; + //! returns the size of element channel in bytes. + size_t elemSize1() const; + //! returns element type, similar to CV_MAT_TYPE(cvmat->type) + int type() const; + //! returns element type, similar to CV_MAT_DEPTH(cvmat->type) + int depth() const; + //! returns element type, similar to CV_MAT_CN(cvmat->type) + int channels() const; + //! returns step/elemSize1() + size_t step1(int i=0) const; + //! returns true if matrix data is NULL + bool empty() const; + //! returns the total number of matrix elements + size_t total() const; + + //! returns N if the matrix is 1-channel (N x ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise + int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const; + + void* handle(int accessFlags) const; + void ndoffset(size_t* ofs) const; + + enum { MAGIC_VAL = 0x42FF0000, AUTO_STEP = 0, CONTINUOUS_FLAG = CV_MAT_CONT_FLAG, SUBMATRIX_FLAG = CV_SUBMAT_FLAG }; + enum { MAGIC_MASK = 0xFFFF0000, TYPE_MASK = 0x00000FFF, DEPTH_MASK = 7 }; + + /*! includes several bit-fields: + - the magic signature + - continuity flag + - depth + - number of channels + */ + int flags; + //! the matrix dimensionality, >= 2 + int dims; + //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions + int rows, cols; + + //! custom allocator + MatAllocator* allocator; + UMatUsageFlags usageFlags; // usage flags for allocator + //! and the standard allocator + static MatAllocator* getStdAllocator(); + + // black-box container of UMat data + UMatData* u; + + // offset of the submatrix (or 0) + size_t offset; + + MatSize size; + MatStep step; + +protected: +}; + + +/////////////////////////// multi-dimensional sparse matrix ////////////////////////// + +/** @brief The class SparseMat represents multi-dimensional sparse numerical arrays. + +Such a sparse array can store elements of any type that Mat can store. *Sparse* means that only +non-zero elements are stored (though, as a result of operations on a sparse matrix, some of its +stored elements can actually become 0. It is up to you to detect such elements and delete them +using SparseMat::erase ). The non-zero elements are stored in a hash table that grows when it is +filled so that the search time is O(1) in average (regardless of whether element is there or not). +Elements can be accessed using the following methods: +- Query operations (SparseMat::ptr and the higher-level SparseMat::ref, SparseMat::value and + SparseMat::find), for example: + @code + const int dims = 5; + int size[] = {10, 10, 10, 10, 10}; + SparseMat sparse_mat(dims, size, CV_32F); + for(int i = 0; i < 1000; i++) + { + int idx[dims]; + for(int k = 0; k < dims; k++) + idx[k] = rand() + sparse_mat.ref(idx) += 1.f; + } + @endcode +- Sparse matrix iterators. They are similar to MatIterator but different from NAryMatIterator. + That is, the iteration loop is familiar to STL users: + @code + // prints elements of a sparse floating-point matrix + // and the sum of elements. + SparseMatConstIterator_ + it = sparse_mat.begin(), + it_end = sparse_mat.end(); + double s = 0; + int dims = sparse_mat.dims(); + for(; it != it_end; ++it) + { + // print element indices and the element value + const SparseMat::Node* n = it.node(); + printf("("); + for(int i = 0; i < dims; i++) + printf("%d%s", n->idx[i], i < dims-1 ? ", " : ")"); + printf(": %g\n", it.value()); + s += *it; + } + printf("Element sum is %g\n", s); + @endcode + If you run this loop, you will notice that elements are not enumerated in a logical order + (lexicographical, and so on). They come in the same order as they are stored in the hash table + (semi-randomly). You may collect pointers to the nodes and sort them to get the proper ordering. + Note, however, that pointers to the nodes may become invalid when you add more elements to the + matrix. This may happen due to possible buffer reallocation. +- Combination of the above 2 methods when you need to process 2 or more sparse matrices + simultaneously. For example, this is how you can compute unnormalized cross-correlation of the 2 + floating-point sparse matrices: + @code + double cross_corr(const SparseMat& a, const SparseMat& b) + { + const SparseMat *_a = &a, *_b = &b; + // if b contains less elements than a, + // it is faster to iterate through b + if(_a->nzcount() > _b->nzcount()) + std::swap(_a, _b); + SparseMatConstIterator_ it = _a->begin(), + it_end = _a->end(); + double ccorr = 0; + for(; it != it_end; ++it) + { + // take the next element from the first matrix + float avalue = *it; + const Node* anode = it.node(); + // and try to find an element with the same index in the second matrix. + // since the hash value depends only on the element index, + // reuse the hash value stored in the node + float bvalue = _b->value(anode->idx,&anode->hashval); + ccorr += avalue*bvalue; + } + return ccorr; + } + @endcode + */ +class CV_EXPORTS SparseMat +{ +public: + typedef SparseMatIterator iterator; + typedef SparseMatConstIterator const_iterator; + + enum { MAGIC_VAL=0x42FD0000, MAX_DIM=32, HASH_SCALE=0x5bd1e995, HASH_BIT=0x80000000 }; + + //! the sparse matrix header + struct CV_EXPORTS Hdr + { + Hdr(int _dims, const int* _sizes, int _type); + void clear(); + int refcount; + int dims; + int valueOffset; + size_t nodeSize; + size_t nodeCount; + size_t freeList; + std::vector pool; + std::vector hashtab; + int size[MAX_DIM]; + }; + + //! sparse matrix node - element of a hash table + struct CV_EXPORTS Node + { + //! hash value + size_t hashval; + //! index of the next node in the same hash table entry + size_t next; + //! index of the matrix element + int idx[MAX_DIM]; + }; + + /** @brief Various SparseMat constructors. + */ + SparseMat(); + + /** @overload + @param dims Array dimensionality. + @param _sizes Sparce matrix size on all dementions. + @param _type Sparse matrix data type. + */ + SparseMat(int dims, const int* _sizes, int _type); + + /** @overload + @param m Source matrix for copy constructor. If m is dense matrix (ocvMat) then it will be converted + to sparse representation. + */ + SparseMat(const SparseMat& m); + + /** @overload + @param m Source matrix for copy constructor. If m is dense matrix (ocvMat) then it will be converted + to sparse representation. + */ + explicit SparseMat(const Mat& m); + + //! the destructor + ~SparseMat(); + + //! assignment operator. This is O(1) operation, i.e. no data is copied + SparseMat& operator = (const SparseMat& m); + //! equivalent to the corresponding constructor + SparseMat& operator = (const Mat& m); + + //! creates full copy of the matrix + SparseMat clone() const; + + //! copies all the data to the destination matrix. All the previous content of m is erased + void copyTo( SparseMat& m ) const; + //! converts sparse matrix to dense matrix. + void copyTo( Mat& m ) const; + //! multiplies all the matrix elements by the specified scale factor alpha and converts the results to the specified data type + void convertTo( SparseMat& m, int rtype, double alpha=1 ) const; + //! converts sparse matrix to dense n-dim matrix with optional type conversion and scaling. + /*! + @param [out] m - output matrix; if it does not have a proper size or type before the operation, + it is reallocated + @param [in] rtype – desired output matrix type or, rather, the depth since the number of channels + are the same as the input has; if rtype is negative, the output matrix will have the + same type as the input. + @param [in] alpha – optional scale factor + @param [in] beta – optional delta added to the scaled values + */ + void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const; + + // not used now + void assignTo( SparseMat& m, int type=-1 ) const; + + //! reallocates sparse matrix. + /*! + If the matrix already had the proper size and type, + it is simply cleared with clear(), otherwise, + the old matrix is released (using release()) and the new one is allocated. + */ + void create(int dims, const int* _sizes, int _type); + //! sets all the sparse matrix elements to 0, which means clearing the hash table. + void clear(); + //! manually increments the reference counter to the header. + void addref(); + // decrements the header reference counter. When the counter reaches 0, the header and all the underlying data are deallocated. + void release(); + + //! converts sparse matrix to the old-style representation; all the elements are copied. + //operator CvSparseMat*() const; + //! returns the size of each element in bytes (not including the overhead - the space occupied by SparseMat::Node elements) + size_t elemSize() const; + //! returns elemSize()/channels() + size_t elemSize1() const; + + //! returns type of sparse matrix elements + int type() const; + //! returns the depth of sparse matrix elements + int depth() const; + //! returns the number of channels + int channels() const; + + //! returns the array of sizes, or NULL if the matrix is not allocated + const int* size() const; + //! returns the size of i-th matrix dimension (or 0) + int size(int i) const; + //! returns the matrix dimensionality + int dims() const; + //! returns the number of non-zero elements (=the number of hash table nodes) + size_t nzcount() const; + + //! computes the element hash value (1D case) + size_t hash(int i0) const; + //! computes the element hash value (2D case) + size_t hash(int i0, int i1) const; + //! computes the element hash value (3D case) + size_t hash(int i0, int i1, int i2) const; + //! computes the element hash value (nD case) + size_t hash(const int* idx) const; + + //!@{ + /*! + specialized variants for 1D, 2D, 3D cases and the generic_type one for n-D case. + return pointer to the matrix element. + - if the element is there (it's non-zero), the pointer to it is returned + - if it's not there and createMissing=false, NULL pointer is returned + - if it's not there and createMissing=true, then the new element + is created and initialized with 0. Pointer to it is returned + - if the optional hashval pointer is not NULL, the element hash value is + not computed, but *hashval is taken instead. + */ + //! returns pointer to the specified element (1D case) + uchar* ptr(int i0, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (2D case) + uchar* ptr(int i0, int i1, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (3D case) + uchar* ptr(int i0, int i1, int i2, bool createMissing, size_t* hashval=0); + //! returns pointer to the specified element (nD case) + uchar* ptr(const int* idx, bool createMissing, size_t* hashval=0); + //!@} + + //!@{ + /*! + return read-write reference to the specified sparse matrix element. + + `ref<_Tp>(i0,...[,hashval])` is equivalent to `*(_Tp*)ptr(i0,...,true[,hashval])`. + The methods always return a valid reference. + If the element did not exist, it is created and initialiazed with 0. + */ + //! returns reference to the specified element (1D case) + template _Tp& ref(int i0, size_t* hashval=0); + //! returns reference to the specified element (2D case) + template _Tp& ref(int i0, int i1, size_t* hashval=0); + //! returns reference to the specified element (3D case) + template _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); + //! returns reference to the specified element (nD case) + template _Tp& ref(const int* idx, size_t* hashval=0); + //!@} + + //!@{ + /*! + return value of the specified sparse matrix element. + + `value<_Tp>(i0,...[,hashval])` is equivalent to + @code + { const _Tp* p = find<_Tp>(i0,...[,hashval]); return p ? *p : _Tp(); } + @endcode + + That is, if the element did not exist, the methods return 0. + */ + //! returns value of the specified element (1D case) + template _Tp value(int i0, size_t* hashval=0) const; + //! returns value of the specified element (2D case) + template _Tp value(int i0, int i1, size_t* hashval=0) const; + //! returns value of the specified element (3D case) + template _Tp value(int i0, int i1, int i2, size_t* hashval=0) const; + //! returns value of the specified element (nD case) + template _Tp value(const int* idx, size_t* hashval=0) const; + //!@} + + //!@{ + /*! + Return pointer to the specified sparse matrix element if it exists + + `find<_Tp>(i0,...[,hashval])` is equivalent to `(_const Tp*)ptr(i0,...false[,hashval])`. + + If the specified element does not exist, the methods return NULL. + */ + //! returns pointer to the specified element (1D case) + template const _Tp* find(int i0, size_t* hashval=0) const; + //! returns pointer to the specified element (2D case) + template const _Tp* find(int i0, int i1, size_t* hashval=0) const; + //! returns pointer to the specified element (3D case) + template const _Tp* find(int i0, int i1, int i2, size_t* hashval=0) const; + //! returns pointer to the specified element (nD case) + template const _Tp* find(const int* idx, size_t* hashval=0) const; + //!@} + + //! erases the specified element (2D case) + void erase(int i0, int i1, size_t* hashval=0); + //! erases the specified element (3D case) + void erase(int i0, int i1, int i2, size_t* hashval=0); + //! erases the specified element (nD case) + void erase(const int* idx, size_t* hashval=0); + + //!@{ + /*! + return the sparse matrix iterator pointing to the first sparse matrix element + */ + //! returns the sparse matrix iterator at the matrix beginning + SparseMatIterator begin(); + //! returns the sparse matrix iterator at the matrix beginning + template SparseMatIterator_<_Tp> begin(); + //! returns the read-only sparse matrix iterator at the matrix beginning + SparseMatConstIterator begin() const; + //! returns the read-only sparse matrix iterator at the matrix beginning + template SparseMatConstIterator_<_Tp> begin() const; + //!@} + /*! + return the sparse matrix iterator pointing to the element following the last sparse matrix element + */ + //! returns the sparse matrix iterator at the matrix end + SparseMatIterator end(); + //! returns the read-only sparse matrix iterator at the matrix end + SparseMatConstIterator end() const; + //! returns the typed sparse matrix iterator at the matrix end + template SparseMatIterator_<_Tp> end(); + //! returns the typed read-only sparse matrix iterator at the matrix end + template SparseMatConstIterator_<_Tp> end() const; + + //! returns the value stored in the sparse martix node + template _Tp& value(Node* n); + //! returns the value stored in the sparse martix node + template const _Tp& value(const Node* n) const; + + ////////////// some internal-use methods /////////////// + Node* node(size_t nidx); + const Node* node(size_t nidx) const; + + uchar* newNode(const int* idx, size_t hashval); + void removeNode(size_t hidx, size_t nidx, size_t previdx); + void resizeHashTab(size_t newsize); + + int flags; + Hdr* hdr; +}; + + + +///////////////////////////////// SparseMat_<_Tp> //////////////////////////////////// + +/** @brief Template sparse n-dimensional array class derived from SparseMat + +SparseMat_ is a thin wrapper on top of SparseMat created in the same way as Mat_ . It simplifies +notation of some operations: +@code + int sz[] = {10, 20, 30}; + SparseMat_ M(3, sz); + ... + M.ref(1, 2, 3) = M(4, 5, 6) + M(7, 8, 9); +@endcode + */ +template class SparseMat_ : public SparseMat +{ +public: + typedef SparseMatIterator_<_Tp> iterator; + typedef SparseMatConstIterator_<_Tp> const_iterator; + + //! the default constructor + SparseMat_(); + //! the full constructor equivelent to SparseMat(dims, _sizes, DataType<_Tp>::type) + SparseMat_(int dims, const int* _sizes); + //! the copy constructor. If DataType<_Tp>.type != m.type(), the m elements are converted + SparseMat_(const SparseMat& m); + //! the copy constructor. This is O(1) operation - no data is copied + SparseMat_(const SparseMat_& m); + //! converts dense matrix to the sparse form + SparseMat_(const Mat& m); + //! converts the old-style sparse matrix to the C++ class. All the elements are copied + //SparseMat_(const CvSparseMat* m); + //! the assignment operator. If DataType<_Tp>.type != m.type(), the m elements are converted + SparseMat_& operator = (const SparseMat& m); + //! the assignment operator. This is O(1) operation - no data is copied + SparseMat_& operator = (const SparseMat_& m); + //! converts dense matrix to the sparse form + SparseMat_& operator = (const Mat& m); + + //! makes full copy of the matrix. All the elements are duplicated + SparseMat_ clone() const; + //! equivalent to cv::SparseMat::create(dims, _sizes, DataType<_Tp>::type) + void create(int dims, const int* _sizes); + //! converts sparse matrix to the old-style CvSparseMat. All the elements are copied + //operator CvSparseMat*() const; + + //! returns type of the matrix elements + int type() const; + //! returns depth of the matrix elements + int depth() const; + //! returns the number of channels in each matrix element + int channels() const; + + //! equivalent to SparseMat::ref<_Tp>(i0, hashval) + _Tp& ref(int i0, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(i0, i1, hashval) + _Tp& ref(int i0, int i1, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(i0, i1, i2, hashval) + _Tp& ref(int i0, int i1, int i2, size_t* hashval=0); + //! equivalent to SparseMat::ref<_Tp>(idx, hashval) + _Tp& ref(const int* idx, size_t* hashval=0); + + //! equivalent to SparseMat::value<_Tp>(i0, hashval) + _Tp operator()(int i0, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(i0, i1, hashval) + _Tp operator()(int i0, int i1, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(i0, i1, i2, hashval) + _Tp operator()(int i0, int i1, int i2, size_t* hashval=0) const; + //! equivalent to SparseMat::value<_Tp>(idx, hashval) + _Tp operator()(const int* idx, size_t* hashval=0) const; + + //! returns sparse matrix iterator pointing to the first sparse matrix element + SparseMatIterator_<_Tp> begin(); + //! returns read-only sparse matrix iterator pointing to the first sparse matrix element + SparseMatConstIterator_<_Tp> begin() const; + //! returns sparse matrix iterator pointing to the element following the last sparse matrix element + SparseMatIterator_<_Tp> end(); + //! returns read-only sparse matrix iterator pointing to the element following the last sparse matrix element + SparseMatConstIterator_<_Tp> end() const; +}; + + + +////////////////////////////////// MatConstIterator ////////////////////////////////// + +class CV_EXPORTS MatConstIterator +{ +public: + typedef uchar* value_type; + typedef ptrdiff_t difference_type; + typedef const uchar** pointer; + typedef uchar* reference; + +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif + + //! default constructor + MatConstIterator(); + //! constructor that sets the iterator to the beginning of the matrix + MatConstIterator(const Mat* _m); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, int _row, int _col=0); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator(const Mat* _m, const int* _idx); + //! copy constructor + MatConstIterator(const MatConstIterator& it); + + //! copy operator + MatConstIterator& operator = (const MatConstIterator& it); + //! returns the current matrix element + const uchar* operator *() const; + //! returns the i-th matrix element, relative to the current + const uchar* operator [](ptrdiff_t i) const; + + //! shifts the iterator forward by the specified number of elements + MatConstIterator& operator += (ptrdiff_t ofs); + //! shifts the iterator backward by the specified number of elements + MatConstIterator& operator -= (ptrdiff_t ofs); + //! decrements the iterator + MatConstIterator& operator --(); + //! decrements the iterator + MatConstIterator operator --(int); + //! increments the iterator + MatConstIterator& operator ++(); + //! increments the iterator + MatConstIterator operator ++(int); + //! returns the current iterator position + Point pos() const; + //! returns the current iterator position + void pos(int* _idx) const; + + ptrdiff_t lpos() const; + void seek(ptrdiff_t ofs, bool relative = false); + void seek(const int* _idx, bool relative = false); + + const Mat* m; + size_t elemSize; + const uchar* ptr; + const uchar* sliceStart; + const uchar* sliceEnd; +}; + + + +////////////////////////////////// MatConstIterator_ ///////////////////////////////// + +/** @brief Matrix read-only iterator + */ +template +class MatConstIterator_ : public MatConstIterator +{ +public: + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif + + //! default constructor + MatConstIterator_(); + //! constructor that sets the iterator to the beginning of the matrix + MatConstIterator_(const Mat_<_Tp>* _m); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col=0); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator_(const Mat_<_Tp>* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatConstIterator_(const Mat_<_Tp>* _m, const int* _idx); + //! copy constructor + MatConstIterator_(const MatConstIterator_& it); + + //! copy operator + MatConstIterator_& operator = (const MatConstIterator_& it); + //! returns the current matrix element + _Tp operator *() const; + //! returns the i-th matrix element, relative to the current + _Tp operator [](ptrdiff_t i) const; + + //! shifts the iterator forward by the specified number of elements + MatConstIterator_& operator += (ptrdiff_t ofs); + //! shifts the iterator backward by the specified number of elements + MatConstIterator_& operator -= (ptrdiff_t ofs); + //! decrements the iterator + MatConstIterator_& operator --(); + //! decrements the iterator + MatConstIterator_ operator --(int); + //! increments the iterator + MatConstIterator_& operator ++(); + //! increments the iterator + MatConstIterator_ operator ++(int); + //! returns the current iterator position + Point pos() const; +}; + + + +//////////////////////////////////// MatIterator_ //////////////////////////////////// + +/** @brief Matrix read-write iterator +*/ +template +class MatIterator_ : public MatConstIterator_<_Tp> +{ +public: + typedef _Tp* pointer; + typedef _Tp& reference; + +#ifndef OPENCV_NOSTL + typedef std::random_access_iterator_tag iterator_category; +#endif + + //! the default constructor + MatIterator_(); + //! constructor that sets the iterator to the beginning of the matrix + MatIterator_(Mat_<_Tp>* _m); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(Mat_<_Tp>* _m, int _row, int _col=0); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(Mat_<_Tp>* _m, Point _pt); + //! constructor that sets the iterator to the specified element of the matrix + MatIterator_(Mat_<_Tp>* _m, const int* _idx); + //! copy constructor + MatIterator_(const MatIterator_& it); + //! copy operator + MatIterator_& operator = (const MatIterator_<_Tp>& it ); + + //! returns the current matrix element + _Tp& operator *() const; + //! returns the i-th matrix element, relative to the current + _Tp& operator [](ptrdiff_t i) const; + + //! shifts the iterator forward by the specified number of elements + MatIterator_& operator += (ptrdiff_t ofs); + //! shifts the iterator backward by the specified number of elements + MatIterator_& operator -= (ptrdiff_t ofs); + //! decrements the iterator + MatIterator_& operator --(); + //! decrements the iterator + MatIterator_ operator --(int); + //! increments the iterator + MatIterator_& operator ++(); + //! increments the iterator + MatIterator_ operator ++(int); +}; + + + +/////////////////////////////// SparseMatConstIterator /////////////////////////////// + +/** @brief Read-Only Sparse Matrix Iterator. + + Here is how to use the iterator to compute the sum of floating-point sparse matrix elements: + + \code + SparseMatConstIterator it = m.begin(), it_end = m.end(); + double s = 0; + CV_Assert( m.type() == CV_32F ); + for( ; it != it_end; ++it ) + s += it.value(); + \endcode +*/ +class CV_EXPORTS SparseMatConstIterator +{ +public: + //! the default constructor + SparseMatConstIterator(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatConstIterator(const SparseMat* _m); + //! the copy constructor + SparseMatConstIterator(const SparseMatConstIterator& it); + + //! the assignment operator + SparseMatConstIterator& operator = (const SparseMatConstIterator& it); + + //! template method returning the current matrix element + template const _Tp& value() const; + //! returns the current node of the sparse matrix. it.node->idx is the current element index + const SparseMat::Node* node() const; + + //! moves iterator to the previous element + SparseMatConstIterator& operator --(); + //! moves iterator to the previous element + SparseMatConstIterator operator --(int); + //! moves iterator to the next element + SparseMatConstIterator& operator ++(); + //! moves iterator to the next element + SparseMatConstIterator operator ++(int); + + //! moves iterator to the element after the last element + void seekEnd(); + + const SparseMat* m; + size_t hashidx; + uchar* ptr; +}; + + + +////////////////////////////////// SparseMatIterator ///////////////////////////////// + +/** @brief Read-write Sparse Matrix Iterator + + The class is similar to cv::SparseMatConstIterator, + but can be used for in-place modification of the matrix elements. +*/ +class CV_EXPORTS SparseMatIterator : public SparseMatConstIterator +{ +public: + //! the default constructor + SparseMatIterator(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatIterator(SparseMat* _m); + //! the full constructor setting the iterator to the specified sparse matrix element + SparseMatIterator(SparseMat* _m, const int* idx); + //! the copy constructor + SparseMatIterator(const SparseMatIterator& it); + + //! the assignment operator + SparseMatIterator& operator = (const SparseMatIterator& it); + //! returns read-write reference to the current sparse matrix element + template _Tp& value() const; + //! returns pointer to the current sparse matrix node. it.node->idx is the index of the current element (do not modify it!) + SparseMat::Node* node() const; + + //! moves iterator to the next element + SparseMatIterator& operator ++(); + //! moves iterator to the next element + SparseMatIterator operator ++(int); +}; + + + +/////////////////////////////// SparseMatConstIterator_ ////////////////////////////// + +/** @brief Template Read-Only Sparse Matrix Iterator Class. + + This is the derived from SparseMatConstIterator class that + introduces more convenient operator *() for accessing the current element. +*/ +template class SparseMatConstIterator_ : public SparseMatConstIterator +{ +public: + +#ifndef OPENCV_NOSTL + typedef std::forward_iterator_tag iterator_category; +#endif + + //! the default constructor + SparseMatConstIterator_(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatConstIterator_(const SparseMat_<_Tp>* _m); + SparseMatConstIterator_(const SparseMat* _m); + //! the copy constructor + SparseMatConstIterator_(const SparseMatConstIterator_& it); + + //! the assignment operator + SparseMatConstIterator_& operator = (const SparseMatConstIterator_& it); + //! the element access operator + const _Tp& operator *() const; + + //! moves iterator to the next element + SparseMatConstIterator_& operator ++(); + //! moves iterator to the next element + SparseMatConstIterator_ operator ++(int); +}; + + + +///////////////////////////////// SparseMatIterator_ ///////////////////////////////// + +/** @brief Template Read-Write Sparse Matrix Iterator Class. + + This is the derived from cv::SparseMatConstIterator_ class that + introduces more convenient operator *() for accessing the current element. +*/ +template class SparseMatIterator_ : public SparseMatConstIterator_<_Tp> +{ +public: + +#ifndef OPENCV_NOSTL + typedef std::forward_iterator_tag iterator_category; +#endif + + //! the default constructor + SparseMatIterator_(); + //! the full constructor setting the iterator to the first sparse matrix element + SparseMatIterator_(SparseMat_<_Tp>* _m); + SparseMatIterator_(SparseMat* _m); + //! the copy constructor + SparseMatIterator_(const SparseMatIterator_& it); + + //! the assignment operator + SparseMatIterator_& operator = (const SparseMatIterator_& it); + //! returns the reference to the current element + _Tp& operator *() const; + + //! moves the iterator to the next element + SparseMatIterator_& operator ++(); + //! moves the iterator to the next element + SparseMatIterator_ operator ++(int); +}; + + + +/////////////////////////////////// NAryMatIterator ////////////////////////////////// + +/** @brief n-ary multi-dimensional array iterator. + +Use the class to implement unary, binary, and, generally, n-ary element-wise operations on +multi-dimensional arrays. Some of the arguments of an n-ary function may be continuous arrays, some +may be not. It is possible to use conventional MatIterator 's for each array but incrementing all of +the iterators after each small operations may be a big overhead. In this case consider using +NAryMatIterator to iterate through several matrices simultaneously as long as they have the same +geometry (dimensionality and all the dimension sizes are the same). On each iteration `it.planes[0]`, +`it.planes[1]`,... will be the slices of the corresponding matrices. + +The example below illustrates how you can compute a normalized and threshold 3D color histogram: +@code + void computeNormalizedColorHist(const Mat& image, Mat& hist, int N, double minProb) + { + const int histSize[] = {N, N, N}; + + // make sure that the histogram has a proper size and type + hist.create(3, histSize, CV_32F); + + // and clear it + hist = Scalar(0); + + // the loop below assumes that the image + // is a 8-bit 3-channel. check it. + CV_Assert(image.type() == CV_8UC3); + MatConstIterator_ it = image.begin(), + it_end = image.end(); + for( ; it != it_end; ++it ) + { + const Vec3b& pix = *it; + hist.at(pix[0]*N/256, pix[1]*N/256, pix[2]*N/256) += 1.f; + } + + minProb *= image.rows*image.cols; + Mat plane; + NAryMatIterator it(&hist, &plane, 1); + double s = 0; + // iterate through the matrix. on each iteration + // it.planes[*] (of type Mat) will be set to the current plane. + for(int p = 0; p < it.nplanes; p++, ++it) + { + threshold(it.planes[0], it.planes[0], minProb, 0, THRESH_TOZERO); + s += sum(it.planes[0])[0]; + } + + s = 1./s; + it = NAryMatIterator(&hist, &plane, 1); + for(int p = 0; p < it.nplanes; p++, ++it) + it.planes[0] *= s; + } +@endcode + */ +class CV_EXPORTS NAryMatIterator +{ +public: + //! the default constructor + NAryMatIterator(); + //! the full constructor taking arbitrary number of n-dim matrices + NAryMatIterator(const Mat** arrays, uchar** ptrs, int narrays=-1); + //! the full constructor taking arbitrary number of n-dim matrices + NAryMatIterator(const Mat** arrays, Mat* planes, int narrays=-1); + //! the separate iterator initialization method + void init(const Mat** arrays, Mat* planes, uchar** ptrs, int narrays=-1); + + //! proceeds to the next plane of every iterated matrix + NAryMatIterator& operator ++(); + //! proceeds to the next plane of every iterated matrix (postfix increment operator) + NAryMatIterator operator ++(int); + + //! the iterated arrays + const Mat** arrays; + //! the current planes + Mat* planes; + //! data pointers + uchar** ptrs; + //! the number of arrays + int narrays; + //! the number of hyper-planes that the iterator steps through + size_t nplanes; + //! the size of each segment (in elements) + size_t size; +protected: + int iterdepth; + size_t idx; +}; + + + +///////////////////////////////// Matrix Expressions ///////////////////////////////// + +class CV_EXPORTS MatOp +{ +public: + MatOp(); + virtual ~MatOp(); + + virtual bool elementWise(const MatExpr& expr) const; + virtual void assign(const MatExpr& expr, Mat& m, int type=-1) const = 0; + virtual void roi(const MatExpr& expr, const Range& rowRange, + const Range& colRange, MatExpr& res) const; + virtual void diag(const MatExpr& expr, int d, MatExpr& res) const; + virtual void augAssignAdd(const MatExpr& expr, Mat& m) const; + virtual void augAssignSubtract(const MatExpr& expr, Mat& m) const; + virtual void augAssignMultiply(const MatExpr& expr, Mat& m) const; + virtual void augAssignDivide(const MatExpr& expr, Mat& m) const; + virtual void augAssignAnd(const MatExpr& expr, Mat& m) const; + virtual void augAssignOr(const MatExpr& expr, Mat& m) const; + virtual void augAssignXor(const MatExpr& expr, Mat& m) const; + + virtual void add(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const; + virtual void add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const; + + virtual void subtract(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const; + virtual void subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const; + + virtual void multiply(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res, double scale=1) const; + virtual void multiply(const MatExpr& expr1, double s, MatExpr& res) const; + + virtual void divide(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res, double scale=1) const; + virtual void divide(double s, const MatExpr& expr, MatExpr& res) const; + + virtual void abs(const MatExpr& expr, MatExpr& res) const; + + virtual void transpose(const MatExpr& expr, MatExpr& res) const; + virtual void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const; + virtual void invert(const MatExpr& expr, int method, MatExpr& res) const; + + virtual Size size(const MatExpr& expr) const; + virtual int type(const MatExpr& expr) const; +}; + +/** @brief Matrix expression representation +@anchor MatrixExpressions +This is a list of implemented matrix operations that can be combined in arbitrary complex +expressions (here A, B stand for matrices ( Mat ), s for a scalar ( Scalar ), alpha for a +real-valued scalar ( double )): +- Addition, subtraction, negation: `A+B`, `A-B`, `A+s`, `A-s`, `s+A`, `s-A`, `-A` +- Scaling: `A*alpha` +- Per-element multiplication and division: `A.mul(B)`, `A/B`, `alpha/A` +- Matrix multiplication: `A*B` +- Transposition: `A.t()` (means AT) +- Matrix inversion and pseudo-inversion, solving linear systems and least-squares problems: + `A.inv([method]) (~ A-1)`, `A.inv([method])*B (~ X: AX=B)` +- Comparison: `A cmpop B`, `A cmpop alpha`, `alpha cmpop A`, where *cmpop* is one of + `>`, `>=`, `==`, `!=`, `<=`, `<`. The result of comparison is an 8-bit single channel mask whose + elements are set to 255 (if the particular element or pair of elements satisfy the condition) or + 0. +- Bitwise logical operations: `A logicop B`, `A logicop s`, `s logicop A`, `~A`, where *logicop* is one of + `&`, `|`, `^`. +- Element-wise minimum and maximum: `min(A, B)`, `min(A, alpha)`, `max(A, B)`, `max(A, alpha)` +- Element-wise absolute value: `abs(A)` +- Cross-product, dot-product: `A.cross(B)`, `A.dot(B)` +- Any function of matrix or matrices and scalars that returns a matrix or a scalar, such as norm, + mean, sum, countNonZero, trace, determinant, repeat, and others. +- Matrix initializers ( Mat::eye(), Mat::zeros(), Mat::ones() ), matrix comma-separated + initializers, matrix constructors and operators that extract sub-matrices (see Mat description). +- Mat_() constructors to cast the result to the proper type. +@note Comma-separated initializers and probably some other operations may require additional +explicit Mat() or Mat_() constructor calls to resolve a possible ambiguity. + +Here are examples of matrix expressions: +@code + // compute pseudo-inverse of A, equivalent to A.inv(DECOMP_SVD) + SVD svd(A); + Mat pinvA = svd.vt.t()*Mat::diag(1./svd.w)*svd.u.t(); + + // compute the new vector of parameters in the Levenberg-Marquardt algorithm + x -= (A.t()*A + lambda*Mat::eye(A.cols,A.cols,A.type())).inv(DECOMP_CHOLESKY)*(A.t()*err); + + // sharpen image using "unsharp mask" algorithm + Mat blurred; double sigma = 1, threshold = 5, amount = 1; + GaussianBlur(img, blurred, Size(), sigma, sigma); + Mat lowConstrastMask = abs(img - blurred) < threshold; + Mat sharpened = img*(1+amount) + blurred*(-amount); + img.copyTo(sharpened, lowContrastMask); +@endcode +*/ +class CV_EXPORTS MatExpr +{ +public: + MatExpr(); + explicit MatExpr(const Mat& m); + + MatExpr(const MatOp* _op, int _flags, const Mat& _a = Mat(), const Mat& _b = Mat(), + const Mat& _c = Mat(), double _alpha = 1, double _beta = 1, const Scalar& _s = Scalar()); + + operator Mat() const; + template operator Mat_<_Tp>() const; + + Size size() const; + int type() const; + + MatExpr row(int y) const; + MatExpr col(int x) const; + MatExpr diag(int d = 0) const; + MatExpr operator()( const Range& rowRange, const Range& colRange ) const; + MatExpr operator()( const Rect& roi ) const; + + MatExpr t() const; + MatExpr inv(int method = DECOMP_LU) const; + MatExpr mul(const MatExpr& e, double scale=1) const; + MatExpr mul(const Mat& m, double scale=1) const; + + Mat cross(const Mat& m) const; + double dot(const Mat& m) const; + + const MatOp* op; + int flags; + + Mat a, b, c; + double alpha, beta; + Scalar s; +}; + +//! @} core_basic + +//! @relates cv::MatExpr +//! @{ +CV_EXPORTS MatExpr operator + (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator + (const Mat& a, const Scalar& s); +CV_EXPORTS MatExpr operator + (const Scalar& s, const Mat& a); +CV_EXPORTS MatExpr operator + (const MatExpr& e, const Mat& m); +CV_EXPORTS MatExpr operator + (const Mat& m, const MatExpr& e); +CV_EXPORTS MatExpr operator + (const MatExpr& e, const Scalar& s); +CV_EXPORTS MatExpr operator + (const Scalar& s, const MatExpr& e); +CV_EXPORTS MatExpr operator + (const MatExpr& e1, const MatExpr& e2); + +CV_EXPORTS MatExpr operator - (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator - (const Mat& a, const Scalar& s); +CV_EXPORTS MatExpr operator - (const Scalar& s, const Mat& a); +CV_EXPORTS MatExpr operator - (const MatExpr& e, const Mat& m); +CV_EXPORTS MatExpr operator - (const Mat& m, const MatExpr& e); +CV_EXPORTS MatExpr operator - (const MatExpr& e, const Scalar& s); +CV_EXPORTS MatExpr operator - (const Scalar& s, const MatExpr& e); +CV_EXPORTS MatExpr operator - (const MatExpr& e1, const MatExpr& e2); + +CV_EXPORTS MatExpr operator - (const Mat& m); +CV_EXPORTS MatExpr operator - (const MatExpr& e); + +CV_EXPORTS MatExpr operator * (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator * (const Mat& a, double s); +CV_EXPORTS MatExpr operator * (double s, const Mat& a); +CV_EXPORTS MatExpr operator * (const MatExpr& e, const Mat& m); +CV_EXPORTS MatExpr operator * (const Mat& m, const MatExpr& e); +CV_EXPORTS MatExpr operator * (const MatExpr& e, double s); +CV_EXPORTS MatExpr operator * (double s, const MatExpr& e); +CV_EXPORTS MatExpr operator * (const MatExpr& e1, const MatExpr& e2); + +CV_EXPORTS MatExpr operator / (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator / (const Mat& a, double s); +CV_EXPORTS MatExpr operator / (double s, const Mat& a); +CV_EXPORTS MatExpr operator / (const MatExpr& e, const Mat& m); +CV_EXPORTS MatExpr operator / (const Mat& m, const MatExpr& e); +CV_EXPORTS MatExpr operator / (const MatExpr& e, double s); +CV_EXPORTS MatExpr operator / (double s, const MatExpr& e); +CV_EXPORTS MatExpr operator / (const MatExpr& e1, const MatExpr& e2); + +CV_EXPORTS MatExpr operator < (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator < (const Mat& a, double s); +CV_EXPORTS MatExpr operator < (double s, const Mat& a); + +CV_EXPORTS MatExpr operator <= (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator <= (const Mat& a, double s); +CV_EXPORTS MatExpr operator <= (double s, const Mat& a); + +CV_EXPORTS MatExpr operator == (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator == (const Mat& a, double s); +CV_EXPORTS MatExpr operator == (double s, const Mat& a); + +CV_EXPORTS MatExpr operator != (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator != (const Mat& a, double s); +CV_EXPORTS MatExpr operator != (double s, const Mat& a); + +CV_EXPORTS MatExpr operator >= (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator >= (const Mat& a, double s); +CV_EXPORTS MatExpr operator >= (double s, const Mat& a); + +CV_EXPORTS MatExpr operator > (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator > (const Mat& a, double s); +CV_EXPORTS MatExpr operator > (double s, const Mat& a); + +CV_EXPORTS MatExpr operator & (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator & (const Mat& a, const Scalar& s); +CV_EXPORTS MatExpr operator & (const Scalar& s, const Mat& a); + +CV_EXPORTS MatExpr operator | (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator | (const Mat& a, const Scalar& s); +CV_EXPORTS MatExpr operator | (const Scalar& s, const Mat& a); + +CV_EXPORTS MatExpr operator ^ (const Mat& a, const Mat& b); +CV_EXPORTS MatExpr operator ^ (const Mat& a, const Scalar& s); +CV_EXPORTS MatExpr operator ^ (const Scalar& s, const Mat& a); + +CV_EXPORTS MatExpr operator ~(const Mat& m); + +CV_EXPORTS MatExpr min(const Mat& a, const Mat& b); +CV_EXPORTS MatExpr min(const Mat& a, double s); +CV_EXPORTS MatExpr min(double s, const Mat& a); + +CV_EXPORTS MatExpr max(const Mat& a, const Mat& b); +CV_EXPORTS MatExpr max(const Mat& a, double s); +CV_EXPORTS MatExpr max(double s, const Mat& a); + +/** @brief Calculates an absolute value of each matrix element. + +abs is a meta-function that is expanded to one of absdiff or convertScaleAbs forms: +- C = abs(A-B) is equivalent to `absdiff(A, B, C)` +- C = abs(A) is equivalent to `absdiff(A, Scalar::all(0), C)` +- C = `Mat_ >(abs(A*alpha + beta))` is equivalent to `convertScaleAbs(A, C, alpha, +beta)` + +The output matrix has the same size and the same type as the input one except for the last case, +where C is depth=CV_8U . +@param m matrix. +@sa @ref MatrixExpressions, absdiff, convertScaleAbs + */ +CV_EXPORTS MatExpr abs(const Mat& m); +/** @overload +@param e matrix expression. +*/ +CV_EXPORTS MatExpr abs(const MatExpr& e); +//! @} relates cv::MatExpr + +} // cv + +#include "opencv2/core/mat.inl.hpp" + +#endif // __OPENCV_CORE_MAT_HPP__ diff --git a/include/opencv2/core/mat.inl.hpp b/include/opencv2/core/mat.inl.hpp new file mode 100644 index 0000000..3779b83 --- /dev/null +++ b/include/opencv2/core/mat.inl.hpp @@ -0,0 +1,3436 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_MATRIX_OPERATIONS_HPP__ +#define __OPENCV_CORE_MATRIX_OPERATIONS_HPP__ + +#ifndef __cplusplus +# error mat.inl.hpp header must be compiled as C++ +#endif + +namespace cv +{ + +//! @cond IGNORED + +//////////////////////// Input/Output Arrays //////////////////////// + +inline void _InputArray::init(int _flags, const void* _obj) +{ flags = _flags; obj = (void*)_obj; } + +inline void _InputArray::init(int _flags, const void* _obj, Size _sz) +{ flags = _flags; obj = (void*)_obj; sz = _sz; } + +inline void* _InputArray::getObj() const { return obj; } +inline int _InputArray::getFlags() const { return flags; } +inline Size _InputArray::getSz() const { return sz; } + +inline _InputArray::_InputArray() { init(NONE, 0); } +inline _InputArray::_InputArray(int _flags, void* _obj) { init(_flags, _obj); } +inline _InputArray::_InputArray(const Mat& m) { init(MAT+ACCESS_READ, &m); } +inline _InputArray::_InputArray(const std::vector& vec) { init(STD_VECTOR_MAT+ACCESS_READ, &vec); } +inline _InputArray::_InputArray(const UMat& m) { init(UMAT+ACCESS_READ, &m); } +inline _InputArray::_InputArray(const std::vector& vec) { init(STD_VECTOR_UMAT+ACCESS_READ, &vec); } + +template inline +_InputArray::_InputArray(const std::vector<_Tp>& vec) +{ init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_READ, &vec); } + +inline +_InputArray::_InputArray(const std::vector& vec) +{ init(FIXED_TYPE + STD_BOOL_VECTOR + DataType::type + ACCESS_READ, &vec); } + +template inline +_InputArray::_InputArray(const std::vector >& vec) +{ init(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_READ, &vec); } + +template inline +_InputArray::_InputArray(const std::vector >& vec) +{ init(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_READ, &vec); } + +template inline +_InputArray::_InputArray(const Matx<_Tp, m, n>& mtx) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_READ, &mtx, Size(n, m)); } + +template inline +_InputArray::_InputArray(const _Tp* vec, int n) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_READ, vec, Size(n, 1)); } + +template inline +_InputArray::_InputArray(const Mat_<_Tp>& m) +{ init(FIXED_TYPE + MAT + DataType<_Tp>::type + ACCESS_READ, &m); } + +inline _InputArray::_InputArray(const double& val) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F + ACCESS_READ, &val, Size(1,1)); } + +inline _InputArray::_InputArray(const MatExpr& expr) +{ init(FIXED_TYPE + FIXED_SIZE + EXPR + ACCESS_READ, &expr); } + +inline _InputArray::_InputArray(const cuda::GpuMat& d_mat) +{ init(CUDA_GPU_MAT + ACCESS_READ, &d_mat); } + +inline _InputArray::_InputArray(const ogl::Buffer& buf) +{ init(OPENGL_BUFFER + ACCESS_READ, &buf); } + +inline _InputArray::_InputArray(const cuda::HostMem& cuda_mem) +{ init(CUDA_HOST_MEM + ACCESS_READ, &cuda_mem); } + +inline _InputArray::~_InputArray() {} + +inline Mat _InputArray::getMat(int i) const +{ + if( kind() == MAT && i < 0 ) + return *(const Mat*)obj; + return getMat_(i); +} + +inline bool _InputArray::isMat() const { return kind() == _InputArray::MAT; } +inline bool _InputArray::isUMat() const { return kind() == _InputArray::UMAT; } +inline bool _InputArray::isMatVector() const { return kind() == _InputArray::STD_VECTOR_MAT; } +inline bool _InputArray::isUMatVector() const { return kind() == _InputArray::STD_VECTOR_UMAT; } +inline bool _InputArray::isMatx() const { return kind() == _InputArray::MATX; } + +//////////////////////////////////////////////////////////////////////////////////////// + +inline _OutputArray::_OutputArray() { init(ACCESS_WRITE, 0); } +inline _OutputArray::_OutputArray(int _flags, void* _obj) { init(_flags|ACCESS_WRITE, _obj); } +inline _OutputArray::_OutputArray(Mat& m) { init(MAT+ACCESS_WRITE, &m); } +inline _OutputArray::_OutputArray(std::vector& vec) { init(STD_VECTOR_MAT+ACCESS_WRITE, &vec); } +inline _OutputArray::_OutputArray(UMat& m) { init(UMAT+ACCESS_WRITE, &m); } +inline _OutputArray::_OutputArray(std::vector& vec) { init(STD_VECTOR_UMAT+ACCESS_WRITE, &vec); } + +template inline +_OutputArray::_OutputArray(std::vector<_Tp>& vec) +{ init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); } + +inline +_OutputArray::_OutputArray(std::vector&) +{ CV_Error(Error::StsUnsupportedFormat, "std::vector cannot be an output array\n"); } + +template inline +_OutputArray::_OutputArray(std::vector >& vec) +{ init(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); } + +template inline +_OutputArray::_OutputArray(std::vector >& vec) +{ init(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_WRITE, &vec); } + +template inline +_OutputArray::_OutputArray(Mat_<_Tp>& m) +{ init(FIXED_TYPE + MAT + DataType<_Tp>::type + ACCESS_WRITE, &m); } + +template inline +_OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_WRITE, &mtx, Size(n, m)); } + +template inline +_OutputArray::_OutputArray(_Tp* vec, int n) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_WRITE, vec, Size(n, 1)); } + +template inline +_OutputArray::_OutputArray(const std::vector<_Tp>& vec) +{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); } + +template inline +_OutputArray::_OutputArray(const std::vector >& vec) +{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); } + +template inline +_OutputArray::_OutputArray(const std::vector >& vec) +{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_WRITE, &vec); } + +template inline +_OutputArray::_OutputArray(const Mat_<_Tp>& m) +{ init(FIXED_TYPE + FIXED_SIZE + MAT + DataType<_Tp>::type + ACCESS_WRITE, &m); } + +template inline +_OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_WRITE, &mtx, Size(n, m)); } + +template inline +_OutputArray::_OutputArray(const _Tp* vec, int n) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_WRITE, vec, Size(n, 1)); } + +inline _OutputArray::_OutputArray(cuda::GpuMat& d_mat) +{ init(CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); } + +inline _OutputArray::_OutputArray(ogl::Buffer& buf) +{ init(OPENGL_BUFFER + ACCESS_WRITE, &buf); } + +inline _OutputArray::_OutputArray(cuda::HostMem& cuda_mem) +{ init(CUDA_HOST_MEM + ACCESS_WRITE, &cuda_mem); } + +inline _OutputArray::_OutputArray(const Mat& m) +{ init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_WRITE, &m); } + +inline _OutputArray::_OutputArray(const std::vector& vec) +{ init(FIXED_SIZE + STD_VECTOR_MAT + ACCESS_WRITE, &vec); } + +inline _OutputArray::_OutputArray(const UMat& m) +{ init(FIXED_TYPE + FIXED_SIZE + UMAT + ACCESS_WRITE, &m); } + +inline _OutputArray::_OutputArray(const std::vector& vec) +{ init(FIXED_SIZE + STD_VECTOR_UMAT + ACCESS_WRITE, &vec); } + +inline _OutputArray::_OutputArray(const cuda::GpuMat& d_mat) +{ init(FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); } + +inline _OutputArray::_OutputArray(const ogl::Buffer& buf) +{ init(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_WRITE, &buf); } + +inline _OutputArray::_OutputArray(const cuda::HostMem& cuda_mem) +{ init(FIXED_TYPE + FIXED_SIZE + CUDA_HOST_MEM + ACCESS_WRITE, &cuda_mem); } + +/////////////////////////////////////////////////////////////////////////////////////////// + +inline _InputOutputArray::_InputOutputArray() { init(ACCESS_RW, 0); } +inline _InputOutputArray::_InputOutputArray(int _flags, void* _obj) { init(_flags|ACCESS_RW, _obj); } +inline _InputOutputArray::_InputOutputArray(Mat& m) { init(MAT+ACCESS_RW, &m); } +inline _InputOutputArray::_InputOutputArray(std::vector& vec) { init(STD_VECTOR_MAT+ACCESS_RW, &vec); } +inline _InputOutputArray::_InputOutputArray(UMat& m) { init(UMAT+ACCESS_RW, &m); } +inline _InputOutputArray::_InputOutputArray(std::vector& vec) { init(STD_VECTOR_UMAT+ACCESS_RW, &vec); } + +template inline +_InputOutputArray::_InputOutputArray(std::vector<_Tp>& vec) +{ init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); } + +inline _InputOutputArray::_InputOutputArray(std::vector&) +{ CV_Error(Error::StsUnsupportedFormat, "std::vector cannot be an input/output array\n"); } + +template inline +_InputOutputArray::_InputOutputArray(std::vector >& vec) +{ init(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); } + +template inline +_InputOutputArray::_InputOutputArray(std::vector >& vec) +{ init(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_RW, &vec); } + +template inline +_InputOutputArray::_InputOutputArray(Mat_<_Tp>& m) +{ init(FIXED_TYPE + MAT + DataType<_Tp>::type + ACCESS_RW, &m); } + +template inline +_InputOutputArray::_InputOutputArray(Matx<_Tp, m, n>& mtx) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_RW, &mtx, Size(n, m)); } + +template inline +_InputOutputArray::_InputOutputArray(_Tp* vec, int n) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_RW, vec, Size(n, 1)); } + +template inline +_InputOutputArray::_InputOutputArray(const std::vector<_Tp>& vec) +{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); } + +template inline +_InputOutputArray::_InputOutputArray(const std::vector >& vec) +{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); } + +template inline +_InputOutputArray::_InputOutputArray(const std::vector >& vec) +{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_RW, &vec); } + +template inline +_InputOutputArray::_InputOutputArray(const Mat_<_Tp>& m) +{ init(FIXED_TYPE + FIXED_SIZE + MAT + DataType<_Tp>::type + ACCESS_RW, &m); } + +template inline +_InputOutputArray::_InputOutputArray(const Matx<_Tp, m, n>& mtx) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_RW, &mtx, Size(n, m)); } + +template inline +_InputOutputArray::_InputOutputArray(const _Tp* vec, int n) +{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_RW, vec, Size(n, 1)); } + +inline _InputOutputArray::_InputOutputArray(cuda::GpuMat& d_mat) +{ init(CUDA_GPU_MAT + ACCESS_RW, &d_mat); } + +inline _InputOutputArray::_InputOutputArray(ogl::Buffer& buf) +{ init(OPENGL_BUFFER + ACCESS_RW, &buf); } + +inline _InputOutputArray::_InputOutputArray(cuda::HostMem& cuda_mem) +{ init(CUDA_HOST_MEM + ACCESS_RW, &cuda_mem); } + +inline _InputOutputArray::_InputOutputArray(const Mat& m) +{ init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_RW, &m); } + +inline _InputOutputArray::_InputOutputArray(const std::vector& vec) +{ init(FIXED_SIZE + STD_VECTOR_MAT + ACCESS_RW, &vec); } + +inline _InputOutputArray::_InputOutputArray(const UMat& m) +{ init(FIXED_TYPE + FIXED_SIZE + UMAT + ACCESS_RW, &m); } + +inline _InputOutputArray::_InputOutputArray(const std::vector& vec) +{ init(FIXED_SIZE + STD_VECTOR_UMAT + ACCESS_RW, &vec); } + +inline _InputOutputArray::_InputOutputArray(const cuda::GpuMat& d_mat) +{ init(FIXED_TYPE + FIXED_SIZE + CUDA_GPU_MAT + ACCESS_RW, &d_mat); } + +inline _InputOutputArray::_InputOutputArray(const ogl::Buffer& buf) +{ init(FIXED_TYPE + FIXED_SIZE + OPENGL_BUFFER + ACCESS_RW, &buf); } + +inline _InputOutputArray::_InputOutputArray(const cuda::HostMem& cuda_mem) +{ init(FIXED_TYPE + FIXED_SIZE + CUDA_HOST_MEM + ACCESS_RW, &cuda_mem); } + +//////////////////////////////////////////// Mat ////////////////////////////////////////// + +inline +Mat::Mat() + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), + datalimit(0), allocator(0), u(0), size(&rows) +{} + +inline +Mat::Mat(int _rows, int _cols, int _type) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), + datalimit(0), allocator(0), u(0), size(&rows) +{ + create(_rows, _cols, _type); +} + +inline +Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), + datalimit(0), allocator(0), u(0), size(&rows) +{ + create(_rows, _cols, _type); + *this = _s; +} + +inline +Mat::Mat(Size _sz, int _type) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), + datalimit(0), allocator(0), u(0), size(&rows) +{ + create( _sz.height, _sz.width, _type ); +} + +inline +Mat::Mat(Size _sz, int _type, const Scalar& _s) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), + datalimit(0), allocator(0), u(0), size(&rows) +{ + create(_sz.height, _sz.width, _type); + *this = _s; +} + +inline +Mat::Mat(int _dims, const int* _sz, int _type) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), + datalimit(0), allocator(0), u(0), size(&rows) +{ + create(_dims, _sz, _type); +} + +inline +Mat::Mat(int _dims, const int* _sz, int _type, const Scalar& _s) + : flags(MAGIC_VAL), dims(0), rows(0), cols(0), data(0), datastart(0), dataend(0), + datalimit(0), allocator(0), u(0), size(&rows) +{ + create(_dims, _sz, _type); + *this = _s; +} + +inline +Mat::Mat(const Mat& m) + : flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), data(m.data), + datastart(m.datastart), dataend(m.dataend), datalimit(m.datalimit), allocator(m.allocator), + u(m.u), size(&rows) +{ + if( u ) + CV_XADD(&u->refcount, 1); + if( m.dims <= 2 ) + { + step[0] = m.step[0]; step[1] = m.step[1]; + } + else + { + dims = 0; + copySize(m); + } +} + +inline +Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step) + : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_rows), cols(_cols), + data((uchar*)_data), datastart((uchar*)_data), dataend(0), datalimit(0), + allocator(0), u(0), size(&rows) +{ + size_t esz = CV_ELEM_SIZE(_type), esz1 = CV_ELEM_SIZE1(_type); + size_t minstep = cols * esz; + if( _step == AUTO_STEP ) + { + _step = minstep; + flags |= CONTINUOUS_FLAG; + } + else + { + if( rows == 1 ) _step = minstep; + CV_DbgAssert( _step >= minstep ); + + if (_step % esz1 != 0) + { + CV_Error(Error::BadStep, "Step must be a multiple of esz1"); + } + + flags |= _step == minstep ? CONTINUOUS_FLAG : 0; + } + step[0] = _step; + step[1] = esz; + datalimit = datastart + _step * rows; + dataend = datalimit - _step + minstep; +} + +inline +Mat::Mat(Size _sz, int _type, void* _data, size_t _step) + : flags(MAGIC_VAL + (_type & TYPE_MASK)), dims(2), rows(_sz.height), cols(_sz.width), + data((uchar*)_data), datastart((uchar*)_data), dataend(0), datalimit(0), + allocator(0), u(0), size(&rows) +{ + size_t esz = CV_ELEM_SIZE(_type), esz1 = CV_ELEM_SIZE1(_type); + size_t minstep = cols*esz; + if( _step == AUTO_STEP ) + { + _step = minstep; + flags |= CONTINUOUS_FLAG; + } + else + { + if( rows == 1 ) _step = minstep; + CV_DbgAssert( _step >= minstep ); + + if (_step % esz1 != 0) + { + CV_Error(Error::BadStep, "Step must be a multiple of esz1"); + } + + flags |= _step == minstep ? CONTINUOUS_FLAG : 0; + } + step[0] = _step; + step[1] = esz; + datalimit = datastart + _step*rows; + dataend = datalimit - _step + minstep; +} + +template inline +Mat::Mat(const std::vector<_Tp>& vec, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()), + cols(1), data(0), datastart(0), dataend(0), allocator(0), u(0), size(&rows) +{ + if(vec.empty()) + return; + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + datastart = data = (uchar*)&vec[0]; + datalimit = dataend = datastart + rows * step[0]; + } + else + Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this); +} + +template inline +Mat::Mat(const Vec<_Tp, n>& vec, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(n), cols(1), data(0), + datastart(0), dataend(0), allocator(0), u(0), size(&rows) +{ + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + datastart = data = (uchar*)vec.val; + datalimit = dataend = datastart + rows * step[0]; + } + else + Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this); +} + + +template inline +Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(m), cols(n), data(0), + datastart(0), dataend(0), allocator(0), u(0), size(&rows) +{ + if( !copyData ) + { + step[0] = cols * sizeof(_Tp); + step[1] = sizeof(_Tp); + datastart = data = (uchar*)M.val; + datalimit = dataend = datastart + rows * step[0]; + } + else + Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this); +} + +template inline +Mat::Mat(const Point_<_Tp>& pt, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(2), cols(1), data(0), + datastart(0), dataend(0), allocator(0), u(0), size(&rows) +{ + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + datastart = data = (uchar*)&pt.x; + datalimit = dataend = datastart + rows * step[0]; + } + else + { + create(2, 1, DataType<_Tp>::type); + ((_Tp*)data)[0] = pt.x; + ((_Tp*)data)[1] = pt.y; + } +} + +template inline +Mat::Mat(const Point3_<_Tp>& pt, bool copyData) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(3), cols(1), data(0), + datastart(0), dataend(0), allocator(0), u(0), size(&rows) +{ + if( !copyData ) + { + step[0] = step[1] = sizeof(_Tp); + datastart = data = (uchar*)&pt.x; + datalimit = dataend = datastart + rows * step[0]; + } + else + { + create(3, 1, DataType<_Tp>::type); + ((_Tp*)data)[0] = pt.x; + ((_Tp*)data)[1] = pt.y; + ((_Tp*)data)[2] = pt.z; + } +} + +template inline +Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer) + : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(0), rows(0), cols(0), data(0), + datastart(0), dataend(0), allocator(0), u(0), size(&rows) +{ + *this = commaInitializer.operator Mat_<_Tp>(); +} + +inline +Mat::~Mat() +{ + release(); + if( step.p != step.buf ) + fastFree(step.p); +} + +inline +Mat& Mat::operator = (const Mat& m) +{ + if( this != &m ) + { + if( m.u ) + CV_XADD(&m.u->refcount, 1); + release(); + flags = m.flags; + if( dims <= 2 && m.dims <= 2 ) + { + dims = m.dims; + rows = m.rows; + cols = m.cols; + step[0] = m.step[0]; + step[1] = m.step[1]; + } + else + copySize(m); + data = m.data; + datastart = m.datastart; + dataend = m.dataend; + datalimit = m.datalimit; + allocator = m.allocator; + u = m.u; + } + return *this; +} + +inline +Mat Mat::row(int y) const +{ + return Mat(*this, Range(y, y + 1), Range::all()); +} + +inline +Mat Mat::col(int x) const +{ + return Mat(*this, Range::all(), Range(x, x + 1)); +} + +inline +Mat Mat::rowRange(int startrow, int endrow) const +{ + return Mat(*this, Range(startrow, endrow), Range::all()); +} + +inline +Mat Mat::rowRange(const Range& r) const +{ + return Mat(*this, r, Range::all()); +} + +inline +Mat Mat::colRange(int startcol, int endcol) const +{ + return Mat(*this, Range::all(), Range(startcol, endcol)); +} + +inline +Mat Mat::colRange(const Range& r) const +{ + return Mat(*this, Range::all(), r); +} + +inline +Mat Mat::clone() const +{ + Mat m; + copyTo(m); + return m; +} + +inline +void Mat::assignTo( Mat& m, int _type ) const +{ + if( _type < 0 ) + m = *this; + else + convertTo(m, _type); +} + +inline +void Mat::create(int _rows, int _cols, int _type) +{ + _type &= TYPE_MASK; + if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && data ) + return; + int sz[] = {_rows, _cols}; + create(2, sz, _type); +} + +inline +void Mat::create(Size _sz, int _type) +{ + create(_sz.height, _sz.width, _type); +} + +inline +void Mat::addref() +{ + if( u ) + CV_XADD(&u->refcount, 1); +} + +inline void Mat::release() +{ + if( u && CV_XADD(&u->refcount, -1) == 1 ) + deallocate(); + u = NULL; + datastart = dataend = datalimit = data = 0; + for(int i = 0; i < dims; i++) + size.p[i] = 0; +} + +inline +Mat Mat::operator()( Range _rowRange, Range _colRange ) const +{ + return Mat(*this, _rowRange, _colRange); +} + +inline +Mat Mat::operator()( const Rect& roi ) const +{ + return Mat(*this, roi); +} + +inline +Mat Mat::operator()(const Range* ranges) const +{ + return Mat(*this, ranges); +} + +inline +bool Mat::isContinuous() const +{ + return (flags & CONTINUOUS_FLAG) != 0; +} + +inline +bool Mat::isSubmatrix() const +{ + return (flags & SUBMATRIX_FLAG) != 0; +} + +inline +size_t Mat::elemSize() const +{ + return dims > 0 ? step.p[dims - 1] : 0; +} + +inline +size_t Mat::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int Mat::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int Mat::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int Mat::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +size_t Mat::step1(int i) const +{ + return step.p[i] / elemSize1(); +} + +inline +bool Mat::empty() const +{ + return data == 0 || total() == 0; +} + +inline +size_t Mat::total() const +{ + if( dims <= 2 ) + return (size_t)rows * cols; + size_t p = 1; + for( int i = 0; i < dims; i++ ) + p *= size[i]; + return p; +} + +inline +uchar* Mat::ptr(int y) +{ + CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); + return data + step.p[0] * y; +} + +inline +const uchar* Mat::ptr(int y) const +{ + CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); + return data + step.p[0] * y; +} + +template inline +_Tp* Mat::ptr(int y) +{ + CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) ); + return (_Tp*)(data + step.p[0] * y); +} + +template inline +const _Tp* Mat::ptr(int y) const +{ + CV_DbgAssert( y == 0 || (data && dims >= 1 && data && (unsigned)y < (unsigned)size.p[0]) ); + return (const _Tp*)(data + step.p[0] * y); +} + +inline +uchar* Mat::ptr(int i0, int i1) +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return data + i0 * step.p[0] + i1 * step.p[1]; +} + +inline +const uchar* Mat::ptr(int i0, int i1) const +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return data + i0 * step.p[0] + i1 * step.p[1]; +} + +template inline +_Tp* Mat::ptr(int i0, int i1) +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return (_Tp*)(data + i0 * step.p[0] + i1 * step.p[1]); +} + +template inline +const _Tp* Mat::ptr(int i0, int i1) const +{ + CV_DbgAssert( dims >= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] ); + return (const _Tp*)(data + i0 * step.p[0] + i1 * step.p[1]); +} + +inline +uchar* Mat::ptr(int i0, int i1, int i2) +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2]; +} + +inline +const uchar* Mat::ptr(int i0, int i1, int i2) const +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2]; +} + +template inline +_Tp* Mat::ptr(int i0, int i1, int i2) +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return (_Tp*)(data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2]); +} + +template inline +const _Tp* Mat::ptr(int i0, int i1, int i2) const +{ + CV_DbgAssert( dims >= 3 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + (unsigned)i2 < (unsigned)size.p[2] ); + return (const _Tp*)(data + i0 * step.p[0] + i1 * step.p[1] + i2 * step.p[2]); +} + +inline +uchar* Mat::ptr(const int* idx) +{ + int i, d = dims; + uchar* p = data; + CV_DbgAssert( d >= 1 && p ); + for( i = 0; i < d; i++ ) + { + CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); + p += idx[i] * step.p[i]; + } + return p; +} + +inline +const uchar* Mat::ptr(const int* idx) const +{ + int i, d = dims; + uchar* p = data; + CV_DbgAssert( d >= 1 && p ); + for( i = 0; i < d; i++ ) + { + CV_DbgAssert( (unsigned)idx[i] < (unsigned)size.p[i] ); + p += idx[i] * step.p[i]; + } + return p; +} + +template inline +_Tp& Mat::at(int i0, int i1) +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((_Tp*)(data + step.p[0] * i0))[i1]; +} + +template inline +const _Tp& Mat::at(int i0, int i1) const +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((const _Tp*)(data + step.p[0] * i0))[i1]; +} + +template inline +_Tp& Mat::at(Point pt) +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)(pt.x * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((_Tp*)(data + step.p[0] * pt.y))[pt.x]; +} + +template inline +const _Tp& Mat::at(Point pt) const +{ + CV_DbgAssert( dims <= 2 && data && (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)(pt.x * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) && + CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); + return ((const _Tp*)(data + step.p[0] * pt.y))[pt.x]; +} + +template inline +_Tp& Mat::at(int i0) +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)(size.p[0] * size.p[1]) && + elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + if( isContinuous() || size.p[0] == 1 ) + return ((_Tp*)data)[i0]; + if( size.p[1] == 1 ) + return *(_Tp*)(data + step.p[0] * i0); + int i = i0 / cols, j = i0 - i * cols; + return ((_Tp*)(data + step.p[0] * i))[j]; +} + +template inline +const _Tp& Mat::at(int i0) const +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)(size.p[0] * size.p[1]) && + elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + if( isContinuous() || size.p[0] == 1 ) + return ((const _Tp*)data)[i0]; + if( size.p[1] == 1 ) + return *(const _Tp*)(data + step.p[0] * i0); + int i = i0 / cols, j = i0 - i * cols; + return ((const _Tp*)(data + step.p[0] * i))[j]; +} + +template inline +_Tp& Mat::at(int i0, int i1, int i2) +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(_Tp*)ptr(i0, i1, i2); +} + +template inline +const _Tp& Mat::at(int i0, int i1, int i2) const +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(const _Tp*)ptr(i0, i1, i2); +} + +template inline +_Tp& Mat::at(const int* idx) +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(_Tp*)ptr(idx); +} + +template inline +const _Tp& Mat::at(const int* idx) const +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(const _Tp*)ptr(idx); +} + +template inline +_Tp& Mat::at(const Vec& idx) +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(_Tp*)ptr(idx.val); +} + +template inline +const _Tp& Mat::at(const Vec& idx) const +{ + CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) ); + return *(const _Tp*)ptr(idx.val); +} + +template inline +MatConstIterator_<_Tp> Mat::begin() const +{ + CV_DbgAssert( elemSize() == sizeof(_Tp) ); + return MatConstIterator_<_Tp>((const Mat_<_Tp>*)this); +} + +template inline +MatConstIterator_<_Tp> Mat::end() const +{ + CV_DbgAssert( elemSize() == sizeof(_Tp) ); + MatConstIterator_<_Tp> it((const Mat_<_Tp>*)this); + it += total(); + return it; +} + +template inline +MatIterator_<_Tp> Mat::begin() +{ + CV_DbgAssert( elemSize() == sizeof(_Tp) ); + return MatIterator_<_Tp>((Mat_<_Tp>*)this); +} + +template inline +MatIterator_<_Tp> Mat::end() +{ + CV_DbgAssert( elemSize() == sizeof(_Tp) ); + MatIterator_<_Tp> it((Mat_<_Tp>*)this); + it += total(); + return it; +} + +template inline +void Mat::forEach(const Functor& operation) { + this->forEach_impl<_Tp>(operation); +} + +template inline +void Mat::forEach(const Functor& operation) const { + // call as not const + (const_cast(this))->forEach(operation); +} + +template inline +Mat::operator std::vector<_Tp>() const +{ + std::vector<_Tp> v; + copyTo(v); + return v; +} + +template inline +Mat::operator Vec<_Tp, n>() const +{ + CV_Assert( data && dims <= 2 && (rows == 1 || cols == 1) && + rows + cols - 1 == n && channels() == 1 ); + + if( isContinuous() && type() == DataType<_Tp>::type ) + return Vec<_Tp, n>((_Tp*)data); + Vec<_Tp, n> v; + Mat tmp(rows, cols, DataType<_Tp>::type, v.val); + convertTo(tmp, tmp.type()); + return v; +} + +template inline +Mat::operator Matx<_Tp, m, n>() const +{ + CV_Assert( data && dims <= 2 && rows == m && cols == n && channels() == 1 ); + + if( isContinuous() && type() == DataType<_Tp>::type ) + return Matx<_Tp, m, n>((_Tp*)data); + Matx<_Tp, m, n> mtx; + Mat tmp(rows, cols, DataType<_Tp>::type, mtx.val); + convertTo(tmp, tmp.type()); + return mtx; +} + +template inline +void Mat::push_back(const _Tp& elem) +{ + if( !data ) + { + *this = Mat(1, 1, DataType<_Tp>::type, (void*)&elem).clone(); + return; + } + CV_Assert(DataType<_Tp>::type == type() && cols == 1 + /* && dims == 2 (cols == 1 implies dims == 2) */); + const uchar* tmp = dataend + step[0]; + if( !isSubmatrix() && isContinuous() && tmp <= datalimit ) + { + *(_Tp*)(data + (size.p[0]++) * step.p[0]) = elem; + dataend = tmp; + } + else + push_back_(&elem); +} + +template inline +void Mat::push_back(const Mat_<_Tp>& m) +{ + push_back((const Mat&)m); +} + +///////////////////////////// MatSize //////////////////////////// + +inline +MatSize::MatSize(int* _p) + : p(_p) {} + +inline +Size MatSize::operator()() const +{ + CV_DbgAssert(p[-1] <= 2); + return Size(p[1], p[0]); +} + +inline +const int& MatSize::operator[](int i) const +{ + return p[i]; +} + +inline +int& MatSize::operator[](int i) +{ + return p[i]; +} + +inline +MatSize::operator const int*() const +{ + return p; +} + +inline +bool MatSize::operator == (const MatSize& sz) const +{ + int d = p[-1]; + int dsz = sz.p[-1]; + if( d != dsz ) + return false; + if( d == 2 ) + return p[0] == sz.p[0] && p[1] == sz.p[1]; + + for( int i = 0; i < d; i++ ) + if( p[i] != sz.p[i] ) + return false; + return true; +} + +inline +bool MatSize::operator != (const MatSize& sz) const +{ + return !(*this == sz); +} + + + +///////////////////////////// MatStep //////////////////////////// + +inline +MatStep::MatStep() +{ + p = buf; p[0] = p[1] = 0; +} + +inline +MatStep::MatStep(size_t s) +{ + p = buf; p[0] = s; p[1] = 0; +} + +inline +const size_t& MatStep::operator[](int i) const +{ + return p[i]; +} + +inline +size_t& MatStep::operator[](int i) +{ + return p[i]; +} + +inline MatStep::operator size_t() const +{ + CV_DbgAssert( p == buf ); + return buf[0]; +} + +inline MatStep& MatStep::operator = (size_t s) +{ + CV_DbgAssert( p == buf ); + buf[0] = s; + return *this; +} + + + +////////////////////////////// Mat_<_Tp> //////////////////////////// + +template inline +Mat_<_Tp>::Mat_() + : Mat() +{ + flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; +} + +template inline +Mat_<_Tp>::Mat_(int _rows, int _cols) + : Mat(_rows, _cols, DataType<_Tp>::type) +{ +} + +template inline +Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value) + : Mat(_rows, _cols, DataType<_Tp>::type) +{ + *this = value; +} + +template inline +Mat_<_Tp>::Mat_(Size _sz) + : Mat(_sz.height, _sz.width, DataType<_Tp>::type) +{} + +template inline +Mat_<_Tp>::Mat_(Size _sz, const _Tp& value) + : Mat(_sz.height, _sz.width, DataType<_Tp>::type) +{ + *this = value; +} + +template inline +Mat_<_Tp>::Mat_(int _dims, const int* _sz) + : Mat(_dims, _sz, DataType<_Tp>::type) +{} + +template inline +Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s) + : Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s)) +{} + +template inline +Mat_<_Tp>::Mat_(const Mat_<_Tp>& m, const Range* ranges) + : Mat(m, ranges) +{} + +template inline +Mat_<_Tp>::Mat_(const Mat& m) + : Mat() +{ + flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; + *this = m; +} + +template inline +Mat_<_Tp>::Mat_(const Mat_& m) + : Mat(m) +{} + +template inline +Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t steps) + : Mat(_rows, _cols, DataType<_Tp>::type, _data, steps) +{} + +template inline +Mat_<_Tp>::Mat_(const Mat_& m, const Range& _rowRange, const Range& _colRange) + : Mat(m, _rowRange, _colRange) +{} + +template inline +Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi) + : Mat(m, roi) +{} + +template template inline +Mat_<_Tp>::Mat_(const Vec::channel_type, n>& vec, bool copyData) + : Mat(n / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&vec) +{ + CV_Assert(n%DataType<_Tp>::channels == 0); + if( copyData ) + *this = clone(); +} + +template template inline +Mat_<_Tp>::Mat_(const Matx::channel_type, m, n>& M, bool copyData) + : Mat(m, n / DataType<_Tp>::channels, DataType<_Tp>::type, (void*)&M) +{ + CV_Assert(n % DataType<_Tp>::channels == 0); + if( copyData ) + *this = clone(); +} + +template inline +Mat_<_Tp>::Mat_(const Point_::channel_type>& pt, bool copyData) + : Mat(2 / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt) +{ + CV_Assert(2 % DataType<_Tp>::channels == 0); + if( copyData ) + *this = clone(); +} + +template inline +Mat_<_Tp>::Mat_(const Point3_::channel_type>& pt, bool copyData) + : Mat(3 / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt) +{ + CV_Assert(3 % DataType<_Tp>::channels == 0); + if( copyData ) + *this = clone(); +} + +template inline +Mat_<_Tp>::Mat_(const MatCommaInitializer_<_Tp>& commaInitializer) + : Mat(commaInitializer) +{} + +template inline +Mat_<_Tp>::Mat_(const std::vector<_Tp>& vec, bool copyData) + : Mat(vec, copyData) +{} + +template inline +Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m) +{ + if( DataType<_Tp>::type == m.type() ) + { + Mat::operator = (m); + return *this; + } + if( DataType<_Tp>::depth == m.depth() ) + { + return (*this = m.reshape(DataType<_Tp>::channels, m.dims, 0)); + } + CV_DbgAssert(DataType<_Tp>::channels == m.channels()); + m.convertTo(*this, type()); + return *this; +} + +template inline +Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat_& m) +{ + Mat::operator=(m); + return *this; +} + +template inline +Mat_<_Tp>& Mat_<_Tp>::operator = (const _Tp& s) +{ + typedef typename DataType<_Tp>::vec_type VT; + Mat::operator=(Scalar((const VT&)s)); + return *this; +} + +template inline +void Mat_<_Tp>::create(int _rows, int _cols) +{ + Mat::create(_rows, _cols, DataType<_Tp>::type); +} + +template inline +void Mat_<_Tp>::create(Size _sz) +{ + Mat::create(_sz, DataType<_Tp>::type); +} + +template inline +void Mat_<_Tp>::create(int _dims, const int* _sz) +{ + Mat::create(_dims, _sz, DataType<_Tp>::type); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::cross(const Mat_& m) const +{ + return Mat_<_Tp>(Mat::cross(m)); +} + +template template inline +Mat_<_Tp>::operator Mat_() const +{ + return Mat_(*this); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::row(int y) const +{ + return Mat_(*this, Range(y, y+1), Range::all()); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::col(int x) const +{ + return Mat_(*this, Range::all(), Range(x, x+1)); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::diag(int d) const +{ + return Mat_(Mat::diag(d)); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::clone() const +{ + return Mat_(Mat::clone()); +} + +template inline +size_t Mat_<_Tp>::elemSize() const +{ + CV_DbgAssert( Mat::elemSize() == sizeof(_Tp) ); + return sizeof(_Tp); +} + +template inline +size_t Mat_<_Tp>::elemSize1() const +{ + CV_DbgAssert( Mat::elemSize1() == sizeof(_Tp) / DataType<_Tp>::channels ); + return sizeof(_Tp) / DataType<_Tp>::channels; +} + +template inline +int Mat_<_Tp>::type() const +{ + CV_DbgAssert( Mat::type() == DataType<_Tp>::type ); + return DataType<_Tp>::type; +} + +template inline +int Mat_<_Tp>::depth() const +{ + CV_DbgAssert( Mat::depth() == DataType<_Tp>::depth ); + return DataType<_Tp>::depth; +} + +template inline +int Mat_<_Tp>::channels() const +{ + CV_DbgAssert( Mat::channels() == DataType<_Tp>::channels ); + return DataType<_Tp>::channels; +} + +template inline +size_t Mat_<_Tp>::stepT(int i) const +{ + return step.p[i] / elemSize(); +} + +template inline +size_t Mat_<_Tp>::step1(int i) const +{ + return step.p[i] / elemSize1(); +} + +template inline +Mat_<_Tp>& Mat_<_Tp>::adjustROI( int dtop, int dbottom, int dleft, int dright ) +{ + return (Mat_<_Tp>&)(Mat::adjustROI(dtop, dbottom, dleft, dright)); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::operator()( const Range& _rowRange, const Range& _colRange ) const +{ + return Mat_<_Tp>(*this, _rowRange, _colRange); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::operator()( const Rect& roi ) const +{ + return Mat_<_Tp>(*this, roi); +} + +template inline +Mat_<_Tp> Mat_<_Tp>::operator()( const Range* ranges ) const +{ + return Mat_<_Tp>(*this, ranges); +} + +template inline +_Tp* Mat_<_Tp>::operator [](int y) +{ + CV_DbgAssert( 0 <= y && y < rows ); + return (_Tp*)(data + y*step.p[0]); +} + +template inline +const _Tp* Mat_<_Tp>::operator [](int y) const +{ + CV_DbgAssert( 0 <= y && y < rows ); + return (const _Tp*)(data + y*step.p[0]); +} + +template inline +_Tp& Mat_<_Tp>::operator ()(int i0, int i1) +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((_Tp*)(data + step.p[0] * i0))[i1]; +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(int i0, int i1) const +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)i0 < (unsigned)size.p[0] && + (unsigned)i1 < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((const _Tp*)(data + step.p[0] * i0))[i1]; +} + +template inline +_Tp& Mat_<_Tp>::operator ()(Point pt) +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)pt.x < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((_Tp*)(data + step.p[0] * pt.y))[pt.x]; +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(Point pt) const +{ + CV_DbgAssert( dims <= 2 && data && + (unsigned)pt.y < (unsigned)size.p[0] && + (unsigned)pt.x < (unsigned)size.p[1] && + type() == DataType<_Tp>::type ); + return ((const _Tp*)(data + step.p[0] * pt.y))[pt.x]; +} + +template inline +_Tp& Mat_<_Tp>::operator ()(const int* idx) +{ + return Mat::at<_Tp>(idx); +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(const int* idx) const +{ + return Mat::at<_Tp>(idx); +} + +template template inline +_Tp& Mat_<_Tp>::operator ()(const Vec& idx) +{ + return Mat::at<_Tp>(idx); +} + +template template inline +const _Tp& Mat_<_Tp>::operator ()(const Vec& idx) const +{ + return Mat::at<_Tp>(idx); +} + +template inline +_Tp& Mat_<_Tp>::operator ()(int i0) +{ + return this->at<_Tp>(i0); +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(int i0) const +{ + return this->at<_Tp>(i0); +} + +template inline +_Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) +{ + return this->at<_Tp>(i0, i1, i2); +} + +template inline +const _Tp& Mat_<_Tp>::operator ()(int i0, int i1, int i2) const +{ + return this->at<_Tp>(i0, i1, i2); +} + +template inline +Mat_<_Tp>::operator std::vector<_Tp>() const +{ + std::vector<_Tp> v; + copyTo(v); + return v; +} + +template template inline +Mat_<_Tp>::operator Vec::channel_type, n>() const +{ + CV_Assert(n % DataType<_Tp>::channels == 0); + return this->Mat::operator Vec::channel_type, n>(); +} + +template template inline +Mat_<_Tp>::operator Matx::channel_type, m, n>() const +{ + CV_Assert(n % DataType<_Tp>::channels == 0); + + Matx::channel_type, m, n> res = this->Mat::operator Matx::channel_type, m, n>(); + return res; +} + +template inline +MatConstIterator_<_Tp> Mat_<_Tp>::begin() const +{ + return Mat::begin<_Tp>(); +} + +template inline +MatConstIterator_<_Tp> Mat_<_Tp>::end() const +{ + return Mat::end<_Tp>(); +} + +template inline +MatIterator_<_Tp> Mat_<_Tp>::begin() +{ + return Mat::begin<_Tp>(); +} + +template inline +MatIterator_<_Tp> Mat_<_Tp>::end() +{ + return Mat::end<_Tp>(); +} + +template template inline +void Mat_<_Tp>::forEach(const Functor& operation) { + Mat::forEach<_Tp, Functor>(operation); +} + +template template inline +void Mat_<_Tp>::forEach(const Functor& operation) const { + Mat::forEach<_Tp, Functor>(operation); +} + +///////////////////////////// SparseMat ///////////////////////////// + +inline +SparseMat::SparseMat() + : flags(MAGIC_VAL), hdr(0) +{} + +inline +SparseMat::SparseMat(int _dims, const int* _sizes, int _type) + : flags(MAGIC_VAL), hdr(0) +{ + create(_dims, _sizes, _type); +} + +inline +SparseMat::SparseMat(const SparseMat& m) + : flags(m.flags), hdr(m.hdr) +{ + addref(); +} + +inline +SparseMat::~SparseMat() +{ + release(); +} + +inline +SparseMat& SparseMat::operator = (const SparseMat& m) +{ + if( this != &m ) + { + if( m.hdr ) + CV_XADD(&m.hdr->refcount, 1); + release(); + flags = m.flags; + hdr = m.hdr; + } + return *this; +} + +inline +SparseMat& SparseMat::operator = (const Mat& m) +{ + return (*this = SparseMat(m)); +} + +inline +SparseMat SparseMat::clone() const +{ + SparseMat temp; + this->copyTo(temp); + return temp; +} + +inline +void SparseMat::assignTo( SparseMat& m, int _type ) const +{ + if( _type < 0 ) + m = *this; + else + convertTo(m, _type); +} + +inline +void SparseMat::addref() +{ + if( hdr ) + CV_XADD(&hdr->refcount, 1); +} + +inline +void SparseMat::release() +{ + if( hdr && CV_XADD(&hdr->refcount, -1) == 1 ) + delete hdr; + hdr = 0; +} + +inline +size_t SparseMat::elemSize() const +{ + return CV_ELEM_SIZE(flags); +} + +inline +size_t SparseMat::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int SparseMat::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int SparseMat::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int SparseMat::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +const int* SparseMat::size() const +{ + return hdr ? hdr->size : 0; +} + +inline +int SparseMat::size(int i) const +{ + if( hdr ) + { + CV_DbgAssert((unsigned)i < (unsigned)hdr->dims); + return hdr->size[i]; + } + return 0; +} + +inline +int SparseMat::dims() const +{ + return hdr ? hdr->dims : 0; +} + +inline +size_t SparseMat::nzcount() const +{ + return hdr ? hdr->nodeCount : 0; +} + +inline +size_t SparseMat::hash(int i0) const +{ + return (size_t)i0; +} + +inline +size_t SparseMat::hash(int i0, int i1) const +{ + return (size_t)(unsigned)i0 * HASH_SCALE + (unsigned)i1; +} + +inline +size_t SparseMat::hash(int i0, int i1, int i2) const +{ + return ((size_t)(unsigned)i0 * HASH_SCALE + (unsigned)i1) * HASH_SCALE + (unsigned)i2; +} + +inline +size_t SparseMat::hash(const int* idx) const +{ + size_t h = (unsigned)idx[0]; + if( !hdr ) + return 0; + int d = hdr->dims; + for(int i = 1; i < d; i++ ) + h = h * HASH_SCALE + (unsigned)idx[i]; + return h; +} + +template inline +_Tp& SparseMat::ref(int i0, size_t* hashval) +{ + return *(_Tp*)((SparseMat*)this)->ptr(i0, true, hashval); +} + +template inline +_Tp& SparseMat::ref(int i0, int i1, size_t* hashval) +{ + return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, true, hashval); +} + +template inline +_Tp& SparseMat::ref(int i0, int i1, int i2, size_t* hashval) +{ + return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, i2, true, hashval); +} + +template inline +_Tp& SparseMat::ref(const int* idx, size_t* hashval) +{ + return *(_Tp*)((SparseMat*)this)->ptr(idx, true, hashval); +} + +template inline +_Tp SparseMat::value(int i0, size_t* hashval) const +{ + const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval); + return p ? *p : _Tp(); +} + +template inline +_Tp SparseMat::value(int i0, int i1, size_t* hashval) const +{ + const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval); + return p ? *p : _Tp(); +} + +template inline +_Tp SparseMat::value(int i0, int i1, int i2, size_t* hashval) const +{ + const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval); + return p ? *p : _Tp(); +} + +template inline +_Tp SparseMat::value(const int* idx, size_t* hashval) const +{ + const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval); + return p ? *p : _Tp(); +} + +template inline +const _Tp* SparseMat::find(int i0, size_t* hashval) const +{ + return (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval); +} + +template inline +const _Tp* SparseMat::find(int i0, int i1, size_t* hashval) const +{ + return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval); +} + +template inline +const _Tp* SparseMat::find(int i0, int i1, int i2, size_t* hashval) const +{ + return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval); +} + +template inline +const _Tp* SparseMat::find(const int* idx, size_t* hashval) const +{ + return (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval); +} + +template inline +_Tp& SparseMat::value(Node* n) +{ + return *(_Tp*)((uchar*)n + hdr->valueOffset); +} + +template inline +const _Tp& SparseMat::value(const Node* n) const +{ + return *(const _Tp*)((const uchar*)n + hdr->valueOffset); +} + +inline +SparseMat::Node* SparseMat::node(size_t nidx) +{ + return (Node*)(void*)&hdr->pool[nidx]; +} + +inline +const SparseMat::Node* SparseMat::node(size_t nidx) const +{ + return (const Node*)(const void*)&hdr->pool[nidx]; +} + +inline +SparseMatIterator SparseMat::begin() +{ + return SparseMatIterator(this); +} + +inline +SparseMatConstIterator SparseMat::begin() const +{ + return SparseMatConstIterator(this); +} + +inline +SparseMatIterator SparseMat::end() +{ + SparseMatIterator it(this); + it.seekEnd(); + return it; +} + +inline +SparseMatConstIterator SparseMat::end() const +{ + SparseMatConstIterator it(this); + it.seekEnd(); + return it; +} + +template inline +SparseMatIterator_<_Tp> SparseMat::begin() +{ + return SparseMatIterator_<_Tp>(this); +} + +template inline +SparseMatConstIterator_<_Tp> SparseMat::begin() const +{ + return SparseMatConstIterator_<_Tp>(this); +} + +template inline +SparseMatIterator_<_Tp> SparseMat::end() +{ + SparseMatIterator_<_Tp> it(this); + it.seekEnd(); + return it; +} + +template inline +SparseMatConstIterator_<_Tp> SparseMat::end() const +{ + SparseMatConstIterator_<_Tp> it(this); + it.seekEnd(); + return it; +} + + + +///////////////////////////// SparseMat_ //////////////////////////// + +template inline +SparseMat_<_Tp>::SparseMat_() +{ + flags = MAGIC_VAL | DataType<_Tp>::type; +} + +template inline +SparseMat_<_Tp>::SparseMat_(int _dims, const int* _sizes) + : SparseMat(_dims, _sizes, DataType<_Tp>::type) +{} + +template inline +SparseMat_<_Tp>::SparseMat_(const SparseMat& m) +{ + if( m.type() == DataType<_Tp>::type ) + *this = (const SparseMat_<_Tp>&)m; + else + m.convertTo(*this, DataType<_Tp>::type); +} + +template inline +SparseMat_<_Tp>::SparseMat_(const SparseMat_<_Tp>& m) +{ + this->flags = m.flags; + this->hdr = m.hdr; + if( this->hdr ) + CV_XADD(&this->hdr->refcount, 1); +} + +template inline +SparseMat_<_Tp>::SparseMat_(const Mat& m) +{ + SparseMat sm(m); + *this = sm; +} + +template inline +SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const SparseMat_<_Tp>& m) +{ + if( this != &m ) + { + if( m.hdr ) CV_XADD(&m.hdr->refcount, 1); + release(); + flags = m.flags; + hdr = m.hdr; + } + return *this; +} + +template inline +SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const SparseMat& m) +{ + if( m.type() == DataType<_Tp>::type ) + return (*this = (const SparseMat_<_Tp>&)m); + m.convertTo(*this, DataType<_Tp>::type); + return *this; +} + +template inline +SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const Mat& m) +{ + return (*this = SparseMat(m)); +} + +template inline +SparseMat_<_Tp> SparseMat_<_Tp>::clone() const +{ + SparseMat_<_Tp> m; + this->copyTo(m); + return m; +} + +template inline +void SparseMat_<_Tp>::create(int _dims, const int* _sizes) +{ + SparseMat::create(_dims, _sizes, DataType<_Tp>::type); +} + +template inline +int SparseMat_<_Tp>::type() const +{ + return DataType<_Tp>::type; +} + +template inline +int SparseMat_<_Tp>::depth() const +{ + return DataType<_Tp>::depth; +} + +template inline +int SparseMat_<_Tp>::channels() const +{ + return DataType<_Tp>::channels; +} + +template inline +_Tp& SparseMat_<_Tp>::ref(int i0, size_t* hashval) +{ + return SparseMat::ref<_Tp>(i0, hashval); +} + +template inline +_Tp SparseMat_<_Tp>::operator()(int i0, size_t* hashval) const +{ + return SparseMat::value<_Tp>(i0, hashval); +} + +template inline +_Tp& SparseMat_<_Tp>::ref(int i0, int i1, size_t* hashval) +{ + return SparseMat::ref<_Tp>(i0, i1, hashval); +} + +template inline +_Tp SparseMat_<_Tp>::operator()(int i0, int i1, size_t* hashval) const +{ + return SparseMat::value<_Tp>(i0, i1, hashval); +} + +template inline +_Tp& SparseMat_<_Tp>::ref(int i0, int i1, int i2, size_t* hashval) +{ + return SparseMat::ref<_Tp>(i0, i1, i2, hashval); +} + +template inline +_Tp SparseMat_<_Tp>::operator()(int i0, int i1, int i2, size_t* hashval) const +{ + return SparseMat::value<_Tp>(i0, i1, i2, hashval); +} + +template inline +_Tp& SparseMat_<_Tp>::ref(const int* idx, size_t* hashval) +{ + return SparseMat::ref<_Tp>(idx, hashval); +} + +template inline +_Tp SparseMat_<_Tp>::operator()(const int* idx, size_t* hashval) const +{ + return SparseMat::value<_Tp>(idx, hashval); +} + +template inline +SparseMatIterator_<_Tp> SparseMat_<_Tp>::begin() +{ + return SparseMatIterator_<_Tp>(this); +} + +template inline +SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::begin() const +{ + return SparseMatConstIterator_<_Tp>(this); +} + +template inline +SparseMatIterator_<_Tp> SparseMat_<_Tp>::end() +{ + SparseMatIterator_<_Tp> it(this); + it.seekEnd(); + return it; +} + +template inline +SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::end() const +{ + SparseMatConstIterator_<_Tp> it(this); + it.seekEnd(); + return it; +} + + + +////////////////////////// MatConstIterator ///////////////////////// + +inline +MatConstIterator::MatConstIterator() + : m(0), elemSize(0), ptr(0), sliceStart(0), sliceEnd(0) +{} + +inline +MatConstIterator::MatConstIterator(const Mat* _m) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) +{ + if( m && m->isContinuous() ) + { + sliceStart = m->ptr(); + sliceEnd = sliceStart + m->total()*elemSize; + } + seek((const int*)0); +} + +inline +MatConstIterator::MatConstIterator(const Mat* _m, int _row, int _col) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) +{ + CV_Assert(m && m->dims <= 2); + if( m->isContinuous() ) + { + sliceStart = m->ptr(); + sliceEnd = sliceStart + m->total()*elemSize; + } + int idx[] = {_row, _col}; + seek(idx); +} + +inline +MatConstIterator::MatConstIterator(const Mat* _m, Point _pt) + : m(_m), elemSize(_m->elemSize()), ptr(0), sliceStart(0), sliceEnd(0) +{ + CV_Assert(m && m->dims <= 2); + if( m->isContinuous() ) + { + sliceStart = m->ptr(); + sliceEnd = sliceStart + m->total()*elemSize; + } + int idx[] = {_pt.y, _pt.x}; + seek(idx); +} + +inline +MatConstIterator::MatConstIterator(const MatConstIterator& it) + : m(it.m), elemSize(it.elemSize), ptr(it.ptr), sliceStart(it.sliceStart), sliceEnd(it.sliceEnd) +{} + +inline +MatConstIterator& MatConstIterator::operator = (const MatConstIterator& it ) +{ + m = it.m; elemSize = it.elemSize; ptr = it.ptr; + sliceStart = it.sliceStart; sliceEnd = it.sliceEnd; + return *this; +} + +inline +const uchar* MatConstIterator::operator *() const +{ + return ptr; +} + +inline MatConstIterator& MatConstIterator::operator += (ptrdiff_t ofs) +{ + if( !m || ofs == 0 ) + return *this; + ptrdiff_t ofsb = ofs*elemSize; + ptr += ofsb; + if( ptr < sliceStart || sliceEnd <= ptr ) + { + ptr -= ofsb; + seek(ofs, true); + } + return *this; +} + +inline +MatConstIterator& MatConstIterator::operator -= (ptrdiff_t ofs) +{ + return (*this += -ofs); +} + +inline +MatConstIterator& MatConstIterator::operator --() +{ + if( m && (ptr -= elemSize) < sliceStart ) + { + ptr += elemSize; + seek(-1, true); + } + return *this; +} + +inline +MatConstIterator MatConstIterator::operator --(int) +{ + MatConstIterator b = *this; + *this += -1; + return b; +} + +inline +MatConstIterator& MatConstIterator::operator ++() +{ + if( m && (ptr += elemSize) >= sliceEnd ) + { + ptr -= elemSize; + seek(1, true); + } + return *this; +} + +inline MatConstIterator MatConstIterator::operator ++(int) +{ + MatConstIterator b = *this; + *this += 1; + return b; +} + + +static inline +bool operator == (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.m == b.m && a.ptr == b.ptr; +} + +static inline +bool operator != (const MatConstIterator& a, const MatConstIterator& b) +{ + return !(a == b); +} + +static inline +bool operator < (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.ptr < b.ptr; +} + +static inline +bool operator > (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.ptr > b.ptr; +} + +static inline +bool operator <= (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.ptr <= b.ptr; +} + +static inline +bool operator >= (const MatConstIterator& a, const MatConstIterator& b) +{ + return a.ptr >= b.ptr; +} + +static inline +ptrdiff_t operator - (const MatConstIterator& b, const MatConstIterator& a) +{ + if( a.m != b.m ) + return ((size_t)(-1) >> 1); + if( a.sliceEnd == b.sliceEnd ) + return (b.ptr - a.ptr)/b.elemSize; + + return b.lpos() - a.lpos(); +} + +static inline +MatConstIterator operator + (const MatConstIterator& a, ptrdiff_t ofs) +{ + MatConstIterator b = a; + return b += ofs; +} + +static inline +MatConstIterator operator + (ptrdiff_t ofs, const MatConstIterator& a) +{ + MatConstIterator b = a; + return b += ofs; +} + +static inline +MatConstIterator operator - (const MatConstIterator& a, ptrdiff_t ofs) +{ + MatConstIterator b = a; + return b += -ofs; +} + + +inline +const uchar* MatConstIterator::operator [](ptrdiff_t i) const +{ + return *(*this + i); +} + + + +///////////////////////// MatConstIterator_ ///////////////////////// + +template inline +MatConstIterator_<_Tp>::MatConstIterator_() +{} + +template inline +MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m) + : MatConstIterator(_m) +{} + +template inline +MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col) + : MatConstIterator(_m, _row, _col) +{} + +template inline +MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m, Point _pt) + : MatConstIterator(_m, _pt) +{} + +template inline +MatConstIterator_<_Tp>::MatConstIterator_(const MatConstIterator_& it) + : MatConstIterator(it) +{} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator = (const MatConstIterator_& it ) +{ + MatConstIterator::operator = (it); + return *this; +} + +template inline +_Tp MatConstIterator_<_Tp>::operator *() const +{ + return *(_Tp*)(this->ptr); +} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (ptrdiff_t ofs) +{ + MatConstIterator::operator += (ofs); + return *this; +} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (ptrdiff_t ofs) +{ + return (*this += -ofs); +} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator --() +{ + MatConstIterator::operator --(); + return *this; +} + +template inline +MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator --(int) +{ + MatConstIterator_ b = *this; + MatConstIterator::operator --(); + return b; +} + +template inline +MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator ++() +{ + MatConstIterator::operator ++(); + return *this; +} + +template inline +MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator ++(int) +{ + MatConstIterator_ b = *this; + MatConstIterator::operator ++(); + return b; +} + + +template inline +Point MatConstIterator_<_Tp>::pos() const +{ + if( !m ) + return Point(); + CV_DbgAssert( m->dims <= 2 ); + if( m->isContinuous() ) + { + ptrdiff_t ofs = (const _Tp*)ptr - (const _Tp*)m->data; + int y = (int)(ofs / m->cols); + int x = (int)(ofs - (ptrdiff_t)y * m->cols); + return Point(x, y); + } + else + { + ptrdiff_t ofs = (uchar*)ptr - m->data; + int y = (int)(ofs / m->step); + int x = (int)((ofs - y * m->step)/sizeof(_Tp)); + return Point(x, y); + } +} + + +template static inline +bool operator == (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) +{ + return a.m == b.m && a.ptr == b.ptr; +} + +template static inline +bool operator != (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b) +{ + return a.m != b.m || a.ptr != b.ptr; +} + +template static inline +MatConstIterator_<_Tp> operator + (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) +{ + MatConstIterator t = (const MatConstIterator&)a + ofs; + return (MatConstIterator_<_Tp>&)t; +} + +template static inline +MatConstIterator_<_Tp> operator + (ptrdiff_t ofs, const MatConstIterator_<_Tp>& a) +{ + MatConstIterator t = (const MatConstIterator&)a + ofs; + return (MatConstIterator_<_Tp>&)t; +} + +template static inline +MatConstIterator_<_Tp> operator - (const MatConstIterator_<_Tp>& a, ptrdiff_t ofs) +{ + MatConstIterator t = (const MatConstIterator&)a - ofs; + return (MatConstIterator_<_Tp>&)t; +} + +template inline +_Tp MatConstIterator_<_Tp>::operator [](ptrdiff_t i) const +{ + return *(_Tp*)MatConstIterator::operator [](i); +} + + + +//////////////////////////// MatIterator_ /////////////////////////// + +template inline +MatIterator_<_Tp>::MatIterator_() + : MatConstIterator_<_Tp>() +{} + +template inline +MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m) + : MatConstIterator_<_Tp>(_m) +{} + +template inline +MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, int _row, int _col) + : MatConstIterator_<_Tp>(_m, _row, _col) +{} + +template inline +MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, Point _pt) + : MatConstIterator_<_Tp>(_m, _pt) +{} + +template inline +MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, const int* _idx) + : MatConstIterator_<_Tp>(_m, _idx) +{} + +template inline +MatIterator_<_Tp>::MatIterator_(const MatIterator_& it) + : MatConstIterator_<_Tp>(it) +{} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator = (const MatIterator_<_Tp>& it ) +{ + MatConstIterator::operator = (it); + return *this; +} + +template inline +_Tp& MatIterator_<_Tp>::operator *() const +{ + return *(_Tp*)(this->ptr); +} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (ptrdiff_t ofs) +{ + MatConstIterator::operator += (ofs); + return *this; +} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (ptrdiff_t ofs) +{ + MatConstIterator::operator += (-ofs); + return *this; +} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator --() +{ + MatConstIterator::operator --(); + return *this; +} + +template inline +MatIterator_<_Tp> MatIterator_<_Tp>::operator --(int) +{ + MatIterator_ b = *this; + MatConstIterator::operator --(); + return b; +} + +template inline +MatIterator_<_Tp>& MatIterator_<_Tp>::operator ++() +{ + MatConstIterator::operator ++(); + return *this; +} + +template inline +MatIterator_<_Tp> MatIterator_<_Tp>::operator ++(int) +{ + MatIterator_ b = *this; + MatConstIterator::operator ++(); + return b; +} + +template inline +_Tp& MatIterator_<_Tp>::operator [](ptrdiff_t i) const +{ + return *(*this + i); +} + + +template static inline +bool operator == (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) +{ + return a.m == b.m && a.ptr == b.ptr; +} + +template static inline +bool operator != (const MatIterator_<_Tp>& a, const MatIterator_<_Tp>& b) +{ + return a.m != b.m || a.ptr != b.ptr; +} + +template static inline +MatIterator_<_Tp> operator + (const MatIterator_<_Tp>& a, ptrdiff_t ofs) +{ + MatConstIterator t = (const MatConstIterator&)a + ofs; + return (MatIterator_<_Tp>&)t; +} + +template static inline +MatIterator_<_Tp> operator + (ptrdiff_t ofs, const MatIterator_<_Tp>& a) +{ + MatConstIterator t = (const MatConstIterator&)a + ofs; + return (MatIterator_<_Tp>&)t; +} + +template static inline +MatIterator_<_Tp> operator - (const MatIterator_<_Tp>& a, ptrdiff_t ofs) +{ + MatConstIterator t = (const MatConstIterator&)a - ofs; + return (MatIterator_<_Tp>&)t; +} + + + +/////////////////////// SparseMatConstIterator ////////////////////// + +inline +SparseMatConstIterator::SparseMatConstIterator() + : m(0), hashidx(0), ptr(0) +{} + +inline +SparseMatConstIterator::SparseMatConstIterator(const SparseMatConstIterator& it) + : m(it.m), hashidx(it.hashidx), ptr(it.ptr) +{} + +inline SparseMatConstIterator& SparseMatConstIterator::operator = (const SparseMatConstIterator& it) +{ + if( this != &it ) + { + m = it.m; + hashidx = it.hashidx; + ptr = it.ptr; + } + return *this; +} + +template inline +const _Tp& SparseMatConstIterator::value() const +{ + return *(const _Tp*)ptr; +} + +inline +const SparseMat::Node* SparseMatConstIterator::node() const +{ + return (ptr && m && m->hdr) ? (const SparseMat::Node*)(const void*)(ptr - m->hdr->valueOffset) : 0; +} + +inline +SparseMatConstIterator SparseMatConstIterator::operator ++(int) +{ + SparseMatConstIterator it = *this; + ++*this; + return it; +} + +inline +void SparseMatConstIterator::seekEnd() +{ + if( m && m->hdr ) + { + hashidx = m->hdr->hashtab.size(); + ptr = 0; + } +} + + +static inline +bool operator == (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) +{ + return it1.m == it2.m && it1.ptr == it2.ptr; +} + +static inline +bool operator != (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2) +{ + return !(it1 == it2); +} + + + +///////////////////////// SparseMatIterator ///////////////////////// + +inline +SparseMatIterator::SparseMatIterator() +{} + +inline +SparseMatIterator::SparseMatIterator(SparseMat* _m) + : SparseMatConstIterator(_m) +{} + +inline +SparseMatIterator::SparseMatIterator(const SparseMatIterator& it) + : SparseMatConstIterator(it) +{} + +inline +SparseMatIterator& SparseMatIterator::operator = (const SparseMatIterator& it) +{ + (SparseMatConstIterator&)*this = it; + return *this; +} + +template inline +_Tp& SparseMatIterator::value() const +{ + return *(_Tp*)ptr; +} + +inline +SparseMat::Node* SparseMatIterator::node() const +{ + return (SparseMat::Node*)SparseMatConstIterator::node(); +} + +inline +SparseMatIterator& SparseMatIterator::operator ++() +{ + SparseMatConstIterator::operator ++(); + return *this; +} + +inline +SparseMatIterator SparseMatIterator::operator ++(int) +{ + SparseMatIterator it = *this; + ++*this; + return it; +} + + + +////////////////////// SparseMatConstIterator_ ////////////////////// + +template inline +SparseMatConstIterator_<_Tp>::SparseMatConstIterator_() +{} + +template inline +SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat_<_Tp>* _m) + : SparseMatConstIterator(_m) +{} + +template inline +SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat* _m) + : SparseMatConstIterator(_m) +{ + CV_Assert( _m->type() == DataType<_Tp>::type ); +} + +template inline +SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMatConstIterator_<_Tp>& it) + : SparseMatConstIterator(it) +{} + +template inline +SparseMatConstIterator_<_Tp>& SparseMatConstIterator_<_Tp>::operator = (const SparseMatConstIterator_<_Tp>& it) +{ + return reinterpret_cast&> + (*reinterpret_cast(this) = + reinterpret_cast(it)); +} + +template inline +const _Tp& SparseMatConstIterator_<_Tp>::operator *() const +{ + return *(const _Tp*)this->ptr; +} + +template inline +SparseMatConstIterator_<_Tp>& SparseMatConstIterator_<_Tp>::operator ++() +{ + SparseMatConstIterator::operator ++(); + return *this; +} + +template inline +SparseMatConstIterator_<_Tp> SparseMatConstIterator_<_Tp>::operator ++(int) +{ + SparseMatConstIterator_<_Tp> it = *this; + SparseMatConstIterator::operator ++(); + return it; +} + + + +///////////////////////// SparseMatIterator_ //////////////////////// + +template inline +SparseMatIterator_<_Tp>::SparseMatIterator_() +{} + +template inline +SparseMatIterator_<_Tp>::SparseMatIterator_(SparseMat_<_Tp>* _m) + : SparseMatConstIterator_<_Tp>(_m) +{} + +template inline +SparseMatIterator_<_Tp>::SparseMatIterator_(SparseMat* _m) + : SparseMatConstIterator_<_Tp>(_m) +{} + +template inline +SparseMatIterator_<_Tp>::SparseMatIterator_(const SparseMatIterator_<_Tp>& it) + : SparseMatConstIterator_<_Tp>(it) +{} + +template inline +SparseMatIterator_<_Tp>& SparseMatIterator_<_Tp>::operator = (const SparseMatIterator_<_Tp>& it) +{ + return reinterpret_cast&> + (*reinterpret_cast(this) = + reinterpret_cast(it)); +} + +template inline +_Tp& SparseMatIterator_<_Tp>::operator *() const +{ + return *(_Tp*)this->ptr; +} + +template inline +SparseMatIterator_<_Tp>& SparseMatIterator_<_Tp>::operator ++() +{ + SparseMatConstIterator::operator ++(); + return *this; +} + +template inline +SparseMatIterator_<_Tp> SparseMatIterator_<_Tp>::operator ++(int) +{ + SparseMatIterator_<_Tp> it = *this; + SparseMatConstIterator::operator ++(); + return it; +} + + + +//////////////////////// MatCommaInitializer_ /////////////////////// + +template inline +MatCommaInitializer_<_Tp>::MatCommaInitializer_(Mat_<_Tp>* _m) + : it(_m) +{} + +template template inline +MatCommaInitializer_<_Tp>& MatCommaInitializer_<_Tp>::operator , (T2 v) +{ + CV_DbgAssert( this->it < ((const Mat_<_Tp>*)this->it.m)->end() ); + *this->it = _Tp(v); + ++this->it; + return *this; +} + +template inline +MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const +{ + CV_DbgAssert( this->it == ((const Mat_<_Tp>*)this->it.m)->end() ); + return Mat_<_Tp>(*this->it.m); +} + + +template static inline +MatCommaInitializer_<_Tp> operator << (const Mat_<_Tp>& m, T2 val) +{ + MatCommaInitializer_<_Tp> commaInitializer((Mat_<_Tp>*)&m); + return (commaInitializer, val); +} + + + +///////////////////////// Matrix Expressions //////////////////////// + +inline +Mat& Mat::operator = (const MatExpr& e) +{ + e.op->assign(e, *this); + return *this; +} + +template inline +Mat_<_Tp>::Mat_(const MatExpr& e) +{ + e.op->assign(e, *this, DataType<_Tp>::type); +} + +template inline +Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr& e) +{ + e.op->assign(e, *this, DataType<_Tp>::type); + return *this; +} + +template inline +MatExpr Mat_<_Tp>::zeros(int rows, int cols) +{ + return Mat::zeros(rows, cols, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::zeros(Size sz) +{ + return Mat::zeros(sz, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::ones(int rows, int cols) +{ + return Mat::ones(rows, cols, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::ones(Size sz) +{ + return Mat::ones(sz, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::eye(int rows, int cols) +{ + return Mat::eye(rows, cols, DataType<_Tp>::type); +} + +template inline +MatExpr Mat_<_Tp>::eye(Size sz) +{ + return Mat::eye(sz, DataType<_Tp>::type); +} + +inline +MatExpr::MatExpr() + : op(0), flags(0), a(Mat()), b(Mat()), c(Mat()), alpha(0), beta(0), s() +{} + +inline +MatExpr::MatExpr(const MatOp* _op, int _flags, const Mat& _a, const Mat& _b, + const Mat& _c, double _alpha, double _beta, const Scalar& _s) + : op(_op), flags(_flags), a(_a), b(_b), c(_c), alpha(_alpha), beta(_beta), s(_s) +{} + +inline +MatExpr::operator Mat() const +{ + Mat m; + op->assign(*this, m); + return m; +} + +template inline +MatExpr::operator Mat_<_Tp>() const +{ + Mat_<_Tp> m; + op->assign(*this, m, DataType<_Tp>::type); + return m; +} + + +template static inline +MatExpr min(const Mat_<_Tp>& a, const Mat_<_Tp>& b) +{ + return cv::min((const Mat&)a, (const Mat&)b); +} + +template static inline +MatExpr min(const Mat_<_Tp>& a, double s) +{ + return cv::min((const Mat&)a, s); +} + +template static inline +MatExpr min(double s, const Mat_<_Tp>& a) +{ + return cv::min((const Mat&)a, s); +} + +template static inline +MatExpr max(const Mat_<_Tp>& a, const Mat_<_Tp>& b) +{ + return cv::max((const Mat&)a, (const Mat&)b); +} + +template static inline +MatExpr max(const Mat_<_Tp>& a, double s) +{ + return cv::max((const Mat&)a, s); +} + +template static inline +MatExpr max(double s, const Mat_<_Tp>& a) +{ + return cv::max((const Mat&)a, s); +} + +template static inline +MatExpr abs(const Mat_<_Tp>& m) +{ + return cv::abs((const Mat&)m); +} + + +static inline +Mat& operator += (Mat& a, const MatExpr& b) +{ + b.op->augAssignAdd(b, a); + return a; +} + +static inline +const Mat& operator += (const Mat& a, const MatExpr& b) +{ + b.op->augAssignAdd(b, (Mat&)a); + return a; +} + +template static inline +Mat_<_Tp>& operator += (Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignAdd(b, a); + return a; +} + +template static inline +const Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignAdd(b, (Mat&)a); + return a; +} + +static inline +Mat& operator -= (Mat& a, const MatExpr& b) +{ + b.op->augAssignSubtract(b, a); + return a; +} + +static inline +const Mat& operator -= (const Mat& a, const MatExpr& b) +{ + b.op->augAssignSubtract(b, (Mat&)a); + return a; +} + +template static inline +Mat_<_Tp>& operator -= (Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignSubtract(b, a); + return a; +} + +template static inline +const Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignSubtract(b, (Mat&)a); + return a; +} + +static inline +Mat& operator *= (Mat& a, const MatExpr& b) +{ + b.op->augAssignMultiply(b, a); + return a; +} + +static inline +const Mat& operator *= (const Mat& a, const MatExpr& b) +{ + b.op->augAssignMultiply(b, (Mat&)a); + return a; +} + +template static inline +Mat_<_Tp>& operator *= (Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignMultiply(b, a); + return a; +} + +template static inline +const Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignMultiply(b, (Mat&)a); + return a; +} + +static inline +Mat& operator /= (Mat& a, const MatExpr& b) +{ + b.op->augAssignDivide(b, a); + return a; +} + +static inline +const Mat& operator /= (const Mat& a, const MatExpr& b) +{ + b.op->augAssignDivide(b, (Mat&)a); + return a; +} + +template static inline +Mat_<_Tp>& operator /= (Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignDivide(b, a); + return a; +} + +template static inline +const Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b) +{ + b.op->augAssignDivide(b, (Mat&)a); + return a; +} + + +//////////////////////////////// UMat //////////////////////////////// + +inline +UMat::UMat(UMatUsageFlags _usageFlags) +: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows) +{} + +inline +UMat::UMat(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags) +: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows) +{ + create(_rows, _cols, _type); +} + +inline +UMat::UMat(int _rows, int _cols, int _type, const Scalar& _s, UMatUsageFlags _usageFlags) +: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows) +{ + create(_rows, _cols, _type); + *this = _s; +} + +inline +UMat::UMat(Size _sz, int _type, UMatUsageFlags _usageFlags) +: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows) +{ + create( _sz.height, _sz.width, _type ); +} + +inline +UMat::UMat(Size _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags) +: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows) +{ + create(_sz.height, _sz.width, _type); + *this = _s; +} + +inline +UMat::UMat(int _dims, const int* _sz, int _type, UMatUsageFlags _usageFlags) +: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows) +{ + create(_dims, _sz, _type); +} + +inline +UMat::UMat(int _dims, const int* _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags) +: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows) +{ + create(_dims, _sz, _type); + *this = _s; +} + +inline +UMat::UMat(const UMat& m) +: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), allocator(m.allocator), + usageFlags(m.usageFlags), u(m.u), offset(m.offset), size(&rows) +{ + addref(); + if( m.dims <= 2 ) + { + step[0] = m.step[0]; step[1] = m.step[1]; + } + else + { + dims = 0; + copySize(m); + } +} + + +template inline +UMat::UMat(const std::vector<_Tp>& vec, bool copyData) +: flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()), +cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows) +{ + if(vec.empty()) + return; + if( !copyData ) + { + // !!!TODO!!! + CV_Error(Error::StsNotImplemented, ""); + } + else + Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this); +} + + +inline +UMat& UMat::operator = (const UMat& m) +{ + if( this != &m ) + { + const_cast(m).addref(); + release(); + flags = m.flags; + if( dims <= 2 && m.dims <= 2 ) + { + dims = m.dims; + rows = m.rows; + cols = m.cols; + step[0] = m.step[0]; + step[1] = m.step[1]; + } + else + copySize(m); + allocator = m.allocator; + if (usageFlags == USAGE_DEFAULT) + usageFlags = m.usageFlags; + u = m.u; + offset = m.offset; + } + return *this; +} + +inline +UMat UMat::row(int y) const +{ + return UMat(*this, Range(y, y + 1), Range::all()); +} + +inline +UMat UMat::col(int x) const +{ + return UMat(*this, Range::all(), Range(x, x + 1)); +} + +inline +UMat UMat::rowRange(int startrow, int endrow) const +{ + return UMat(*this, Range(startrow, endrow), Range::all()); +} + +inline +UMat UMat::rowRange(const Range& r) const +{ + return UMat(*this, r, Range::all()); +} + +inline +UMat UMat::colRange(int startcol, int endcol) const +{ + return UMat(*this, Range::all(), Range(startcol, endcol)); +} + +inline +UMat UMat::colRange(const Range& r) const +{ + return UMat(*this, Range::all(), r); +} + +inline +UMat UMat::clone() const +{ + UMat m; + copyTo(m); + return m; +} + +inline +void UMat::assignTo( UMat& m, int _type ) const +{ + if( _type < 0 ) + m = *this; + else + convertTo(m, _type); +} + +inline +void UMat::create(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags) +{ + _type &= TYPE_MASK; + if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && u ) + return; + int sz[] = {_rows, _cols}; + create(2, sz, _type, _usageFlags); +} + +inline +void UMat::create(Size _sz, int _type, UMatUsageFlags _usageFlags) +{ + create(_sz.height, _sz.width, _type, _usageFlags); +} + +inline +void UMat::addref() +{ + if( u ) + CV_XADD(&(u->urefcount), 1); +} + +inline void UMat::release() +{ + if( u && CV_XADD(&(u->urefcount), -1) == 1 ) + deallocate(); + for(int i = 0; i < dims; i++) + size.p[i] = 0; + u = 0; +} + +inline +UMat UMat::operator()( Range _rowRange, Range _colRange ) const +{ + return UMat(*this, _rowRange, _colRange); +} + +inline +UMat UMat::operator()( const Rect& roi ) const +{ + return UMat(*this, roi); +} + +inline +UMat UMat::operator()(const Range* ranges) const +{ + return UMat(*this, ranges); +} + +inline +bool UMat::isContinuous() const +{ + return (flags & CONTINUOUS_FLAG) != 0; +} + +inline +bool UMat::isSubmatrix() const +{ + return (flags & SUBMATRIX_FLAG) != 0; +} + +inline +size_t UMat::elemSize() const +{ + return dims > 0 ? step.p[dims - 1] : 0; +} + +inline +size_t UMat::elemSize1() const +{ + return CV_ELEM_SIZE1(flags); +} + +inline +int UMat::type() const +{ + return CV_MAT_TYPE(flags); +} + +inline +int UMat::depth() const +{ + return CV_MAT_DEPTH(flags); +} + +inline +int UMat::channels() const +{ + return CV_MAT_CN(flags); +} + +inline +size_t UMat::step1(int i) const +{ + return step.p[i] / elemSize1(); +} + +inline +bool UMat::empty() const +{ + return u == 0 || total() == 0; +} + +inline +size_t UMat::total() const +{ + if( dims <= 2 ) + return (size_t)rows * cols; + size_t p = 1; + for( int i = 0; i < dims; i++ ) + p *= size[i]; + return p; +} + +inline bool UMatData::hostCopyObsolete() const { return (flags & HOST_COPY_OBSOLETE) != 0; } +inline bool UMatData::deviceCopyObsolete() const { return (flags & DEVICE_COPY_OBSOLETE) != 0; } +inline bool UMatData::deviceMemMapped() const { return (flags & DEVICE_MEM_MAPPED) != 0; } +inline bool UMatData::copyOnMap() const { return (flags & COPY_ON_MAP) != 0; } +inline bool UMatData::tempUMat() const { return (flags & TEMP_UMAT) != 0; } +inline bool UMatData::tempCopiedUMat() const { return (flags & TEMP_COPIED_UMAT) == TEMP_COPIED_UMAT; } + +inline void UMatData::markDeviceMemMapped(bool flag) +{ + if(flag) + flags |= DEVICE_MEM_MAPPED; + else + flags &= ~DEVICE_MEM_MAPPED; +} + +inline void UMatData::markHostCopyObsolete(bool flag) +{ + if(flag) + flags |= HOST_COPY_OBSOLETE; + else + flags &= ~HOST_COPY_OBSOLETE; +} +inline void UMatData::markDeviceCopyObsolete(bool flag) +{ + if(flag) + flags |= DEVICE_COPY_OBSOLETE; + else + flags &= ~DEVICE_COPY_OBSOLETE; +} + +inline UMatDataAutoLock::UMatDataAutoLock(UMatData* _u) : u(_u) { u->lock(); } +inline UMatDataAutoLock::~UMatDataAutoLock() { u->unlock(); } + +//! @endcond + +} //cv + +#endif diff --git a/include/opencv2/core/matx.hpp b/include/opencv2/core/matx.hpp new file mode 100644 index 0000000..2a17744 --- /dev/null +++ b/include/opencv2/core/matx.hpp @@ -0,0 +1,1376 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_MATX_HPP__ +#define __OPENCV_CORE_MATX_HPP__ + +#ifndef __cplusplus +# error matx.hpp header must be compiled as C++ +#endif + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/base.hpp" +#include "opencv2/core/traits.hpp" + +namespace cv +{ + +//! @addtogroup core_basic +//! @{ + +////////////////////////////// Small Matrix /////////////////////////// + +//! @cond IGNORED +struct CV_EXPORTS Matx_AddOp {}; +struct CV_EXPORTS Matx_SubOp {}; +struct CV_EXPORTS Matx_ScaleOp {}; +struct CV_EXPORTS Matx_MulOp {}; +struct CV_EXPORTS Matx_DivOp {}; +struct CV_EXPORTS Matx_MatMulOp {}; +struct CV_EXPORTS Matx_TOp {}; +//! @endcond + +/** @brief Template class for small matrices whose type and size are known at compilation time + +If you need a more flexible type, use Mat . The elements of the matrix M are accessible using the +M(i,j) notation. Most of the common matrix operations (see also @ref MatrixExpressions ) are +available. To do an operation on Matx that is not implemented, you can easily convert the matrix to +Mat and backwards: +@code + Matx33f m(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + cout << sum(Mat(m*m.t())) << endl; + @endcode + */ +template class Matx +{ +public: + enum { depth = DataType<_Tp>::depth, + rows = m, + cols = n, + channels = rows*cols, + type = CV_MAKETYPE(depth, channels), + shortdim = (m < n ? m : n) + }; + + typedef _Tp value_type; + typedef Matx<_Tp, m, n> mat_type; + typedef Matx<_Tp, shortdim, 1> diag_type; + + //! default constructor + Matx(); + + Matx(_Tp v0); //!< 1x1 matrix + Matx(_Tp v0, _Tp v1); //!< 1x2 or 2x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2); //!< 1x3 or 3x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 1x4, 2x2 or 4x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 1x5 or 5x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 1x6, 2x3, 3x2 or 6x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 1x7 or 7x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 1x8, 2x4, 4x2 or 8x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 1x9, 3x3 or 9x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 1x10, 2x5 or 5x2 or 10x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, + _Tp v4, _Tp v5, _Tp v6, _Tp v7, + _Tp v8, _Tp v9, _Tp v10, _Tp v11); //!< 1x12, 2x6, 3x4, 4x3, 6x2 or 12x1 matrix + Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, + _Tp v4, _Tp v5, _Tp v6, _Tp v7, + _Tp v8, _Tp v9, _Tp v10, _Tp v11, + _Tp v12, _Tp v13, _Tp v14, _Tp v15); //!< 1x16, 4x4 or 16x1 matrix + explicit Matx(const _Tp* vals); //!< initialize from a plain array + + static Matx all(_Tp alpha); + static Matx zeros(); + static Matx ones(); + static Matx eye(); + static Matx diag(const diag_type& d); + static Matx randu(_Tp a, _Tp b); + static Matx randn(_Tp a, _Tp b); + + //! dot product computed with the default precision + _Tp dot(const Matx<_Tp, m, n>& v) const; + + //! dot product computed in double-precision arithmetics + double ddot(const Matx<_Tp, m, n>& v) const; + + //! conversion to another data type + template operator Matx() const; + + //! change the matrix shape + template Matx<_Tp, m1, n1> reshape() const; + + //! extract part of the matrix + template Matx<_Tp, m1, n1> get_minor(int i, int j) const; + + //! extract the matrix row + Matx<_Tp, 1, n> row(int i) const; + + //! extract the matrix column + Matx<_Tp, m, 1> col(int i) const; + + //! extract the matrix diagonal + diag_type diag() const; + + //! transpose the matrix + Matx<_Tp, n, m> t() const; + + //! invert the matrix + Matx<_Tp, n, m> inv(int method=DECOMP_LU, bool *p_is_ok = NULL) const; + + //! solve linear system + template Matx<_Tp, n, l> solve(const Matx<_Tp, m, l>& rhs, int flags=DECOMP_LU) const; + Vec<_Tp, n> solve(const Vec<_Tp, m>& rhs, int method) const; + + //! multiply two matrices element-wise + Matx<_Tp, m, n> mul(const Matx<_Tp, m, n>& a) const; + + //! divide two matrices element-wise + Matx<_Tp, m, n> div(const Matx<_Tp, m, n>& a) const; + + //! element access + const _Tp& operator ()(int i, int j) const; + _Tp& operator ()(int i, int j); + + //! 1D element access + const _Tp& operator ()(int i) const; + _Tp& operator ()(int i); + + Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp); + Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp); + template Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp); + Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp); + Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_DivOp); + template Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp); + Matx(const Matx<_Tp, n, m>& a, Matx_TOp); + + _Tp val[m*n]; //< matrix elements +}; + +typedef Matx Matx12f; +typedef Matx Matx12d; +typedef Matx Matx13f; +typedef Matx Matx13d; +typedef Matx Matx14f; +typedef Matx Matx14d; +typedef Matx Matx16f; +typedef Matx Matx16d; + +typedef Matx Matx21f; +typedef Matx Matx21d; +typedef Matx Matx31f; +typedef Matx Matx31d; +typedef Matx Matx41f; +typedef Matx Matx41d; +typedef Matx Matx61f; +typedef Matx Matx61d; + +typedef Matx Matx22f; +typedef Matx Matx22d; +typedef Matx Matx23f; +typedef Matx Matx23d; +typedef Matx Matx32f; +typedef Matx Matx32d; + +typedef Matx Matx33f; +typedef Matx Matx33d; + +typedef Matx Matx34f; +typedef Matx Matx34d; +typedef Matx Matx43f; +typedef Matx Matx43d; + +typedef Matx Matx44f; +typedef Matx Matx44d; +typedef Matx Matx66f; +typedef Matx Matx66d; + +/*! + traits +*/ +template class DataType< Matx<_Tp, m, n> > +{ +public: + typedef Matx<_Tp, m, n> value_type; + typedef Matx::work_type, m, n> work_type; + typedef _Tp channel_type; + typedef value_type vec_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = m * n, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; +}; + +/** @brief Comma-separated Matrix Initializer +*/ +template class MatxCommaInitializer +{ +public: + MatxCommaInitializer(Matx<_Tp, m, n>* _mtx); + template MatxCommaInitializer<_Tp, m, n>& operator , (T2 val); + Matx<_Tp, m, n> operator *() const; + + Matx<_Tp, m, n>* dst; + int idx; +}; + +/* + Utility methods +*/ +template static double determinant(const Matx<_Tp, m, m>& a); +template static double trace(const Matx<_Tp, m, n>& a); +template static double norm(const Matx<_Tp, m, n>& M); +template static double norm(const Matx<_Tp, m, n>& M, int normType); + + + +/////////////////////// Vec (used as element of multi-channel images ///////////////////// + +/** @brief Template class for short numerical vectors, a partial case of Matx + +This template class represents short numerical vectors (of 1, 2, 3, 4 ... elements) on which you +can perform basic arithmetical operations, access individual elements using [] operator etc. The +vectors are allocated on stack, as opposite to std::valarray, std::vector, cv::Mat etc., which +elements are dynamically allocated in the heap. + +The template takes 2 parameters: +@tparam _Tp element type +@tparam cn the number of elements + +In addition to the universal notation like Vec, you can use shorter aliases +for the most popular specialized variants of Vec, e.g. Vec3f ~ Vec. + +It is possible to convert Vec\ to/from Point_, Vec\ to/from Point3_ , and Vec\ +to CvScalar or Scalar_. Use operator[] to access the elements of Vec. + +All the expected vector operations are also implemented: +- v1 = v2 + v3 +- v1 = v2 - v3 +- v1 = v2 \* scale +- v1 = scale \* v2 +- v1 = -v2 +- v1 += v2 and other augmenting operations +- v1 == v2, v1 != v2 +- norm(v1) (euclidean norm) +The Vec class is commonly used to describe pixel types of multi-channel arrays. See Mat for details. +*/ +template class Vec : public Matx<_Tp, cn, 1> +{ +public: + typedef _Tp value_type; + enum { depth = Matx<_Tp, cn, 1>::depth, + channels = cn, + type = CV_MAKETYPE(depth, channels) + }; + + //! default constructor + Vec(); + + Vec(_Tp v0); //!< 1-element vector constructor + Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructor + Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 10-element vector constructor + explicit Vec(const _Tp* values); + + Vec(const Vec<_Tp, cn>& v); + + static Vec all(_Tp alpha); + + //! per-element multiplication + Vec mul(const Vec<_Tp, cn>& v) const; + + //! conjugation (makes sense for complex numbers and quaternions) + Vec conj() const; + + /*! + cross product of the two 3D vectors. + + For other dimensionalities the exception is raised + */ + Vec cross(const Vec& v) const; + //! conversion to another data type + template operator Vec() const; + + /*! element access */ + const _Tp& operator [](int i) const; + _Tp& operator[](int i); + const _Tp& operator ()(int i) const; + _Tp& operator ()(int i); + + Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp); + Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp); + template Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp); +}; + +/** @name Shorter aliases for the most popular specializations of Vec + @{ +*/ +typedef Vec Vec2b; +typedef Vec Vec3b; +typedef Vec Vec4b; + +typedef Vec Vec2s; +typedef Vec Vec3s; +typedef Vec Vec4s; + +typedef Vec Vec2w; +typedef Vec Vec3w; +typedef Vec Vec4w; + +typedef Vec Vec2i; +typedef Vec Vec3i; +typedef Vec Vec4i; +typedef Vec Vec6i; +typedef Vec Vec8i; + +typedef Vec Vec2f; +typedef Vec Vec3f; +typedef Vec Vec4f; +typedef Vec Vec6f; + +typedef Vec Vec2d; +typedef Vec Vec3d; +typedef Vec Vec4d; +typedef Vec Vec6d; +/** @} */ + +/*! + traits +*/ +template class DataType< Vec<_Tp, cn> > +{ +public: + typedef Vec<_Tp, cn> value_type; + typedef Vec::work_type, cn> work_type; + typedef _Tp channel_type; + typedef value_type vec_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = cn, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; +}; + +/** @brief Comma-separated Vec Initializer +*/ +template class VecCommaInitializer : public MatxCommaInitializer<_Tp, m, 1> +{ +public: + VecCommaInitializer(Vec<_Tp, m>* _vec); + template VecCommaInitializer<_Tp, m>& operator , (T2 val); + Vec<_Tp, m> operator *() const; +}; + +template static Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v); + +//! @} core_basic + +//! @cond IGNORED + +///////////////////////////////////// helper classes ///////////////////////////////////// +namespace internal +{ + +template struct Matx_DetOp +{ + double operator ()(const Matx<_Tp, m, m>& a) const + { + Matx<_Tp, m, m> temp = a; + double p = LU(temp.val, m*sizeof(_Tp), m, 0, 0, 0); + if( p == 0 ) + return p; + for( int i = 0; i < m; i++ ) + p *= temp(i, i); + return 1./p; + } +}; + +template struct Matx_DetOp<_Tp, 1> +{ + double operator ()(const Matx<_Tp, 1, 1>& a) const + { + return a(0,0); + } +}; + +template struct Matx_DetOp<_Tp, 2> +{ + double operator ()(const Matx<_Tp, 2, 2>& a) const + { + return a(0,0)*a(1,1) - a(0,1)*a(1,0); + } +}; + +template struct Matx_DetOp<_Tp, 3> +{ + double operator ()(const Matx<_Tp, 3, 3>& a) const + { + return a(0,0)*(a(1,1)*a(2,2) - a(2,1)*a(1,2)) - + a(0,1)*(a(1,0)*a(2,2) - a(2,0)*a(1,2)) + + a(0,2)*(a(1,0)*a(2,1) - a(2,0)*a(1,1)); + } +}; + +template Vec<_Tp, 2> inline conjugate(const Vec<_Tp, 2>& v) +{ + return Vec<_Tp, 2>(v[0], -v[1]); +} + +template Vec<_Tp, 4> inline conjugate(const Vec<_Tp, 4>& v) +{ + return Vec<_Tp, 4>(v[0], -v[1], -v[2], -v[3]); +} + +} // internal + + + +////////////////////////////////// Matx Implementation /////////////////////////////////// + +template inline +Matx<_Tp, m, n>::Matx() +{ + for(int i = 0; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0) +{ + val[0] = v0; + for(int i = 1; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1) +{ + CV_StaticAssert(channels >= 2, "Matx should have at least 2 elaments."); + val[0] = v0; val[1] = v1; + for(int i = 2; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2) +{ + CV_StaticAssert(channels >= 3, "Matx should have at least 3 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; + for(int i = 3; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3) +{ + CV_StaticAssert(channels >= 4, "Matx should have at least 4 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + for(int i = 4; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) +{ + CV_StaticAssert(channels >= 5, "Matx should have at least 5 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; + for(int i = 5; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5) +{ + CV_StaticAssert(channels >= 6, "Matx should have at least 6 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + val[4] = v4; val[5] = v5; + for(int i = 6; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6) +{ + CV_StaticAssert(channels >= 7, "Matx should have at least 7 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + val[4] = v4; val[5] = v5; val[6] = v6; + for(int i = 7; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7) +{ + CV_StaticAssert(channels >= 8, "Matx should have at least 8 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; + for(int i = 8; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8) +{ + CV_StaticAssert(channels >= 9, "Matx should have at least 9 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; + val[8] = v8; + for(int i = 9; i < channels; i++) val[i] = _Tp(0); +} + +template inline +Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9) +{ + CV_StaticAssert(channels >= 10, "Matx should have at least 10 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; + val[8] = v8; val[9] = v9; + for(int i = 10; i < channels; i++) val[i] = _Tp(0); +} + + +template inline +Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11) +{ + CV_StaticAssert(channels == 12, "Matx should have at least 12 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; + val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11; +} + +template inline +Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13, _Tp v14, _Tp v15) +{ + CV_StaticAssert(channels == 16, "Matx should have at least 16 elaments."); + val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; + val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; + val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11; + val[12] = v12; val[13] = v13; val[14] = v14; val[15] = v15; +} + +template inline +Matx<_Tp, m, n>::Matx(const _Tp* values) +{ + for( int i = 0; i < channels; i++ ) val[i] = values[i]; +} + +template inline +Matx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha) +{ + Matx<_Tp, m, n> M; + for( int i = 0; i < m*n; i++ ) M.val[i] = alpha; + return M; +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::zeros() +{ + return all(0); +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::ones() +{ + return all(1); +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::eye() +{ + Matx<_Tp,m,n> M; + for(int i = 0; i < shortdim; i++) + M(i,i) = 1; + return M; +} + +template inline +_Tp Matx<_Tp, m, n>::dot(const Matx<_Tp, m, n>& M) const +{ + _Tp s = 0; + for( int i = 0; i < channels; i++ ) s += val[i]*M.val[i]; + return s; +} + +template inline +double Matx<_Tp, m, n>::ddot(const Matx<_Tp, m, n>& M) const +{ + double s = 0; + for( int i = 0; i < channels; i++ ) s += (double)val[i]*M.val[i]; + return s; +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::diag(const typename Matx<_Tp,m,n>::diag_type& d) +{ + Matx<_Tp,m,n> M; + for(int i = 0; i < shortdim; i++) + M(i,i) = d(i, 0); + return M; +} + +template template +inline Matx<_Tp, m, n>::operator Matx() const +{ + Matx M; + for( int i = 0; i < m*n; i++ ) M.val[i] = saturate_cast(val[i]); + return M; +} + +template template inline +Matx<_Tp, m1, n1> Matx<_Tp, m, n>::reshape() const +{ + CV_StaticAssert(m1*n1 == m*n, "Input and destnarion matrices must have the same number of elements"); + return (const Matx<_Tp, m1, n1>&)*this; +} + +template +template inline +Matx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int i, int j) const +{ + CV_DbgAssert(0 <= i && i+m1 <= m && 0 <= j && j+n1 <= n); + Matx<_Tp, m1, n1> s; + for( int di = 0; di < m1; di++ ) + for( int dj = 0; dj < n1; dj++ ) + s(di, dj) = (*this)(i+di, j+dj); + return s; +} + +template inline +Matx<_Tp, 1, n> Matx<_Tp, m, n>::row(int i) const +{ + CV_DbgAssert((unsigned)i < (unsigned)m); + return Matx<_Tp, 1, n>(&val[i*n]); +} + +template inline +Matx<_Tp, m, 1> Matx<_Tp, m, n>::col(int j) const +{ + CV_DbgAssert((unsigned)j < (unsigned)n); + Matx<_Tp, m, 1> v; + for( int i = 0; i < m; i++ ) + v.val[i] = val[i*n + j]; + return v; +} + +template inline +typename Matx<_Tp, m, n>::diag_type Matx<_Tp, m, n>::diag() const +{ + diag_type d; + for( int i = 0; i < shortdim; i++ ) + d.val[i] = val[i*n + i]; + return d; +} + +template inline +const _Tp& Matx<_Tp, m, n>::operator()(int i, int j) const +{ + CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n ); + return this->val[i*n + j]; +} + +template inline +_Tp& Matx<_Tp, m, n>::operator ()(int i, int j) +{ + CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n ); + return val[i*n + j]; +} + +template inline +const _Tp& Matx<_Tp, m, n>::operator ()(int i) const +{ + CV_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row"); + CV_DbgAssert( (unsigned)i < (unsigned)(m+n-1) ); + return val[i]; +} + +template inline +_Tp& Matx<_Tp, m, n>::operator ()(int i) +{ + CV_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row"); + CV_DbgAssert( (unsigned)i < (unsigned)(m+n-1) ); + return val[i]; +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]); +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]); +} + +template template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] * alpha); +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] * b.val[i]); +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_DivOp) +{ + for( int i = 0; i < channels; i++ ) + val[i] = saturate_cast<_Tp>(a.val[i] / b.val[i]); +} + +template template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp) +{ + for( int i = 0; i < m; i++ ) + for( int j = 0; j < n; j++ ) + { + _Tp s = 0; + for( int k = 0; k < l; k++ ) + s += a(i, k) * b(k, j); + val[i*n + j] = s; + } +} + +template inline +Matx<_Tp,m,n>::Matx(const Matx<_Tp, n, m>& a, Matx_TOp) +{ + for( int i = 0; i < m; i++ ) + for( int j = 0; j < n; j++ ) + val[i*n + j] = a(j, i); +} + +template inline +Matx<_Tp, m, n> Matx<_Tp, m, n>::mul(const Matx<_Tp, m, n>& a) const +{ + return Matx<_Tp, m, n>(*this, a, Matx_MulOp()); +} + +template inline +Matx<_Tp, m, n> Matx<_Tp, m, n>::div(const Matx<_Tp, m, n>& a) const +{ + return Matx<_Tp, m, n>(*this, a, Matx_DivOp()); +} + +template inline +Matx<_Tp, n, m> Matx<_Tp, m, n>::t() const +{ + return Matx<_Tp, n, m>(*this, Matx_TOp()); +} + +template inline +Vec<_Tp, n> Matx<_Tp, m, n>::solve(const Vec<_Tp, m>& rhs, int method) const +{ + Matx<_Tp, n, 1> x = solve((const Matx<_Tp, m, 1>&)(rhs), method); + return (Vec<_Tp, n>&)(x); +} + +template static inline +double determinant(const Matx<_Tp, m, m>& a) +{ + return cv::internal::Matx_DetOp<_Tp, m>()(a); +} + +template static inline +double trace(const Matx<_Tp, m, n>& a) +{ + _Tp s = 0; + for( int i = 0; i < std::min(m, n); i++ ) + s += a(i,i); + return s; +} + +template static inline +double norm(const Matx<_Tp, m, n>& M) +{ + return std::sqrt(normL2Sqr<_Tp, double>(M.val, m*n)); +} + +template static inline +double norm(const Matx<_Tp, m, n>& M, int normType) +{ + return normType == NORM_INF ? (double)normInf<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) : + normType == NORM_L1 ? (double)normL1<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) : + std::sqrt((double)normL2Sqr<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n)); +} + + + +//////////////////////////////// matx comma initializer ////////////////////////////////// + +template static inline +MatxCommaInitializer<_Tp, m, n> operator << (const Matx<_Tp, m, n>& mtx, _T2 val) +{ + MatxCommaInitializer<_Tp, m, n> commaInitializer((Matx<_Tp, m, n>*)&mtx); + return (commaInitializer, val); +} + +template inline +MatxCommaInitializer<_Tp, m, n>::MatxCommaInitializer(Matx<_Tp, m, n>* _mtx) + : dst(_mtx), idx(0) +{} + +template template inline +MatxCommaInitializer<_Tp, m, n>& MatxCommaInitializer<_Tp, m, n>::operator , (_T2 value) +{ + CV_DbgAssert( idx < m*n ); + dst->val[idx++] = saturate_cast<_Tp>(value); + return *this; +} + +template inline +Matx<_Tp, m, n> MatxCommaInitializer<_Tp, m, n>::operator *() const +{ + CV_DbgAssert( idx == n*m ); + return *dst; +} + + + +/////////////////////////////////// Vec Implementation /////////////////////////////////// + +template inline +Vec<_Tp, cn>::Vec() {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0) + : Matx<_Tp, cn, 1>(v0) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1) + : Matx<_Tp, cn, 1>(v0, v1) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2) + : Matx<_Tp, cn, 1>(v0, v1, v2) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8) {} + +template inline +Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9) + : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {} + +template inline +Vec<_Tp, cn>::Vec(const _Tp* values) + : Matx<_Tp, cn, 1>(values) {} + +template inline +Vec<_Tp, cn>::Vec(const Vec<_Tp, cn>& m) + : Matx<_Tp, cn, 1>(m.val) {} + +template inline +Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp op) + : Matx<_Tp, cn, 1>(a, b, op) {} + +template inline +Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp op) + : Matx<_Tp, cn, 1>(a, b, op) {} + +template template inline +Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp op) + : Matx<_Tp, cn, 1>(a, alpha, op) {} + +template inline +Vec<_Tp, cn> Vec<_Tp, cn>::all(_Tp alpha) +{ + Vec v; + for( int i = 0; i < cn; i++ ) v.val[i] = alpha; + return v; +} + +template inline +Vec<_Tp, cn> Vec<_Tp, cn>::mul(const Vec<_Tp, cn>& v) const +{ + Vec<_Tp, cn> w; + for( int i = 0; i < cn; i++ ) w.val[i] = saturate_cast<_Tp>(this->val[i]*v.val[i]); + return w; +} + +template<> inline +Vec Vec::conj() const +{ + return cv::internal::conjugate(*this); +} + +template<> inline +Vec Vec::conj() const +{ + return cv::internal::conjugate(*this); +} + +template<> inline +Vec Vec::conj() const +{ + return cv::internal::conjugate(*this); +} + +template<> inline +Vec Vec::conj() const +{ + return cv::internal::conjugate(*this); +} + +template inline +Vec<_Tp, cn> Vec<_Tp, cn>::cross(const Vec<_Tp, cn>&) const +{ + CV_StaticAssert(cn == 3, "for arbitrary-size vector there is no cross-product defined"); + return Vec<_Tp, cn>(); +} + +template<> inline +Vec Vec::cross(const Vec& v) const +{ + return Vec(val[1]*v.val[2] - val[2]*v.val[1], + val[2]*v.val[0] - val[0]*v.val[2], + val[0]*v.val[1] - val[1]*v.val[0]); +} + +template<> inline +Vec Vec::cross(const Vec& v) const +{ + return Vec(val[1]*v.val[2] - val[2]*v.val[1], + val[2]*v.val[0] - val[0]*v.val[2], + val[0]*v.val[1] - val[1]*v.val[0]); +} + +template template inline +Vec<_Tp, cn>::operator Vec() const +{ + Vec v; + for( int i = 0; i < cn; i++ ) v.val[i] = saturate_cast(this->val[i]); + return v; +} + +template inline +const _Tp& Vec<_Tp, cn>::operator [](int i) const +{ + CV_DbgAssert( (unsigned)i < (unsigned)cn ); + return this->val[i]; +} + +template inline +_Tp& Vec<_Tp, cn>::operator [](int i) +{ + CV_DbgAssert( (unsigned)i < (unsigned)cn ); + return this->val[i]; +} + +template inline +const _Tp& Vec<_Tp, cn>::operator ()(int i) const +{ + CV_DbgAssert( (unsigned)i < (unsigned)cn ); + return this->val[i]; +} + +template inline +_Tp& Vec<_Tp, cn>::operator ()(int i) +{ + CV_DbgAssert( (unsigned)i < (unsigned)cn ); + return this->val[i]; +} + +template inline +Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v) +{ + double nv = norm(v); + return v * (nv ? 1./nv : 0.); +} + + + +//////////////////////////////// matx comma initializer ////////////////////////////////// + + +template static inline +VecCommaInitializer<_Tp, cn> operator << (const Vec<_Tp, cn>& vec, _T2 val) +{ + VecCommaInitializer<_Tp, cn> commaInitializer((Vec<_Tp, cn>*)&vec); + return (commaInitializer, val); +} + +template inline +VecCommaInitializer<_Tp, cn>::VecCommaInitializer(Vec<_Tp, cn>* _vec) + : MatxCommaInitializer<_Tp, cn, 1>(_vec) +{} + +template template inline +VecCommaInitializer<_Tp, cn>& VecCommaInitializer<_Tp, cn>::operator , (_T2 value) +{ + CV_DbgAssert( this->idx < cn ); + this->dst->val[this->idx++] = saturate_cast<_Tp>(value); + return *this; +} + +template inline +Vec<_Tp, cn> VecCommaInitializer<_Tp, cn>::operator *() const +{ + CV_DbgAssert( this->idx == cn ); + return *this->dst; +} + +//! @endcond + +///////////////////////////// Matx out-of-class operators //////////////////////////////// + +//! @relates cv::Matx +//! @{ + +template static inline +Matx<_Tp1, m, n>& operator += (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]); + return a; +} + +template static inline +Matx<_Tp1, m, n>& operator -= (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]); + return a; +} + +template static inline +Matx<_Tp, m, n> operator + (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) +{ + return Matx<_Tp, m, n>(a, b, Matx_AddOp()); +} + +template static inline +Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) +{ + return Matx<_Tp, m, n>(a, b, Matx_SubOp()); +} + +template static inline +Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, int alpha) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); + return a; +} + +template static inline +Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, float alpha) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); + return a; +} + +template static inline +Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, double alpha) +{ + for( int i = 0; i < m*n; i++ ) + a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); + return a; +} + +template static inline +Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, int alpha) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, float alpha) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, double alpha) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (int alpha, const Matx<_Tp, m, n>& a) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (float alpha, const Matx<_Tp, m, n>& a) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (double alpha, const Matx<_Tp, m, n>& a) +{ + return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a) +{ + return Matx<_Tp, m, n>(a, -1, Matx_ScaleOp()); +} + +template static inline +Matx<_Tp, m, n> operator * (const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b) +{ + return Matx<_Tp, m, n>(a, b, Matx_MatMulOp()); +} + +template static inline +Vec<_Tp, m> operator * (const Matx<_Tp, m, n>& a, const Vec<_Tp, n>& b) +{ + Matx<_Tp, m, 1> c(a, b, Matx_MatMulOp()); + return (const Vec<_Tp, m>&)(c); +} + +template static inline +bool operator == (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) +{ + for( int i = 0; i < m*n; i++ ) + if( a.val[i] != b.val[i] ) return false; + return true; +} + +template static inline +bool operator != (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) +{ + return !(a == b); +} + +//! @} + +////////////////////////////// Vec out-of-class operators //////////////////////////////// + +//! @relates cv::Vec +//! @{ + +template static inline +Vec<_Tp1, cn>& operator += (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b) +{ + for( int i = 0; i < cn; i++ ) + a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]); + return a; +} + +template static inline +Vec<_Tp1, cn>& operator -= (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b) +{ + for( int i = 0; i < cn; i++ ) + a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]); + return a; +} + +template static inline +Vec<_Tp, cn> operator + (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b) +{ + return Vec<_Tp, cn>(a, b, Matx_AddOp()); +} + +template static inline +Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b) +{ + return Vec<_Tp, cn>(a, b, Matx_SubOp()); +} + +template static inline +Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, int alpha) +{ + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*alpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, float alpha) +{ + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*alpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, double alpha) +{ + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*alpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, int alpha) +{ + double ialpha = 1./alpha; + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*ialpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, float alpha) +{ + float ialpha = 1.f/alpha; + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*ialpha); + return a; +} + +template static inline +Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, double alpha) +{ + double ialpha = 1./alpha; + for( int i = 0; i < cn; i++ ) + a[i] = saturate_cast<_Tp>(a[i]*ialpha); + return a; +} + +template static inline +Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, int alpha) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (int alpha, const Vec<_Tp, cn>& a) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, float alpha) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (float alpha, const Vec<_Tp, cn>& a) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, double alpha) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator * (double alpha, const Vec<_Tp, cn>& a) +{ + return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, int alpha) +{ + return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, float alpha) +{ + return Vec<_Tp, cn>(a, 1.f/alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, double alpha) +{ + return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp()); +} + +template static inline +Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a) +{ + Vec<_Tp,cn> t; + for( int i = 0; i < cn; i++ ) t.val[i] = saturate_cast<_Tp>(-a.val[i]); + return t; +} + +template inline Vec<_Tp, 4> operator * (const Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2) +{ + return Vec<_Tp, 4>(saturate_cast<_Tp>(v1[0]*v2[0] - v1[1]*v2[1] - v1[2]*v2[2] - v1[3]*v2[3]), + saturate_cast<_Tp>(v1[0]*v2[1] + v1[1]*v2[0] + v1[2]*v2[3] - v1[3]*v2[2]), + saturate_cast<_Tp>(v1[0]*v2[2] - v1[1]*v2[3] + v1[2]*v2[0] + v1[3]*v2[1]), + saturate_cast<_Tp>(v1[0]*v2[3] + v1[1]*v2[2] - v1[2]*v2[1] + v1[3]*v2[0])); +} + +template inline Vec<_Tp, 4>& operator *= (Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2) +{ + v1 = v1 * v2; + return v1; +} + +//! @} + +} // cv + +#endif // __OPENCV_CORE_MATX_HPP__ diff --git a/include/opencv2/core/ocl.hpp b/include/opencv2/core/ocl.hpp new file mode 100644 index 0000000..173722f --- /dev/null +++ b/include/opencv2/core/ocl.hpp @@ -0,0 +1,691 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the OpenCV Foundation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_OPENCL_HPP__ +#define __OPENCV_OPENCL_HPP__ + +#include "opencv2/core.hpp" + +namespace cv { namespace ocl { + +//! @addtogroup core_opencl +//! @{ + +CV_EXPORTS_W bool haveOpenCL(); +CV_EXPORTS_W bool useOpenCL(); +CV_EXPORTS_W bool haveAmdBlas(); +CV_EXPORTS_W bool haveAmdFft(); +CV_EXPORTS_W void setUseOpenCL(bool flag); +CV_EXPORTS_W void finish(); + +CV_EXPORTS bool haveSVM(); + +class CV_EXPORTS Context; +class CV_EXPORTS Device; +class CV_EXPORTS Kernel; +class CV_EXPORTS Program; +class CV_EXPORTS ProgramSource; +class CV_EXPORTS Queue; +class CV_EXPORTS PlatformInfo; +class CV_EXPORTS Image2D; + +class CV_EXPORTS Device +{ +public: + Device(); + explicit Device(void* d); + Device(const Device& d); + Device& operator = (const Device& d); + ~Device(); + + void set(void* d); + + enum + { + TYPE_DEFAULT = (1 << 0), + TYPE_CPU = (1 << 1), + TYPE_GPU = (1 << 2), + TYPE_ACCELERATOR = (1 << 3), + TYPE_DGPU = TYPE_GPU + (1 << 16), + TYPE_IGPU = TYPE_GPU + (1 << 17), + TYPE_ALL = 0xFFFFFFFF + }; + + String name() const; + String extensions() const; + String version() const; + String vendorName() const; + String OpenCL_C_Version() const; + String OpenCLVersion() const; + int deviceVersionMajor() const; + int deviceVersionMinor() const; + String driverVersion() const; + void* ptr() const; + + int type() const; + + int addressBits() const; + bool available() const; + bool compilerAvailable() const; + bool linkerAvailable() const; + + enum + { + FP_DENORM=(1 << 0), + FP_INF_NAN=(1 << 1), + FP_ROUND_TO_NEAREST=(1 << 2), + FP_ROUND_TO_ZERO=(1 << 3), + FP_ROUND_TO_INF=(1 << 4), + FP_FMA=(1 << 5), + FP_SOFT_FLOAT=(1 << 6), + FP_CORRECTLY_ROUNDED_DIVIDE_SQRT=(1 << 7) + }; + int doubleFPConfig() const; + int singleFPConfig() const; + int halfFPConfig() const; + + bool endianLittle() const; + bool errorCorrectionSupport() const; + + enum + { + EXEC_KERNEL=(1 << 0), + EXEC_NATIVE_KERNEL=(1 << 1) + }; + int executionCapabilities() const; + + size_t globalMemCacheSize() const; + + enum + { + NO_CACHE=0, + READ_ONLY_CACHE=1, + READ_WRITE_CACHE=2 + }; + int globalMemCacheType() const; + int globalMemCacheLineSize() const; + size_t globalMemSize() const; + + size_t localMemSize() const; + enum + { + NO_LOCAL_MEM=0, + LOCAL_IS_LOCAL=1, + LOCAL_IS_GLOBAL=2 + }; + int localMemType() const; + bool hostUnifiedMemory() const; + + bool imageSupport() const; + + bool imageFromBufferSupport() const; + uint imagePitchAlignment() const; + uint imageBaseAddressAlignment() const; + + size_t image2DMaxWidth() const; + size_t image2DMaxHeight() const; + + size_t image3DMaxWidth() const; + size_t image3DMaxHeight() const; + size_t image3DMaxDepth() const; + + size_t imageMaxBufferSize() const; + size_t imageMaxArraySize() const; + + enum + { + UNKNOWN_VENDOR=0, + VENDOR_AMD=1, + VENDOR_INTEL=2, + VENDOR_NVIDIA=3 + }; + int vendorID() const; + // FIXIT + // dev.isAMD() doesn't work for OpenCL CPU devices from AMD OpenCL platform. + // This method should use platform name instead of vendor name. + // After fix restore code in arithm.cpp: ocl_compare() + inline bool isAMD() const { return vendorID() == VENDOR_AMD; } + inline bool isIntel() const { return vendorID() == VENDOR_INTEL; } + inline bool isNVidia() const { return vendorID() == VENDOR_NVIDIA; } + + int maxClockFrequency() const; + int maxComputeUnits() const; + int maxConstantArgs() const; + size_t maxConstantBufferSize() const; + + size_t maxMemAllocSize() const; + size_t maxParameterSize() const; + + int maxReadImageArgs() const; + int maxWriteImageArgs() const; + int maxSamplers() const; + + size_t maxWorkGroupSize() const; + int maxWorkItemDims() const; + void maxWorkItemSizes(size_t*) const; + + int memBaseAddrAlign() const; + + int nativeVectorWidthChar() const; + int nativeVectorWidthShort() const; + int nativeVectorWidthInt() const; + int nativeVectorWidthLong() const; + int nativeVectorWidthFloat() const; + int nativeVectorWidthDouble() const; + int nativeVectorWidthHalf() const; + + int preferredVectorWidthChar() const; + int preferredVectorWidthShort() const; + int preferredVectorWidthInt() const; + int preferredVectorWidthLong() const; + int preferredVectorWidthFloat() const; + int preferredVectorWidthDouble() const; + int preferredVectorWidthHalf() const; + + size_t printfBufferSize() const; + size_t profilingTimerResolution() const; + + static const Device& getDefault(); + +protected: + struct Impl; + Impl* p; +}; + + +class CV_EXPORTS Context +{ +public: + Context(); + explicit Context(int dtype); + ~Context(); + Context(const Context& c); + Context& operator = (const Context& c); + + bool create(); + bool create(int dtype); + size_t ndevices() const; + const Device& device(size_t idx) const; + Program getProg(const ProgramSource& prog, + const String& buildopt, String& errmsg); + + static Context& getDefault(bool initialize = true); + void* ptr() const; + + friend void initializeContextFromHandle(Context& ctx, void* platform, void* context, void* device); + + bool useSVM() const; + void setUseSVM(bool enabled); + + struct Impl; + Impl* p; +}; + +class CV_EXPORTS Platform +{ +public: + Platform(); + ~Platform(); + Platform(const Platform& p); + Platform& operator = (const Platform& p); + + void* ptr() const; + static Platform& getDefault(); + + friend void initializeContextFromHandle(Context& ctx, void* platform, void* context, void* device); +protected: + struct Impl; + Impl* p; +}; + +// TODO Move to internal header +void initializeContextFromHandle(Context& ctx, void* platform, void* context, void* device); + +class CV_EXPORTS Queue +{ +public: + Queue(); + explicit Queue(const Context& c, const Device& d=Device()); + ~Queue(); + Queue(const Queue& q); + Queue& operator = (const Queue& q); + + bool create(const Context& c=Context(), const Device& d=Device()); + void finish(); + void* ptr() const; + static Queue& getDefault(); + +protected: + struct Impl; + Impl* p; +}; + + +class CV_EXPORTS KernelArg +{ +public: + enum { LOCAL=1, READ_ONLY=2, WRITE_ONLY=4, READ_WRITE=6, CONSTANT=8, PTR_ONLY = 16, NO_SIZE=256 }; + KernelArg(int _flags, UMat* _m, int wscale=1, int iwscale=1, const void* _obj=0, size_t _sz=0); + KernelArg(); + + static KernelArg Local() { return KernelArg(LOCAL, 0); } + static KernelArg PtrWriteOnly(const UMat& m) + { return KernelArg(PTR_ONLY+WRITE_ONLY, (UMat*)&m); } + static KernelArg PtrReadOnly(const UMat& m) + { return KernelArg(PTR_ONLY+READ_ONLY, (UMat*)&m); } + static KernelArg PtrReadWrite(const UMat& m) + { return KernelArg(PTR_ONLY+READ_WRITE, (UMat*)&m); } + static KernelArg ReadWrite(const UMat& m, int wscale=1, int iwscale=1) + { return KernelArg(READ_WRITE, (UMat*)&m, wscale, iwscale); } + static KernelArg ReadWriteNoSize(const UMat& m, int wscale=1, int iwscale=1) + { return KernelArg(READ_WRITE+NO_SIZE, (UMat*)&m, wscale, iwscale); } + static KernelArg ReadOnly(const UMat& m, int wscale=1, int iwscale=1) + { return KernelArg(READ_ONLY, (UMat*)&m, wscale, iwscale); } + static KernelArg WriteOnly(const UMat& m, int wscale=1, int iwscale=1) + { return KernelArg(WRITE_ONLY, (UMat*)&m, wscale, iwscale); } + static KernelArg ReadOnlyNoSize(const UMat& m, int wscale=1, int iwscale=1) + { return KernelArg(READ_ONLY+NO_SIZE, (UMat*)&m, wscale, iwscale); } + static KernelArg WriteOnlyNoSize(const UMat& m, int wscale=1, int iwscale=1) + { return KernelArg(WRITE_ONLY+NO_SIZE, (UMat*)&m, wscale, iwscale); } + static KernelArg Constant(const Mat& m); + template static KernelArg Constant(const _Tp* arr, size_t n) + { return KernelArg(CONSTANT, 0, 1, 1, (void*)arr, n); } + + int flags; + UMat* m; + const void* obj; + size_t sz; + int wscale, iwscale; +}; + + +class CV_EXPORTS Kernel +{ +public: + Kernel(); + Kernel(const char* kname, const Program& prog); + Kernel(const char* kname, const ProgramSource& prog, + const String& buildopts = String(), String* errmsg=0); + ~Kernel(); + Kernel(const Kernel& k); + Kernel& operator = (const Kernel& k); + + bool empty() const; + bool create(const char* kname, const Program& prog); + bool create(const char* kname, const ProgramSource& prog, + const String& buildopts, String* errmsg=0); + + int set(int i, const void* value, size_t sz); + int set(int i, const Image2D& image2D); + int set(int i, const UMat& m); + int set(int i, const KernelArg& arg); + template int set(int i, const _Tp& value) + { return set(i, &value, sizeof(value)); } + + template + Kernel& args(const _Tp0& a0) + { + set(0, a0); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1) + { + int i = set(0, a0); set(i, a1); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2) + { + int i = set(0, a0); i = set(i, a1); set(i, a2); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, + const _Tp3& a3, const _Tp4& a4) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); + i = set(i, a3); set(i, a4); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, + const _Tp3& a3, const _Tp4& a4, const _Tp5& a5) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); + i = set(i, a3); i = set(i, a4); set(i, a5); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); + i = set(i, a4); i = set(i, a5); set(i, a6); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); + i = set(i, a4); i = set(i, a5); i = set(i, a6); set(i, a7); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7, + const _Tp8& a8) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); i = set(i, a4); + i = set(i, a5); i = set(i, a6); i = set(i, a7); set(i, a8); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7, + const _Tp8& a8, const _Tp9& a9) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); i = set(i, a4); i = set(i, a5); + i = set(i, a6); i = set(i, a7); i = set(i, a8); set(i, a9); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7, + const _Tp8& a8, const _Tp9& a9, const _Tp10& a10) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); i = set(i, a4); i = set(i, a5); + i = set(i, a6); i = set(i, a7); i = set(i, a8); i = set(i, a9); set(i, a10); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7, + const _Tp8& a8, const _Tp9& a9, const _Tp10& a10, const _Tp11& a11) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); i = set(i, a4); i = set(i, a5); + i = set(i, a6); i = set(i, a7); i = set(i, a8); i = set(i, a9); i = set(i, a10); set(i, a11); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7, + const _Tp8& a8, const _Tp9& a9, const _Tp10& a10, const _Tp11& a11, + const _Tp12& a12) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); i = set(i, a4); i = set(i, a5); + i = set(i, a6); i = set(i, a7); i = set(i, a8); i = set(i, a9); i = set(i, a10); i = set(i, a11); + set(i, a12); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7, + const _Tp8& a8, const _Tp9& a9, const _Tp10& a10, const _Tp11& a11, + const _Tp12& a12, const _Tp13& a13) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); i = set(i, a4); i = set(i, a5); + i = set(i, a6); i = set(i, a7); i = set(i, a8); i = set(i, a9); i = set(i, a10); i = set(i, a11); + i = set(i, a12); set(i, a13); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7, + const _Tp8& a8, const _Tp9& a9, const _Tp10& a10, const _Tp11& a11, + const _Tp12& a12, const _Tp13& a13, const _Tp14& a14) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); i = set(i, a4); i = set(i, a5); + i = set(i, a6); i = set(i, a7); i = set(i, a8); i = set(i, a9); i = set(i, a10); i = set(i, a11); + i = set(i, a12); i = set(i, a13); set(i, a14); return *this; + } + + template + Kernel& args(const _Tp0& a0, const _Tp1& a1, const _Tp2& a2, const _Tp3& a3, + const _Tp4& a4, const _Tp5& a5, const _Tp6& a6, const _Tp7& a7, + const _Tp8& a8, const _Tp9& a9, const _Tp10& a10, const _Tp11& a11, + const _Tp12& a12, const _Tp13& a13, const _Tp14& a14, const _Tp15& a15) + { + int i = set(0, a0); i = set(i, a1); i = set(i, a2); i = set(i, a3); i = set(i, a4); i = set(i, a5); + i = set(i, a6); i = set(i, a7); i = set(i, a8); i = set(i, a9); i = set(i, a10); i = set(i, a11); + i = set(i, a12); i = set(i, a13); i = set(i, a14); set(i, a15); return *this; + } + + bool run(int dims, size_t globalsize[], + size_t localsize[], bool sync, const Queue& q=Queue()); + bool runTask(bool sync, const Queue& q=Queue()); + + size_t workGroupSize() const; + size_t preferedWorkGroupSizeMultiple() const; + bool compileWorkGroupSize(size_t wsz[]) const; + size_t localMemSize() const; + + void* ptr() const; + struct Impl; + +protected: + Impl* p; +}; + +class CV_EXPORTS Program +{ +public: + Program(); + Program(const ProgramSource& src, + const String& buildflags, String& errmsg); + explicit Program(const String& buf); + Program(const Program& prog); + + Program& operator = (const Program& prog); + ~Program(); + + bool create(const ProgramSource& src, + const String& buildflags, String& errmsg); + bool read(const String& buf, const String& buildflags); + bool write(String& buf) const; + + const ProgramSource& source() const; + void* ptr() const; + + String getPrefix() const; + static String getPrefix(const String& buildflags); + +protected: + struct Impl; + Impl* p; +}; + + +class CV_EXPORTS ProgramSource +{ +public: + typedef uint64 hash_t; + + ProgramSource(); + explicit ProgramSource(const String& prog); + explicit ProgramSource(const char* prog); + ~ProgramSource(); + ProgramSource(const ProgramSource& prog); + ProgramSource& operator = (const ProgramSource& prog); + + const String& source() const; + hash_t hash() const; + +protected: + struct Impl; + Impl* p; +}; + +class CV_EXPORTS PlatformInfo +{ +public: + PlatformInfo(); + explicit PlatformInfo(void* id); + ~PlatformInfo(); + + PlatformInfo(const PlatformInfo& i); + PlatformInfo& operator =(const PlatformInfo& i); + + String name() const; + String vendor() const; + String version() const; + int deviceNumber() const; + void getDevice(Device& device, int d) const; + +protected: + struct Impl; + Impl* p; +}; + +CV_EXPORTS const char* convertTypeStr(int sdepth, int ddepth, int cn, char* buf); +CV_EXPORTS const char* typeToStr(int t); +CV_EXPORTS const char* memopTypeToStr(int t); +CV_EXPORTS const char* vecopTypeToStr(int t); +CV_EXPORTS String kernelToStr(InputArray _kernel, int ddepth = -1, const char * name = NULL); +CV_EXPORTS void getPlatfomsInfo(std::vector& platform_info); + + +enum OclVectorStrategy +{ + // all matrices have its own vector width + OCL_VECTOR_OWN = 0, + // all matrices have maximal vector width among all matrices + // (useful for cases when matrices have different data types) + OCL_VECTOR_MAX = 1, + + // default strategy + OCL_VECTOR_DEFAULT = OCL_VECTOR_OWN +}; + +CV_EXPORTS int predictOptimalVectorWidth(InputArray src1, InputArray src2 = noArray(), InputArray src3 = noArray(), + InputArray src4 = noArray(), InputArray src5 = noArray(), InputArray src6 = noArray(), + InputArray src7 = noArray(), InputArray src8 = noArray(), InputArray src9 = noArray(), + OclVectorStrategy strat = OCL_VECTOR_DEFAULT); + +CV_EXPORTS int checkOptimalVectorWidth(const int *vectorWidths, + InputArray src1, InputArray src2 = noArray(), InputArray src3 = noArray(), + InputArray src4 = noArray(), InputArray src5 = noArray(), InputArray src6 = noArray(), + InputArray src7 = noArray(), InputArray src8 = noArray(), InputArray src9 = noArray(), + OclVectorStrategy strat = OCL_VECTOR_DEFAULT); + +// with OCL_VECTOR_MAX strategy +CV_EXPORTS int predictOptimalVectorWidthMax(InputArray src1, InputArray src2 = noArray(), InputArray src3 = noArray(), + InputArray src4 = noArray(), InputArray src5 = noArray(), InputArray src6 = noArray(), + InputArray src7 = noArray(), InputArray src8 = noArray(), InputArray src9 = noArray()); + +CV_EXPORTS void buildOptionsAddMatrixDescription(String& buildOptions, const String& name, InputArray _m); + +class CV_EXPORTS Image2D +{ +public: + Image2D(); + + // src: The UMat from which to get image properties and data + // norm: Flag to enable the use of normalized channel data types + // alias: Flag indicating that the image should alias the src UMat. + // If true, changes to the image or src will be reflected in + // both objects. + explicit Image2D(const UMat &src, bool norm = false, bool alias = false); + Image2D(const Image2D & i); + ~Image2D(); + + Image2D & operator = (const Image2D & i); + + // Indicates if creating an aliased image should succeed. Depends on the + // underlying platform and the dimensions of the UMat. + static bool canCreateAlias(const UMat &u); + + // Indicates if the image format is supported. + static bool isFormatSupported(int depth, int cn, bool norm); + + void* ptr() const; +protected: + struct Impl; + Impl* p; +}; + + +CV_EXPORTS MatAllocator* getOpenCLAllocator(); + + +#ifdef __OPENCV_BUILD +namespace internal { + +CV_EXPORTS bool isPerformanceCheckBypassed(); +#define OCL_PERFORMANCE_CHECK(condition) (cv::ocl::internal::isPerformanceCheckBypassed() || (condition)) + +CV_EXPORTS bool isCLBuffer(UMat& u); + +} // namespace internal +#endif + +//! @} + +}} + +#endif diff --git a/include/opencv2/core/ocl_genbase.hpp b/include/opencv2/core/ocl_genbase.hpp new file mode 100644 index 0000000..d53bc1a --- /dev/null +++ b/include/opencv2/core/ocl_genbase.hpp @@ -0,0 +1,64 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the OpenCV Foundation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_OPENCL_GENBASE_HPP__ +#define __OPENCV_OPENCL_GENBASE_HPP__ + +namespace cv +{ +namespace ocl +{ + +//! @cond IGNORED + +struct ProgramEntry +{ + const char* name; + const char* programStr; + const char* programHash; +}; + +//! @endcond + +} +} + +#endif diff --git a/include/opencv2/core/opengl.hpp b/include/opencv2/core/opengl.hpp new file mode 100644 index 0000000..15c635c --- /dev/null +++ b/include/opencv2/core/opengl.hpp @@ -0,0 +1,684 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_OPENGL_HPP__ +#define __OPENCV_CORE_OPENGL_HPP__ + +#ifndef __cplusplus +# error opengl.hpp header must be compiled as C++ +#endif + +#include "opencv2/core.hpp" + +namespace cv { namespace ogl { + +/** @addtogroup core_opengl +This section describes OpenGL interoperability. + +To enable OpenGL support, configure OpenCV using CMake with WITH_OPENGL=ON . Currently OpenGL is +supported only with WIN32, GTK and Qt backends on Windows and Linux (MacOS and Android are not +supported). For GTK backend gtkglext-1.0 library is required. + +To use OpenGL functionality you should first create OpenGL context (window or frame buffer). You can +do this with namedWindow function or with other OpenGL toolkit (GLUT, for example). +*/ +//! @{ + +/////////////////// OpenGL Objects /////////////////// + +/** @brief Smart pointer for OpenGL buffer object with reference counting. + +Buffer Objects are OpenGL objects that store an array of unformatted memory allocated by the OpenGL +context. These can be used to store vertex data, pixel data retrieved from images or the +framebuffer, and a variety of other things. + +ogl::Buffer has interface similar with Mat interface and represents 2D array memory. + +ogl::Buffer supports memory transfers between host and device and also can be mapped to CUDA memory. + */ +class CV_EXPORTS Buffer +{ +public: + /** @brief The target defines how you intend to use the buffer object. + */ + enum Target + { + ARRAY_BUFFER = 0x8892, //!< The buffer will be used as a source for vertex data + ELEMENT_ARRAY_BUFFER = 0x8893, //!< The buffer will be used for indices (in glDrawElements, for example) + PIXEL_PACK_BUFFER = 0x88EB, //!< The buffer will be used for reading from OpenGL textures + PIXEL_UNPACK_BUFFER = 0x88EC //!< The buffer will be used for writing to OpenGL textures + }; + + enum Access + { + READ_ONLY = 0x88B8, + WRITE_ONLY = 0x88B9, + READ_WRITE = 0x88BA + }; + + /** @brief The constructors. + + Creates empty ogl::Buffer object, creates ogl::Buffer object from existed buffer ( abufId + parameter), allocates memory for ogl::Buffer object or copies from host/device memory. + */ + Buffer(); + + /** @overload + @param arows Number of rows in a 2D array. + @param acols Number of columns in a 2D array. + @param atype Array type ( CV_8UC1, ..., CV_64FC4 ). See Mat for details. + @param abufId Buffer object name. + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + Buffer(int arows, int acols, int atype, unsigned int abufId, bool autoRelease = false); + + /** @overload + @param asize 2D array size. + @param atype Array type ( CV_8UC1, ..., CV_64FC4 ). See Mat for details. + @param abufId Buffer object name. + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + Buffer(Size asize, int atype, unsigned int abufId, bool autoRelease = false); + + /** @overload + @param arows Number of rows in a 2D array. + @param acols Number of columns in a 2D array. + @param atype Array type ( CV_8UC1, ..., CV_64FC4 ). See Mat for details. + @param target Buffer usage. See cv::ogl::Buffer::Target . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + Buffer(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false); + + /** @overload + @param asize 2D array size. + @param atype Array type ( CV_8UC1, ..., CV_64FC4 ). See Mat for details. + @param target Buffer usage. See cv::ogl::Buffer::Target . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + Buffer(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false); + + /** @overload + @param arr Input array (host or device memory, it can be Mat , cuda::GpuMat or std::vector ). + @param target Buffer usage. See cv::ogl::Buffer::Target . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + explicit Buffer(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false); + + /** @brief Allocates memory for ogl::Buffer object. + + @param arows Number of rows in a 2D array. + @param acols Number of columns in a 2D array. + @param atype Array type ( CV_8UC1, ..., CV_64FC4 ). See Mat for details. + @param target Buffer usage. See cv::ogl::Buffer::Target . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + void create(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false); + + /** @overload + @param asize 2D array size. + @param atype Array type ( CV_8UC1, ..., CV_64FC4 ). See Mat for details. + @param target Buffer usage. See cv::ogl::Buffer::Target . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + void create(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false); + + /** @brief Decrements the reference counter and destroys the buffer object if needed. + + The function will call setAutoRelease(true) . + */ + void release(); + + /** @brief Sets auto release mode. + + The lifetime of the OpenGL object is tied to the lifetime of the context. If OpenGL context was + bound to a window it could be released at any time (user can close a window). If object's destructor + is called after destruction of the context it will cause an error. Thus ogl::Buffer doesn't destroy + OpenGL object in destructor by default (all OpenGL resources will be released with OpenGL context). + This function can force ogl::Buffer destructor to destroy OpenGL object. + @param flag Auto release mode (if true, release will be called in object's destructor). + */ + void setAutoRelease(bool flag); + + /** @brief Copies from host/device memory to OpenGL buffer. + @param arr Input array (host or device memory, it can be Mat , cuda::GpuMat or std::vector ). + @param target Buffer usage. See cv::ogl::Buffer::Target . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + void copyFrom(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false); + + /** @overload */ + void copyFrom(InputArray arr, cuda::Stream& stream, Target target = ARRAY_BUFFER, bool autoRelease = false); + + /** @brief Copies from OpenGL buffer to host/device memory or another OpenGL buffer object. + + @param arr Destination array (host or device memory, can be Mat , cuda::GpuMat , std::vector or + ogl::Buffer ). + */ + void copyTo(OutputArray arr) const; + + /** @overload */ + void copyTo(OutputArray arr, cuda::Stream& stream) const; + + /** @brief Creates a full copy of the buffer object and the underlying data. + + @param target Buffer usage for destination buffer. + @param autoRelease Auto release mode for destination buffer. + */ + Buffer clone(Target target = ARRAY_BUFFER, bool autoRelease = false) const; + + /** @brief Binds OpenGL buffer to the specified buffer binding point. + + @param target Binding point. See cv::ogl::Buffer::Target . + */ + void bind(Target target) const; + + /** @brief Unbind any buffers from the specified binding point. + + @param target Binding point. See cv::ogl::Buffer::Target . + */ + static void unbind(Target target); + + /** @brief Maps OpenGL buffer to host memory. + + mapHost maps to the client's address space the entire data store of the buffer object. The data can + then be directly read and/or written relative to the returned pointer, depending on the specified + access policy. + + A mapped data store must be unmapped with ogl::Buffer::unmapHost before its buffer object is used. + + This operation can lead to memory transfers between host and device. + + Only one buffer object can be mapped at a time. + @param access Access policy, indicating whether it will be possible to read from, write to, or both + read from and write to the buffer object's mapped data store. The symbolic constant must be + ogl::Buffer::READ_ONLY , ogl::Buffer::WRITE_ONLY or ogl::Buffer::READ_WRITE . + */ + Mat mapHost(Access access); + + /** @brief Unmaps OpenGL buffer. + */ + void unmapHost(); + + //! map to device memory (blocking) + cuda::GpuMat mapDevice(); + void unmapDevice(); + + /** @brief Maps OpenGL buffer to CUDA device memory. + + This operatation doesn't copy data. Several buffer objects can be mapped to CUDA memory at a time. + + A mapped data store must be unmapped with ogl::Buffer::unmapDevice before its buffer object is used. + */ + cuda::GpuMat mapDevice(cuda::Stream& stream); + + /** @brief Unmaps OpenGL buffer. + */ + void unmapDevice(cuda::Stream& stream); + + int rows() const; + int cols() const; + Size size() const; + bool empty() const; + + int type() const; + int depth() const; + int channels() const; + int elemSize() const; + int elemSize1() const; + + //! get OpenGL opject id + unsigned int bufId() const; + + class Impl; + +private: + Ptr impl_; + int rows_; + int cols_; + int type_; +}; + +/** @brief Smart pointer for OpenGL 2D texture memory with reference counting. + */ +class CV_EXPORTS Texture2D +{ +public: + /** @brief An Image Format describes the way that the images in Textures store their data. + */ + enum Format + { + NONE = 0, + DEPTH_COMPONENT = 0x1902, //!< Depth + RGB = 0x1907, //!< Red, Green, Blue + RGBA = 0x1908 //!< Red, Green, Blue, Alpha + }; + + /** @brief The constructors. + + Creates empty ogl::Texture2D object, allocates memory for ogl::Texture2D object or copies from + host/device memory. + */ + Texture2D(); + + /** @overload */ + Texture2D(int arows, int acols, Format aformat, unsigned int atexId, bool autoRelease = false); + + /** @overload */ + Texture2D(Size asize, Format aformat, unsigned int atexId, bool autoRelease = false); + + /** @overload + @param arows Number of rows. + @param acols Number of columns. + @param aformat Image format. See cv::ogl::Texture2D::Format . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + Texture2D(int arows, int acols, Format aformat, bool autoRelease = false); + + /** @overload + @param asize 2D array size. + @param aformat Image format. See cv::ogl::Texture2D::Format . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + Texture2D(Size asize, Format aformat, bool autoRelease = false); + + /** @overload + @param arr Input array (host or device memory, it can be Mat , cuda::GpuMat or ogl::Buffer ). + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + explicit Texture2D(InputArray arr, bool autoRelease = false); + + /** @brief Allocates memory for ogl::Texture2D object. + + @param arows Number of rows. + @param acols Number of columns. + @param aformat Image format. See cv::ogl::Texture2D::Format . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + void create(int arows, int acols, Format aformat, bool autoRelease = false); + /** @overload + @param asize 2D array size. + @param aformat Image format. See cv::ogl::Texture2D::Format . + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + void create(Size asize, Format aformat, bool autoRelease = false); + + /** @brief Decrements the reference counter and destroys the texture object if needed. + + The function will call setAutoRelease(true) . + */ + void release(); + + /** @brief Sets auto release mode. + + @param flag Auto release mode (if true, release will be called in object's destructor). + + The lifetime of the OpenGL object is tied to the lifetime of the context. If OpenGL context was + bound to a window it could be released at any time (user can close a window). If object's destructor + is called after destruction of the context it will cause an error. Thus ogl::Texture2D doesn't + destroy OpenGL object in destructor by default (all OpenGL resources will be released with OpenGL + context). This function can force ogl::Texture2D destructor to destroy OpenGL object. + */ + void setAutoRelease(bool flag); + + /** @brief Copies from host/device memory to OpenGL texture. + + @param arr Input array (host or device memory, it can be Mat , cuda::GpuMat or ogl::Buffer ). + @param autoRelease Auto release mode (if true, release will be called in object's destructor). + */ + void copyFrom(InputArray arr, bool autoRelease = false); + + /** @brief Copies from OpenGL texture to host/device memory or another OpenGL texture object. + + @param arr Destination array (host or device memory, can be Mat , cuda::GpuMat , ogl::Buffer or + ogl::Texture2D ). + @param ddepth Destination depth. + @param autoRelease Auto release mode for destination buffer (if arr is OpenGL buffer or texture). + */ + void copyTo(OutputArray arr, int ddepth = CV_32F, bool autoRelease = false) const; + + /** @brief Binds texture to current active texture unit for GL_TEXTURE_2D target. + */ + void bind() const; + + int rows() const; + int cols() const; + Size size() const; + bool empty() const; + + Format format() const; + + //! get OpenGL opject id + unsigned int texId() const; + + class Impl; + +private: + Ptr impl_; + int rows_; + int cols_; + Format format_; +}; + +/** @brief Wrapper for OpenGL Client-Side Vertex arrays. + +ogl::Arrays stores vertex data in ogl::Buffer objects. + */ +class CV_EXPORTS Arrays +{ +public: + /** @brief Default constructor + */ + Arrays(); + + /** @brief Sets an array of vertex coordinates. + @param vertex array with vertex coordinates, can be both host and device memory. + */ + void setVertexArray(InputArray vertex); + + /** @brief Resets vertex coordinates. + */ + void resetVertexArray(); + + /** @brief Sets an array of vertex colors. + @param color array with vertex colors, can be both host and device memory. + */ + void setColorArray(InputArray color); + + /** @brief Resets vertex colors. + */ + void resetColorArray(); + + /** @brief Sets an array of vertex normals. + @param normal array with vertex normals, can be both host and device memory. + */ + void setNormalArray(InputArray normal); + + /** @brief Resets vertex normals. + */ + void resetNormalArray(); + + /** @brief Sets an array of vertex texture coordinates. + @param texCoord array with vertex texture coordinates, can be both host and device memory. + */ + void setTexCoordArray(InputArray texCoord); + + /** @brief Resets vertex texture coordinates. + */ + void resetTexCoordArray(); + + /** @brief Releases all inner buffers. + */ + void release(); + + /** @brief Sets auto release mode all inner buffers. + @param flag Auto release mode. + */ + void setAutoRelease(bool flag); + + /** @brief Binds all vertex arrays. + */ + void bind() const; + + /** @brief Returns the vertex count. + */ + int size() const; + bool empty() const; + +private: + int size_; + Buffer vertex_; + Buffer color_; + Buffer normal_; + Buffer texCoord_; +}; + +/////////////////// Render Functions /////////////////// + +//! render mode +enum RenderModes { + POINTS = 0x0000, + LINES = 0x0001, + LINE_LOOP = 0x0002, + LINE_STRIP = 0x0003, + TRIANGLES = 0x0004, + TRIANGLE_STRIP = 0x0005, + TRIANGLE_FAN = 0x0006, + QUADS = 0x0007, + QUAD_STRIP = 0x0008, + POLYGON = 0x0009 +}; + +/** @brief Render OpenGL texture or primitives. +@param tex Texture to draw. +@param wndRect Region of window, where to draw a texture (normalized coordinates). +@param texRect Region of texture to draw (normalized coordinates). + */ +CV_EXPORTS void render(const Texture2D& tex, + Rect_ wndRect = Rect_(0.0, 0.0, 1.0, 1.0), + Rect_ texRect = Rect_(0.0, 0.0, 1.0, 1.0)); + +/** @overload +@param arr Array of privitives vertices. +@param mode Render mode. One of cv::ogl::RenderModes +@param color Color for all vertices. Will be used if arr doesn't contain color array. +*/ +CV_EXPORTS void render(const Arrays& arr, int mode = POINTS, Scalar color = Scalar::all(255)); + +/** @overload +@param arr Array of privitives vertices. +@param indices Array of vertices indices (host or device memory). +@param mode Render mode. One of cv::ogl::RenderModes +@param color Color for all vertices. Will be used if arr doesn't contain color array. +*/ +CV_EXPORTS void render(const Arrays& arr, InputArray indices, int mode = POINTS, Scalar color = Scalar::all(255)); + +//! @} core_opengl + +}} // namespace cv::ogl + +namespace cv { namespace cuda { + +//! @addtogroup cuda +//! @{ + +/** @brief Sets a CUDA device and initializes it for the current thread with OpenGL interoperability. + +This function should be explicitly called after OpenGL context creation and before any CUDA calls. +@param device System index of a CUDA device starting with 0. +@ingroup core_opengl + */ +CV_EXPORTS void setGlDevice(int device = 0); + +//! @} + +}} + +//! @cond IGNORED + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +inline +cv::ogl::Buffer::Buffer(int arows, int acols, int atype, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0) +{ + create(arows, acols, atype, target, autoRelease); +} + +inline +cv::ogl::Buffer::Buffer(Size asize, int atype, Target target, bool autoRelease) : rows_(0), cols_(0), type_(0) +{ + create(asize, atype, target, autoRelease); +} + +inline +void cv::ogl::Buffer::create(Size asize, int atype, Target target, bool autoRelease) +{ + create(asize.height, asize.width, atype, target, autoRelease); +} + +inline +int cv::ogl::Buffer::rows() const +{ + return rows_; +} + +inline +int cv::ogl::Buffer::cols() const +{ + return cols_; +} + +inline +cv::Size cv::ogl::Buffer::size() const +{ + return Size(cols_, rows_); +} + +inline +bool cv::ogl::Buffer::empty() const +{ + return rows_ == 0 || cols_ == 0; +} + +inline +int cv::ogl::Buffer::type() const +{ + return type_; +} + +inline +int cv::ogl::Buffer::depth() const +{ + return CV_MAT_DEPTH(type_); +} + +inline +int cv::ogl::Buffer::channels() const +{ + return CV_MAT_CN(type_); +} + +inline +int cv::ogl::Buffer::elemSize() const +{ + return CV_ELEM_SIZE(type_); +} + +inline +int cv::ogl::Buffer::elemSize1() const +{ + return CV_ELEM_SIZE1(type_); +} + +/////// + +inline +cv::ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, bool autoRelease) : rows_(0), cols_(0), format_(NONE) +{ + create(arows, acols, aformat, autoRelease); +} + +inline +cv::ogl::Texture2D::Texture2D(Size asize, Format aformat, bool autoRelease) : rows_(0), cols_(0), format_(NONE) +{ + create(asize, aformat, autoRelease); +} + +inline +void cv::ogl::Texture2D::create(Size asize, Format aformat, bool autoRelease) +{ + create(asize.height, asize.width, aformat, autoRelease); +} + +inline +int cv::ogl::Texture2D::rows() const +{ + return rows_; +} + +inline +int cv::ogl::Texture2D::cols() const +{ + return cols_; +} + +inline +cv::Size cv::ogl::Texture2D::size() const +{ + return Size(cols_, rows_); +} + +inline +bool cv::ogl::Texture2D::empty() const +{ + return rows_ == 0 || cols_ == 0; +} + +inline +cv::ogl::Texture2D::Format cv::ogl::Texture2D::format() const +{ + return format_; +} + +/////// + +inline +cv::ogl::Arrays::Arrays() : size_(0) +{ +} + +inline +int cv::ogl::Arrays::size() const +{ + return size_; +} + +inline +bool cv::ogl::Arrays::empty() const +{ + return size_ == 0; +} + +//! @endcond + +#endif /* __OPENCV_CORE_OPENGL_HPP__ */ diff --git a/include/opencv2/core/operations.hpp b/include/opencv2/core/operations.hpp new file mode 100644 index 0000000..bced1a7 --- /dev/null +++ b/include/opencv2/core/operations.hpp @@ -0,0 +1,530 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_OPERATIONS_HPP__ +#define __OPENCV_CORE_OPERATIONS_HPP__ + +#ifndef __cplusplus +# error operations.hpp header must be compiled as C++ +#endif + +#include + +//! @cond IGNORED + +namespace cv +{ + +////////////////////////////// Matx methods depending on core API ///////////////////////////// + +namespace internal +{ + +template struct Matx_FastInvOp +{ + bool operator()(const Matx<_Tp, m, m>& a, Matx<_Tp, m, m>& b, int method) const + { + Matx<_Tp, m, m> temp = a; + + // assume that b is all 0's on input => make it a unity matrix + for( int i = 0; i < m; i++ ) + b(i, i) = (_Tp)1; + + if( method == DECOMP_CHOLESKY ) + return Cholesky(temp.val, m*sizeof(_Tp), m, b.val, m*sizeof(_Tp), m); + + return LU(temp.val, m*sizeof(_Tp), m, b.val, m*sizeof(_Tp), m) != 0; + } +}; + +template struct Matx_FastInvOp<_Tp, 2> +{ + bool operator()(const Matx<_Tp, 2, 2>& a, Matx<_Tp, 2, 2>& b, int) const + { + _Tp d = determinant(a); + if( d == 0 ) + return false; + d = 1/d; + b(1,1) = a(0,0)*d; + b(0,0) = a(1,1)*d; + b(0,1) = -a(0,1)*d; + b(1,0) = -a(1,0)*d; + return true; + } +}; + +template struct Matx_FastInvOp<_Tp, 3> +{ + bool operator()(const Matx<_Tp, 3, 3>& a, Matx<_Tp, 3, 3>& b, int) const + { + _Tp d = (_Tp)determinant(a); + if( d == 0 ) + return false; + d = 1/d; + b(0,0) = (a(1,1) * a(2,2) - a(1,2) * a(2,1)) * d; + b(0,1) = (a(0,2) * a(2,1) - a(0,1) * a(2,2)) * d; + b(0,2) = (a(0,1) * a(1,2) - a(0,2) * a(1,1)) * d; + + b(1,0) = (a(1,2) * a(2,0) - a(1,0) * a(2,2)) * d; + b(1,1) = (a(0,0) * a(2,2) - a(0,2) * a(2,0)) * d; + b(1,2) = (a(0,2) * a(1,0) - a(0,0) * a(1,2)) * d; + + b(2,0) = (a(1,0) * a(2,1) - a(1,1) * a(2,0)) * d; + b(2,1) = (a(0,1) * a(2,0) - a(0,0) * a(2,1)) * d; + b(2,2) = (a(0,0) * a(1,1) - a(0,1) * a(1,0)) * d; + return true; + } +}; + + +template struct Matx_FastSolveOp +{ + bool operator()(const Matx<_Tp, m, m>& a, const Matx<_Tp, m, n>& b, + Matx<_Tp, m, n>& x, int method) const + { + Matx<_Tp, m, m> temp = a; + x = b; + if( method == DECOMP_CHOLESKY ) + return Cholesky(temp.val, m*sizeof(_Tp), m, x.val, n*sizeof(_Tp), n); + + return LU(temp.val, m*sizeof(_Tp), m, x.val, n*sizeof(_Tp), n) != 0; + } +}; + +template struct Matx_FastSolveOp<_Tp, 2, 1> +{ + bool operator()(const Matx<_Tp, 2, 2>& a, const Matx<_Tp, 2, 1>& b, + Matx<_Tp, 2, 1>& x, int) const + { + _Tp d = determinant(a); + if( d == 0 ) + return false; + d = 1/d; + x(0) = (b(0)*a(1,1) - b(1)*a(0,1))*d; + x(1) = (b(1)*a(0,0) - b(0)*a(1,0))*d; + return true; + } +}; + +template struct Matx_FastSolveOp<_Tp, 3, 1> +{ + bool operator()(const Matx<_Tp, 3, 3>& a, const Matx<_Tp, 3, 1>& b, + Matx<_Tp, 3, 1>& x, int) const + { + _Tp d = (_Tp)determinant(a); + if( d == 0 ) + return false; + d = 1/d; + x(0) = d*(b(0)*(a(1,1)*a(2,2) - a(1,2)*a(2,1)) - + a(0,1)*(b(1)*a(2,2) - a(1,2)*b(2)) + + a(0,2)*(b(1)*a(2,1) - a(1,1)*b(2))); + + x(1) = d*(a(0,0)*(b(1)*a(2,2) - a(1,2)*b(2)) - + b(0)*(a(1,0)*a(2,2) - a(1,2)*a(2,0)) + + a(0,2)*(a(1,0)*b(2) - b(1)*a(2,0))); + + x(2) = d*(a(0,0)*(a(1,1)*b(2) - b(1)*a(2,1)) - + a(0,1)*(a(1,0)*b(2) - b(1)*a(2,0)) + + b(0)*(a(1,0)*a(2,1) - a(1,1)*a(2,0))); + return true; + } +}; + +} // internal + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::randu(_Tp a, _Tp b) +{ + Matx<_Tp,m,n> M; + cv::randu(M, Scalar(a), Scalar(b)); + return M; +} + +template inline +Matx<_Tp,m,n> Matx<_Tp,m,n>::randn(_Tp a, _Tp b) +{ + Matx<_Tp,m,n> M; + cv::randn(M, Scalar(a), Scalar(b)); + return M; +} + +template inline +Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method, bool *p_is_ok /*= NULL*/) const +{ + Matx<_Tp, n, m> b; + bool ok; + if( method == DECOMP_LU || method == DECOMP_CHOLESKY ) + ok = cv::internal::Matx_FastInvOp<_Tp, m>()(*this, b, method); + else + { + Mat A(*this, false), B(b, false); + ok = (invert(A, B, method) != 0); + } + if( NULL != p_is_ok ) { *p_is_ok = ok; } + return ok ? b : Matx<_Tp, n, m>::zeros(); +} + +template template inline +Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) const +{ + Matx<_Tp, n, l> x; + bool ok; + if( method == DECOMP_LU || method == DECOMP_CHOLESKY ) + ok = cv::internal::Matx_FastSolveOp<_Tp, m, l>()(*this, rhs, x, method); + else + { + Mat A(*this, false), B(rhs, false), X(x, false); + ok = cv::solve(A, B, X, method); + } + + return ok ? x : Matx<_Tp, n, l>::zeros(); +} + + + +////////////////////////// Augmenting algebraic & logical operations ////////////////////////// + +#define CV_MAT_AUG_OPERATOR1(op, cvop, A, B) \ + static inline A& operator op (A& a, const B& b) { cvop; return a; } + +#define CV_MAT_AUG_OPERATOR(op, cvop, A, B) \ + CV_MAT_AUG_OPERATOR1(op, cvop, A, B) \ + CV_MAT_AUG_OPERATOR1(op, cvop, const A, B) + +#define CV_MAT_AUG_OPERATOR_T(op, cvop, A, B) \ + template CV_MAT_AUG_OPERATOR1(op, cvop, A, B) \ + template CV_MAT_AUG_OPERATOR1(op, cvop, const A, B) + +CV_MAT_AUG_OPERATOR (+=, cv::add(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (+=, cv::add(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(+=, cv::add(a,b,a), Mat_<_Tp>, Mat_<_Tp>) + +CV_MAT_AUG_OPERATOR (-=, cv::subtract(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (-=, cv::subtract(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(-=, cv::subtract(a,b,a), Mat_<_Tp>, Mat_<_Tp>) + +CV_MAT_AUG_OPERATOR (*=, cv::gemm(a, b, 1, Mat(), 0, a, 0), Mat, Mat) +CV_MAT_AUG_OPERATOR_T(*=, cv::gemm(a, b, 1, Mat(), 0, a, 0), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(*=, cv::gemm(a, b, 1, Mat(), 0, a, 0), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (*=, a.convertTo(a, -1, b), Mat, double) +CV_MAT_AUG_OPERATOR_T(*=, a.convertTo(a, -1, b), Mat_<_Tp>, double) + +CV_MAT_AUG_OPERATOR (/=, cv::divide(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR_T(/=, cv::divide(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(/=, cv::divide(a,b,a), Mat_<_Tp>, Mat_<_Tp>) +CV_MAT_AUG_OPERATOR (/=, a.convertTo((Mat&)a, -1, 1./b), Mat, double) +CV_MAT_AUG_OPERATOR_T(/=, a.convertTo((Mat&)a, -1, 1./b), Mat_<_Tp>, double) + +CV_MAT_AUG_OPERATOR (&=, cv::bitwise_and(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (&=, cv::bitwise_and(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(&=, cv::bitwise_and(a,b,a), Mat_<_Tp>, Mat_<_Tp>) + +CV_MAT_AUG_OPERATOR (|=, cv::bitwise_or(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (|=, cv::bitwise_or(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(|=, cv::bitwise_or(a,b,a), Mat_<_Tp>, Mat_<_Tp>) + +CV_MAT_AUG_OPERATOR (^=, cv::bitwise_xor(a,b,a), Mat, Mat) +CV_MAT_AUG_OPERATOR (^=, cv::bitwise_xor(a,b,a), Mat, Scalar) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Mat) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Scalar) +CV_MAT_AUG_OPERATOR_T(^=, cv::bitwise_xor(a,b,a), Mat_<_Tp>, Mat_<_Tp>) + +#undef CV_MAT_AUG_OPERATOR_T +#undef CV_MAT_AUG_OPERATOR +#undef CV_MAT_AUG_OPERATOR1 + + + +///////////////////////////////////////////// SVD ///////////////////////////////////////////// + +inline SVD::SVD() {} +inline SVD::SVD( InputArray m, int flags ) { operator ()(m, flags); } +inline void SVD::solveZ( InputArray m, OutputArray _dst ) +{ + Mat mtx = m.getMat(); + SVD svd(mtx, (mtx.rows >= mtx.cols ? 0 : SVD::FULL_UV)); + _dst.create(svd.vt.cols, 1, svd.vt.type()); + Mat dst = _dst.getMat(); + svd.vt.row(svd.vt.rows-1).reshape(1,svd.vt.cols).copyTo(dst); +} + +template inline void + SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ) +{ + CV_StaticAssert( nm == MIN(m, n), "Invalid size of output vector."); + Mat _a(a, false), _u(u, false), _w(w, false), _vt(vt, false); + SVD::compute(_a, _w, _u, _vt); + CV_Assert(_w.data == (uchar*)&w.val[0] && _u.data == (uchar*)&u.val[0] && _vt.data == (uchar*)&vt.val[0]); +} + +template inline void +SVD::compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w ) +{ + CV_StaticAssert( nm == MIN(m, n), "Invalid size of output vector."); + Mat _a(a, false), _w(w, false); + SVD::compute(_a, _w); + CV_Assert(_w.data == (uchar*)&w.val[0]); +} + +template inline void +SVD::backSubst( const Matx<_Tp, nm, 1>& w, const Matx<_Tp, m, nm>& u, + const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, + Matx<_Tp, n, nb>& dst ) +{ + CV_StaticAssert( nm == MIN(m, n), "Invalid size of output vector."); + Mat _u(u, false), _w(w, false), _vt(vt, false), _rhs(rhs, false), _dst(dst, false); + SVD::backSubst(_w, _u, _vt, _rhs, _dst); + CV_Assert(_dst.data == (uchar*)&dst.val[0]); +} + + + +/////////////////////////////////// Multiply-with-Carry RNG /////////////////////////////////// + +inline RNG::RNG() { state = 0xffffffff; } +inline RNG::RNG(uint64 _state) { state = _state ? _state : 0xffffffff; } + +inline RNG::operator uchar() { return (uchar)next(); } +inline RNG::operator schar() { return (schar)next(); } +inline RNG::operator ushort() { return (ushort)next(); } +inline RNG::operator short() { return (short)next(); } +inline RNG::operator int() { return (int)next(); } +inline RNG::operator unsigned() { return next(); } +inline RNG::operator float() { return next()*2.3283064365386962890625e-10f; } +inline RNG::operator double() { unsigned t = next(); return (((uint64)t << 32) | next()) * 5.4210108624275221700372640043497e-20; } + +inline unsigned RNG::operator ()(unsigned N) { return (unsigned)uniform(0,N); } +inline unsigned RNG::operator ()() { return next(); } + +inline int RNG::uniform(int a, int b) { return a == b ? a : (int)(next() % (b - a) + a); } +inline float RNG::uniform(float a, float b) { return ((float)*this)*(b - a) + a; } +inline double RNG::uniform(double a, double b) { return ((double)*this)*(b - a) + a; } + +inline unsigned RNG::next() +{ + state = (uint64)(unsigned)state* /*CV_RNG_COEFF*/ 4164903690U + (unsigned)(state >> 32); + return (unsigned)state; +} + +//! returns the next unifomly-distributed random number of the specified type +template static inline _Tp randu() +{ + return (_Tp)theRNG(); +} + +///////////////////////////////// Formatted string generation ///////////////////////////////// + +CV_EXPORTS String format( const char* fmt, ... ); + +///////////////////////////////// Formatted output of cv::Mat ///////////////////////////////// + +static inline +Ptr format(InputArray mtx, int fmt) +{ + return Formatter::get(fmt)->format(mtx.getMat()); +} + +static inline +int print(Ptr fmtd, FILE* stream = stdout) +{ + int written = 0; + fmtd->reset(); + for(const char* str = fmtd->next(); str; str = fmtd->next()) + written += fputs(str, stream); + + return written; +} + +static inline +int print(const Mat& mtx, FILE* stream = stdout) +{ + return print(Formatter::get()->format(mtx), stream); +} + +static inline +int print(const UMat& mtx, FILE* stream = stdout) +{ + return print(Formatter::get()->format(mtx.getMat(ACCESS_READ)), stream); +} + +template static inline +int print(const std::vector >& vec, FILE* stream = stdout) +{ + return print(Formatter::get()->format(Mat(vec)), stream); +} + +template static inline +int print(const std::vector >& vec, FILE* stream = stdout) +{ + return print(Formatter::get()->format(Mat(vec)), stream); +} + +template static inline +int print(const Matx<_Tp, m, n>& matx, FILE* stream = stdout) +{ + return print(Formatter::get()->format(cv::Mat(matx)), stream); +} + +//! @endcond + +/****************************************************************************************\ +* Auxiliary algorithms * +\****************************************************************************************/ + +/** @brief Splits an element set into equivalency classes. + +The generic function partition implements an \f$O(N^2)\f$ algorithm for splitting a set of \f$N\f$ elements +into one or more equivalency classes, as described in + . The function returns the number of +equivalency classes. +@param _vec Set of elements stored as a vector. +@param labels Output vector of labels. It contains as many elements as vec. Each label labels[i] is +a 0-based cluster index of `vec[i]`. +@param predicate Equivalence predicate (pointer to a boolean function of two arguments or an +instance of the class that has the method bool operator()(const _Tp& a, const _Tp& b) ). The +predicate returns true when the elements are certainly in the same class, and returns false if they +may or may not be in the same class. +@ingroup core_cluster +*/ +template int +partition( const std::vector<_Tp>& _vec, std::vector& labels, + _EqPredicate predicate=_EqPredicate()) +{ + int i, j, N = (int)_vec.size(); + const _Tp* vec = &_vec[0]; + + const int PARENT=0; + const int RANK=1; + + std::vector _nodes(N*2); + int (*nodes)[2] = (int(*)[2])&_nodes[0]; + + // The first O(N) pass: create N single-vertex trees + for(i = 0; i < N; i++) + { + nodes[i][PARENT]=-1; + nodes[i][RANK] = 0; + } + + // The main O(N^2) pass: merge connected components + for( i = 0; i < N; i++ ) + { + int root = i; + + // find root + while( nodes[root][PARENT] >= 0 ) + root = nodes[root][PARENT]; + + for( j = 0; j < N; j++ ) + { + if( i == j || !predicate(vec[i], vec[j])) + continue; + int root2 = j; + + while( nodes[root2][PARENT] >= 0 ) + root2 = nodes[root2][PARENT]; + + if( root2 != root ) + { + // unite both trees + int rank = nodes[root][RANK], rank2 = nodes[root2][RANK]; + if( rank > rank2 ) + nodes[root2][PARENT] = root; + else + { + nodes[root][PARENT] = root2; + nodes[root2][RANK] += rank == rank2; + root = root2; + } + CV_Assert( nodes[root][PARENT] < 0 ); + + int k = j, parent; + + // compress the path from node2 to root + while( (parent = nodes[k][PARENT]) >= 0 ) + { + nodes[k][PARENT] = root; + k = parent; + } + + // compress the path from node to root + k = i; + while( (parent = nodes[k][PARENT]) >= 0 ) + { + nodes[k][PARENT] = root; + k = parent; + } + } + } + } + + // Final O(N) pass: enumerate classes + labels.resize(N); + int nclasses = 0; + + for( i = 0; i < N; i++ ) + { + int root = i; + while( nodes[root][PARENT] >= 0 ) + root = nodes[root][PARENT]; + // re-use the rank as the class label + if( nodes[root][RANK] >= 0 ) + nodes[root][RANK] = ~nclasses++; + labels[i] = ~nodes[root][RANK]; + } + + return nclasses; +} + +} // cv + +#endif diff --git a/include/opencv2/core/optim.hpp b/include/opencv2/core/optim.hpp new file mode 100644 index 0000000..23e2155 --- /dev/null +++ b/include/opencv2/core/optim.hpp @@ -0,0 +1,302 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the OpenCV Foundation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_OPTIM_HPP__ +#define __OPENCV_OPTIM_HPP__ + +#include "opencv2/core.hpp" + +namespace cv +{ + +/** @addtogroup core_optim +The algorithms in this section minimize or maximize function value within specified constraints or +without any constraints. +@{ +*/ + +/** @brief Basic interface for all solvers + */ +class CV_EXPORTS MinProblemSolver : public Algorithm +{ +public: + /** @brief Represents function being optimized + */ + class CV_EXPORTS Function + { + public: + virtual ~Function() {} + virtual int getDims() const = 0; + virtual double getGradientEps() const; + virtual double calc(const double* x) const = 0; + virtual void getGradient(const double* x,double* grad); + }; + + /** @brief Getter for the optimized function. + + The optimized function is represented by Function interface, which requires derivatives to + implement the sole method calc(double*) to evaluate the function. + + @return Smart-pointer to an object that implements Function interface - it represents the + function that is being optimized. It can be empty, if no function was given so far. + */ + virtual Ptr getFunction() const = 0; + + /** @brief Setter for the optimized function. + + *It should be called at least once before the call to* minimize(), as default value is not usable. + + @param f The new function to optimize. + */ + virtual void setFunction(const Ptr& f) = 0; + + /** @brief Getter for the previously set terminal criteria for this algorithm. + + @return Deep copy of the terminal criteria used at the moment. + */ + virtual TermCriteria getTermCriteria() const = 0; + + /** @brief Set terminal criteria for solver. + + This method *is not necessary* to be called before the first call to minimize(), as the default + value is sensible. + + Algorithm stops when the number of function evaluations done exceeds termcrit.maxCount, when + the function values at the vertices of simplex are within termcrit.epsilon range or simplex + becomes so small that it can enclosed in a box with termcrit.epsilon sides, whatever comes + first. + @param termcrit Terminal criteria to be used, represented as cv::TermCriteria structure. + */ + virtual void setTermCriteria(const TermCriteria& termcrit) = 0; + + /** @brief actually runs the algorithm and performs the minimization. + + The sole input parameter determines the centroid of the starting simplex (roughly, it tells + where to start), all the others (terminal criteria, initial step, function to be minimized) are + supposed to be set via the setters before the call to this method or the default values (not + always sensible) will be used. + + @param x The initial point, that will become a centroid of an initial simplex. After the algorithm + will terminate, it will be setted to the point where the algorithm stops, the point of possible + minimum. + @return The value of a function at the point found. + */ + virtual double minimize(InputOutputArray x) = 0; +}; + +/** @brief This class is used to perform the non-linear non-constrained minimization of a function, + +defined on an `n`-dimensional Euclidean space, using the **Nelder-Mead method**, also known as +**downhill simplex method**. The basic idea about the method can be obtained from +. + +It should be noted, that this method, although deterministic, is rather a heuristic and therefore +may converge to a local minima, not necessary a global one. It is iterative optimization technique, +which at each step uses an information about the values of a function evaluated only at `n+1` +points, arranged as a *simplex* in `n`-dimensional space (hence the second name of the method). At +each step new point is chosen to evaluate function at, obtained value is compared with previous +ones and based on this information simplex changes it's shape , slowly moving to the local minimum. +Thus this method is using *only* function values to make decision, on contrary to, say, Nonlinear +Conjugate Gradient method (which is also implemented in optim). + +Algorithm stops when the number of function evaluations done exceeds termcrit.maxCount, when the +function values at the vertices of simplex are within termcrit.epsilon range or simplex becomes so +small that it can enclosed in a box with termcrit.epsilon sides, whatever comes first, for some +defined by user positive integer termcrit.maxCount and positive non-integer termcrit.epsilon. + +@note DownhillSolver is a derivative of the abstract interface +cv::MinProblemSolver, which in turn is derived from the Algorithm interface and is used to +encapsulate the functionality, common to all non-linear optimization algorithms in the optim +module. + +@note term criteria should meet following condition: +@code + termcrit.type == (TermCriteria::MAX_ITER + TermCriteria::EPS) && termcrit.epsilon > 0 && termcrit.maxCount > 0 +@endcode + */ +class CV_EXPORTS DownhillSolver : public MinProblemSolver +{ +public: + /** @brief Returns the initial step that will be used in downhill simplex algorithm. + + @param step Initial step that will be used in algorithm. Note, that although corresponding setter + accepts column-vectors as well as row-vectors, this method will return a row-vector. + @see DownhillSolver::setInitStep + */ + virtual void getInitStep(OutputArray step) const=0; + + /** @brief Sets the initial step that will be used in downhill simplex algorithm. + + Step, together with initial point (givin in DownhillSolver::minimize) are two `n`-dimensional + vectors that are used to determine the shape of initial simplex. Roughly said, initial point + determines the position of a simplex (it will become simplex's centroid), while step determines the + spread (size in each dimension) of a simplex. To be more precise, if \f$s,x_0\in\mathbb{R}^n\f$ are + the initial step and initial point respectively, the vertices of a simplex will be: + \f$v_0:=x_0-\frac{1}{2} s\f$ and \f$v_i:=x_0+s_i\f$ for \f$i=1,2,\dots,n\f$ where \f$s_i\f$ denotes + projections of the initial step of *n*-th coordinate (the result of projection is treated to be + vector given by \f$s_i:=e_i\cdot\left\f$, where \f$e_i\f$ form canonical basis) + + @param step Initial step that will be used in algorithm. Roughly said, it determines the spread + (size in each dimension) of an initial simplex. + */ + virtual void setInitStep(InputArray step)=0; + + /** @brief This function returns the reference to the ready-to-use DownhillSolver object. + + All the parameters are optional, so this procedure can be called even without parameters at + all. In this case, the default values will be used. As default value for terminal criteria are + the only sensible ones, MinProblemSolver::setFunction() and DownhillSolver::setInitStep() + should be called upon the obtained object, if the respective parameters were not given to + create(). Otherwise, the two ways (give parameters to createDownhillSolver() or miss them out + and call the MinProblemSolver::setFunction() and DownhillSolver::setInitStep()) are absolutely + equivalent (and will drop the same errors in the same way, should invalid input be detected). + @param f Pointer to the function that will be minimized, similarly to the one you submit via + MinProblemSolver::setFunction. + @param initStep Initial step, that will be used to construct the initial simplex, similarly to the one + you submit via MinProblemSolver::setInitStep. + @param termcrit Terminal criteria to the algorithm, similarly to the one you submit via + MinProblemSolver::setTermCriteria. + */ + static Ptr create(const Ptr& f=Ptr(), + InputArray initStep=Mat_(1,1,0.0), + TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5000,0.000001)); +}; + +/** @brief This class is used to perform the non-linear non-constrained minimization of a function +with known gradient, + +defined on an *n*-dimensional Euclidean space, using the **Nonlinear Conjugate Gradient method**. +The implementation was done based on the beautifully clear explanatory article [An Introduction to +the Conjugate Gradient Method Without the Agonizing +Pain](http://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf) by Jonathan Richard +Shewchuk. The method can be seen as an adaptation of a standard Conjugate Gradient method (see, for +example ) for numerically solving the +systems of linear equations. + +It should be noted, that this method, although deterministic, is rather a heuristic method and +therefore may converge to a local minima, not necessary a global one. What is even more disastrous, +most of its behaviour is ruled by gradient, therefore it essentially cannot distinguish between +local minima and maxima. Therefore, if it starts sufficiently near to the local maximum, it may +converge to it. Another obvious restriction is that it should be possible to compute the gradient of +a function at any point, thus it is preferable to have analytic expression for gradient and +computational burden should be born by the user. + +The latter responsibility is accompilished via the getGradient method of a +MinProblemSolver::Function interface (which represents function being optimized). This method takes +point a point in *n*-dimensional space (first argument represents the array of coordinates of that +point) and comput its gradient (it should be stored in the second argument as an array). + +@note class ConjGradSolver thus does not add any new methods to the basic MinProblemSolver interface. + +@note term criteria should meet following condition: +@code + termcrit.type == (TermCriteria::MAX_ITER + TermCriteria::EPS) && termcrit.epsilon > 0 && termcrit.maxCount > 0 + // or + termcrit.type == TermCriteria::MAX_ITER) && termcrit.maxCount > 0 +@endcode + */ +class CV_EXPORTS ConjGradSolver : public MinProblemSolver +{ +public: + /** @brief This function returns the reference to the ready-to-use ConjGradSolver object. + + All the parameters are optional, so this procedure can be called even without parameters at + all. In this case, the default values will be used. As default value for terminal criteria are + the only sensible ones, MinProblemSolver::setFunction() should be called upon the obtained + object, if the function was not given to create(). Otherwise, the two ways (submit it to + create() or miss it out and call the MinProblemSolver::setFunction()) are absolutely equivalent + (and will drop the same errors in the same way, should invalid input be detected). + @param f Pointer to the function that will be minimized, similarly to the one you submit via + MinProblemSolver::setFunction. + @param termcrit Terminal criteria to the algorithm, similarly to the one you submit via + MinProblemSolver::setTermCriteria. + */ + static Ptr create(const Ptr& f=Ptr(), + TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5000,0.000001)); +}; + +//! return codes for cv::solveLP() function +enum SolveLPResult +{ + SOLVELP_UNBOUNDED = -2, //!< problem is unbounded (target function can achieve arbitrary high values) + SOLVELP_UNFEASIBLE = -1, //!< problem is unfeasible (there are no points that satisfy all the constraints imposed) + SOLVELP_SINGLE = 0, //!< there is only one maximum for target function + SOLVELP_MULTI = 1 //!< there are multiple maxima for target function - the arbitrary one is returned +}; + +/** @brief Solve given (non-integer) linear programming problem using the Simplex Algorithm (Simplex Method). + +What we mean here by "linear programming problem" (or LP problem, for short) can be formulated as: + +\f[\mbox{Maximize } c\cdot x\\ + \mbox{Subject to:}\\ + Ax\leq b\\ + x\geq 0\f] + +Where \f$c\f$ is fixed `1`-by-`n` row-vector, \f$A\f$ is fixed `m`-by-`n` matrix, \f$b\f$ is fixed `m`-by-`1` +column vector and \f$x\f$ is an arbitrary `n`-by-`1` column vector, which satisfies the constraints. + +Simplex algorithm is one of many algorithms that are designed to handle this sort of problems +efficiently. Although it is not optimal in theoretical sense (there exist algorithms that can solve +any problem written as above in polynomial time, while simplex method degenerates to exponential +time for some special cases), it is well-studied, easy to implement and is shown to work well for +real-life purposes. + +The particular implementation is taken almost verbatim from **Introduction to Algorithms, third +edition** by T. H. Cormen, C. E. Leiserson, R. L. Rivest and Clifford Stein. In particular, the +Bland's rule is used to prevent cycling. + +@param Func This row-vector corresponds to \f$c\f$ in the LP problem formulation (see above). It should +contain 32- or 64-bit floating point numbers. As a convenience, column-vector may be also submitted, +in the latter case it is understood to correspond to \f$c^T\f$. +@param Constr `m`-by-`n+1` matrix, whose rightmost column corresponds to \f$b\f$ in formulation above +and the remaining to \f$A\f$. It should containt 32- or 64-bit floating point numbers. +@param z The solution will be returned here as a column-vector - it corresponds to \f$c\f$ in the +formulation above. It will contain 64-bit floating point numbers. +@return One of cv::SolveLPResult + */ +CV_EXPORTS_W int solveLP(const Mat& Func, const Mat& Constr, Mat& z); + +//! @} + +}// cv + +#endif diff --git a/include/opencv2/core/persistence.hpp b/include/opencv2/core/persistence.hpp new file mode 100644 index 0000000..17686dd --- /dev/null +++ b/include/opencv2/core/persistence.hpp @@ -0,0 +1,1195 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_PERSISTENCE_HPP__ +#define __OPENCV_CORE_PERSISTENCE_HPP__ + +#ifndef __cplusplus +# error persistence.hpp header must be compiled as C++ +#endif + +//! @addtogroup core_c +//! @{ + +/** @brief "black box" representation of the file storage associated with a file on disk. + +Several functions that are described below take CvFileStorage\* as inputs and allow the user to +save or to load hierarchical collections that consist of scalar values, standard CXCore objects +(such as matrices, sequences, graphs), and user-defined objects. + +OpenCV can read and write data in XML () or YAML () +formats. Below is an example of 3x3 floating-point identity matrix A, stored in XML and YAML files +using CXCore functions: +XML: +@code{.xml} + + + + 3 + 3 +
f
+ 1. 0. 0. 0. 1. 0. 0. 0. 1. +
+
+@endcode +YAML: +@code{.yaml} + %YAML:1.0 + A: !!opencv-matrix + rows: 3 + cols: 3 + dt: f + data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.] +@endcode +As it can be seen from the examples, XML uses nested tags to represent hierarchy, while YAML uses +indentation for that purpose (similar to the Python programming language). + +The same functions can read and write data in both formats; the particular format is determined by +the extension of the opened file, ".xml" for XML files and ".yml" or ".yaml" for YAML. + */ +typedef struct CvFileStorage CvFileStorage; +typedef struct CvFileNode CvFileNode; + +//! @} core_c + +#include "opencv2/core/types.hpp" +#include "opencv2/core/mat.hpp" + +namespace cv { + +/** @addtogroup core_xml + +XML/YAML file storages. {#xml_storage} +======================= +Writing to a file storage. +-------------------------- +You can store and then restore various OpenCV data structures to/from XML () +or YAML () formats. Also, it is possible store and load arbitrarily complex +data structures, which include OpenCV data structures, as well as primitive data types (integer and +floating-point numbers and text strings) as their elements. + +Use the following procedure to write something to XML or YAML: +-# Create new FileStorage and open it for writing. It can be done with a single call to +FileStorage::FileStorage constructor that takes a filename, or you can use the default constructor +and then call FileStorage::open. Format of the file (XML or YAML) is determined from the filename +extension (".xml" and ".yml"/".yaml", respectively) +-# Write all the data you want using the streaming operator `<<`, just like in the case of STL +streams. +-# Close the file using FileStorage::release. FileStorage destructor also closes the file. + +Here is an example: +@code + #include "opencv2/opencv.hpp" + #include + + using namespace cv; + + int main(int, char** argv) + { + FileStorage fs("test.yml", FileStorage::WRITE); + + fs << "frameCount" << 5; + time_t rawtime; time(&rawtime); + fs << "calibrationDate" << asctime(localtime(&rawtime)); + Mat cameraMatrix = (Mat_(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1); + Mat distCoeffs = (Mat_(5,1) << 0.1, 0.01, -0.001, 0, 0); + fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs; + fs << "features" << "["; + for( int i = 0; i < 3; i++ ) + { + int x = rand() % 640; + int y = rand() % 480; + uchar lbp = rand() % 256; + + fs << "{:" << "x" << x << "y" << y << "lbp" << "[:"; + for( int j = 0; j < 8; j++ ) + fs << ((lbp >> j) & 1); + fs << "]" << "}"; + } + fs << "]"; + fs.release(); + return 0; + } +@endcode +The sample above stores to XML and integer, text string (calibration date), 2 matrices, and a custom +structure "feature", which includes feature coordinates and LBP (local binary pattern) value. Here +is output of the sample: +@code{.yaml} +%YAML:1.0 +frameCount: 5 +calibrationDate: "Fri Jun 17 14:09:29 2011\n" +cameraMatrix: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ] +distCoeffs: !!opencv-matrix + rows: 5 + cols: 1 + dt: d + data: [ 1.0000000000000001e-01, 1.0000000000000000e-02, + -1.0000000000000000e-03, 0., 0. ] +features: + - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] } + - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] } + - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] } +@endcode + +As an exercise, you can replace ".yml" with ".xml" in the sample above and see, how the +corresponding XML file will look like. + +Several things can be noted by looking at the sample code and the output: + +- The produced YAML (and XML) consists of heterogeneous collections that can be nested. There are 2 + types of collections: named collections (mappings) and unnamed collections (sequences). In mappings + each element has a name and is accessed by name. This is similar to structures and std::map in + C/C++ and dictionaries in Python. In sequences elements do not have names, they are accessed by + indices. This is similar to arrays and std::vector in C/C++ and lists, tuples in Python. + "Heterogeneous" means that elements of each single collection can have different types. + + Top-level collection in YAML/XML is a mapping. Each matrix is stored as a mapping, and the matrix + elements are stored as a sequence. Then, there is a sequence of features, where each feature is + represented a mapping, and lbp value in a nested sequence. + +- When you write to a mapping (a structure), you write element name followed by its value. When you + write to a sequence, you simply write the elements one by one. OpenCV data structures (such as + cv::Mat) are written in absolutely the same way as simple C data structures - using `<<` + operator. + +- To write a mapping, you first write the special string `{` to the storage, then write the + elements as pairs (`fs << << `) and then write the closing + `}`. + +- To write a sequence, you first write the special string `[`, then write the elements, then + write the closing `]`. + +- In YAML (but not XML), mappings and sequences can be written in a compact Python-like inline + form. In the sample above matrix elements, as well as each feature, including its lbp value, is + stored in such inline form. To store a mapping/sequence in a compact form, put `:` after the + opening character, e.g. use `{:` instead of `{` and `[:` instead of `[`. When the + data is written to XML, those extra `:` are ignored. + +Reading data from a file storage. +--------------------------------- +To read the previously written XML or YAML file, do the following: +-# Open the file storage using FileStorage::FileStorage constructor or FileStorage::open method. + In the current implementation the whole file is parsed and the whole representation of file + storage is built in memory as a hierarchy of file nodes (see FileNode) + +-# Read the data you are interested in. Use FileStorage::operator [], FileNode::operator [] + and/or FileNodeIterator. + +-# Close the storage using FileStorage::release. + +Here is how to read the file created by the code sample above: +@code + FileStorage fs2("test.yml", FileStorage::READ); + + // first method: use (type) operator on FileNode. + int frameCount = (int)fs2["frameCount"]; + + String date; + // second method: use FileNode::operator >> + fs2["calibrationDate"] >> date; + + Mat cameraMatrix2, distCoeffs2; + fs2["cameraMatrix"] >> cameraMatrix2; + fs2["distCoeffs"] >> distCoeffs2; + + cout << "frameCount: " << frameCount << endl + << "calibration date: " << date << endl + << "camera matrix: " << cameraMatrix2 << endl + << "distortion coeffs: " << distCoeffs2 << endl; + + FileNode features = fs2["features"]; + FileNodeIterator it = features.begin(), it_end = features.end(); + int idx = 0; + std::vector lbpval; + + // iterate through a sequence using FileNodeIterator + for( ; it != it_end; ++it, idx++ ) + { + cout << "feature #" << idx << ": "; + cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: ("; + // you can also easily read numerical arrays using FileNode >> std::vector operator. + (*it)["lbp"] >> lbpval; + for( int i = 0; i < (int)lbpval.size(); i++ ) + cout << " " << (int)lbpval[i]; + cout << ")" << endl; + } + fs2.release(); +@endcode + +Format specification {#format_spec} +-------------------- +`([count]{u|c|w|s|i|f|d})`... where the characters correspond to fundamental C++ types: +- `u` 8-bit unsigned number +- `c` 8-bit signed number +- `w` 16-bit unsigned number +- `s` 16-bit signed number +- `i` 32-bit signed number +- `f` single precision floating-point number +- `d` double precision floating-point number +- `r` pointer, 32 lower bits of which are written as a signed integer. The type can be used to + store structures with links between the elements. + +`count` is the optional counter of values of a given type. For example, `2if` means that each array +element is a structure of 2 integers, followed by a single-precision floating-point number. The +equivalent notations of the above specification are `iif`, `2i1f` and so forth. Other examples: `u` +means that the array consists of bytes, and `2d` means the array consists of pairs of doubles. + +@see @ref filestorage.cpp +*/ + +//! @{ + +/** @example filestorage.cpp +A complete example using the FileStorage interface +*/ + +////////////////////////// XML & YAML I/O ////////////////////////// + +class CV_EXPORTS FileNode; +class CV_EXPORTS FileNodeIterator; + +/** @brief XML/YAML file storage class that encapsulates all the information necessary for writing or reading +data to/from a file. + */ +class CV_EXPORTS_W FileStorage +{ +public: + //! file storage mode + enum Mode + { + READ = 0, //!< value, open the file for reading + WRITE = 1, //!< value, open the file for writing + APPEND = 2, //!< value, open the file for appending + MEMORY = 4, //!< flag, read data from source or write data to the internal buffer (which is + //!< returned by FileStorage::release) + FORMAT_MASK = (7<<3), //!< mask for format flags + FORMAT_AUTO = 0, //!< flag, auto format + FORMAT_XML = (1<<3), //!< flag, XML format + FORMAT_YAML = (2<<3) //!< flag, YAML format + }; + enum + { + UNDEFINED = 0, + VALUE_EXPECTED = 1, + NAME_EXPECTED = 2, + INSIDE_MAP = 4 + }; + + /** @brief The constructors. + + The full constructor opens the file. Alternatively you can use the default constructor and then + call FileStorage::open. + */ + CV_WRAP FileStorage(); + + /** @overload + @param source Name of the file to open or the text string to read the data from. Extension of the + file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). Also you can append .gz + to work with compressed files, for example myHugeMatrix.xml.gz. If both FileStorage::WRITE and + FileStorage::MEMORY flags are specified, source is used just to specify the output file format (e.g. + mydata.xml, .yml etc.). + @param flags Mode of operation. See FileStorage::Mode + @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and + you should use 8-bit encoding instead of it. + */ + CV_WRAP FileStorage(const String& source, int flags, const String& encoding=String()); + + /** @overload */ + FileStorage(CvFileStorage* fs, bool owning=true); + + //! the destructor. calls release() + virtual ~FileStorage(); + + /** @brief Opens a file. + + See description of parameters in FileStorage::FileStorage. The method calls FileStorage::release + before opening the file. + @param filename Name of the file to open or the text string to read the data from. + Extension of the file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). + Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both + FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify + the output file format (e.g. mydata.xml, .yml etc.). + @param flags Mode of operation. One of FileStorage::Mode + @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and + you should use 8-bit encoding instead of it. + */ + CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String()); + + /** @brief Checks whether the file is opened. + + @returns true if the object is associated with the current file and false otherwise. It is a + good practice to call this method after you tried to open a file. + */ + CV_WRAP virtual bool isOpened() const; + + /** @brief Closes the file and releases all the memory buffers. + + Call this method after all I/O operations with the storage are finished. + */ + CV_WRAP virtual void release(); + + /** @brief Closes the file and releases all the memory buffers. + + Call this method after all I/O operations with the storage are finished. If the storage was + opened for writing data and FileStorage::WRITE was specified + */ + CV_WRAP virtual String releaseAndGetString(); + + /** @brief Returns the first element of the top-level mapping. + @returns The first element of the top-level mapping. + */ + CV_WRAP FileNode getFirstTopLevelNode() const; + + /** @brief Returns the top-level mapping + @param streamidx Zero-based index of the stream. In most cases there is only one stream in the file. + However, YAML supports multiple streams and so there can be several. + @returns The top-level mapping. + */ + CV_WRAP FileNode root(int streamidx=0) const; + + /** @brief Returns the specified element of the top-level mapping. + @param nodename Name of the file node. + @returns Node with the given name. + */ + FileNode operator[](const String& nodename) const; + + /** @overload */ + CV_WRAP FileNode operator[](const char* nodename) const; + + /** @brief Returns the obsolete C FileStorage structure. + @returns Pointer to the underlying C FileStorage structure + */ + CvFileStorage* operator *() { return fs.get(); } + + /** @overload */ + const CvFileStorage* operator *() const { return fs.get(); } + + /** @brief Writes multiple numbers. + + Writes one or more numbers of the specified format to the currently written structure. Usually it is + more convenient to use operator `<<` instead of this method. + @param fmt Specification of each array element, see @ref format_spec "format specification" + @param vec Pointer to the written array. + @param len Number of the uchar elements to write. + */ + void writeRaw( const String& fmt, const uchar* vec, size_t len ); + + /** @brief Writes the registered C structure (CvMat, CvMatND, CvSeq). + @param name Name of the written object. + @param obj Pointer to the object. + @see ocvWrite for details. + */ + void writeObj( const String& name, const void* obj ); + + /** @brief Returns the normalized object name for the specified name of a file. + @param filename Name of a file + @returns The normalized object name. + */ + static String getDefaultObjectName(const String& filename); + + Ptr fs; //!< the underlying C FileStorage structure + String elname; //!< the currently written element + std::vector structs; //!< the stack of written structures + int state; //!< the writer state +}; + +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvFileStorage* obj) const; + +/** @brief File Storage Node class. + +The node is used to store each and every element of the file storage opened for reading. When +XML/YAML file is read, it is first parsed and stored in the memory as a hierarchical collection of +nodes. Each node can be a “leaf” that is contain a single number or a string, or be a collection of +other nodes. There can be named collections (mappings) where each element has a name and it is +accessed by a name, and ordered collections (sequences) where elements do not have names but rather +accessed by index. Type of the file node can be determined using FileNode::type method. + +Note that file nodes are only used for navigating file storages opened for reading. When a file +storage is opened for writing, no data is stored in memory after it is written. + */ +class CV_EXPORTS_W_SIMPLE FileNode +{ +public: + //! type of the file storage node + enum Type + { + NONE = 0, //!< empty node + INT = 1, //!< an integer + REAL = 2, //!< floating-point number + FLOAT = REAL, //!< synonym or REAL + STR = 3, //!< text string in UTF-8 encoding + STRING = STR, //!< synonym for STR + REF = 4, //!< integer of size size_t. Typically used for storing complex dynamic structures where some elements reference the others + SEQ = 5, //!< sequence + MAP = 6, //!< mapping + TYPE_MASK = 7, + FLOW = 8, //!< compact representation of a sequence or mapping. Used only by YAML writer + USER = 16, //!< a registered object (e.g. a matrix) + EMPTY = 32, //!< empty structure (sequence or mapping) + NAMED = 64 //!< the node has a name (i.e. it is element of a mapping) + }; + /** @brief The constructors. + + These constructors are used to create a default file node, construct it from obsolete structures or + from the another file node. + */ + CV_WRAP FileNode(); + + /** @overload + @param fs Pointer to the obsolete file storage structure. + @param node File node to be used as initialization for the created file node. + */ + FileNode(const CvFileStorage* fs, const CvFileNode* node); + + /** @overload + @param node File node to be used as initialization for the created file node. + */ + FileNode(const FileNode& node); + + /** @brief Returns element of a mapping node or a sequence node. + @param nodename Name of an element in the mapping node. + @returns Returns the element with the given identifier. + */ + FileNode operator[](const String& nodename) const; + + /** @overload + @param nodename Name of an element in the mapping node. + */ + CV_WRAP FileNode operator[](const char* nodename) const; + + /** @overload + @param i Index of an element in the sequence node. + */ + CV_WRAP FileNode operator[](int i) const; + + /** @brief Returns type of the node. + @returns Type of the node. See FileNode::Type + */ + CV_WRAP int type() const; + + //! returns true if the node is empty + CV_WRAP bool empty() const; + //! returns true if the node is a "none" object + CV_WRAP bool isNone() const; + //! returns true if the node is a sequence + CV_WRAP bool isSeq() const; + //! returns true if the node is a mapping + CV_WRAP bool isMap() const; + //! returns true if the node is an integer + CV_WRAP bool isInt() const; + //! returns true if the node is a floating-point number + CV_WRAP bool isReal() const; + //! returns true if the node is a text string + CV_WRAP bool isString() const; + //! returns true if the node has a name + CV_WRAP bool isNamed() const; + //! returns the node name or an empty string if the node is nameless + CV_WRAP String name() const; + //! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise. + CV_WRAP size_t size() const; + //! returns the node content as an integer. If the node stores floating-point number, it is rounded. + operator int() const; + //! returns the node content as float + operator float() const; + //! returns the node content as double + operator double() const; + //! returns the node content as text string + operator String() const; +#ifndef OPENCV_NOSTL + operator std::string() const; +#endif + + //! returns pointer to the underlying file node + CvFileNode* operator *(); + //! returns pointer to the underlying file node + const CvFileNode* operator* () const; + + //! returns iterator pointing to the first node element + FileNodeIterator begin() const; + //! returns iterator pointing to the element following the last node element + FileNodeIterator end() const; + + /** @brief Reads node elements to the buffer with the specified format. + + Usually it is more convenient to use operator `>>` instead of this method. + @param fmt Specification of each array element. See @ref format_spec "format specification" + @param vec Pointer to the destination array. + @param len Number of elements to read. If it is greater than number of remaining elements then all + of them will be read. + */ + void readRaw( const String& fmt, uchar* vec, size_t len ) const; + + //! reads the registered object and returns pointer to it + void* readObj() const; + + // do not use wrapper pointer classes for better efficiency + const CvFileStorage* fs; + const CvFileNode* node; +}; + + +/** @brief used to iterate through sequences and mappings. + +A standard STL notation, with node.begin(), node.end() denoting the beginning and the end of a +sequence, stored in node. See the data reading sample in the beginning of the section. + */ +class CV_EXPORTS FileNodeIterator +{ +public: + /** @brief The constructors. + + These constructors are used to create a default iterator, set it to specific element in a file node + or construct it from another iterator. + */ + FileNodeIterator(); + + /** @overload + @param fs File storage for the iterator. + @param node File node for the iterator. + @param ofs Index of the element in the node. The created iterator will point to this element. + */ + FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0); + + /** @overload + @param it Iterator to be used as initialization for the created iterator. + */ + FileNodeIterator(const FileNodeIterator& it); + + //! returns the currently observed element + FileNode operator *() const; + //! accesses the currently observed element methods + FileNode operator ->() const; + + //! moves iterator to the next node + FileNodeIterator& operator ++ (); + //! moves iterator to the next node + FileNodeIterator operator ++ (int); + //! moves iterator to the previous node + FileNodeIterator& operator -- (); + //! moves iterator to the previous node + FileNodeIterator operator -- (int); + //! moves iterator forward by the specified offset (possibly negative) + FileNodeIterator& operator += (int ofs); + //! moves iterator backward by the specified offset (possibly negative) + FileNodeIterator& operator -= (int ofs); + + /** @brief Reads node elements to the buffer with the specified format. + + Usually it is more convenient to use operator `>>` instead of this method. + @param fmt Specification of each array element. See @ref format_spec "format specification" + @param vec Pointer to the destination array. + @param maxCount Number of elements to read. If it is greater than number of remaining elements then + all of them will be read. + */ + FileNodeIterator& readRaw( const String& fmt, uchar* vec, + size_t maxCount=(size_t)INT_MAX ); + + struct SeqReader + { + int header_size; + void* seq; /* sequence, beign read; CvSeq */ + void* block; /* current block; CvSeqBlock */ + schar* ptr; /* pointer to element be read next */ + schar* block_min; /* pointer to the beginning of block */ + schar* block_max; /* pointer to the end of block */ + int delta_index;/* = seq->first->start_index */ + schar* prev_elem; /* pointer to previous element */ + }; + + const CvFileStorage* fs; + const CvFileNode* container; + SeqReader reader; + size_t remaining; +}; + +//! @} core_xml + +/////////////////// XML & YAML I/O implementation ////////////////// + +//! @relates cv::FileStorage +//! @{ + +CV_EXPORTS void write( FileStorage& fs, const String& name, int value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, float value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, double value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, const String& value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, const Mat& value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, const SparseMat& value ); +CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector& value); +CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector& value); + +CV_EXPORTS void writeScalar( FileStorage& fs, int value ); +CV_EXPORTS void writeScalar( FileStorage& fs, float value ); +CV_EXPORTS void writeScalar( FileStorage& fs, double value ); +CV_EXPORTS void writeScalar( FileStorage& fs, const String& value ); + +//! @} + +//! @relates cv::FileNode +//! @{ + +CV_EXPORTS void read(const FileNode& node, int& value, int default_value); +CV_EXPORTS void read(const FileNode& node, float& value, float default_value); +CV_EXPORTS void read(const FileNode& node, double& value, double default_value); +CV_EXPORTS void read(const FileNode& node, String& value, const String& default_value); +CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat = Mat() ); +CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat = SparseMat() ); +CV_EXPORTS void read(const FileNode& node, std::vector& keypoints); +CV_EXPORTS void read(const FileNode& node, std::vector& matches); + +template static inline void read(const FileNode& node, Point_<_Tp>& value, const Point_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 2 ? default_value : Point_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); +} + +template static inline void read(const FileNode& node, Point3_<_Tp>& value, const Point3_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 3 ? default_value : Point3_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), + saturate_cast<_Tp>(temp[2])); +} + +template static inline void read(const FileNode& node, Size_<_Tp>& value, const Size_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 2 ? default_value : Size_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); +} + +template static inline void read(const FileNode& node, Complex<_Tp>& value, const Complex<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 2 ? default_value : Complex<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); +} + +template static inline void read(const FileNode& node, Rect_<_Tp>& value, const Rect_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 4 ? default_value : Rect_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), + saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3])); +} + +template static inline void read(const FileNode& node, Vec<_Tp, cn>& value, const Vec<_Tp, cn>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != cn ? default_value : Vec<_Tp, cn>(&temp[0]); +} + +template static inline void read(const FileNode& node, Scalar_<_Tp>& value, const Scalar_<_Tp>& default_value) +{ + std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; + value = temp.size() != 4 ? default_value : Scalar_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), + saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3])); +} + +static inline void read(const FileNode& node, Range& value, const Range& default_value) +{ + Point2i temp(value.start, value.end); const Point2i default_temp = Point2i(default_value.start, default_value.end); + read(node, temp, default_temp); + value.start = temp.x; value.end = temp.y; +} + +//! @} + +/** @brief Writes string to a file storage. +@relates cv::FileStorage + */ +CV_EXPORTS FileStorage& operator << (FileStorage& fs, const String& str); + +//! @cond IGNORED + +namespace internal +{ + class CV_EXPORTS WriteStructContext + { + public: + WriteStructContext(FileStorage& _fs, const String& name, int flags, const String& typeName = String()); + ~WriteStructContext(); + private: + FileStorage* fs; + }; + + template class VecWriterProxy + { + public: + VecWriterProxy( FileStorage* _fs ) : fs(_fs) {} + void operator()(const std::vector<_Tp>& vec) const + { + size_t count = vec.size(); + for (size_t i = 0; i < count; i++) + write(*fs, vec[i]); + } + private: + FileStorage* fs; + }; + + template class VecWriterProxy<_Tp, 1> + { + public: + VecWriterProxy( FileStorage* _fs ) : fs(_fs) {} + void operator()(const std::vector<_Tp>& vec) const + { + int _fmt = DataType<_Tp>::fmt; + char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' }; + fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp)); + } + private: + FileStorage* fs; + }; + + template class VecReaderProxy + { + public: + VecReaderProxy( FileNodeIterator* _it ) : it(_it) {} + void operator()(std::vector<_Tp>& vec, size_t count) const + { + count = std::min(count, it->remaining); + vec.resize(count); + for (size_t i = 0; i < count; i++, ++(*it)) + read(**it, vec[i], _Tp()); + } + private: + FileNodeIterator* it; + }; + + template class VecReaderProxy<_Tp, 1> + { + public: + VecReaderProxy( FileNodeIterator* _it ) : it(_it) {} + void operator()(std::vector<_Tp>& vec, size_t count) const + { + size_t remaining = it->remaining; + size_t cn = DataType<_Tp>::channels; + int _fmt = DataType<_Tp>::fmt; + char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' }; + size_t remaining1 = remaining / cn; + count = count < remaining1 ? count : remaining1; + vec.resize(count); + it->readRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, count*sizeof(_Tp)); + } + private: + FileNodeIterator* it; + }; + +} // internal + +//! @endcond + +//! @relates cv::FileStorage +//! @{ + +template static inline +void write(FileStorage& fs, const _Tp& value) +{ + write(fs, String(), value); +} + +template<> inline +void write( FileStorage& fs, const int& value ) +{ + writeScalar(fs, value); +} + +template<> inline +void write( FileStorage& fs, const float& value ) +{ + writeScalar(fs, value); +} + +template<> inline +void write( FileStorage& fs, const double& value ) +{ + writeScalar(fs, value); +} + +template<> inline +void write( FileStorage& fs, const String& value ) +{ + writeScalar(fs, value); +} + +template static inline +void write(FileStorage& fs, const Point_<_Tp>& pt ) +{ + write(fs, pt.x); + write(fs, pt.y); +} + +template static inline +void write(FileStorage& fs, const Point3_<_Tp>& pt ) +{ + write(fs, pt.x); + write(fs, pt.y); + write(fs, pt.z); +} + +template static inline +void write(FileStorage& fs, const Size_<_Tp>& sz ) +{ + write(fs, sz.width); + write(fs, sz.height); +} + +template static inline +void write(FileStorage& fs, const Complex<_Tp>& c ) +{ + write(fs, c.re); + write(fs, c.im); +} + +template static inline +void write(FileStorage& fs, const Rect_<_Tp>& r ) +{ + write(fs, r.x); + write(fs, r.y); + write(fs, r.width); + write(fs, r.height); +} + +template static inline +void write(FileStorage& fs, const Vec<_Tp, cn>& v ) +{ + for(int i = 0; i < cn; i++) + write(fs, v.val[i]); +} + +template static inline +void write(FileStorage& fs, const Scalar_<_Tp>& s ) +{ + write(fs, s.val[0]); + write(fs, s.val[1]); + write(fs, s.val[2]); + write(fs, s.val[3]); +} + +static inline +void write(FileStorage& fs, const Range& r ) +{ + write(fs, r.start); + write(fs, r.end); +} + +template static inline +void write( FileStorage& fs, const std::vector<_Tp>& vec ) +{ + cv::internal::VecWriterProxy<_Tp, DataType<_Tp>::fmt != 0> w(&fs); + w(vec); +} + + +template static inline +void write(FileStorage& fs, const String& name, const Point_<_Tp>& pt ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, pt); +} + +template static inline +void write(FileStorage& fs, const String& name, const Point3_<_Tp>& pt ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, pt); +} + +template static inline +void write(FileStorage& fs, const String& name, const Size_<_Tp>& sz ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, sz); +} + +template static inline +void write(FileStorage& fs, const String& name, const Complex<_Tp>& c ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, c); +} + +template static inline +void write(FileStorage& fs, const String& name, const Rect_<_Tp>& r ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, r); +} + +template static inline +void write(FileStorage& fs, const String& name, const Vec<_Tp, cn>& v ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, v); +} + +template static inline +void write(FileStorage& fs, const String& name, const Scalar_<_Tp>& s ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, s); +} + +static inline +void write(FileStorage& fs, const String& name, const Range& r ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); + write(fs, r); +} + +template static inline +void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec ) +{ + cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0)); + write(fs, vec); +} + +//! @} FileStorage + +//! @relates cv::FileNode +//! @{ + +static inline +void read(const FileNode& node, bool& value, bool default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = temp != 0; +} + +static inline +void read(const FileNode& node, uchar& value, uchar default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = saturate_cast(temp); +} + +static inline +void read(const FileNode& node, schar& value, schar default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = saturate_cast(temp); +} + +static inline +void read(const FileNode& node, ushort& value, ushort default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = saturate_cast(temp); +} + +static inline +void read(const FileNode& node, short& value, short default_value) +{ + int temp; + read(node, temp, (int)default_value); + value = saturate_cast(temp); +} + +template static inline +void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX ) +{ + cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it); + r(vec, maxCount); +} + +template static inline +void read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& default_value = std::vector<_Tp>() ) +{ + if(!node.node) + vec = default_value; + else + { + FileNodeIterator it = node.begin(); + read( it, vec ); + } +} + +//! @} FileNode + +//! @relates cv::FileStorage +//! @{ + +/** @brief Writes data to a file storage. + */ +template static inline +FileStorage& operator << (FileStorage& fs, const _Tp& value) +{ + if( !fs.isOpened() ) + return fs; + if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP ) + CV_Error( Error::StsError, "No element name has been given" ); + write( fs, fs.elname, value ); + if( fs.state & FileStorage::INSIDE_MAP ) + fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; + return fs; +} + +/** @brief Writes data to a file storage. + */ +static inline +FileStorage& operator << (FileStorage& fs, const char* str) +{ + return (fs << String(str)); +} + +/** @brief Writes data to a file storage. + */ +static inline +FileStorage& operator << (FileStorage& fs, char* value) +{ + return (fs << String(value)); +} + +//! @} FileStorage + +//! @relates cv::FileNodeIterator +//! @{ + +/** @brief Reads data from a file storage. + */ +template static inline +FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value) +{ + read( *it, value, _Tp()); + return ++it; +} + +/** @brief Reads data from a file storage. + */ +template static inline +FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec) +{ + cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it); + r(vec, (size_t)INT_MAX); + return it; +} + +//! @} FileNodeIterator + +//! @relates cv::FileNode +//! @{ + +/** @brief Reads data from a file storage. + */ +template static inline +void operator >> (const FileNode& n, _Tp& value) +{ + read( n, value, _Tp()); +} + +/** @brief Reads data from a file storage. + */ +template static inline +void operator >> (const FileNode& n, std::vector<_Tp>& vec) +{ + FileNodeIterator it = n.begin(); + it >> vec; +} + +//! @} FileNode + +//! @relates cv::FileNodeIterator +//! @{ + +static inline +bool operator == (const FileNodeIterator& it1, const FileNodeIterator& it2) +{ + return it1.fs == it2.fs && it1.container == it2.container && + it1.reader.ptr == it2.reader.ptr && it1.remaining == it2.remaining; +} + +static inline +bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2) +{ + return !(it1 == it2); +} + +static inline +ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2) +{ + return it2.remaining - it1.remaining; +} + +static inline +bool operator < (const FileNodeIterator& it1, const FileNodeIterator& it2) +{ + return it1.remaining > it2.remaining; +} + +//! @} FileNodeIterator + +//! @cond IGNORED + +inline FileNode FileStorage::getFirstTopLevelNode() const { FileNode r = root(); FileNodeIterator it = r.begin(); return it != r.end() ? *it : FileNode(); } +inline FileNode::FileNode() : fs(0), node(0) {} +inline FileNode::FileNode(const CvFileStorage* _fs, const CvFileNode* _node) : fs(_fs), node(_node) {} +inline FileNode::FileNode(const FileNode& _node) : fs(_node.fs), node(_node.node) {} +inline bool FileNode::empty() const { return node == 0; } +inline bool FileNode::isNone() const { return type() == NONE; } +inline bool FileNode::isSeq() const { return type() == SEQ; } +inline bool FileNode::isMap() const { return type() == MAP; } +inline bool FileNode::isInt() const { return type() == INT; } +inline bool FileNode::isReal() const { return type() == REAL; } +inline bool FileNode::isString() const { return type() == STR; } +inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; } +inline const CvFileNode* FileNode::operator* () const { return node; } +inline FileNode::operator int() const { int value; read(*this, value, 0); return value; } +inline FileNode::operator float() const { float value; read(*this, value, 0.f); return value; } +inline FileNode::operator double() const { double value; read(*this, value, 0.); return value; } +inline FileNode::operator String() const { String value; read(*this, value, value); return value; } +inline FileNodeIterator FileNode::begin() const { return FileNodeIterator(fs, node); } +inline FileNodeIterator FileNode::end() const { return FileNodeIterator(fs, node, size()); } +inline void FileNode::readRaw( const String& fmt, uchar* vec, size_t len ) const { begin().readRaw( fmt, vec, len ); } +inline FileNode FileNodeIterator::operator *() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); } +inline FileNode FileNodeIterator::operator ->() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); } +inline String::String(const FileNode& fn): cstr_(0), len_(0) { read(fn, *this, *this); } + +//! @endcond + +} // cv + +#endif // __OPENCV_CORE_PERSISTENCE_HPP__ diff --git a/include/opencv2/core/private.cuda.hpp b/include/opencv2/core/private.cuda.hpp new file mode 100644 index 0000000..d676ce8 --- /dev/null +++ b/include/opencv2/core/private.cuda.hpp @@ -0,0 +1,172 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_PRIVATE_CUDA_HPP__ +#define __OPENCV_CORE_PRIVATE_CUDA_HPP__ + +#ifndef __OPENCV_BUILD +# error this is a private header which should not be used from outside of the OpenCV library +#endif + +#include "cvconfig.h" + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/base.hpp" + +#include "opencv2/core/cuda.hpp" + +#ifdef HAVE_CUDA +# include +# include +# include +# include "opencv2/core/cuda_stream_accessor.hpp" +# include "opencv2/core/cuda/common.hpp" + +# define NPP_VERSION (NPP_VERSION_MAJOR * 1000 + NPP_VERSION_MINOR * 100 + NPP_VERSION_BUILD) + +# define CUDART_MINIMUM_REQUIRED_VERSION 4020 + +# if (CUDART_VERSION < CUDART_MINIMUM_REQUIRED_VERSION) +# error "Insufficient Cuda Runtime library version, please update it." +# endif + +# if defined(CUDA_ARCH_BIN_OR_PTX_10) +# error "OpenCV CUDA module doesn't support NVIDIA compute capability 1.0" +# endif +#endif + +//! @cond IGNORED + +namespace cv { namespace cuda { + CV_EXPORTS cv::String getNppErrorMessage(int code); + CV_EXPORTS cv::String getCudaDriverApiErrorMessage(int code); + + CV_EXPORTS GpuMat getInputMat(InputArray _src, Stream& stream); + + CV_EXPORTS GpuMat getOutputMat(OutputArray _dst, int rows, int cols, int type, Stream& stream); + static inline GpuMat getOutputMat(OutputArray _dst, Size size, int type, Stream& stream) + { + return getOutputMat(_dst, size.height, size.width, type, stream); + } + + CV_EXPORTS void syncOutput(const GpuMat& dst, OutputArray _dst, Stream& stream); +}} + +#ifndef HAVE_CUDA + +static inline void throw_no_cuda() { CV_Error(cv::Error::GpuNotSupported, "The library is compiled without CUDA support"); } + +#else // HAVE_CUDA + +static inline void throw_no_cuda() { CV_Error(cv::Error::StsNotImplemented, "The called functionality is disabled for current build or platform"); } + +namespace cv { namespace cuda +{ + class CV_EXPORTS BufferPool + { + public: + explicit BufferPool(Stream& stream); + + GpuMat getBuffer(int rows, int cols, int type); + GpuMat getBuffer(Size size, int type) { return getBuffer(size.height, size.width, type); } + + GpuMat::Allocator* getAllocator() const { return allocator_; } + + private: + GpuMat::Allocator* allocator_; + }; + + static inline void checkNppError(int code, const char* file, const int line, const char* func) + { + if (code < 0) + cv::error(cv::Error::GpuApiCallError, getNppErrorMessage(code), func, file, line); + } + + static inline void checkCudaDriverApiError(int code, const char* file, const int line, const char* func) + { + if (code != CUDA_SUCCESS) + cv::error(cv::Error::GpuApiCallError, getCudaDriverApiErrorMessage(code), func, file, line); + } + + template struct NPPTypeTraits; + template<> struct NPPTypeTraits { typedef Npp8u npp_type; }; + template<> struct NPPTypeTraits { typedef Npp8s npp_type; }; + template<> struct NPPTypeTraits { typedef Npp16u npp_type; }; + template<> struct NPPTypeTraits { typedef Npp16s npp_type; }; + template<> struct NPPTypeTraits { typedef Npp32s npp_type; }; + template<> struct NPPTypeTraits { typedef Npp32f npp_type; }; + template<> struct NPPTypeTraits { typedef Npp64f npp_type; }; + + class NppStreamHandler + { + public: + inline explicit NppStreamHandler(Stream& newStream) + { + oldStream = nppGetStream(); + nppSetStream(StreamAccessor::getStream(newStream)); + } + + inline explicit NppStreamHandler(cudaStream_t newStream) + { + oldStream = nppGetStream(); + nppSetStream(newStream); + } + + inline ~NppStreamHandler() + { + nppSetStream(oldStream); + } + + private: + cudaStream_t oldStream; + }; +}} + +#define nppSafeCall(expr) cv::cuda::checkNppError(expr, __FILE__, __LINE__, CV_Func) +#define cuSafeCall(expr) cv::cuda::checkCudaDriverApiError(expr, __FILE__, __LINE__, CV_Func) + +#endif // HAVE_CUDA + +//! @endcond + +#endif // __OPENCV_CORE_CUDA_PRIVATE_HPP__ diff --git a/include/opencv2/core/private.hpp b/include/opencv2/core/private.hpp new file mode 100644 index 0000000..4f9f487 --- /dev/null +++ b/include/opencv2/core/private.hpp @@ -0,0 +1,296 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_PRIVATE_HPP__ +#define __OPENCV_CORE_PRIVATE_HPP__ + +#ifndef __OPENCV_BUILD +# error this is a private header which should not be used from outside of the OpenCV library +#endif + +#include "opencv2/core.hpp" +#include "cvconfig.h" + +#ifdef HAVE_EIGEN +# if defined __GNUC__ && defined __APPLE__ +# pragma GCC diagnostic ignored "-Wshadow" +# endif +# include +# include "opencv2/core/eigen.hpp" +#endif + +#ifdef HAVE_TBB +# include "tbb/tbb_stddef.h" +# if TBB_VERSION_MAJOR*100 + TBB_VERSION_MINOR >= 202 +# include "tbb/tbb.h" +# include "tbb/task.h" +# undef min +# undef max +# else +# undef HAVE_TBB +# endif +#endif + +//! @cond IGNORED + +namespace cv +{ +#ifdef HAVE_TBB + + typedef tbb::blocked_range BlockedRange; + + template static inline + void parallel_for( const BlockedRange& range, const Body& body ) + { + tbb::parallel_for(range, body); + } + + typedef tbb::split Split; + + template static inline + void parallel_reduce( const BlockedRange& range, Body& body ) + { + tbb::parallel_reduce(range, body); + } + + typedef tbb::concurrent_vector ConcurrentRectVector; +#else + class BlockedRange + { + public: + BlockedRange() : _begin(0), _end(0), _grainsize(0) {} + BlockedRange(int b, int e, int g=1) : _begin(b), _end(e), _grainsize(g) {} + int begin() const { return _begin; } + int end() const { return _end; } + int grainsize() const { return _grainsize; } + + protected: + int _begin, _end, _grainsize; + }; + + template static inline + void parallel_for( const BlockedRange& range, const Body& body ) + { + body(range); + } + typedef std::vector ConcurrentRectVector; + + class Split {}; + + template static inline + void parallel_reduce( const BlockedRange& range, Body& body ) + { + body(range); + } +#endif + + // Returns a static string if there is a parallel framework, + // NULL otherwise. + CV_EXPORTS const char* currentParallelFramework(); +} //namespace cv + +/****************************************************************************************\ +* Common declarations * +\****************************************************************************************/ + +/* the alignment of all the allocated buffers */ +#define CV_MALLOC_ALIGN 16 + +/* IEEE754 constants and macros */ +#define CV_TOGGLE_FLT(x) ((x)^((int)(x) < 0 ? 0x7fffffff : 0)) +#define CV_TOGGLE_DBL(x) ((x)^((int64)(x) < 0 ? CV_BIG_INT(0x7fffffffffffffff) : 0)) + +static inline void* cvAlignPtr( const void* ptr, int align = 32 ) +{ + CV_DbgAssert ( (align & (align-1)) == 0 ); + return (void*)( ((size_t)ptr + align - 1) & ~(size_t)(align-1) ); +} + +static inline int cvAlign( int size, int align ) +{ + CV_DbgAssert( (align & (align-1)) == 0 && size < INT_MAX ); + return (size + align - 1) & -align; +} + +#ifdef IPL_DEPTH_8U +static inline cv::Size cvGetMatSize( const CvMat* mat ) +{ + return cv::Size(mat->cols, mat->rows); +} +#endif + +namespace cv +{ +CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int unroll_to = 0); +} + +// property implementation macros + +#define CV_IMPL_PROPERTY_RO(type, name, member) \ + inline type get##name() const { return member; } + +#define CV_HELP_IMPL_PROPERTY(r_type, w_type, name, member) \ + CV_IMPL_PROPERTY_RO(r_type, name, member) \ + inline void set##name(w_type val) { member = val; } + +#define CV_HELP_WRAP_PROPERTY(r_type, w_type, name, internal_name, internal_obj) \ + r_type get##name() const { return internal_obj.get##internal_name(); } \ + void set##name(w_type val) { internal_obj.set##internal_name(val); } + +#define CV_IMPL_PROPERTY(type, name, member) CV_HELP_IMPL_PROPERTY(type, type, name, member) +#define CV_IMPL_PROPERTY_S(type, name, member) CV_HELP_IMPL_PROPERTY(type, const type &, name, member) + +#define CV_WRAP_PROPERTY(type, name, internal_name, internal_obj) CV_HELP_WRAP_PROPERTY(type, type, name, internal_name, internal_obj) +#define CV_WRAP_PROPERTY_S(type, name, internal_name, internal_obj) CV_HELP_WRAP_PROPERTY(type, const type &, name, internal_name, internal_obj) + +#define CV_WRAP_SAME_PROPERTY(type, name, internal_obj) CV_WRAP_PROPERTY(type, name, name, internal_obj) +#define CV_WRAP_SAME_PROPERTY_S(type, name, internal_obj) CV_WRAP_PROPERTY_S(type, name, name, internal_obj) + +/****************************************************************************************\ +* Structures and macros for integration with IPP * +\****************************************************************************************/ + +#ifdef HAVE_IPP +# include "ipp.h" + +# define IPP_VERSION_X100 (IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR) + +#define IPP_ALIGN 32 // required for AVX optimization + +#define setIppErrorStatus() cv::ipp::setIppStatus(-1, CV_Func, __FILE__, __LINE__) + +static inline IppiSize ippiSize(int width, int height) +{ + IppiSize size = { width, height }; + return size; +} + +static inline IppiSize ippiSize(const cv::Size & _size) +{ + IppiSize size = { _size.width, _size.height }; + return size; +} + +static inline IppiBorderType ippiGetBorderType(int borderTypeNI) +{ + return borderTypeNI == cv::BORDER_CONSTANT ? ippBorderConst : + borderTypeNI == cv::BORDER_WRAP ? ippBorderWrap : + borderTypeNI == cv::BORDER_REPLICATE ? ippBorderRepl : + borderTypeNI == cv::BORDER_REFLECT_101 ? ippBorderMirror : + borderTypeNI == cv::BORDER_REFLECT ? ippBorderMirrorR : (IppiBorderType)-1; +} + +static inline IppDataType ippiGetDataType(int depth) +{ + return depth == CV_8U ? ipp8u : + depth == CV_8S ? ipp8s : + depth == CV_16U ? ipp16u : + depth == CV_16S ? ipp16s : + depth == CV_32S ? ipp32s : + depth == CV_32F ? ipp32f : + depth == CV_64F ? ipp64f : (IppDataType)-1; +} + +#else +# define IPP_VERSION_X100 0 +#endif + +#define CV_IPP_CHECK_COND (cv::ipp::useIPP()) +#define CV_IPP_CHECK() if(CV_IPP_CHECK_COND) + +#ifndef IPPI_CALL +# define IPPI_CALL(func) CV_Assert((func) >= 0) +#endif + +/* IPP-compatible return codes */ +typedef enum CvStatus +{ + CV_BADMEMBLOCK_ERR = -113, + CV_INPLACE_NOT_SUPPORTED_ERR= -112, + CV_UNMATCHED_ROI_ERR = -111, + CV_NOTFOUND_ERR = -110, + CV_BADCONVERGENCE_ERR = -109, + + CV_BADDEPTH_ERR = -107, + CV_BADROI_ERR = -106, + CV_BADHEADER_ERR = -105, + CV_UNMATCHED_FORMATS_ERR = -104, + CV_UNSUPPORTED_COI_ERR = -103, + CV_UNSUPPORTED_CHANNELS_ERR = -102, + CV_UNSUPPORTED_DEPTH_ERR = -101, + CV_UNSUPPORTED_FORMAT_ERR = -100, + + CV_BADARG_ERR = -49, //ipp comp + CV_NOTDEFINED_ERR = -48, //ipp comp + + CV_BADCHANNELS_ERR = -47, //ipp comp + CV_BADRANGE_ERR = -44, //ipp comp + CV_BADSTEP_ERR = -29, //ipp comp + + CV_BADFLAG_ERR = -12, + CV_DIV_BY_ZERO_ERR = -11, //ipp comp + CV_BADCOEF_ERR = -10, + + CV_BADFACTOR_ERR = -7, + CV_BADPOINT_ERR = -6, + CV_BADSCALE_ERR = -4, + CV_OUTOFMEM_ERR = -3, + CV_NULLPTR_ERR = -2, + CV_BADSIZE_ERR = -1, + CV_NO_ERR = 0, + CV_OK = CV_NO_ERR +} +CvStatus; + +#ifdef HAVE_TEGRA_OPTIMIZATION +namespace tegra { + +CV_EXPORTS bool useTegra(); +CV_EXPORTS void setUseTegra(bool flag); + +} +#endif + +//! @endcond + +#endif // __OPENCV_CORE_PRIVATE_HPP__ diff --git a/include/opencv2/core/ptr.inl.hpp b/include/opencv2/core/ptr.inl.hpp new file mode 100644 index 0000000..65c09d1 --- /dev/null +++ b/include/opencv2/core/ptr.inl.hpp @@ -0,0 +1,342 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, NVIDIA Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the copyright holders or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_PTR_INL_HPP__ +#define __OPENCV_CORE_PTR_INL_HPP__ + +#include + +//! @cond IGNORED + +namespace cv { + +template +void DefaultDeleter::operator () (Y* p) const +{ + delete p; +} + +namespace detail +{ + +struct PtrOwner +{ + PtrOwner() : refCount(1) + {} + + void incRef() + { + CV_XADD(&refCount, 1); + } + + void decRef() + { + if (CV_XADD(&refCount, -1) == 1) deleteSelf(); + } + +protected: + /* This doesn't really need to be virtual, since PtrOwner is never deleted + directly, but it doesn't hurt and it helps avoid warnings. */ + virtual ~PtrOwner() + {} + + virtual void deleteSelf() = 0; + +private: + unsigned int refCount; + + // noncopyable + PtrOwner(const PtrOwner&); + PtrOwner& operator = (const PtrOwner&); +}; + +template +struct PtrOwnerImpl : PtrOwner +{ + PtrOwnerImpl(Y* p, D d) : owned(p), deleter(d) + {} + + void deleteSelf() + { + deleter(owned); + delete this; + } + +private: + Y* owned; + D deleter; +}; + + +} + +template +Ptr::Ptr() : owner(NULL), stored(NULL) +{} + +template +template +Ptr::Ptr(Y* p) + : owner(p + ? new detail::PtrOwnerImpl >(p, DefaultDeleter()) + : NULL), + stored(p) +{} + +template +template +Ptr::Ptr(Y* p, D d) + : owner(p + ? new detail::PtrOwnerImpl(p, d) + : NULL), + stored(p) +{} + +template +Ptr::Ptr(const Ptr& o) : owner(o.owner), stored(o.stored) +{ + if (owner) owner->incRef(); +} + +template +template +Ptr::Ptr(const Ptr& o) : owner(o.owner), stored(o.stored) +{ + if (owner) owner->incRef(); +} + +template +template +Ptr::Ptr(const Ptr& o, T* p) : owner(o.owner), stored(p) +{ + if (owner) owner->incRef(); +} + +template +Ptr::~Ptr() +{ + release(); +} + +template +Ptr& Ptr::operator = (const Ptr& o) +{ + Ptr(o).swap(*this); + return *this; +} + +template +template +Ptr& Ptr::operator = (const Ptr& o) +{ + Ptr(o).swap(*this); + return *this; +} + +template +void Ptr::release() +{ + if (owner) owner->decRef(); + owner = NULL; + stored = NULL; +} + +template +template +void Ptr::reset(Y* p) +{ + Ptr(p).swap(*this); +} + +template +template +void Ptr::reset(Y* p, D d) +{ + Ptr(p, d).swap(*this); +} + +template +void Ptr::swap(Ptr& o) +{ + std::swap(owner, o.owner); + std::swap(stored, o.stored); +} + +template +T* Ptr::get() const +{ + return stored; +} + +template +typename detail::RefOrVoid::type Ptr::operator * () const +{ + return *stored; +} + +template +T* Ptr::operator -> () const +{ + return stored; +} + +template +Ptr::operator T* () const +{ + return stored; +} + + +template +bool Ptr::empty() const +{ + return !stored; +} + +template +template +Ptr Ptr::staticCast() const +{ + return Ptr(*this, static_cast(stored)); +} + +template +template +Ptr Ptr::constCast() const +{ + return Ptr(*this, const_cast(stored)); +} + +template +template +Ptr Ptr::dynamicCast() const +{ + return Ptr(*this, dynamic_cast(stored)); +} + +template +void swap(Ptr& ptr1, Ptr& ptr2){ + ptr1.swap(ptr2); +} + +template +bool operator == (const Ptr& ptr1, const Ptr& ptr2) +{ + return ptr1.get() == ptr2.get(); +} + +template +bool operator != (const Ptr& ptr1, const Ptr& ptr2) +{ + return ptr1.get() != ptr2.get(); +} + +template +Ptr makePtr() +{ + return Ptr(new T()); +} + +template +Ptr makePtr(const A1& a1) +{ + return Ptr(new T(a1)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2) +{ + return Ptr(new T(a1, a2)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3) +{ + return Ptr(new T(a1, a2, a3)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4) +{ + return Ptr(new T(a1, a2, a3, a4)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) +{ + return Ptr(new T(a1, a2, a3, a4, a5)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} + +template +Ptr makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10) +{ + return Ptr(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); +} + +} // namespace cv + +//! @endcond + +#endif // __OPENCV_CORE_PTR_INL_HPP__ diff --git a/include/opencv2/core/sse_utils.hpp b/include/opencv2/core/sse_utils.hpp new file mode 100644 index 0000000..e0283eb --- /dev/null +++ b/include/opencv2/core/sse_utils.hpp @@ -0,0 +1,645 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_SSE_UTILS_HPP__ +#define __OPENCV_CORE_SSE_UTILS_HPP__ + +#ifndef __cplusplus +# error sse_utils.hpp header must be compiled as C++ +#endif + +#if CV_SSE2 + +inline void _mm_deinterleave_epi8(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, __m128i & v_g1) +{ + __m128i layer1_chunk0 = _mm_unpacklo_epi8(v_r0, v_g0); + __m128i layer1_chunk1 = _mm_unpackhi_epi8(v_r0, v_g0); + __m128i layer1_chunk2 = _mm_unpacklo_epi8(v_r1, v_g1); + __m128i layer1_chunk3 = _mm_unpackhi_epi8(v_r1, v_g1); + + __m128i layer2_chunk0 = _mm_unpacklo_epi8(layer1_chunk0, layer1_chunk2); + __m128i layer2_chunk1 = _mm_unpackhi_epi8(layer1_chunk0, layer1_chunk2); + __m128i layer2_chunk2 = _mm_unpacklo_epi8(layer1_chunk1, layer1_chunk3); + __m128i layer2_chunk3 = _mm_unpackhi_epi8(layer1_chunk1, layer1_chunk3); + + __m128i layer3_chunk0 = _mm_unpacklo_epi8(layer2_chunk0, layer2_chunk2); + __m128i layer3_chunk1 = _mm_unpackhi_epi8(layer2_chunk0, layer2_chunk2); + __m128i layer3_chunk2 = _mm_unpacklo_epi8(layer2_chunk1, layer2_chunk3); + __m128i layer3_chunk3 = _mm_unpackhi_epi8(layer2_chunk1, layer2_chunk3); + + __m128i layer4_chunk0 = _mm_unpacklo_epi8(layer3_chunk0, layer3_chunk2); + __m128i layer4_chunk1 = _mm_unpackhi_epi8(layer3_chunk0, layer3_chunk2); + __m128i layer4_chunk2 = _mm_unpacklo_epi8(layer3_chunk1, layer3_chunk3); + __m128i layer4_chunk3 = _mm_unpackhi_epi8(layer3_chunk1, layer3_chunk3); + + v_r0 = _mm_unpacklo_epi8(layer4_chunk0, layer4_chunk2); + v_r1 = _mm_unpackhi_epi8(layer4_chunk0, layer4_chunk2); + v_g0 = _mm_unpacklo_epi8(layer4_chunk1, layer4_chunk3); + v_g1 = _mm_unpackhi_epi8(layer4_chunk1, layer4_chunk3); +} + +inline void _mm_deinterleave_epi8(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, + __m128i & v_g1, __m128i & v_b0, __m128i & v_b1) +{ + __m128i layer1_chunk0 = _mm_unpacklo_epi8(v_r0, v_g1); + __m128i layer1_chunk1 = _mm_unpackhi_epi8(v_r0, v_g1); + __m128i layer1_chunk2 = _mm_unpacklo_epi8(v_r1, v_b0); + __m128i layer1_chunk3 = _mm_unpackhi_epi8(v_r1, v_b0); + __m128i layer1_chunk4 = _mm_unpacklo_epi8(v_g0, v_b1); + __m128i layer1_chunk5 = _mm_unpackhi_epi8(v_g0, v_b1); + + __m128i layer2_chunk0 = _mm_unpacklo_epi8(layer1_chunk0, layer1_chunk3); + __m128i layer2_chunk1 = _mm_unpackhi_epi8(layer1_chunk0, layer1_chunk3); + __m128i layer2_chunk2 = _mm_unpacklo_epi8(layer1_chunk1, layer1_chunk4); + __m128i layer2_chunk3 = _mm_unpackhi_epi8(layer1_chunk1, layer1_chunk4); + __m128i layer2_chunk4 = _mm_unpacklo_epi8(layer1_chunk2, layer1_chunk5); + __m128i layer2_chunk5 = _mm_unpackhi_epi8(layer1_chunk2, layer1_chunk5); + + __m128i layer3_chunk0 = _mm_unpacklo_epi8(layer2_chunk0, layer2_chunk3); + __m128i layer3_chunk1 = _mm_unpackhi_epi8(layer2_chunk0, layer2_chunk3); + __m128i layer3_chunk2 = _mm_unpacklo_epi8(layer2_chunk1, layer2_chunk4); + __m128i layer3_chunk3 = _mm_unpackhi_epi8(layer2_chunk1, layer2_chunk4); + __m128i layer3_chunk4 = _mm_unpacklo_epi8(layer2_chunk2, layer2_chunk5); + __m128i layer3_chunk5 = _mm_unpackhi_epi8(layer2_chunk2, layer2_chunk5); + + __m128i layer4_chunk0 = _mm_unpacklo_epi8(layer3_chunk0, layer3_chunk3); + __m128i layer4_chunk1 = _mm_unpackhi_epi8(layer3_chunk0, layer3_chunk3); + __m128i layer4_chunk2 = _mm_unpacklo_epi8(layer3_chunk1, layer3_chunk4); + __m128i layer4_chunk3 = _mm_unpackhi_epi8(layer3_chunk1, layer3_chunk4); + __m128i layer4_chunk4 = _mm_unpacklo_epi8(layer3_chunk2, layer3_chunk5); + __m128i layer4_chunk5 = _mm_unpackhi_epi8(layer3_chunk2, layer3_chunk5); + + v_r0 = _mm_unpacklo_epi8(layer4_chunk0, layer4_chunk3); + v_r1 = _mm_unpackhi_epi8(layer4_chunk0, layer4_chunk3); + v_g0 = _mm_unpacklo_epi8(layer4_chunk1, layer4_chunk4); + v_g1 = _mm_unpackhi_epi8(layer4_chunk1, layer4_chunk4); + v_b0 = _mm_unpacklo_epi8(layer4_chunk2, layer4_chunk5); + v_b1 = _mm_unpackhi_epi8(layer4_chunk2, layer4_chunk5); +} + +inline void _mm_deinterleave_epi8(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, __m128i & v_g1, + __m128i & v_b0, __m128i & v_b1, __m128i & v_a0, __m128i & v_a1) +{ + __m128i layer1_chunk0 = _mm_unpacklo_epi8(v_r0, v_b0); + __m128i layer1_chunk1 = _mm_unpackhi_epi8(v_r0, v_b0); + __m128i layer1_chunk2 = _mm_unpacklo_epi8(v_r1, v_b1); + __m128i layer1_chunk3 = _mm_unpackhi_epi8(v_r1, v_b1); + __m128i layer1_chunk4 = _mm_unpacklo_epi8(v_g0, v_a0); + __m128i layer1_chunk5 = _mm_unpackhi_epi8(v_g0, v_a0); + __m128i layer1_chunk6 = _mm_unpacklo_epi8(v_g1, v_a1); + __m128i layer1_chunk7 = _mm_unpackhi_epi8(v_g1, v_a1); + + __m128i layer2_chunk0 = _mm_unpacklo_epi8(layer1_chunk0, layer1_chunk4); + __m128i layer2_chunk1 = _mm_unpackhi_epi8(layer1_chunk0, layer1_chunk4); + __m128i layer2_chunk2 = _mm_unpacklo_epi8(layer1_chunk1, layer1_chunk5); + __m128i layer2_chunk3 = _mm_unpackhi_epi8(layer1_chunk1, layer1_chunk5); + __m128i layer2_chunk4 = _mm_unpacklo_epi8(layer1_chunk2, layer1_chunk6); + __m128i layer2_chunk5 = _mm_unpackhi_epi8(layer1_chunk2, layer1_chunk6); + __m128i layer2_chunk6 = _mm_unpacklo_epi8(layer1_chunk3, layer1_chunk7); + __m128i layer2_chunk7 = _mm_unpackhi_epi8(layer1_chunk3, layer1_chunk7); + + __m128i layer3_chunk0 = _mm_unpacklo_epi8(layer2_chunk0, layer2_chunk4); + __m128i layer3_chunk1 = _mm_unpackhi_epi8(layer2_chunk0, layer2_chunk4); + __m128i layer3_chunk2 = _mm_unpacklo_epi8(layer2_chunk1, layer2_chunk5); + __m128i layer3_chunk3 = _mm_unpackhi_epi8(layer2_chunk1, layer2_chunk5); + __m128i layer3_chunk4 = _mm_unpacklo_epi8(layer2_chunk2, layer2_chunk6); + __m128i layer3_chunk5 = _mm_unpackhi_epi8(layer2_chunk2, layer2_chunk6); + __m128i layer3_chunk6 = _mm_unpacklo_epi8(layer2_chunk3, layer2_chunk7); + __m128i layer3_chunk7 = _mm_unpackhi_epi8(layer2_chunk3, layer2_chunk7); + + __m128i layer4_chunk0 = _mm_unpacklo_epi8(layer3_chunk0, layer3_chunk4); + __m128i layer4_chunk1 = _mm_unpackhi_epi8(layer3_chunk0, layer3_chunk4); + __m128i layer4_chunk2 = _mm_unpacklo_epi8(layer3_chunk1, layer3_chunk5); + __m128i layer4_chunk3 = _mm_unpackhi_epi8(layer3_chunk1, layer3_chunk5); + __m128i layer4_chunk4 = _mm_unpacklo_epi8(layer3_chunk2, layer3_chunk6); + __m128i layer4_chunk5 = _mm_unpackhi_epi8(layer3_chunk2, layer3_chunk6); + __m128i layer4_chunk6 = _mm_unpacklo_epi8(layer3_chunk3, layer3_chunk7); + __m128i layer4_chunk7 = _mm_unpackhi_epi8(layer3_chunk3, layer3_chunk7); + + v_r0 = _mm_unpacklo_epi8(layer4_chunk0, layer4_chunk4); + v_r1 = _mm_unpackhi_epi8(layer4_chunk0, layer4_chunk4); + v_g0 = _mm_unpacklo_epi8(layer4_chunk1, layer4_chunk5); + v_g1 = _mm_unpackhi_epi8(layer4_chunk1, layer4_chunk5); + v_b0 = _mm_unpacklo_epi8(layer4_chunk2, layer4_chunk6); + v_b1 = _mm_unpackhi_epi8(layer4_chunk2, layer4_chunk6); + v_a0 = _mm_unpacklo_epi8(layer4_chunk3, layer4_chunk7); + v_a1 = _mm_unpackhi_epi8(layer4_chunk3, layer4_chunk7); +} + +inline void _mm_interleave_epi8(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, __m128i & v_g1) +{ + __m128i v_mask = _mm_set1_epi16(0x00ff); + + __m128i layer4_chunk0 = _mm_packus_epi16(_mm_and_si128(v_r0, v_mask), _mm_and_si128(v_r1, v_mask)); + __m128i layer4_chunk2 = _mm_packus_epi16(_mm_srli_epi16(v_r0, 8), _mm_srli_epi16(v_r1, 8)); + __m128i layer4_chunk1 = _mm_packus_epi16(_mm_and_si128(v_g0, v_mask), _mm_and_si128(v_g1, v_mask)); + __m128i layer4_chunk3 = _mm_packus_epi16(_mm_srli_epi16(v_g0, 8), _mm_srli_epi16(v_g1, 8)); + + __m128i layer3_chunk0 = _mm_packus_epi16(_mm_and_si128(layer4_chunk0, v_mask), _mm_and_si128(layer4_chunk1, v_mask)); + __m128i layer3_chunk2 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk0, 8), _mm_srli_epi16(layer4_chunk1, 8)); + __m128i layer3_chunk1 = _mm_packus_epi16(_mm_and_si128(layer4_chunk2, v_mask), _mm_and_si128(layer4_chunk3, v_mask)); + __m128i layer3_chunk3 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk2, 8), _mm_srli_epi16(layer4_chunk3, 8)); + + __m128i layer2_chunk0 = _mm_packus_epi16(_mm_and_si128(layer3_chunk0, v_mask), _mm_and_si128(layer3_chunk1, v_mask)); + __m128i layer2_chunk2 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk0, 8), _mm_srli_epi16(layer3_chunk1, 8)); + __m128i layer2_chunk1 = _mm_packus_epi16(_mm_and_si128(layer3_chunk2, v_mask), _mm_and_si128(layer3_chunk3, v_mask)); + __m128i layer2_chunk3 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk2, 8), _mm_srli_epi16(layer3_chunk3, 8)); + + __m128i layer1_chunk0 = _mm_packus_epi16(_mm_and_si128(layer2_chunk0, v_mask), _mm_and_si128(layer2_chunk1, v_mask)); + __m128i layer1_chunk2 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk0, 8), _mm_srli_epi16(layer2_chunk1, 8)); + __m128i layer1_chunk1 = _mm_packus_epi16(_mm_and_si128(layer2_chunk2, v_mask), _mm_and_si128(layer2_chunk3, v_mask)); + __m128i layer1_chunk3 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk2, 8), _mm_srli_epi16(layer2_chunk3, 8)); + + v_r0 = _mm_packus_epi16(_mm_and_si128(layer1_chunk0, v_mask), _mm_and_si128(layer1_chunk1, v_mask)); + v_g0 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk0, 8), _mm_srli_epi16(layer1_chunk1, 8)); + v_r1 = _mm_packus_epi16(_mm_and_si128(layer1_chunk2, v_mask), _mm_and_si128(layer1_chunk3, v_mask)); + v_g1 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk2, 8), _mm_srli_epi16(layer1_chunk3, 8)); +} + +inline void _mm_interleave_epi8(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, + __m128i & v_g1, __m128i & v_b0, __m128i & v_b1) +{ + __m128i v_mask = _mm_set1_epi16(0x00ff); + + __m128i layer4_chunk0 = _mm_packus_epi16(_mm_and_si128(v_r0, v_mask), _mm_and_si128(v_r1, v_mask)); + __m128i layer4_chunk3 = _mm_packus_epi16(_mm_srli_epi16(v_r0, 8), _mm_srli_epi16(v_r1, 8)); + __m128i layer4_chunk1 = _mm_packus_epi16(_mm_and_si128(v_g0, v_mask), _mm_and_si128(v_g1, v_mask)); + __m128i layer4_chunk4 = _mm_packus_epi16(_mm_srli_epi16(v_g0, 8), _mm_srli_epi16(v_g1, 8)); + __m128i layer4_chunk2 = _mm_packus_epi16(_mm_and_si128(v_b0, v_mask), _mm_and_si128(v_b1, v_mask)); + __m128i layer4_chunk5 = _mm_packus_epi16(_mm_srli_epi16(v_b0, 8), _mm_srli_epi16(v_b1, 8)); + + __m128i layer3_chunk0 = _mm_packus_epi16(_mm_and_si128(layer4_chunk0, v_mask), _mm_and_si128(layer4_chunk1, v_mask)); + __m128i layer3_chunk3 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk0, 8), _mm_srli_epi16(layer4_chunk1, 8)); + __m128i layer3_chunk1 = _mm_packus_epi16(_mm_and_si128(layer4_chunk2, v_mask), _mm_and_si128(layer4_chunk3, v_mask)); + __m128i layer3_chunk4 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk2, 8), _mm_srli_epi16(layer4_chunk3, 8)); + __m128i layer3_chunk2 = _mm_packus_epi16(_mm_and_si128(layer4_chunk4, v_mask), _mm_and_si128(layer4_chunk5, v_mask)); + __m128i layer3_chunk5 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk4, 8), _mm_srli_epi16(layer4_chunk5, 8)); + + __m128i layer2_chunk0 = _mm_packus_epi16(_mm_and_si128(layer3_chunk0, v_mask), _mm_and_si128(layer3_chunk1, v_mask)); + __m128i layer2_chunk3 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk0, 8), _mm_srli_epi16(layer3_chunk1, 8)); + __m128i layer2_chunk1 = _mm_packus_epi16(_mm_and_si128(layer3_chunk2, v_mask), _mm_and_si128(layer3_chunk3, v_mask)); + __m128i layer2_chunk4 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk2, 8), _mm_srli_epi16(layer3_chunk3, 8)); + __m128i layer2_chunk2 = _mm_packus_epi16(_mm_and_si128(layer3_chunk4, v_mask), _mm_and_si128(layer3_chunk5, v_mask)); + __m128i layer2_chunk5 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk4, 8), _mm_srli_epi16(layer3_chunk5, 8)); + + __m128i layer1_chunk0 = _mm_packus_epi16(_mm_and_si128(layer2_chunk0, v_mask), _mm_and_si128(layer2_chunk1, v_mask)); + __m128i layer1_chunk3 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk0, 8), _mm_srli_epi16(layer2_chunk1, 8)); + __m128i layer1_chunk1 = _mm_packus_epi16(_mm_and_si128(layer2_chunk2, v_mask), _mm_and_si128(layer2_chunk3, v_mask)); + __m128i layer1_chunk4 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk2, 8), _mm_srli_epi16(layer2_chunk3, 8)); + __m128i layer1_chunk2 = _mm_packus_epi16(_mm_and_si128(layer2_chunk4, v_mask), _mm_and_si128(layer2_chunk5, v_mask)); + __m128i layer1_chunk5 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk4, 8), _mm_srli_epi16(layer2_chunk5, 8)); + + v_r0 = _mm_packus_epi16(_mm_and_si128(layer1_chunk0, v_mask), _mm_and_si128(layer1_chunk1, v_mask)); + v_g1 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk0, 8), _mm_srli_epi16(layer1_chunk1, 8)); + v_r1 = _mm_packus_epi16(_mm_and_si128(layer1_chunk2, v_mask), _mm_and_si128(layer1_chunk3, v_mask)); + v_b0 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk2, 8), _mm_srli_epi16(layer1_chunk3, 8)); + v_g0 = _mm_packus_epi16(_mm_and_si128(layer1_chunk4, v_mask), _mm_and_si128(layer1_chunk5, v_mask)); + v_b1 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk4, 8), _mm_srli_epi16(layer1_chunk5, 8)); +} + +inline void _mm_interleave_epi8(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, __m128i & v_g1, + __m128i & v_b0, __m128i & v_b1, __m128i & v_a0, __m128i & v_a1) +{ + __m128i v_mask = _mm_set1_epi16(0x00ff); + + __m128i layer4_chunk0 = _mm_packus_epi16(_mm_and_si128(v_r0, v_mask), _mm_and_si128(v_r1, v_mask)); + __m128i layer4_chunk4 = _mm_packus_epi16(_mm_srli_epi16(v_r0, 8), _mm_srli_epi16(v_r1, 8)); + __m128i layer4_chunk1 = _mm_packus_epi16(_mm_and_si128(v_g0, v_mask), _mm_and_si128(v_g1, v_mask)); + __m128i layer4_chunk5 = _mm_packus_epi16(_mm_srli_epi16(v_g0, 8), _mm_srli_epi16(v_g1, 8)); + __m128i layer4_chunk2 = _mm_packus_epi16(_mm_and_si128(v_b0, v_mask), _mm_and_si128(v_b1, v_mask)); + __m128i layer4_chunk6 = _mm_packus_epi16(_mm_srli_epi16(v_b0, 8), _mm_srli_epi16(v_b1, 8)); + __m128i layer4_chunk3 = _mm_packus_epi16(_mm_and_si128(v_a0, v_mask), _mm_and_si128(v_a1, v_mask)); + __m128i layer4_chunk7 = _mm_packus_epi16(_mm_srli_epi16(v_a0, 8), _mm_srli_epi16(v_a1, 8)); + + __m128i layer3_chunk0 = _mm_packus_epi16(_mm_and_si128(layer4_chunk0, v_mask), _mm_and_si128(layer4_chunk1, v_mask)); + __m128i layer3_chunk4 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk0, 8), _mm_srli_epi16(layer4_chunk1, 8)); + __m128i layer3_chunk1 = _mm_packus_epi16(_mm_and_si128(layer4_chunk2, v_mask), _mm_and_si128(layer4_chunk3, v_mask)); + __m128i layer3_chunk5 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk2, 8), _mm_srli_epi16(layer4_chunk3, 8)); + __m128i layer3_chunk2 = _mm_packus_epi16(_mm_and_si128(layer4_chunk4, v_mask), _mm_and_si128(layer4_chunk5, v_mask)); + __m128i layer3_chunk6 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk4, 8), _mm_srli_epi16(layer4_chunk5, 8)); + __m128i layer3_chunk3 = _mm_packus_epi16(_mm_and_si128(layer4_chunk6, v_mask), _mm_and_si128(layer4_chunk7, v_mask)); + __m128i layer3_chunk7 = _mm_packus_epi16(_mm_srli_epi16(layer4_chunk6, 8), _mm_srli_epi16(layer4_chunk7, 8)); + + __m128i layer2_chunk0 = _mm_packus_epi16(_mm_and_si128(layer3_chunk0, v_mask), _mm_and_si128(layer3_chunk1, v_mask)); + __m128i layer2_chunk4 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk0, 8), _mm_srli_epi16(layer3_chunk1, 8)); + __m128i layer2_chunk1 = _mm_packus_epi16(_mm_and_si128(layer3_chunk2, v_mask), _mm_and_si128(layer3_chunk3, v_mask)); + __m128i layer2_chunk5 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk2, 8), _mm_srli_epi16(layer3_chunk3, 8)); + __m128i layer2_chunk2 = _mm_packus_epi16(_mm_and_si128(layer3_chunk4, v_mask), _mm_and_si128(layer3_chunk5, v_mask)); + __m128i layer2_chunk6 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk4, 8), _mm_srli_epi16(layer3_chunk5, 8)); + __m128i layer2_chunk3 = _mm_packus_epi16(_mm_and_si128(layer3_chunk6, v_mask), _mm_and_si128(layer3_chunk7, v_mask)); + __m128i layer2_chunk7 = _mm_packus_epi16(_mm_srli_epi16(layer3_chunk6, 8), _mm_srli_epi16(layer3_chunk7, 8)); + + __m128i layer1_chunk0 = _mm_packus_epi16(_mm_and_si128(layer2_chunk0, v_mask), _mm_and_si128(layer2_chunk1, v_mask)); + __m128i layer1_chunk4 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk0, 8), _mm_srli_epi16(layer2_chunk1, 8)); + __m128i layer1_chunk1 = _mm_packus_epi16(_mm_and_si128(layer2_chunk2, v_mask), _mm_and_si128(layer2_chunk3, v_mask)); + __m128i layer1_chunk5 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk2, 8), _mm_srli_epi16(layer2_chunk3, 8)); + __m128i layer1_chunk2 = _mm_packus_epi16(_mm_and_si128(layer2_chunk4, v_mask), _mm_and_si128(layer2_chunk5, v_mask)); + __m128i layer1_chunk6 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk4, 8), _mm_srli_epi16(layer2_chunk5, 8)); + __m128i layer1_chunk3 = _mm_packus_epi16(_mm_and_si128(layer2_chunk6, v_mask), _mm_and_si128(layer2_chunk7, v_mask)); + __m128i layer1_chunk7 = _mm_packus_epi16(_mm_srli_epi16(layer2_chunk6, 8), _mm_srli_epi16(layer2_chunk7, 8)); + + v_r0 = _mm_packus_epi16(_mm_and_si128(layer1_chunk0, v_mask), _mm_and_si128(layer1_chunk1, v_mask)); + v_b0 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk0, 8), _mm_srli_epi16(layer1_chunk1, 8)); + v_r1 = _mm_packus_epi16(_mm_and_si128(layer1_chunk2, v_mask), _mm_and_si128(layer1_chunk3, v_mask)); + v_b1 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk2, 8), _mm_srli_epi16(layer1_chunk3, 8)); + v_g0 = _mm_packus_epi16(_mm_and_si128(layer1_chunk4, v_mask), _mm_and_si128(layer1_chunk5, v_mask)); + v_a0 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk4, 8), _mm_srli_epi16(layer1_chunk5, 8)); + v_g1 = _mm_packus_epi16(_mm_and_si128(layer1_chunk6, v_mask), _mm_and_si128(layer1_chunk7, v_mask)); + v_a1 = _mm_packus_epi16(_mm_srli_epi16(layer1_chunk6, 8), _mm_srli_epi16(layer1_chunk7, 8)); +} + +inline void _mm_deinterleave_epi16(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, __m128i & v_g1) +{ + __m128i layer1_chunk0 = _mm_unpacklo_epi16(v_r0, v_g0); + __m128i layer1_chunk1 = _mm_unpackhi_epi16(v_r0, v_g0); + __m128i layer1_chunk2 = _mm_unpacklo_epi16(v_r1, v_g1); + __m128i layer1_chunk3 = _mm_unpackhi_epi16(v_r1, v_g1); + + __m128i layer2_chunk0 = _mm_unpacklo_epi16(layer1_chunk0, layer1_chunk2); + __m128i layer2_chunk1 = _mm_unpackhi_epi16(layer1_chunk0, layer1_chunk2); + __m128i layer2_chunk2 = _mm_unpacklo_epi16(layer1_chunk1, layer1_chunk3); + __m128i layer2_chunk3 = _mm_unpackhi_epi16(layer1_chunk1, layer1_chunk3); + + __m128i layer3_chunk0 = _mm_unpacklo_epi16(layer2_chunk0, layer2_chunk2); + __m128i layer3_chunk1 = _mm_unpackhi_epi16(layer2_chunk0, layer2_chunk2); + __m128i layer3_chunk2 = _mm_unpacklo_epi16(layer2_chunk1, layer2_chunk3); + __m128i layer3_chunk3 = _mm_unpackhi_epi16(layer2_chunk1, layer2_chunk3); + + v_r0 = _mm_unpacklo_epi16(layer3_chunk0, layer3_chunk2); + v_r1 = _mm_unpackhi_epi16(layer3_chunk0, layer3_chunk2); + v_g0 = _mm_unpacklo_epi16(layer3_chunk1, layer3_chunk3); + v_g1 = _mm_unpackhi_epi16(layer3_chunk1, layer3_chunk3); +} + +inline void _mm_deinterleave_epi16(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, + __m128i & v_g1, __m128i & v_b0, __m128i & v_b1) +{ + __m128i layer1_chunk0 = _mm_unpacklo_epi16(v_r0, v_g1); + __m128i layer1_chunk1 = _mm_unpackhi_epi16(v_r0, v_g1); + __m128i layer1_chunk2 = _mm_unpacklo_epi16(v_r1, v_b0); + __m128i layer1_chunk3 = _mm_unpackhi_epi16(v_r1, v_b0); + __m128i layer1_chunk4 = _mm_unpacklo_epi16(v_g0, v_b1); + __m128i layer1_chunk5 = _mm_unpackhi_epi16(v_g0, v_b1); + + __m128i layer2_chunk0 = _mm_unpacklo_epi16(layer1_chunk0, layer1_chunk3); + __m128i layer2_chunk1 = _mm_unpackhi_epi16(layer1_chunk0, layer1_chunk3); + __m128i layer2_chunk2 = _mm_unpacklo_epi16(layer1_chunk1, layer1_chunk4); + __m128i layer2_chunk3 = _mm_unpackhi_epi16(layer1_chunk1, layer1_chunk4); + __m128i layer2_chunk4 = _mm_unpacklo_epi16(layer1_chunk2, layer1_chunk5); + __m128i layer2_chunk5 = _mm_unpackhi_epi16(layer1_chunk2, layer1_chunk5); + + __m128i layer3_chunk0 = _mm_unpacklo_epi16(layer2_chunk0, layer2_chunk3); + __m128i layer3_chunk1 = _mm_unpackhi_epi16(layer2_chunk0, layer2_chunk3); + __m128i layer3_chunk2 = _mm_unpacklo_epi16(layer2_chunk1, layer2_chunk4); + __m128i layer3_chunk3 = _mm_unpackhi_epi16(layer2_chunk1, layer2_chunk4); + __m128i layer3_chunk4 = _mm_unpacklo_epi16(layer2_chunk2, layer2_chunk5); + __m128i layer3_chunk5 = _mm_unpackhi_epi16(layer2_chunk2, layer2_chunk5); + + v_r0 = _mm_unpacklo_epi16(layer3_chunk0, layer3_chunk3); + v_r1 = _mm_unpackhi_epi16(layer3_chunk0, layer3_chunk3); + v_g0 = _mm_unpacklo_epi16(layer3_chunk1, layer3_chunk4); + v_g1 = _mm_unpackhi_epi16(layer3_chunk1, layer3_chunk4); + v_b0 = _mm_unpacklo_epi16(layer3_chunk2, layer3_chunk5); + v_b1 = _mm_unpackhi_epi16(layer3_chunk2, layer3_chunk5); +} + +inline void _mm_deinterleave_epi16(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, __m128i & v_g1, + __m128i & v_b0, __m128i & v_b1, __m128i & v_a0, __m128i & v_a1) +{ + __m128i layer1_chunk0 = _mm_unpacklo_epi16(v_r0, v_b0); + __m128i layer1_chunk1 = _mm_unpackhi_epi16(v_r0, v_b0); + __m128i layer1_chunk2 = _mm_unpacklo_epi16(v_r1, v_b1); + __m128i layer1_chunk3 = _mm_unpackhi_epi16(v_r1, v_b1); + __m128i layer1_chunk4 = _mm_unpacklo_epi16(v_g0, v_a0); + __m128i layer1_chunk5 = _mm_unpackhi_epi16(v_g0, v_a0); + __m128i layer1_chunk6 = _mm_unpacklo_epi16(v_g1, v_a1); + __m128i layer1_chunk7 = _mm_unpackhi_epi16(v_g1, v_a1); + + __m128i layer2_chunk0 = _mm_unpacklo_epi16(layer1_chunk0, layer1_chunk4); + __m128i layer2_chunk1 = _mm_unpackhi_epi16(layer1_chunk0, layer1_chunk4); + __m128i layer2_chunk2 = _mm_unpacklo_epi16(layer1_chunk1, layer1_chunk5); + __m128i layer2_chunk3 = _mm_unpackhi_epi16(layer1_chunk1, layer1_chunk5); + __m128i layer2_chunk4 = _mm_unpacklo_epi16(layer1_chunk2, layer1_chunk6); + __m128i layer2_chunk5 = _mm_unpackhi_epi16(layer1_chunk2, layer1_chunk6); + __m128i layer2_chunk6 = _mm_unpacklo_epi16(layer1_chunk3, layer1_chunk7); + __m128i layer2_chunk7 = _mm_unpackhi_epi16(layer1_chunk3, layer1_chunk7); + + __m128i layer3_chunk0 = _mm_unpacklo_epi16(layer2_chunk0, layer2_chunk4); + __m128i layer3_chunk1 = _mm_unpackhi_epi16(layer2_chunk0, layer2_chunk4); + __m128i layer3_chunk2 = _mm_unpacklo_epi16(layer2_chunk1, layer2_chunk5); + __m128i layer3_chunk3 = _mm_unpackhi_epi16(layer2_chunk1, layer2_chunk5); + __m128i layer3_chunk4 = _mm_unpacklo_epi16(layer2_chunk2, layer2_chunk6); + __m128i layer3_chunk5 = _mm_unpackhi_epi16(layer2_chunk2, layer2_chunk6); + __m128i layer3_chunk6 = _mm_unpacklo_epi16(layer2_chunk3, layer2_chunk7); + __m128i layer3_chunk7 = _mm_unpackhi_epi16(layer2_chunk3, layer2_chunk7); + + v_r0 = _mm_unpacklo_epi16(layer3_chunk0, layer3_chunk4); + v_r1 = _mm_unpackhi_epi16(layer3_chunk0, layer3_chunk4); + v_g0 = _mm_unpacklo_epi16(layer3_chunk1, layer3_chunk5); + v_g1 = _mm_unpackhi_epi16(layer3_chunk1, layer3_chunk5); + v_b0 = _mm_unpacklo_epi16(layer3_chunk2, layer3_chunk6); + v_b1 = _mm_unpackhi_epi16(layer3_chunk2, layer3_chunk6); + v_a0 = _mm_unpacklo_epi16(layer3_chunk3, layer3_chunk7); + v_a1 = _mm_unpackhi_epi16(layer3_chunk3, layer3_chunk7); +} + +#if CV_SSE4_1 + +inline void _mm_interleave_epi16(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, __m128i & v_g1) +{ + __m128i v_mask = _mm_set1_epi32(0x0000ffff); + + __m128i layer3_chunk0 = _mm_packus_epi32(_mm_and_si128(v_r0, v_mask), _mm_and_si128(v_r1, v_mask)); + __m128i layer3_chunk2 = _mm_packus_epi32(_mm_srli_epi32(v_r0, 16), _mm_srli_epi32(v_r1, 16)); + __m128i layer3_chunk1 = _mm_packus_epi32(_mm_and_si128(v_g0, v_mask), _mm_and_si128(v_g1, v_mask)); + __m128i layer3_chunk3 = _mm_packus_epi32(_mm_srli_epi32(v_g0, 16), _mm_srli_epi32(v_g1, 16)); + + __m128i layer2_chunk0 = _mm_packus_epi32(_mm_and_si128(layer3_chunk0, v_mask), _mm_and_si128(layer3_chunk1, v_mask)); + __m128i layer2_chunk2 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk0, 16), _mm_srli_epi32(layer3_chunk1, 16)); + __m128i layer2_chunk1 = _mm_packus_epi32(_mm_and_si128(layer3_chunk2, v_mask), _mm_and_si128(layer3_chunk3, v_mask)); + __m128i layer2_chunk3 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk2, 16), _mm_srli_epi32(layer3_chunk3, 16)); + + __m128i layer1_chunk0 = _mm_packus_epi32(_mm_and_si128(layer2_chunk0, v_mask), _mm_and_si128(layer2_chunk1, v_mask)); + __m128i layer1_chunk2 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk0, 16), _mm_srli_epi32(layer2_chunk1, 16)); + __m128i layer1_chunk1 = _mm_packus_epi32(_mm_and_si128(layer2_chunk2, v_mask), _mm_and_si128(layer2_chunk3, v_mask)); + __m128i layer1_chunk3 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk2, 16), _mm_srli_epi32(layer2_chunk3, 16)); + + v_r0 = _mm_packus_epi32(_mm_and_si128(layer1_chunk0, v_mask), _mm_and_si128(layer1_chunk1, v_mask)); + v_g0 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk0, 16), _mm_srli_epi32(layer1_chunk1, 16)); + v_r1 = _mm_packus_epi32(_mm_and_si128(layer1_chunk2, v_mask), _mm_and_si128(layer1_chunk3, v_mask)); + v_g1 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk2, 16), _mm_srli_epi32(layer1_chunk3, 16)); +} + +inline void _mm_interleave_epi16(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, + __m128i & v_g1, __m128i & v_b0, __m128i & v_b1) +{ + __m128i v_mask = _mm_set1_epi32(0x0000ffff); + + __m128i layer3_chunk0 = _mm_packus_epi32(_mm_and_si128(v_r0, v_mask), _mm_and_si128(v_r1, v_mask)); + __m128i layer3_chunk3 = _mm_packus_epi32(_mm_srli_epi32(v_r0, 16), _mm_srli_epi32(v_r1, 16)); + __m128i layer3_chunk1 = _mm_packus_epi32(_mm_and_si128(v_g0, v_mask), _mm_and_si128(v_g1, v_mask)); + __m128i layer3_chunk4 = _mm_packus_epi32(_mm_srli_epi32(v_g0, 16), _mm_srli_epi32(v_g1, 16)); + __m128i layer3_chunk2 = _mm_packus_epi32(_mm_and_si128(v_b0, v_mask), _mm_and_si128(v_b1, v_mask)); + __m128i layer3_chunk5 = _mm_packus_epi32(_mm_srli_epi32(v_b0, 16), _mm_srli_epi32(v_b1, 16)); + + __m128i layer2_chunk0 = _mm_packus_epi32(_mm_and_si128(layer3_chunk0, v_mask), _mm_and_si128(layer3_chunk1, v_mask)); + __m128i layer2_chunk3 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk0, 16), _mm_srli_epi32(layer3_chunk1, 16)); + __m128i layer2_chunk1 = _mm_packus_epi32(_mm_and_si128(layer3_chunk2, v_mask), _mm_and_si128(layer3_chunk3, v_mask)); + __m128i layer2_chunk4 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk2, 16), _mm_srli_epi32(layer3_chunk3, 16)); + __m128i layer2_chunk2 = _mm_packus_epi32(_mm_and_si128(layer3_chunk4, v_mask), _mm_and_si128(layer3_chunk5, v_mask)); + __m128i layer2_chunk5 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk4, 16), _mm_srli_epi32(layer3_chunk5, 16)); + + __m128i layer1_chunk0 = _mm_packus_epi32(_mm_and_si128(layer2_chunk0, v_mask), _mm_and_si128(layer2_chunk1, v_mask)); + __m128i layer1_chunk3 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk0, 16), _mm_srli_epi32(layer2_chunk1, 16)); + __m128i layer1_chunk1 = _mm_packus_epi32(_mm_and_si128(layer2_chunk2, v_mask), _mm_and_si128(layer2_chunk3, v_mask)); + __m128i layer1_chunk4 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk2, 16), _mm_srli_epi32(layer2_chunk3, 16)); + __m128i layer1_chunk2 = _mm_packus_epi32(_mm_and_si128(layer2_chunk4, v_mask), _mm_and_si128(layer2_chunk5, v_mask)); + __m128i layer1_chunk5 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk4, 16), _mm_srli_epi32(layer2_chunk5, 16)); + + v_r0 = _mm_packus_epi32(_mm_and_si128(layer1_chunk0, v_mask), _mm_and_si128(layer1_chunk1, v_mask)); + v_g1 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk0, 16), _mm_srli_epi32(layer1_chunk1, 16)); + v_r1 = _mm_packus_epi32(_mm_and_si128(layer1_chunk2, v_mask), _mm_and_si128(layer1_chunk3, v_mask)); + v_b0 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk2, 16), _mm_srli_epi32(layer1_chunk3, 16)); + v_g0 = _mm_packus_epi32(_mm_and_si128(layer1_chunk4, v_mask), _mm_and_si128(layer1_chunk5, v_mask)); + v_b1 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk4, 16), _mm_srli_epi32(layer1_chunk5, 16)); +} + +inline void _mm_interleave_epi16(__m128i & v_r0, __m128i & v_r1, __m128i & v_g0, __m128i & v_g1, + __m128i & v_b0, __m128i & v_b1, __m128i & v_a0, __m128i & v_a1) +{ + __m128i v_mask = _mm_set1_epi32(0x0000ffff); + + __m128i layer3_chunk0 = _mm_packus_epi32(_mm_and_si128(v_r0, v_mask), _mm_and_si128(v_r1, v_mask)); + __m128i layer3_chunk4 = _mm_packus_epi32(_mm_srli_epi32(v_r0, 16), _mm_srli_epi32(v_r1, 16)); + __m128i layer3_chunk1 = _mm_packus_epi32(_mm_and_si128(v_g0, v_mask), _mm_and_si128(v_g1, v_mask)); + __m128i layer3_chunk5 = _mm_packus_epi32(_mm_srli_epi32(v_g0, 16), _mm_srli_epi32(v_g1, 16)); + __m128i layer3_chunk2 = _mm_packus_epi32(_mm_and_si128(v_b0, v_mask), _mm_and_si128(v_b1, v_mask)); + __m128i layer3_chunk6 = _mm_packus_epi32(_mm_srli_epi32(v_b0, 16), _mm_srli_epi32(v_b1, 16)); + __m128i layer3_chunk3 = _mm_packus_epi32(_mm_and_si128(v_a0, v_mask), _mm_and_si128(v_a1, v_mask)); + __m128i layer3_chunk7 = _mm_packus_epi32(_mm_srli_epi32(v_a0, 16), _mm_srli_epi32(v_a1, 16)); + + __m128i layer2_chunk0 = _mm_packus_epi32(_mm_and_si128(layer3_chunk0, v_mask), _mm_and_si128(layer3_chunk1, v_mask)); + __m128i layer2_chunk4 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk0, 16), _mm_srli_epi32(layer3_chunk1, 16)); + __m128i layer2_chunk1 = _mm_packus_epi32(_mm_and_si128(layer3_chunk2, v_mask), _mm_and_si128(layer3_chunk3, v_mask)); + __m128i layer2_chunk5 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk2, 16), _mm_srli_epi32(layer3_chunk3, 16)); + __m128i layer2_chunk2 = _mm_packus_epi32(_mm_and_si128(layer3_chunk4, v_mask), _mm_and_si128(layer3_chunk5, v_mask)); + __m128i layer2_chunk6 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk4, 16), _mm_srli_epi32(layer3_chunk5, 16)); + __m128i layer2_chunk3 = _mm_packus_epi32(_mm_and_si128(layer3_chunk6, v_mask), _mm_and_si128(layer3_chunk7, v_mask)); + __m128i layer2_chunk7 = _mm_packus_epi32(_mm_srli_epi32(layer3_chunk6, 16), _mm_srli_epi32(layer3_chunk7, 16)); + + __m128i layer1_chunk0 = _mm_packus_epi32(_mm_and_si128(layer2_chunk0, v_mask), _mm_and_si128(layer2_chunk1, v_mask)); + __m128i layer1_chunk4 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk0, 16), _mm_srli_epi32(layer2_chunk1, 16)); + __m128i layer1_chunk1 = _mm_packus_epi32(_mm_and_si128(layer2_chunk2, v_mask), _mm_and_si128(layer2_chunk3, v_mask)); + __m128i layer1_chunk5 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk2, 16), _mm_srli_epi32(layer2_chunk3, 16)); + __m128i layer1_chunk2 = _mm_packus_epi32(_mm_and_si128(layer2_chunk4, v_mask), _mm_and_si128(layer2_chunk5, v_mask)); + __m128i layer1_chunk6 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk4, 16), _mm_srli_epi32(layer2_chunk5, 16)); + __m128i layer1_chunk3 = _mm_packus_epi32(_mm_and_si128(layer2_chunk6, v_mask), _mm_and_si128(layer2_chunk7, v_mask)); + __m128i layer1_chunk7 = _mm_packus_epi32(_mm_srli_epi32(layer2_chunk6, 16), _mm_srli_epi32(layer2_chunk7, 16)); + + v_r0 = _mm_packus_epi32(_mm_and_si128(layer1_chunk0, v_mask), _mm_and_si128(layer1_chunk1, v_mask)); + v_b0 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk0, 16), _mm_srli_epi32(layer1_chunk1, 16)); + v_r1 = _mm_packus_epi32(_mm_and_si128(layer1_chunk2, v_mask), _mm_and_si128(layer1_chunk3, v_mask)); + v_b1 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk2, 16), _mm_srli_epi32(layer1_chunk3, 16)); + v_g0 = _mm_packus_epi32(_mm_and_si128(layer1_chunk4, v_mask), _mm_and_si128(layer1_chunk5, v_mask)); + v_a0 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk4, 16), _mm_srli_epi32(layer1_chunk5, 16)); + v_g1 = _mm_packus_epi32(_mm_and_si128(layer1_chunk6, v_mask), _mm_and_si128(layer1_chunk7, v_mask)); + v_a1 = _mm_packus_epi32(_mm_srli_epi32(layer1_chunk6, 16), _mm_srli_epi32(layer1_chunk7, 16)); +} + +#endif // CV_SSE4_1 + +inline void _mm_deinterleave_ps(__m128 & v_r0, __m128 & v_r1, __m128 & v_g0, __m128 & v_g1) +{ + __m128 layer1_chunk0 = _mm_unpacklo_ps(v_r0, v_g0); + __m128 layer1_chunk1 = _mm_unpackhi_ps(v_r0, v_g0); + __m128 layer1_chunk2 = _mm_unpacklo_ps(v_r1, v_g1); + __m128 layer1_chunk3 = _mm_unpackhi_ps(v_r1, v_g1); + + __m128 layer2_chunk0 = _mm_unpacklo_ps(layer1_chunk0, layer1_chunk2); + __m128 layer2_chunk1 = _mm_unpackhi_ps(layer1_chunk0, layer1_chunk2); + __m128 layer2_chunk2 = _mm_unpacklo_ps(layer1_chunk1, layer1_chunk3); + __m128 layer2_chunk3 = _mm_unpackhi_ps(layer1_chunk1, layer1_chunk3); + + v_r0 = _mm_unpacklo_ps(layer2_chunk0, layer2_chunk2); + v_r1 = _mm_unpackhi_ps(layer2_chunk0, layer2_chunk2); + v_g0 = _mm_unpacklo_ps(layer2_chunk1, layer2_chunk3); + v_g1 = _mm_unpackhi_ps(layer2_chunk1, layer2_chunk3); +} + +inline void _mm_deinterleave_ps(__m128 & v_r0, __m128 & v_r1, __m128 & v_g0, + __m128 & v_g1, __m128 & v_b0, __m128 & v_b1) +{ + __m128 layer1_chunk0 = _mm_unpacklo_ps(v_r0, v_g1); + __m128 layer1_chunk1 = _mm_unpackhi_ps(v_r0, v_g1); + __m128 layer1_chunk2 = _mm_unpacklo_ps(v_r1, v_b0); + __m128 layer1_chunk3 = _mm_unpackhi_ps(v_r1, v_b0); + __m128 layer1_chunk4 = _mm_unpacklo_ps(v_g0, v_b1); + __m128 layer1_chunk5 = _mm_unpackhi_ps(v_g0, v_b1); + + __m128 layer2_chunk0 = _mm_unpacklo_ps(layer1_chunk0, layer1_chunk3); + __m128 layer2_chunk1 = _mm_unpackhi_ps(layer1_chunk0, layer1_chunk3); + __m128 layer2_chunk2 = _mm_unpacklo_ps(layer1_chunk1, layer1_chunk4); + __m128 layer2_chunk3 = _mm_unpackhi_ps(layer1_chunk1, layer1_chunk4); + __m128 layer2_chunk4 = _mm_unpacklo_ps(layer1_chunk2, layer1_chunk5); + __m128 layer2_chunk5 = _mm_unpackhi_ps(layer1_chunk2, layer1_chunk5); + + v_r0 = _mm_unpacklo_ps(layer2_chunk0, layer2_chunk3); + v_r1 = _mm_unpackhi_ps(layer2_chunk0, layer2_chunk3); + v_g0 = _mm_unpacklo_ps(layer2_chunk1, layer2_chunk4); + v_g1 = _mm_unpackhi_ps(layer2_chunk1, layer2_chunk4); + v_b0 = _mm_unpacklo_ps(layer2_chunk2, layer2_chunk5); + v_b1 = _mm_unpackhi_ps(layer2_chunk2, layer2_chunk5); +} + +inline void _mm_deinterleave_ps(__m128 & v_r0, __m128 & v_r1, __m128 & v_g0, __m128 & v_g1, + __m128 & v_b0, __m128 & v_b1, __m128 & v_a0, __m128 & v_a1) +{ + __m128 layer1_chunk0 = _mm_unpacklo_ps(v_r0, v_b0); + __m128 layer1_chunk1 = _mm_unpackhi_ps(v_r0, v_b0); + __m128 layer1_chunk2 = _mm_unpacklo_ps(v_r1, v_b1); + __m128 layer1_chunk3 = _mm_unpackhi_ps(v_r1, v_b1); + __m128 layer1_chunk4 = _mm_unpacklo_ps(v_g0, v_a0); + __m128 layer1_chunk5 = _mm_unpackhi_ps(v_g0, v_a0); + __m128 layer1_chunk6 = _mm_unpacklo_ps(v_g1, v_a1); + __m128 layer1_chunk7 = _mm_unpackhi_ps(v_g1, v_a1); + + __m128 layer2_chunk0 = _mm_unpacklo_ps(layer1_chunk0, layer1_chunk4); + __m128 layer2_chunk1 = _mm_unpackhi_ps(layer1_chunk0, layer1_chunk4); + __m128 layer2_chunk2 = _mm_unpacklo_ps(layer1_chunk1, layer1_chunk5); + __m128 layer2_chunk3 = _mm_unpackhi_ps(layer1_chunk1, layer1_chunk5); + __m128 layer2_chunk4 = _mm_unpacklo_ps(layer1_chunk2, layer1_chunk6); + __m128 layer2_chunk5 = _mm_unpackhi_ps(layer1_chunk2, layer1_chunk6); + __m128 layer2_chunk6 = _mm_unpacklo_ps(layer1_chunk3, layer1_chunk7); + __m128 layer2_chunk7 = _mm_unpackhi_ps(layer1_chunk3, layer1_chunk7); + + v_r0 = _mm_unpacklo_ps(layer2_chunk0, layer2_chunk4); + v_r1 = _mm_unpackhi_ps(layer2_chunk0, layer2_chunk4); + v_g0 = _mm_unpacklo_ps(layer2_chunk1, layer2_chunk5); + v_g1 = _mm_unpackhi_ps(layer2_chunk1, layer2_chunk5); + v_b0 = _mm_unpacklo_ps(layer2_chunk2, layer2_chunk6); + v_b1 = _mm_unpackhi_ps(layer2_chunk2, layer2_chunk6); + v_a0 = _mm_unpacklo_ps(layer2_chunk3, layer2_chunk7); + v_a1 = _mm_unpackhi_ps(layer2_chunk3, layer2_chunk7); +} + +inline void _mm_interleave_ps(__m128 & v_r0, __m128 & v_r1, __m128 & v_g0, __m128 & v_g1) +{ + const int mask_lo = _MM_SHUFFLE(2, 0, 2, 0), mask_hi = _MM_SHUFFLE(3, 1, 3, 1); + + __m128 layer2_chunk0 = _mm_shuffle_ps(v_r0, v_r1, mask_lo); + __m128 layer2_chunk2 = _mm_shuffle_ps(v_r0, v_r1, mask_hi); + __m128 layer2_chunk1 = _mm_shuffle_ps(v_g0, v_g1, mask_lo); + __m128 layer2_chunk3 = _mm_shuffle_ps(v_g0, v_g1, mask_hi); + + __m128 layer1_chunk0 = _mm_shuffle_ps(layer2_chunk0, layer2_chunk1, mask_lo); + __m128 layer1_chunk2 = _mm_shuffle_ps(layer2_chunk0, layer2_chunk1, mask_hi); + __m128 layer1_chunk1 = _mm_shuffle_ps(layer2_chunk2, layer2_chunk3, mask_lo); + __m128 layer1_chunk3 = _mm_shuffle_ps(layer2_chunk2, layer2_chunk3, mask_hi); + + v_r0 = _mm_shuffle_ps(layer1_chunk0, layer1_chunk1, mask_lo); + v_g0 = _mm_shuffle_ps(layer1_chunk0, layer1_chunk1, mask_hi); + v_r1 = _mm_shuffle_ps(layer1_chunk2, layer1_chunk3, mask_lo); + v_g1 = _mm_shuffle_ps(layer1_chunk2, layer1_chunk3, mask_hi); +} + +inline void _mm_interleave_ps(__m128 & v_r0, __m128 & v_r1, __m128 & v_g0, + __m128 & v_g1, __m128 & v_b0, __m128 & v_b1) +{ + const int mask_lo = _MM_SHUFFLE(2, 0, 2, 0), mask_hi = _MM_SHUFFLE(3, 1, 3, 1); + + __m128 layer2_chunk0 = _mm_shuffle_ps(v_r0, v_r1, mask_lo); + __m128 layer2_chunk3 = _mm_shuffle_ps(v_r0, v_r1, mask_hi); + __m128 layer2_chunk1 = _mm_shuffle_ps(v_g0, v_g1, mask_lo); + __m128 layer2_chunk4 = _mm_shuffle_ps(v_g0, v_g1, mask_hi); + __m128 layer2_chunk2 = _mm_shuffle_ps(v_b0, v_b1, mask_lo); + __m128 layer2_chunk5 = _mm_shuffle_ps(v_b0, v_b1, mask_hi); + + __m128 layer1_chunk0 = _mm_shuffle_ps(layer2_chunk0, layer2_chunk1, mask_lo); + __m128 layer1_chunk3 = _mm_shuffle_ps(layer2_chunk0, layer2_chunk1, mask_hi); + __m128 layer1_chunk1 = _mm_shuffle_ps(layer2_chunk2, layer2_chunk3, mask_lo); + __m128 layer1_chunk4 = _mm_shuffle_ps(layer2_chunk2, layer2_chunk3, mask_hi); + __m128 layer1_chunk2 = _mm_shuffle_ps(layer2_chunk4, layer2_chunk5, mask_lo); + __m128 layer1_chunk5 = _mm_shuffle_ps(layer2_chunk4, layer2_chunk5, mask_hi); + + v_r0 = _mm_shuffle_ps(layer1_chunk0, layer1_chunk1, mask_lo); + v_g1 = _mm_shuffle_ps(layer1_chunk0, layer1_chunk1, mask_hi); + v_r1 = _mm_shuffle_ps(layer1_chunk2, layer1_chunk3, mask_lo); + v_b0 = _mm_shuffle_ps(layer1_chunk2, layer1_chunk3, mask_hi); + v_g0 = _mm_shuffle_ps(layer1_chunk4, layer1_chunk5, mask_lo); + v_b1 = _mm_shuffle_ps(layer1_chunk4, layer1_chunk5, mask_hi); +} + +inline void _mm_interleave_ps(__m128 & v_r0, __m128 & v_r1, __m128 & v_g0, __m128 & v_g1, + __m128 & v_b0, __m128 & v_b1, __m128 & v_a0, __m128 & v_a1) +{ + const int mask_lo = _MM_SHUFFLE(2, 0, 2, 0), mask_hi = _MM_SHUFFLE(3, 1, 3, 1); + + __m128 layer2_chunk0 = _mm_shuffle_ps(v_r0, v_r1, mask_lo); + __m128 layer2_chunk4 = _mm_shuffle_ps(v_r0, v_r1, mask_hi); + __m128 layer2_chunk1 = _mm_shuffle_ps(v_g0, v_g1, mask_lo); + __m128 layer2_chunk5 = _mm_shuffle_ps(v_g0, v_g1, mask_hi); + __m128 layer2_chunk2 = _mm_shuffle_ps(v_b0, v_b1, mask_lo); + __m128 layer2_chunk6 = _mm_shuffle_ps(v_b0, v_b1, mask_hi); + __m128 layer2_chunk3 = _mm_shuffle_ps(v_a0, v_a1, mask_lo); + __m128 layer2_chunk7 = _mm_shuffle_ps(v_a0, v_a1, mask_hi); + + __m128 layer1_chunk0 = _mm_shuffle_ps(layer2_chunk0, layer2_chunk1, mask_lo); + __m128 layer1_chunk4 = _mm_shuffle_ps(layer2_chunk0, layer2_chunk1, mask_hi); + __m128 layer1_chunk1 = _mm_shuffle_ps(layer2_chunk2, layer2_chunk3, mask_lo); + __m128 layer1_chunk5 = _mm_shuffle_ps(layer2_chunk2, layer2_chunk3, mask_hi); + __m128 layer1_chunk2 = _mm_shuffle_ps(layer2_chunk4, layer2_chunk5, mask_lo); + __m128 layer1_chunk6 = _mm_shuffle_ps(layer2_chunk4, layer2_chunk5, mask_hi); + __m128 layer1_chunk3 = _mm_shuffle_ps(layer2_chunk6, layer2_chunk7, mask_lo); + __m128 layer1_chunk7 = _mm_shuffle_ps(layer2_chunk6, layer2_chunk7, mask_hi); + + v_r0 = _mm_shuffle_ps(layer1_chunk0, layer1_chunk1, mask_lo); + v_b0 = _mm_shuffle_ps(layer1_chunk0, layer1_chunk1, mask_hi); + v_r1 = _mm_shuffle_ps(layer1_chunk2, layer1_chunk3, mask_lo); + v_b1 = _mm_shuffle_ps(layer1_chunk2, layer1_chunk3, mask_hi); + v_g0 = _mm_shuffle_ps(layer1_chunk4, layer1_chunk5, mask_lo); + v_a0 = _mm_shuffle_ps(layer1_chunk4, layer1_chunk5, mask_hi); + v_g1 = _mm_shuffle_ps(layer1_chunk6, layer1_chunk7, mask_lo); + v_a1 = _mm_shuffle_ps(layer1_chunk6, layer1_chunk7, mask_hi); +} + +#endif // CV_SSE2 + +#endif //__OPENCV_CORE_SSE_UTILS_HPP__ diff --git a/include/opencv2/core/traits.hpp b/include/opencv2/core/traits.hpp new file mode 100644 index 0000000..49bc844 --- /dev/null +++ b/include/opencv2/core/traits.hpp @@ -0,0 +1,326 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_TRAITS_HPP__ +#define __OPENCV_CORE_TRAITS_HPP__ + +#include "opencv2/core/cvdef.h" + +namespace cv +{ + +//! @addtogroup core_basic +//! @{ + +/** @brief Template "trait" class for OpenCV primitive data types. + +A primitive OpenCV data type is one of unsigned char, bool, signed char, unsigned short, signed +short, int, float, double, or a tuple of values of one of these types, where all the values in the +tuple have the same type. Any primitive type from the list can be defined by an identifier in the +form CV_\{U|S|F}C(\), for example: uchar \~ CV_8UC1, 3-element +floating-point tuple \~ CV_32FC3, and so on. A universal OpenCV structure that is able to store a +single instance of such a primitive data type is Vec. Multiple instances of such a type can be +stored in a std::vector, Mat, Mat_, SparseMat, SparseMat_, or any other container that is able to +store Vec instances. + +The DataType class is basically used to provide a description of such primitive data types without +adding any fields or methods to the corresponding classes (and it is actually impossible to add +anything to primitive C/C++ data types). This technique is known in C++ as class traits. It is not +DataType itself that is used but its specialized versions, such as: +@code + template<> class DataType + { + typedef uchar value_type; + typedef int work_type; + typedef uchar channel_type; + enum { channel_type = CV_8U, channels = 1, fmt='u', type = CV_8U }; + }; + ... + template DataType > + { + typedef std::complex<_Tp> value_type; + typedef std::complex<_Tp> work_type; + typedef _Tp channel_type; + // DataDepth is another helper trait class + enum { depth = DataDepth<_Tp>::value, channels=2, + fmt=(channels-1)*256+DataDepth<_Tp>::fmt, + type=CV_MAKETYPE(depth, channels) }; + }; + ... +@endcode +The main purpose of this class is to convert compilation-time type information to an +OpenCV-compatible data type identifier, for example: +@code + // allocates a 30x40 floating-point matrix + Mat A(30, 40, DataType::type); + + Mat B = Mat_ >(3, 3); + // the statement below will print 6, 2 , that is depth == CV_64F, channels == 2 + cout << B.depth() << ", " << B.channels() << endl; +@endcode +So, such traits are used to tell OpenCV which data type you are working with, even if such a type is +not native to OpenCV. For example, the matrix B initialization above is compiled because OpenCV +defines the proper specialized template class DataType\ \> . This mechanism is also +useful (and used in OpenCV this way) for generic algorithms implementations. +*/ +template class DataType +{ +public: + typedef _Tp value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 1, + depth = -1, + channels = 1, + fmt = 0, + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef bool value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_8U, + channels = 1, + fmt = (int)'u', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef uchar value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_8U, + channels = 1, + fmt = (int)'u', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef schar value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_8S, + channels = 1, + fmt = (int)'c', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef schar value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_8S, + channels = 1, + fmt = (int)'c', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef ushort value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_16U, + channels = 1, + fmt = (int)'w', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef short value_type; + typedef int work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_16S, + channels = 1, + fmt = (int)'s', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef int value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_32S, + channels = 1, + fmt = (int)'i', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef float value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_32F, + channels = 1, + fmt = (int)'f', + type = CV_MAKETYPE(depth, channels) + }; +}; + +template<> class DataType +{ +public: + typedef double value_type; + typedef value_type work_type; + typedef value_type channel_type; + typedef value_type vec_type; + enum { generic_type = 0, + depth = CV_64F, + channels = 1, + fmt = (int)'d', + type = CV_MAKETYPE(depth, channels) + }; +}; + + +/** @brief A helper class for cv::DataType + +The class is specialized for each fundamental numerical data type supported by OpenCV. It provides +DataDepth::value constant. +*/ +template class DataDepth +{ +public: + enum + { + value = DataType<_Tp>::depth, + fmt = DataType<_Tp>::fmt + }; +}; + + + +template class TypeDepth +{ + enum { depth = CV_USRTYPE1 }; + typedef void value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_8U }; + typedef uchar value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_8S }; + typedef schar value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_16U }; + typedef ushort value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_16S }; + typedef short value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_32S }; + typedef int value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_32F }; + typedef float value_type; +}; + +template<> class TypeDepth +{ + enum { depth = CV_64F }; + typedef double value_type; +}; + +//! @} + +} // cv + +#endif // __OPENCV_CORE_TRAITS_HPP__ diff --git a/include/opencv2/core/types.hpp b/include/opencv2/core/types.hpp new file mode 100644 index 0000000..e166556 --- /dev/null +++ b/include/opencv2/core/types.hpp @@ -0,0 +1,2228 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_TYPES_HPP__ +#define __OPENCV_CORE_TYPES_HPP__ + +#ifndef __cplusplus +# error types.hpp header must be compiled as C++ +#endif + +#include +#include +#include + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/cvstd.hpp" +#include "opencv2/core/matx.hpp" + +namespace cv +{ + +//! @addtogroup core_basic +//! @{ + +//////////////////////////////// Complex ////////////////////////////// + +/** @brief A complex number class. + + The template class is similar and compatible with std::complex, however it provides slightly + more convenient access to the real and imaginary parts using through the simple field access, as opposite + to std::complex::real() and std::complex::imag(). +*/ +template class Complex +{ +public: + + //! constructors + Complex(); + Complex( _Tp _re, _Tp _im = 0 ); + + //! conversion to another data type + template operator Complex() const; + //! conjugation + Complex conj() const; + + _Tp re, im; //< the real and the imaginary parts +}; + +typedef Complex Complexf; +typedef Complex Complexd; + +template class DataType< Complex<_Tp> > +{ +public: + typedef Complex<_Tp> value_type; + typedef value_type work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Point_ //////////////////////////////// + +/** @brief Template class for 2D points specified by its coordinates `x` and `y`. + +An instance of the class is interchangeable with C structures, CvPoint and CvPoint2D32f . There is +also a cast operator to convert point coordinates to the specified type. The conversion from +floating-point coordinates to integer coordinates is done by rounding. Commonly, the conversion +uses this operation for each of the coordinates. Besides the class members listed in the +declaration above, the following operations on points are implemented: +@code + pt1 = pt2 + pt3; + pt1 = pt2 - pt3; + pt1 = pt2 * a; + pt1 = a * pt2; + pt1 = pt2 / a; + pt1 += pt2; + pt1 -= pt2; + pt1 *= a; + pt1 /= a; + double value = norm(pt); // L2 norm + pt1 == pt2; + pt1 != pt2; +@endcode +For your convenience, the following type aliases are defined: +@code + typedef Point_ Point2i; + typedef Point2i Point; + typedef Point_ Point2f; + typedef Point_ Point2d; +@endcode +Example: +@code + Point2f a(0.3f, 0.f), b(0.f, 0.4f); + Point pt = (a + b)*10.f; + cout << pt.x << ", " << pt.y << endl; +@endcode +*/ +template class Point_ +{ +public: + typedef _Tp value_type; + + // various constructors + Point_(); + Point_(_Tp _x, _Tp _y); + Point_(const Point_& pt); + Point_(const Size_<_Tp>& sz); + Point_(const Vec<_Tp, 2>& v); + + Point_& operator = (const Point_& pt); + //! conversion to another data type + template operator Point_<_Tp2>() const; + + //! conversion to the old-style C structures + operator Vec<_Tp, 2>() const; + + //! dot product + _Tp dot(const Point_& pt) const; + //! dot product computed in double-precision arithmetics + double ddot(const Point_& pt) const; + //! cross-product + double cross(const Point_& pt) const; + //! checks whether the point is inside the specified rectangle + bool inside(const Rect_<_Tp>& r) const; + + _Tp x, y; //< the point coordinates +}; + +typedef Point_ Point2i; +typedef Point_ Point2f; +typedef Point_ Point2d; +typedef Point2i Point; + +template class DataType< Point_<_Tp> > +{ +public: + typedef Point_<_Tp> value_type; + typedef Point_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Point3_ //////////////////////////////// + +/** @brief Template class for 3D points specified by its coordinates `x`, `y` and `z`. + +An instance of the class is interchangeable with the C structure CvPoint2D32f . Similarly to +Point_ , the coordinates of 3D points can be converted to another type. The vector arithmetic and +comparison operations are also supported. + +The following Point3_\<\> aliases are available: +@code + typedef Point3_ Point3i; + typedef Point3_ Point3f; + typedef Point3_ Point3d; +@endcode +@see cv::Point3i, cv::Point3f and cv::Point3d +*/ +template class Point3_ +{ +public: + typedef _Tp value_type; + + // various constructors + Point3_(); + Point3_(_Tp _x, _Tp _y, _Tp _z); + Point3_(const Point3_& pt); + explicit Point3_(const Point_<_Tp>& pt); + Point3_(const Vec<_Tp, 3>& v); + + Point3_& operator = (const Point3_& pt); + //! conversion to another data type + template operator Point3_<_Tp2>() const; + //! conversion to cv::Vec<> + operator Vec<_Tp, 3>() const; + + //! dot product + _Tp dot(const Point3_& pt) const; + //! dot product computed in double-precision arithmetics + double ddot(const Point3_& pt) const; + //! cross product of the 2 3D points + Point3_ cross(const Point3_& pt) const; + + _Tp x, y, z; //< the point coordinates +}; + +typedef Point3_ Point3i; +typedef Point3_ Point3f; +typedef Point3_ Point3d; + +template class DataType< Point3_<_Tp> > +{ +public: + typedef Point3_<_Tp> value_type; + typedef Point3_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 3, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Size_ //////////////////////////////// + +/** @brief Template class for specifying the size of an image or rectangle. + +The class includes two members called width and height. The structure can be converted to and from +the old OpenCV structures CvSize and CvSize2D32f . The same set of arithmetic and comparison +operations as for Point_ is available. + +OpenCV defines the following Size_\<\> aliases: +@code + typedef Size_ Size2i; + typedef Size2i Size; + typedef Size_ Size2f; +@endcode +*/ +template class Size_ +{ +public: + typedef _Tp value_type; + + //! various constructors + Size_(); + Size_(_Tp _width, _Tp _height); + Size_(const Size_& sz); + Size_(const Point_<_Tp>& pt); + + Size_& operator = (const Size_& sz); + //! the area (width*height) + _Tp area() const; + + //! conversion of another data type. + template operator Size_<_Tp2>() const; + + _Tp width, height; // the width and the height +}; + +typedef Size_ Size2i; +typedef Size_ Size2f; +typedef Size_ Size2d; +typedef Size2i Size; + +template class DataType< Size_<_Tp> > +{ +public: + typedef Size_<_Tp> value_type; + typedef Size_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Rect_ //////////////////////////////// + +/** @brief Template class for 2D rectangles + +described by the following parameters: +- Coordinates of the top-left corner. This is a default interpretation of Rect_::x and Rect_::y + in OpenCV. Though, in your algorithms you may count x and y from the bottom-left corner. +- Rectangle width and height. + +OpenCV typically assumes that the top and left boundary of the rectangle are inclusive, while the +right and bottom boundaries are not. For example, the method Rect_::contains returns true if + +\f[x \leq pt.x < x+width, + y \leq pt.y < y+height\f] + +Virtually every loop over an image ROI in OpenCV (where ROI is specified by Rect_\ ) is +implemented as: +@code + for(int y = roi.y; y < roi.y + roi.height; y++) + for(int x = roi.x; x < roi.x + roi.width; x++) + { + // ... + } +@endcode +In addition to the class members, the following operations on rectangles are implemented: +- \f$\texttt{rect} = \texttt{rect} \pm \texttt{point}\f$ (shifting a rectangle by a certain offset) +- \f$\texttt{rect} = \texttt{rect} \pm \texttt{size}\f$ (expanding or shrinking a rectangle by a + certain amount) +- rect += point, rect -= point, rect += size, rect -= size (augmenting operations) +- rect = rect1 & rect2 (rectangle intersection) +- rect = rect1 | rect2 (minimum area rectangle containing rect1 and rect2 ) +- rect &= rect1, rect |= rect1 (and the corresponding augmenting operations) +- rect == rect1, rect != rect1 (rectangle comparison) + +This is an example how the partial ordering on rectangles can be established (rect1 \f$\subseteq\f$ +rect2): +@code + template inline bool + operator <= (const Rect_<_Tp>& r1, const Rect_<_Tp>& r2) + { + return (r1 & r2) == r1; + } +@endcode +For your convenience, the Rect_\<\> alias is available: cv::Rect +*/ +template class Rect_ +{ +public: + typedef _Tp value_type; + + //! various constructors + Rect_(); + Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height); + Rect_(const Rect_& r); + Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz); + Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2); + + Rect_& operator = ( const Rect_& r ); + //! the top-left corner + Point_<_Tp> tl() const; + //! the bottom-right corner + Point_<_Tp> br() const; + + //! size (width, height) of the rectangle + Size_<_Tp> size() const; + //! area (width*height) of the rectangle + _Tp area() const; + + //! conversion to another data type + template operator Rect_<_Tp2>() const; + + //! checks whether the rectangle contains the point + bool contains(const Point_<_Tp>& pt) const; + + _Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle +}; + +typedef Rect_ Rect2i; +typedef Rect_ Rect2f; +typedef Rect_ Rect2d; +typedef Rect2i Rect; + +template class DataType< Rect_<_Tp> > +{ +public: + typedef Rect_<_Tp> value_type; + typedef Rect_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 4, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +///////////////////////////// RotatedRect ///////////////////////////// + +/** @brief The class represents rotated (i.e. not up-right) rectangles on a plane. + +Each rectangle is specified by the center point (mass center), length of each side (represented by +cv::Size2f structure) and the rotation angle in degrees. + +The sample below demonstrates how to use RotatedRect: +@code + Mat image(200, 200, CV_8UC3, Scalar(0)); + RotatedRect rRect = RotatedRect(Point2f(100,100), Size2f(100,50), 30); + + Point2f vertices[4]; + rRect.points(vertices); + for (int i = 0; i < 4; i++) + line(image, vertices[i], vertices[(i+1)%4], Scalar(0,255,0)); + + Rect brect = rRect.boundingRect(); + rectangle(image, brect, Scalar(255,0,0)); + + imshow("rectangles", image); + waitKey(0); +@endcode +![image](pics/rotatedrect.png) + +@sa CamShift, fitEllipse, minAreaRect, CvBox2D +*/ +class CV_EXPORTS RotatedRect +{ +public: + //! various constructors + RotatedRect(); + /** + @param center The rectangle mass center. + @param size Width and height of the rectangle. + @param angle The rotation angle in a clockwise direction. When the angle is 0, 90, 180, 270 etc., + the rectangle becomes an up-right rectangle. + */ + RotatedRect(const Point2f& center, const Size2f& size, float angle); + /** + Any 3 end points of the RotatedRect. They must be given in order (either clockwise or + anticlockwise). + */ + RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3); + + /** returns 4 vertices of the rectangle + @param pts The points array for storing rectangle vertices. + */ + void points(Point2f pts[]) const; + //! returns the minimal up-right rectangle containing the rotated rectangle + Rect boundingRect() const; + + Point2f center; //< the rectangle mass center + Size2f size; //< width and height of the rectangle + float angle; //< the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle. +}; + +template<> class DataType< RotatedRect > +{ +public: + typedef RotatedRect value_type; + typedef value_type work_type; + typedef float channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = (int)sizeof(value_type)/sizeof(channel_type), // 5 + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Range ///////////////////////////////// + +/** @brief Template class specifying a continuous subsequence (slice) of a sequence. + +The class is used to specify a row or a column span in a matrix ( Mat ) and for many other purposes. +Range(a,b) is basically the same as a:b in Matlab or a..b in Python. As in Python, start is an +inclusive left boundary of the range and end is an exclusive right boundary of the range. Such a +half-opened interval is usually denoted as \f$[start,end)\f$ . + +The static method Range::all() returns a special variable that means "the whole sequence" or "the +whole range", just like " : " in Matlab or " ... " in Python. All the methods and functions in +OpenCV that take Range support this special Range::all() value. But, of course, in case of your own +custom processing, you will probably have to check and handle it explicitly: +@code + void my_function(..., const Range& r, ....) + { + if(r == Range::all()) { + // process all the data + } + else { + // process [r.start, r.end) + } + } +@endcode +*/ +class CV_EXPORTS Range +{ +public: + Range(); + Range(int _start, int _end); + int size() const; + bool empty() const; + static Range all(); + + int start, end; +}; + +template<> class DataType +{ +public: + typedef Range value_type; + typedef value_type work_type; + typedef int channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 2, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// Scalar_ /////////////////////////////// + +/** @brief Template class for a 4-element vector derived from Vec. + +Being derived from Vec\<_Tp, 4\> , Scalar_ and Scalar can be used just as typical 4-element +vectors. In addition, they can be converted to/from CvScalar . The type Scalar is widely used in +OpenCV to pass pixel values. +*/ +template class Scalar_ : public Vec<_Tp, 4> +{ +public: + //! various constructors + Scalar_(); + Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0); + Scalar_(_Tp v0); + + template + Scalar_(const Vec<_Tp2, cn>& v); + + //! returns a scalar with all elements set to v0 + static Scalar_<_Tp> all(_Tp v0); + + //! conversion to another data type + template operator Scalar_() const; + + //! per-element product + Scalar_<_Tp> mul(const Scalar_<_Tp>& a, double scale=1 ) const; + + // returns (v0, -v1, -v2, -v3) + Scalar_<_Tp> conj() const; + + // returns true iff v1 == v2 == v3 == 0 + bool isReal() const; +}; + +typedef Scalar_ Scalar; + +template class DataType< Scalar_<_Tp> > +{ +public: + typedef Scalar_<_Tp> value_type; + typedef Scalar_::work_type> work_type; + typedef _Tp channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = 4, + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +/////////////////////////////// KeyPoint //////////////////////////////// + +/** @brief Data structure for salient point detectors. + +The class instance stores a keypoint, i.e. a point feature found by one of many available keypoint +detectors, such as Harris corner detector, cv::FAST, cv::StarDetector, cv::SURF, cv::SIFT, +cv::LDetector etc. + +The keypoint is characterized by the 2D position, scale (proportional to the diameter of the +neighborhood that needs to be taken into account), orientation and some other parameters. The +keypoint neighborhood is then analyzed by another algorithm that builds a descriptor (usually +represented as a feature vector). The keypoints representing the same object in different images +can then be matched using cv::KDTree or another method. +*/ +class CV_EXPORTS_W_SIMPLE KeyPoint +{ +public: + //! the default constructor + CV_WRAP KeyPoint(); + /** + @param _pt x & y coordinates of the keypoint + @param _size keypoint diameter + @param _angle keypoint orientation + @param _response keypoint detector response on the keypoint (that is, strength of the keypoint) + @param _octave pyramid octave in which the keypoint has been detected + @param _class_id object id + */ + KeyPoint(Point2f _pt, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1); + /** + @param x x-coordinate of the keypoint + @param y y-coordinate of the keypoint + @param _size keypoint diameter + @param _angle keypoint orientation + @param _response keypoint detector response on the keypoint (that is, strength of the keypoint) + @param _octave pyramid octave in which the keypoint has been detected + @param _class_id object id + */ + CV_WRAP KeyPoint(float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1); + + size_t hash() const; + + /** + This method converts vector of keypoints to vector of points or the reverse, where each keypoint is + assigned the same size and the same orientation. + + @param keypoints Keypoints obtained from any feature detection algorithm like SIFT/SURF/ORB + @param points2f Array of (x,y) coordinates of each keypoint + @param keypointIndexes Array of indexes of keypoints to be converted to points. (Acts like a mask to + convert only specified keypoints) + */ + CV_WRAP static void convert(const std::vector& keypoints, + CV_OUT std::vector& points2f, + const std::vector& keypointIndexes=std::vector()); + /** @overload + @param points2f Array of (x,y) coordinates of each keypoint + @param keypoints Keypoints obtained from any feature detection algorithm like SIFT/SURF/ORB + @param size keypoint diameter + @param response keypoint detector response on the keypoint (that is, strength of the keypoint) + @param octave pyramid octave in which the keypoint has been detected + @param class_id object id + */ + CV_WRAP static void convert(const std::vector& points2f, + CV_OUT std::vector& keypoints, + float size=1, float response=1, int octave=0, int class_id=-1); + + /** + This method computes overlap for pair of keypoints. Overlap is the ratio between area of keypoint + regions' intersection and area of keypoint regions' union (considering keypoint region as circle). + If they don't overlap, we get zero. If they coincide at same location with same size, we get 1. + @param kp1 First keypoint + @param kp2 Second keypoint + */ + CV_WRAP static float overlap(const KeyPoint& kp1, const KeyPoint& kp2); + + CV_PROP_RW Point2f pt; //!< coordinates of the keypoints + CV_PROP_RW float size; //!< diameter of the meaningful keypoint neighborhood + CV_PROP_RW float angle; //!< computed orientation of the keypoint (-1 if not applicable); + //!< it's in [0,360) degrees and measured relative to + //!< image coordinate system, ie in clockwise. + CV_PROP_RW float response; //!< the response by which the most strong keypoints have been selected. Can be used for the further sorting or subsampling + CV_PROP_RW int octave; //!< octave (pyramid layer) from which the keypoint has been extracted + CV_PROP_RW int class_id; //!< object class (if the keypoints need to be clustered by an object they belong to) +}; + +template<> class DataType +{ +public: + typedef KeyPoint value_type; + typedef float work_type; + typedef float channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = (int)(sizeof(value_type)/sizeof(channel_type)), // 7 + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +//////////////////////////////// DMatch ///////////////////////////////// + +/** @brief Class for matching keypoint descriptors + +query descriptor index, train descriptor index, train image index, and distance between +descriptors. +*/ +class CV_EXPORTS_W_SIMPLE DMatch +{ +public: + CV_WRAP DMatch(); + CV_WRAP DMatch(int _queryIdx, int _trainIdx, float _distance); + CV_WRAP DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance); + + CV_PROP_RW int queryIdx; // query descriptor index + CV_PROP_RW int trainIdx; // train descriptor index + CV_PROP_RW int imgIdx; // train image index + + CV_PROP_RW float distance; + + // less is better + bool operator<(const DMatch &m) const; +}; + +template<> class DataType +{ +public: + typedef DMatch value_type; + typedef int work_type; + typedef int channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = (int)(sizeof(value_type)/sizeof(channel_type)), // 4 + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + + + +///////////////////////////// TermCriteria ////////////////////////////// + +/** @brief The class defining termination criteria for iterative algorithms. + +You can initialize it by default constructor and then override any parameters, or the structure may +be fully initialized using the advanced variant of the constructor. +*/ +class CV_EXPORTS TermCriteria +{ +public: + /** + Criteria type, can be one of: COUNT, EPS or COUNT + EPS + */ + enum Type + { + COUNT=1, //!< the maximum number of iterations or elements to compute + MAX_ITER=COUNT, //!< ditto + EPS=2 //!< the desired accuracy or change in parameters at which the iterative algorithm stops + }; + + //! default constructor + TermCriteria(); + /** + @param type The type of termination criteria, one of TermCriteria::Type + @param maxCount The maximum number of iterations or elements to compute. + @param epsilon The desired accuracy or change in parameters at which the iterative algorithm stops. + */ + TermCriteria(int type, int maxCount, double epsilon); + + int type; //!< the type of termination criteria: COUNT, EPS or COUNT + EPS + int maxCount; // the maximum number of iterations/elements + double epsilon; // the desired accuracy +}; + + +//! @} core_basic + +///////////////////////// raster image moments ////////////////////////// + +//! @addtogroup imgproc_shape +//! @{ + +/** @brief struct returned by cv::moments + +The spatial moments \f$\texttt{Moments::m}_{ji}\f$ are computed as: + +\f[\texttt{m} _{ji}= \sum _{x,y} \left ( \texttt{array} (x,y) \cdot x^j \cdot y^i \right )\f] + +The central moments \f$\texttt{Moments::mu}_{ji}\f$ are computed as: + +\f[\texttt{mu} _{ji}= \sum _{x,y} \left ( \texttt{array} (x,y) \cdot (x - \bar{x} )^j \cdot (y - \bar{y} )^i \right )\f] + +where \f$(\bar{x}, \bar{y})\f$ is the mass center: + +\f[\bar{x} = \frac{\texttt{m}_{10}}{\texttt{m}_{00}} , \; \bar{y} = \frac{\texttt{m}_{01}}{\texttt{m}_{00}}\f] + +The normalized central moments \f$\texttt{Moments::nu}_{ij}\f$ are computed as: + +\f[\texttt{nu} _{ji}= \frac{\texttt{mu}_{ji}}{\texttt{m}_{00}^{(i+j)/2+1}} .\f] + +@note +\f$\texttt{mu}_{00}=\texttt{m}_{00}\f$, \f$\texttt{nu}_{00}=1\f$ +\f$\texttt{nu}_{10}=\texttt{mu}_{10}=\texttt{mu}_{01}=\texttt{mu}_{10}=0\f$ , hence the values are not +stored. + +The moments of a contour are defined in the same way but computed using the Green's formula (see +). So, due to a limited raster resolution, the moments +computed for a contour are slightly different from the moments computed for the same rasterized +contour. + +@note +Since the contour moments are computed using Green formula, you may get seemingly odd results for +contours with self-intersections, e.g. a zero area (m00) for butterfly-shaped contours. + */ +class CV_EXPORTS_W_MAP Moments +{ +public: + //! the default constructor + Moments(); + //! the full constructor + Moments(double m00, double m10, double m01, double m20, double m11, + double m02, double m30, double m21, double m12, double m03 ); + ////! the conversion from CvMoments + //Moments( const CvMoments& moments ); + ////! the conversion to CvMoments + //operator CvMoments() const; + + //! @name spatial moments + //! @{ + CV_PROP_RW double m00, m10, m01, m20, m11, m02, m30, m21, m12, m03; + //! @} + + //! @name central moments + //! @{ + CV_PROP_RW double mu20, mu11, mu02, mu30, mu21, mu12, mu03; + //! @} + + //! @name central normalized moments + //! @{ + CV_PROP_RW double nu20, nu11, nu02, nu30, nu21, nu12, nu03; + //! @} +}; + +template<> class DataType +{ +public: + typedef Moments value_type; + typedef double work_type; + typedef double channel_type; + + enum { generic_type = 0, + depth = DataType::depth, + channels = (int)(sizeof(value_type)/sizeof(channel_type)), // 24 + fmt = DataType::fmt + ((channels - 1) << 8), + type = CV_MAKETYPE(depth, channels) + }; + + typedef Vec vec_type; +}; + +//! @} imgproc_shape + +//! @cond IGNORED + +///////////////////////////////////////////////////////////////////////// +///////////////////////////// Implementation //////////////////////////// +///////////////////////////////////////////////////////////////////////// + +//////////////////////////////// Complex //////////////////////////////// + +template inline +Complex<_Tp>::Complex() + : re(0), im(0) {} + +template inline +Complex<_Tp>::Complex( _Tp _re, _Tp _im ) + : re(_re), im(_im) {} + +template template inline +Complex<_Tp>::operator Complex() const +{ + return Complex(saturate_cast(re), saturate_cast(im)); +} + +template inline +Complex<_Tp> Complex<_Tp>::conj() const +{ + return Complex<_Tp>(re, -im); +} + + +template static inline +bool operator == (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return a.re == b.re && a.im == b.im; +} + +template static inline +bool operator != (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return a.re != b.re || a.im != b.im; +} + +template static inline +Complex<_Tp> operator + (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return Complex<_Tp>( a.re + b.re, a.im + b.im ); +} + +template static inline +Complex<_Tp>& operator += (Complex<_Tp>& a, const Complex<_Tp>& b) +{ + a.re += b.re; a.im += b.im; + return a; +} + +template static inline +Complex<_Tp> operator - (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return Complex<_Tp>( a.re - b.re, a.im - b.im ); +} + +template static inline +Complex<_Tp>& operator -= (Complex<_Tp>& a, const Complex<_Tp>& b) +{ + a.re -= b.re; a.im -= b.im; + return a; +} + +template static inline +Complex<_Tp> operator - (const Complex<_Tp>& a) +{ + return Complex<_Tp>(-a.re, -a.im); +} + +template static inline +Complex<_Tp> operator * (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return Complex<_Tp>( a.re*b.re - a.im*b.im, a.re*b.im + a.im*b.re ); +} + +template static inline +Complex<_Tp> operator * (const Complex<_Tp>& a, _Tp b) +{ + return Complex<_Tp>( a.re*b, a.im*b ); +} + +template static inline +Complex<_Tp> operator * (_Tp b, const Complex<_Tp>& a) +{ + return Complex<_Tp>( a.re*b, a.im*b ); +} + +template static inline +Complex<_Tp> operator + (const Complex<_Tp>& a, _Tp b) +{ + return Complex<_Tp>( a.re + b, a.im ); +} + +template static inline +Complex<_Tp> operator - (const Complex<_Tp>& a, _Tp b) +{ return Complex<_Tp>( a.re - b, a.im ); } + +template static inline +Complex<_Tp> operator + (_Tp b, const Complex<_Tp>& a) +{ + return Complex<_Tp>( a.re + b, a.im ); +} + +template static inline +Complex<_Tp> operator - (_Tp b, const Complex<_Tp>& a) +{ + return Complex<_Tp>( b - a.re, -a.im ); +} + +template static inline +Complex<_Tp>& operator += (Complex<_Tp>& a, _Tp b) +{ + a.re += b; return a; +} + +template static inline +Complex<_Tp>& operator -= (Complex<_Tp>& a, _Tp b) +{ + a.re -= b; return a; +} + +template static inline +Complex<_Tp>& operator *= (Complex<_Tp>& a, _Tp b) +{ + a.re *= b; a.im *= b; return a; +} + +template static inline +double abs(const Complex<_Tp>& a) +{ + return std::sqrt( (double)a.re*a.re + (double)a.im*a.im); +} + +template static inline +Complex<_Tp> operator / (const Complex<_Tp>& a, const Complex<_Tp>& b) +{ + double t = 1./((double)b.re*b.re + (double)b.im*b.im); + return Complex<_Tp>( (_Tp)((a.re*b.re + a.im*b.im)*t), + (_Tp)((-a.re*b.im + a.im*b.re)*t) ); +} + +template static inline +Complex<_Tp>& operator /= (Complex<_Tp>& a, const Complex<_Tp>& b) +{ + return (a = a / b); +} + +template static inline +Complex<_Tp> operator / (const Complex<_Tp>& a, _Tp b) +{ + _Tp t = (_Tp)1/b; + return Complex<_Tp>( a.re*t, a.im*t ); +} + +template static inline +Complex<_Tp> operator / (_Tp b, const Complex<_Tp>& a) +{ + return Complex<_Tp>(b)/a; +} + +template static inline +Complex<_Tp> operator /= (const Complex<_Tp>& a, _Tp b) +{ + _Tp t = (_Tp)1/b; + a.re *= t; a.im *= t; return a; +} + + + +//////////////////////////////// 2D Point /////////////////////////////// + +template inline +Point_<_Tp>::Point_() + : x(0), y(0) {} + +template inline +Point_<_Tp>::Point_(_Tp _x, _Tp _y) + : x(_x), y(_y) {} + +template inline +Point_<_Tp>::Point_(const Point_& pt) + : x(pt.x), y(pt.y) {} + +template inline +Point_<_Tp>::Point_(const Size_<_Tp>& sz) + : x(sz.width), y(sz.height) {} + +template inline +Point_<_Tp>::Point_(const Vec<_Tp,2>& v) + : x(v[0]), y(v[1]) {} + +template inline +Point_<_Tp>& Point_<_Tp>::operator = (const Point_& pt) +{ + x = pt.x; y = pt.y; + return *this; +} + +template template inline +Point_<_Tp>::operator Point_<_Tp2>() const +{ + return Point_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y)); +} + +template inline +Point_<_Tp>::operator Vec<_Tp, 2>() const +{ + return Vec<_Tp, 2>(x, y); +} + +template inline +_Tp Point_<_Tp>::dot(const Point_& pt) const +{ + return saturate_cast<_Tp>(x*pt.x + y*pt.y); +} + +template inline +double Point_<_Tp>::ddot(const Point_& pt) const +{ + return (double)x*pt.x + (double)y*pt.y; +} + +template inline +double Point_<_Tp>::cross(const Point_& pt) const +{ + return (double)x*pt.y - (double)y*pt.x; +} + +template inline bool +Point_<_Tp>::inside( const Rect_<_Tp>& r ) const +{ + return r.contains(*this); +} + + +template static inline +Point_<_Tp>& operator += (Point_<_Tp>& a, const Point_<_Tp>& b) +{ + a.x += b.x; + a.y += b.y; + return a; +} + +template static inline +Point_<_Tp>& operator -= (Point_<_Tp>& a, const Point_<_Tp>& b) +{ + a.x -= b.x; + a.y -= b.y; + return a; +} + +template static inline +Point_<_Tp>& operator *= (Point_<_Tp>& a, int b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + return a; +} + +template static inline +Point_<_Tp>& operator *= (Point_<_Tp>& a, float b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + return a; +} + +template static inline +Point_<_Tp>& operator *= (Point_<_Tp>& a, double b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + return a; +} + +template static inline +Point_<_Tp>& operator /= (Point_<_Tp>& a, int b) +{ + a.x = saturate_cast<_Tp>(a.x / b); + a.y = saturate_cast<_Tp>(a.y / b); + return a; +} + +template static inline +Point_<_Tp>& operator /= (Point_<_Tp>& a, float b) +{ + a.x = saturate_cast<_Tp>(a.x / b); + a.y = saturate_cast<_Tp>(a.y / b); + return a; +} + +template static inline +Point_<_Tp>& operator /= (Point_<_Tp>& a, double b) +{ + a.x = saturate_cast<_Tp>(a.x / b); + a.y = saturate_cast<_Tp>(a.y / b); + return a; +} + +template static inline +double norm(const Point_<_Tp>& pt) +{ + return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y); +} + +template static inline +bool operator == (const Point_<_Tp>& a, const Point_<_Tp>& b) +{ + return a.x == b.x && a.y == b.y; +} + +template static inline +bool operator != (const Point_<_Tp>& a, const Point_<_Tp>& b) +{ + return a.x != b.x || a.y != b.y; +} + +template static inline +Point_<_Tp> operator + (const Point_<_Tp>& a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x + b.x), saturate_cast<_Tp>(a.y + b.y) ); +} + +template static inline +Point_<_Tp> operator - (const Point_<_Tp>& a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x - b.x), saturate_cast<_Tp>(a.y - b.y) ); +} + +template static inline +Point_<_Tp> operator - (const Point_<_Tp>& a) +{ + return Point_<_Tp>( saturate_cast<_Tp>(-a.x), saturate_cast<_Tp>(-a.y) ); +} + +template static inline +Point_<_Tp> operator * (const Point_<_Tp>& a, int b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); +} + +template static inline +Point_<_Tp> operator * (int a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); +} + +template static inline +Point_<_Tp> operator * (const Point_<_Tp>& a, float b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); +} + +template static inline +Point_<_Tp> operator * (float a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); +} + +template static inline +Point_<_Tp> operator * (const Point_<_Tp>& a, double b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) ); +} + +template static inline +Point_<_Tp> operator * (double a, const Point_<_Tp>& b) +{ + return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) ); +} + +template static inline +Point_<_Tp> operator * (const Matx<_Tp, 2, 2>& a, const Point_<_Tp>& b) +{ + Matx<_Tp, 2, 1> tmp = a * Vec<_Tp,2>(b.x, b.y); + return Point_<_Tp>(tmp.val[0], tmp.val[1]); +} + +template static inline +Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point_<_Tp>& b) +{ + Matx<_Tp, 3, 1> tmp = a * Vec<_Tp,3>(b.x, b.y, 1); + return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]); +} + +template static inline +Point_<_Tp> operator / (const Point_<_Tp>& a, int b) +{ + Point_<_Tp> tmp(a); + tmp /= b; + return tmp; +} + +template static inline +Point_<_Tp> operator / (const Point_<_Tp>& a, float b) +{ + Point_<_Tp> tmp(a); + tmp /= b; + return tmp; +} + +template static inline +Point_<_Tp> operator / (const Point_<_Tp>& a, double b) +{ + Point_<_Tp> tmp(a); + tmp /= b; + return tmp; +} + + + +//////////////////////////////// 3D Point /////////////////////////////// + +template inline +Point3_<_Tp>::Point3_() + : x(0), y(0), z(0) {} + +template inline +Point3_<_Tp>::Point3_(_Tp _x, _Tp _y, _Tp _z) + : x(_x), y(_y), z(_z) {} + +template inline +Point3_<_Tp>::Point3_(const Point3_& pt) + : x(pt.x), y(pt.y), z(pt.z) {} + +template inline +Point3_<_Tp>::Point3_(const Point_<_Tp>& pt) + : x(pt.x), y(pt.y), z(_Tp()) {} + +template inline +Point3_<_Tp>::Point3_(const Vec<_Tp, 3>& v) + : x(v[0]), y(v[1]), z(v[2]) {} + +template template inline +Point3_<_Tp>::operator Point3_<_Tp2>() const +{ + return Point3_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y), saturate_cast<_Tp2>(z)); +} + +template inline +Point3_<_Tp>::operator Vec<_Tp, 3>() const +{ + return Vec<_Tp, 3>(x, y, z); +} + +template inline +Point3_<_Tp>& Point3_<_Tp>::operator = (const Point3_& pt) +{ + x = pt.x; y = pt.y; z = pt.z; + return *this; +} + +template inline +_Tp Point3_<_Tp>::dot(const Point3_& pt) const +{ + return saturate_cast<_Tp>(x*pt.x + y*pt.y + z*pt.z); +} + +template inline +double Point3_<_Tp>::ddot(const Point3_& pt) const +{ + return (double)x*pt.x + (double)y*pt.y + (double)z*pt.z; +} + +template inline +Point3_<_Tp> Point3_<_Tp>::cross(const Point3_<_Tp>& pt) const +{ + return Point3_<_Tp>(y*pt.z - z*pt.y, z*pt.x - x*pt.z, x*pt.y - y*pt.x); +} + + +template static inline +Point3_<_Tp>& operator += (Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + a.x += b.x; + a.y += b.y; + a.z += b.z; + return a; +} + +template static inline +Point3_<_Tp>& operator -= (Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + a.x -= b.x; + a.y -= b.y; + a.z -= b.z; + return a; +} + +template static inline +Point3_<_Tp>& operator *= (Point3_<_Tp>& a, int b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + a.z = saturate_cast<_Tp>(a.z * b); + return a; +} + +template static inline +Point3_<_Tp>& operator *= (Point3_<_Tp>& a, float b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + a.z = saturate_cast<_Tp>(a.z * b); + return a; +} + +template static inline +Point3_<_Tp>& operator *= (Point3_<_Tp>& a, double b) +{ + a.x = saturate_cast<_Tp>(a.x * b); + a.y = saturate_cast<_Tp>(a.y * b); + a.z = saturate_cast<_Tp>(a.z * b); + return a; +} + +template static inline +Point3_<_Tp>& operator /= (Point3_<_Tp>& a, int b) +{ + a.x = saturate_cast<_Tp>(a.x / b); + a.y = saturate_cast<_Tp>(a.y / b); + a.z = saturate_cast<_Tp>(a.z / b); + return a; +} + +template static inline +Point3_<_Tp>& operator /= (Point3_<_Tp>& a, float b) +{ + a.x = saturate_cast<_Tp>(a.x / b); + a.y = saturate_cast<_Tp>(a.y / b); + a.z = saturate_cast<_Tp>(a.z / b); + return a; +} + +template static inline +Point3_<_Tp>& operator /= (Point3_<_Tp>& a, double b) +{ + a.x = saturate_cast<_Tp>(a.x / b); + a.y = saturate_cast<_Tp>(a.y / b); + a.z = saturate_cast<_Tp>(a.z / b); + return a; +} + +template static inline +double norm(const Point3_<_Tp>& pt) +{ + return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y + (double)pt.z*pt.z); +} + +template static inline +bool operator == (const Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + return a.x == b.x && a.y == b.y && a.z == b.z; +} + +template static inline +bool operator != (const Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + return a.x != b.x || a.y != b.y || a.z != b.z; +} + +template static inline +Point3_<_Tp> operator + (const Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x + b.x), saturate_cast<_Tp>(a.y + b.y), saturate_cast<_Tp>(a.z + b.z)); +} + +template static inline +Point3_<_Tp> operator - (const Point3_<_Tp>& a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x - b.x), saturate_cast<_Tp>(a.y - b.y), saturate_cast<_Tp>(a.z - b.z)); +} + +template static inline +Point3_<_Tp> operator - (const Point3_<_Tp>& a) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(-a.x), saturate_cast<_Tp>(-a.y), saturate_cast<_Tp>(-a.z) ); +} + +template static inline +Point3_<_Tp> operator * (const Point3_<_Tp>& a, int b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b), saturate_cast<_Tp>(a.z*b) ); +} + +template static inline +Point3_<_Tp> operator * (int a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(b.x * a), saturate_cast<_Tp>(b.y * a), saturate_cast<_Tp>(b.z * a) ); +} + +template static inline +Point3_<_Tp> operator * (const Point3_<_Tp>& a, float b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x * b), saturate_cast<_Tp>(a.y * b), saturate_cast<_Tp>(a.z * b) ); +} + +template static inline +Point3_<_Tp> operator * (float a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(b.x * a), saturate_cast<_Tp>(b.y * a), saturate_cast<_Tp>(b.z * a) ); +} + +template static inline +Point3_<_Tp> operator * (const Point3_<_Tp>& a, double b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(a.x * b), saturate_cast<_Tp>(a.y * b), saturate_cast<_Tp>(a.z * b) ); +} + +template static inline +Point3_<_Tp> operator * (double a, const Point3_<_Tp>& b) +{ + return Point3_<_Tp>( saturate_cast<_Tp>(b.x * a), saturate_cast<_Tp>(b.y * a), saturate_cast<_Tp>(b.z * a) ); +} + +template static inline +Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point3_<_Tp>& b) +{ + Matx<_Tp, 3, 1> tmp = a * Vec<_Tp,3>(b.x, b.y, b.z); + return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]); +} + +template static inline +Matx<_Tp, 4, 1> operator * (const Matx<_Tp, 4, 4>& a, const Point3_<_Tp>& b) +{ + return a * Matx<_Tp, 4, 1>(b.x, b.y, b.z, 1); +} + +template static inline +Point3_<_Tp> operator / (const Point3_<_Tp>& a, int b) +{ + Point3_<_Tp> tmp(a); + tmp /= b; + return tmp; +} + +template static inline +Point3_<_Tp> operator / (const Point3_<_Tp>& a, float b) +{ + Point3_<_Tp> tmp(a); + tmp /= b; + return tmp; +} + +template static inline +Point3_<_Tp> operator / (const Point3_<_Tp>& a, double b) +{ + Point3_<_Tp> tmp(a); + tmp /= b; + return tmp; +} + + + +////////////////////////////////// Size ///////////////////////////////// + +template inline +Size_<_Tp>::Size_() + : width(0), height(0) {} + +template inline +Size_<_Tp>::Size_(_Tp _width, _Tp _height) + : width(_width), height(_height) {} + +template inline +Size_<_Tp>::Size_(const Size_& sz) + : width(sz.width), height(sz.height) {} + +template inline +Size_<_Tp>::Size_(const Point_<_Tp>& pt) + : width(pt.x), height(pt.y) {} + +template template inline +Size_<_Tp>::operator Size_<_Tp2>() const +{ + return Size_<_Tp2>(saturate_cast<_Tp2>(width), saturate_cast<_Tp2>(height)); +} + +template inline +Size_<_Tp>& Size_<_Tp>::operator = (const Size_<_Tp>& sz) +{ + width = sz.width; height = sz.height; + return *this; +} + +template inline +_Tp Size_<_Tp>::area() const +{ + return width * height; +} + +template static inline +Size_<_Tp>& operator *= (Size_<_Tp>& a, _Tp b) +{ + a.width *= b; + a.height *= b; + return a; +} + +template static inline +Size_<_Tp> operator * (const Size_<_Tp>& a, _Tp b) +{ + Size_<_Tp> tmp(a); + tmp *= b; + return tmp; +} + +template static inline +Size_<_Tp>& operator /= (Size_<_Tp>& a, _Tp b) +{ + a.width /= b; + a.height /= b; + return a; +} + +template static inline +Size_<_Tp> operator / (const Size_<_Tp>& a, _Tp b) +{ + Size_<_Tp> tmp(a); + tmp /= b; + return tmp; +} + +template static inline +Size_<_Tp>& operator += (Size_<_Tp>& a, const Size_<_Tp>& b) +{ + a.width += b.width; + a.height += b.height; + return a; +} + +template static inline +Size_<_Tp> operator + (const Size_<_Tp>& a, const Size_<_Tp>& b) +{ + Size_<_Tp> tmp(a); + tmp += b; + return tmp; +} + +template static inline +Size_<_Tp>& operator -= (Size_<_Tp>& a, const Size_<_Tp>& b) +{ + a.width -= b.width; + a.height -= b.height; + return a; +} + +template static inline +Size_<_Tp> operator - (const Size_<_Tp>& a, const Size_<_Tp>& b) +{ + Size_<_Tp> tmp(a); + tmp -= b; + return tmp; +} + +template static inline +bool operator == (const Size_<_Tp>& a, const Size_<_Tp>& b) +{ + return a.width == b.width && a.height == b.height; +} + +template static inline +bool operator != (const Size_<_Tp>& a, const Size_<_Tp>& b) +{ + return !(a == b); +} + + + +////////////////////////////////// Rect ///////////////////////////////// + +template inline +Rect_<_Tp>::Rect_() + : x(0), y(0), width(0), height(0) {} + +template inline +Rect_<_Tp>::Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height) + : x(_x), y(_y), width(_width), height(_height) {} + +template inline +Rect_<_Tp>::Rect_(const Rect_<_Tp>& r) + : x(r.x), y(r.y), width(r.width), height(r.height) {} + +template inline +Rect_<_Tp>::Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz) + : x(org.x), y(org.y), width(sz.width), height(sz.height) {} + +template inline +Rect_<_Tp>::Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2) +{ + x = std::min(pt1.x, pt2.x); + y = std::min(pt1.y, pt2.y); + width = std::max(pt1.x, pt2.x) - x; + height = std::max(pt1.y, pt2.y) - y; +} + +template inline +Rect_<_Tp>& Rect_<_Tp>::operator = ( const Rect_<_Tp>& r ) +{ + x = r.x; + y = r.y; + width = r.width; + height = r.height; + return *this; +} + +template inline +Point_<_Tp> Rect_<_Tp>::tl() const +{ + return Point_<_Tp>(x,y); +} + +template inline +Point_<_Tp> Rect_<_Tp>::br() const +{ + return Point_<_Tp>(x + width, y + height); +} + +template inline +Size_<_Tp> Rect_<_Tp>::size() const +{ + return Size_<_Tp>(width, height); +} + +template inline +_Tp Rect_<_Tp>::area() const +{ + return width * height; +} + +template template inline +Rect_<_Tp>::operator Rect_<_Tp2>() const +{ + return Rect_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y), saturate_cast<_Tp2>(width), saturate_cast<_Tp2>(height)); +} + +template inline +bool Rect_<_Tp>::contains(const Point_<_Tp>& pt) const +{ + return x <= pt.x && pt.x < x + width && y <= pt.y && pt.y < y + height; +} + + +template static inline +Rect_<_Tp>& operator += ( Rect_<_Tp>& a, const Point_<_Tp>& b ) +{ + a.x += b.x; + a.y += b.y; + return a; +} + +template static inline +Rect_<_Tp>& operator -= ( Rect_<_Tp>& a, const Point_<_Tp>& b ) +{ + a.x -= b.x; + a.y -= b.y; + return a; +} + +template static inline +Rect_<_Tp>& operator += ( Rect_<_Tp>& a, const Size_<_Tp>& b ) +{ + a.width += b.width; + a.height += b.height; + return a; +} + +template static inline +Rect_<_Tp>& operator -= ( Rect_<_Tp>& a, const Size_<_Tp>& b ) +{ + a.width -= b.width; + a.height -= b.height; + return a; +} + +template static inline +Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) +{ + _Tp x1 = std::max(a.x, b.x); + _Tp y1 = std::max(a.y, b.y); + a.width = std::min(a.x + a.width, b.x + b.width) - x1; + a.height = std::min(a.y + a.height, b.y + b.height) - y1; + a.x = x1; + a.y = y1; + if( a.width <= 0 || a.height <= 0 ) + a = Rect(); + return a; +} + +template static inline +Rect_<_Tp>& operator |= ( Rect_<_Tp>& a, const Rect_<_Tp>& b ) +{ + _Tp x1 = std::min(a.x, b.x); + _Tp y1 = std::min(a.y, b.y); + a.width = std::max(a.x + a.width, b.x + b.width) - x1; + a.height = std::max(a.y + a.height, b.y + b.height) - y1; + a.x = x1; + a.y = y1; + return a; +} + +template static inline +bool operator == (const Rect_<_Tp>& a, const Rect_<_Tp>& b) +{ + return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height; +} + +template static inline +bool operator != (const Rect_<_Tp>& a, const Rect_<_Tp>& b) +{ + return a.x != b.x || a.y != b.y || a.width != b.width || a.height != b.height; +} + +template static inline +Rect_<_Tp> operator + (const Rect_<_Tp>& a, const Point_<_Tp>& b) +{ + return Rect_<_Tp>( a.x + b.x, a.y + b.y, a.width, a.height ); +} + +template static inline +Rect_<_Tp> operator - (const Rect_<_Tp>& a, const Point_<_Tp>& b) +{ + return Rect_<_Tp>( a.x - b.x, a.y - b.y, a.width, a.height ); +} + +template static inline +Rect_<_Tp> operator + (const Rect_<_Tp>& a, const Size_<_Tp>& b) +{ + return Rect_<_Tp>( a.x, a.y, a.width + b.width, a.height + b.height ); +} + +template static inline +Rect_<_Tp> operator & (const Rect_<_Tp>& a, const Rect_<_Tp>& b) +{ + Rect_<_Tp> c = a; + return c &= b; +} + +template static inline +Rect_<_Tp> operator | (const Rect_<_Tp>& a, const Rect_<_Tp>& b) +{ + Rect_<_Tp> c = a; + return c |= b; +} + + + +////////////////////////////// RotatedRect ////////////////////////////// + +inline +RotatedRect::RotatedRect() + : center(), size(), angle(0) {} + +inline +RotatedRect::RotatedRect(const Point2f& _center, const Size2f& _size, float _angle) + : center(_center), size(_size), angle(_angle) {} + + + +///////////////////////////////// Range ///////////////////////////////// + +inline +Range::Range() + : start(0), end(0) {} + +inline +Range::Range(int _start, int _end) + : start(_start), end(_end) {} + +inline +int Range::size() const +{ + return end - start; +} + +inline +bool Range::empty() const +{ + return start == end; +} + +inline +Range Range::all() +{ + return Range(INT_MIN, INT_MAX); +} + + +static inline +bool operator == (const Range& r1, const Range& r2) +{ + return r1.start == r2.start && r1.end == r2.end; +} + +static inline +bool operator != (const Range& r1, const Range& r2) +{ + return !(r1 == r2); +} + +static inline +bool operator !(const Range& r) +{ + return r.start == r.end; +} + +static inline +Range operator & (const Range& r1, const Range& r2) +{ + Range r(std::max(r1.start, r2.start), std::min(r1.end, r2.end)); + r.end = std::max(r.end, r.start); + return r; +} + +static inline +Range& operator &= (Range& r1, const Range& r2) +{ + r1 = r1 & r2; + return r1; +} + +static inline +Range operator + (const Range& r1, int delta) +{ + return Range(r1.start + delta, r1.end + delta); +} + +static inline +Range operator + (int delta, const Range& r1) +{ + return Range(r1.start + delta, r1.end + delta); +} + +static inline +Range operator - (const Range& r1, int delta) +{ + return r1 + (-delta); +} + + + +///////////////////////////////// Scalar //////////////////////////////// + +template inline +Scalar_<_Tp>::Scalar_() +{ + this->val[0] = this->val[1] = this->val[2] = this->val[3] = 0; +} + +template inline +Scalar_<_Tp>::Scalar_(_Tp v0, _Tp v1, _Tp v2, _Tp v3) +{ + this->val[0] = v0; + this->val[1] = v1; + this->val[2] = v2; + this->val[3] = v3; +} + +template template inline +Scalar_<_Tp>::Scalar_(const Vec<_Tp2, cn>& v) +{ + int i; + for( i = 0; i < (cn < 4 ? cn : 4); i++ ) + this->val[i] = cv::saturate_cast<_Tp>(v.val[i]); + for( ; i < 4; i++ ) + this->val[i] = 0; +} + +template inline +Scalar_<_Tp>::Scalar_(_Tp v0) +{ + this->val[0] = v0; + this->val[1] = this->val[2] = this->val[3] = 0; +} + +template inline +Scalar_<_Tp> Scalar_<_Tp>::all(_Tp v0) +{ + return Scalar_<_Tp>(v0, v0, v0, v0); +} + + +template inline +Scalar_<_Tp> Scalar_<_Tp>::mul(const Scalar_<_Tp>& a, double scale ) const +{ + return Scalar_<_Tp>(saturate_cast<_Tp>(this->val[0] * a.val[0] * scale), + saturate_cast<_Tp>(this->val[1] * a.val[1] * scale), + saturate_cast<_Tp>(this->val[2] * a.val[2] * scale), + saturate_cast<_Tp>(this->val[3] * a.val[3] * scale)); +} + +template inline +Scalar_<_Tp> Scalar_<_Tp>::conj() const +{ + return Scalar_<_Tp>(saturate_cast<_Tp>( this->val[0]), + saturate_cast<_Tp>(-this->val[1]), + saturate_cast<_Tp>(-this->val[2]), + saturate_cast<_Tp>(-this->val[3])); +} + +template inline +bool Scalar_<_Tp>::isReal() const +{ + return this->val[1] == 0 && this->val[2] == 0 && this->val[3] == 0; +} + + +template template inline +Scalar_<_Tp>::operator Scalar_() const +{ + return Scalar_(saturate_cast(this->val[0]), + saturate_cast(this->val[1]), + saturate_cast(this->val[2]), + saturate_cast(this->val[3])); +} + + +template static inline +Scalar_<_Tp>& operator += (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + a.val[0] += b.val[0]; + a.val[1] += b.val[1]; + a.val[2] += b.val[2]; + a.val[3] += b.val[3]; + return a; +} + +template static inline +Scalar_<_Tp>& operator -= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + a.val[0] -= b.val[0]; + a.val[1] -= b.val[1]; + a.val[2] -= b.val[2]; + a.val[3] -= b.val[3]; + return a; +} + +template static inline +Scalar_<_Tp>& operator *= ( Scalar_<_Tp>& a, _Tp v ) +{ + a.val[0] *= v; + a.val[1] *= v; + a.val[2] *= v; + a.val[3] *= v; + return a; +} + +template static inline +bool operator == ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b ) +{ + return a.val[0] == b.val[0] && a.val[1] == b.val[1] && + a.val[2] == b.val[2] && a.val[3] == b.val[3]; +} + +template static inline +bool operator != ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b ) +{ + return a.val[0] != b.val[0] || a.val[1] != b.val[1] || + a.val[2] != b.val[2] || a.val[3] != b.val[3]; +} + +template static inline +Scalar_<_Tp> operator + (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + return Scalar_<_Tp>(a.val[0] + b.val[0], + a.val[1] + b.val[1], + a.val[2] + b.val[2], + a.val[3] + b.val[3]); +} + +template static inline +Scalar_<_Tp> operator - (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + return Scalar_<_Tp>(saturate_cast<_Tp>(a.val[0] - b.val[0]), + saturate_cast<_Tp>(a.val[1] - b.val[1]), + saturate_cast<_Tp>(a.val[2] - b.val[2]), + saturate_cast<_Tp>(a.val[3] - b.val[3])); +} + +template static inline +Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, _Tp alpha) +{ + return Scalar_<_Tp>(a.val[0] * alpha, + a.val[1] * alpha, + a.val[2] * alpha, + a.val[3] * alpha); +} + +template static inline +Scalar_<_Tp> operator * (_Tp alpha, const Scalar_<_Tp>& a) +{ + return a*alpha; +} + +template static inline +Scalar_<_Tp> operator - (const Scalar_<_Tp>& a) +{ + return Scalar_<_Tp>(saturate_cast<_Tp>(-a.val[0]), + saturate_cast<_Tp>(-a.val[1]), + saturate_cast<_Tp>(-a.val[2]), + saturate_cast<_Tp>(-a.val[3])); +} + + +template static inline +Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + return Scalar_<_Tp>(saturate_cast<_Tp>(a[0]*b[0] - a[1]*b[1] - a[2]*b[2] - a[3]*b[3]), + saturate_cast<_Tp>(a[0]*b[1] + a[1]*b[0] + a[2]*b[3] - a[3]*b[2]), + saturate_cast<_Tp>(a[0]*b[2] - a[1]*b[3] + a[2]*b[0] + a[3]*b[1]), + saturate_cast<_Tp>(a[0]*b[3] + a[1]*b[2] - a[2]*b[1] + a[3]*b[0])); +} + +template static inline +Scalar_<_Tp>& operator *= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + a = a * b; + return a; +} + +template static inline +Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, _Tp alpha) +{ + return Scalar_<_Tp>(a.val[0] / alpha, + a.val[1] / alpha, + a.val[2] / alpha, + a.val[3] / alpha); +} + +template static inline +Scalar_ operator / (const Scalar_& a, float alpha) +{ + float s = 1 / alpha; + return Scalar_(a.val[0] * s, a.val[1] * s, a.val[2] * s, a.val[3] * s); +} + +template static inline +Scalar_ operator / (const Scalar_& a, double alpha) +{ + double s = 1 / alpha; + return Scalar_(a.val[0] * s, a.val[1] * s, a.val[2] * s, a.val[3] * s); +} + +template static inline +Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, _Tp alpha) +{ + a = a / alpha; + return a; +} + +template static inline +Scalar_<_Tp> operator / (_Tp a, const Scalar_<_Tp>& b) +{ + _Tp s = a / (b[0]*b[0] + b[1]*b[1] + b[2]*b[2] + b[3]*b[3]); + return b.conj() * s; +} + +template static inline +Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + return a * ((_Tp)1 / b); +} + +template static inline +Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b) +{ + a = a / b; + return a; +} + +template static inline +Scalar operator * (const Matx<_Tp, 4, 4>& a, const Scalar& b) +{ + Matx c((Matx)a, b, Matx_MatMulOp()); + return reinterpret_cast(c); +} + +template<> inline +Scalar operator * (const Matx& a, const Scalar& b) +{ + Matx c(a, b, Matx_MatMulOp()); + return reinterpret_cast(c); +} + + + +//////////////////////////////// KeyPoint /////////////////////////////// + +inline +KeyPoint::KeyPoint() + : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {} + +inline +KeyPoint::KeyPoint(Point2f _pt, float _size, float _angle, float _response, int _octave, int _class_id) + : pt(_pt), size(_size), angle(_angle), response(_response), octave(_octave), class_id(_class_id) {} + +inline +KeyPoint::KeyPoint(float x, float y, float _size, float _angle, float _response, int _octave, int _class_id) + : pt(x, y), size(_size), angle(_angle), response(_response), octave(_octave), class_id(_class_id) {} + + + +///////////////////////////////// DMatch //////////////////////////////// + +inline +DMatch::DMatch() + : queryIdx(-1), trainIdx(-1), imgIdx(-1), distance(FLT_MAX) {} + +inline +DMatch::DMatch(int _queryIdx, int _trainIdx, float _distance) + : queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), distance(_distance) {} + +inline +DMatch::DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance) + : queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), distance(_distance) {} + +inline +bool DMatch::operator < (const DMatch &m) const +{ + return distance < m.distance; +} + + + +////////////////////////////// TermCriteria ///////////////////////////// + +inline +TermCriteria::TermCriteria() + : type(0), maxCount(0), epsilon(0) {} + +inline +TermCriteria::TermCriteria(int _type, int _maxCount, double _epsilon) + : type(_type), maxCount(_maxCount), epsilon(_epsilon) {} + +//! @endcond + +} // cv + +#endif //__OPENCV_CORE_TYPES_HPP__ diff --git a/include/opencv2/core/types_c.h b/include/opencv2/core/types_c.h new file mode 100644 index 0000000..cb39587 --- /dev/null +++ b/include/opencv2/core/types_c.h @@ -0,0 +1,1834 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_TYPES_H__ +#define __OPENCV_CORE_TYPES_H__ + +#ifdef HAVE_IPL +# ifndef __IPL_H__ +# if defined WIN32 || defined _WIN32 +# include +# else +# include +# endif +# endif +#elif defined __IPL_H__ +# define HAVE_IPL +#endif + +#include "opencv2/core/cvdef.h" + +#ifndef SKIP_INCLUDES +#include +#include +#include +#include +#endif // SKIP_INCLUDES + +#if defined WIN32 || defined _WIN32 +# define CV_CDECL __cdecl +# define CV_STDCALL __stdcall +#else +# define CV_CDECL +# define CV_STDCALL +#endif + +#ifndef CV_DEFAULT +# ifdef __cplusplus +# define CV_DEFAULT(val) = val +# else +# define CV_DEFAULT(val) +# endif +#endif + +#ifndef CV_EXTERN_C_FUNCPTR +# ifdef __cplusplus +# define CV_EXTERN_C_FUNCPTR(x) extern "C" { typedef x; } +# else +# define CV_EXTERN_C_FUNCPTR(x) typedef x +# endif +#endif + +#ifndef CVAPI +# define CVAPI(rettype) CV_EXTERN_C CV_EXPORTS rettype CV_CDECL +#endif + +#ifndef CV_IMPL +# define CV_IMPL CV_EXTERN_C +#endif + +#ifdef __cplusplus +# include "opencv2/core.hpp" +#endif + +/** @addtogroup core_c + @{ +*/ + +/** @brief This is the "metatype" used *only* as a function parameter. + +It denotes that the function accepts arrays of multiple types, such as IplImage*, CvMat* or even +CvSeq* sometimes. The particular array type is determined at runtime by analyzing the first 4 +bytes of the header. In C++ interface the role of CvArr is played by InputArray and OutputArray. + */ +typedef void CvArr; + +typedef int CVStatus; + +/** @see cv::Error::Code */ +enum { + CV_StsOk= 0, /**< everything is ok */ + CV_StsBackTrace= -1, /**< pseudo error for back trace */ + CV_StsError= -2, /**< unknown /unspecified error */ + CV_StsInternal= -3, /**< internal error (bad state) */ + CV_StsNoMem= -4, /**< insufficient memory */ + CV_StsBadArg= -5, /**< function arg/param is bad */ + CV_StsBadFunc= -6, /**< unsupported function */ + CV_StsNoConv= -7, /**< iter. didn't converge */ + CV_StsAutoTrace= -8, /**< tracing */ + CV_HeaderIsNull= -9, /**< image header is NULL */ + CV_BadImageSize= -10, /**< image size is invalid */ + CV_BadOffset= -11, /**< offset is invalid */ + CV_BadDataPtr= -12, /**/ + CV_BadStep= -13, /**/ + CV_BadModelOrChSeq= -14, /**/ + CV_BadNumChannels= -15, /**/ + CV_BadNumChannel1U= -16, /**/ + CV_BadDepth= -17, /**/ + CV_BadAlphaChannel= -18, /**/ + CV_BadOrder= -19, /**/ + CV_BadOrigin= -20, /**/ + CV_BadAlign= -21, /**/ + CV_BadCallBack= -22, /**/ + CV_BadTileSize= -23, /**/ + CV_BadCOI= -24, /**/ + CV_BadROISize= -25, /**/ + CV_MaskIsTiled= -26, /**/ + CV_StsNullPtr= -27, /**< null pointer */ + CV_StsVecLengthErr= -28, /**< incorrect vector length */ + CV_StsFilterStructContentErr= -29, /**< incorr. filter structure content */ + CV_StsKernelStructContentErr= -30, /**< incorr. transform kernel content */ + CV_StsFilterOffsetErr= -31, /**< incorrect filter offset value */ + CV_StsBadSize= -201, /**< the input/output structure size is incorrect */ + CV_StsDivByZero= -202, /**< division by zero */ + CV_StsInplaceNotSupported= -203, /**< in-place operation is not supported */ + CV_StsObjectNotFound= -204, /**< request can't be completed */ + CV_StsUnmatchedFormats= -205, /**< formats of input/output arrays differ */ + CV_StsBadFlag= -206, /**< flag is wrong or not supported */ + CV_StsBadPoint= -207, /**< bad CvPoint */ + CV_StsBadMask= -208, /**< bad format of mask (neither 8uC1 nor 8sC1)*/ + CV_StsUnmatchedSizes= -209, /**< sizes of input/output structures do not match */ + CV_StsUnsupportedFormat= -210, /**< the data format/type is not supported by the function*/ + CV_StsOutOfRange= -211, /**< some of parameters are out of range */ + CV_StsParseError= -212, /**< invalid syntax/structure of the parsed file */ + CV_StsNotImplemented= -213, /**< the requested function/feature is not implemented */ + CV_StsBadMemBlock= -214, /**< an allocated block has been corrupted */ + CV_StsAssert= -215, /**< assertion failed */ + CV_GpuNotSupported= -216, + CV_GpuApiCallError= -217, + CV_OpenGlNotSupported= -218, + CV_OpenGlApiCallError= -219, + CV_OpenCLApiCallError= -220, + CV_OpenCLDoubleNotSupported= -221, + CV_OpenCLInitError= -222, + CV_OpenCLNoAMDBlasFft= -223 +}; + +/****************************************************************************************\ +* Common macros and inline functions * +\****************************************************************************************/ + +#define CV_SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t)) + +/** min & max without jumps */ +#define CV_IMIN(a, b) ((a) ^ (((a)^(b)) & (((a) < (b)) - 1))) + +#define CV_IMAX(a, b) ((a) ^ (((a)^(b)) & (((a) > (b)) - 1))) + +/** absolute value without jumps */ +#ifndef __cplusplus +# define CV_IABS(a) (((a) ^ ((a) < 0 ? -1 : 0)) - ((a) < 0 ? -1 : 0)) +#else +# define CV_IABS(a) abs(a) +#endif +#define CV_CMP(a,b) (((a) > (b)) - ((a) < (b))) +#define CV_SIGN(a) CV_CMP((a),0) + +#define cvInvSqrt(value) ((float)(1./sqrt(value))) +#define cvSqrt(value) ((float)sqrt(value)) + + +/*************** Random number generation *******************/ + +typedef uint64 CvRNG; + +#define CV_RNG_COEFF 4164903690U + +/** @brief Initializes a random number generator state. + +The function initializes a random number generator and returns the state. The pointer to the state +can be then passed to the cvRandInt, cvRandReal and cvRandArr functions. In the current +implementation a multiply-with-carry generator is used. +@param seed 64-bit value used to initiate a random sequence +@sa the C++ class RNG replaced CvRNG. + */ +CV_INLINE CvRNG cvRNG( int64 seed CV_DEFAULT(-1)) +{ + CvRNG rng = seed ? (uint64)seed : (uint64)(int64)-1; + return rng; +} + +/** @brief Returns a 32-bit unsigned integer and updates RNG. + +The function returns a uniformly-distributed random 32-bit unsigned integer and updates the RNG +state. It is similar to the rand() function from the C runtime library, except that OpenCV functions +always generates a 32-bit random number, regardless of the platform. +@param rng CvRNG state initialized by cvRNG. + */ +CV_INLINE unsigned cvRandInt( CvRNG* rng ) +{ + uint64 temp = *rng; + temp = (uint64)(unsigned)temp*CV_RNG_COEFF + (temp >> 32); + *rng = temp; + return (unsigned)temp; +} + +/** @brief Returns a floating-point random number and updates RNG. + +The function returns a uniformly-distributed random floating-point number between 0 and 1 (1 is not +included). +@param rng RNG state initialized by cvRNG + */ +CV_INLINE double cvRandReal( CvRNG* rng ) +{ + return cvRandInt(rng)*2.3283064365386962890625e-10 /* 2^-32 */; +} + +/****************************************************************************************\ +* Image type (IplImage) * +\****************************************************************************************/ + +#ifndef HAVE_IPL + +/* + * The following definitions (until #endif) + * is an extract from IPL headers. + * Copyright (c) 1995 Intel Corporation. + */ +#define IPL_DEPTH_SIGN 0x80000000 + +#define IPL_DEPTH_1U 1 +#define IPL_DEPTH_8U 8 +#define IPL_DEPTH_16U 16 +#define IPL_DEPTH_32F 32 + +#define IPL_DEPTH_8S (IPL_DEPTH_SIGN| 8) +#define IPL_DEPTH_16S (IPL_DEPTH_SIGN|16) +#define IPL_DEPTH_32S (IPL_DEPTH_SIGN|32) + +#define IPL_DATA_ORDER_PIXEL 0 +#define IPL_DATA_ORDER_PLANE 1 + +#define IPL_ORIGIN_TL 0 +#define IPL_ORIGIN_BL 1 + +#define IPL_ALIGN_4BYTES 4 +#define IPL_ALIGN_8BYTES 8 +#define IPL_ALIGN_16BYTES 16 +#define IPL_ALIGN_32BYTES 32 + +#define IPL_ALIGN_DWORD IPL_ALIGN_4BYTES +#define IPL_ALIGN_QWORD IPL_ALIGN_8BYTES + +#define IPL_BORDER_CONSTANT 0 +#define IPL_BORDER_REPLICATE 1 +#define IPL_BORDER_REFLECT 2 +#define IPL_BORDER_WRAP 3 + +/** The IplImage is taken from the Intel Image Processing Library, in which the format is native. OpenCV +only supports a subset of possible IplImage formats, as outlined in the parameter list above. + +In addition to the above restrictions, OpenCV handles ROIs differently. OpenCV functions require +that the image size or ROI size of all source and destination images match exactly. On the other +hand, the Intel Image Processing Library processes the area of intersection between the source and +destination images (or ROIs), allowing them to vary independently. +*/ +typedef struct +#ifdef __cplusplus + CV_EXPORTS +#endif +_IplImage +{ + int nSize; /**< sizeof(IplImage) */ + int ID; /**< version (=0)*/ + int nChannels; /**< Most of OpenCV functions support 1,2,3 or 4 channels */ + int alphaChannel; /**< Ignored by OpenCV */ + int depth; /**< Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S, + IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */ + char colorModel[4]; /**< Ignored by OpenCV */ + char channelSeq[4]; /**< ditto */ + int dataOrder; /**< 0 - interleaved color channels, 1 - separate color channels. + cvCreateImage can only create interleaved images */ + int origin; /**< 0 - top-left origin, + 1 - bottom-left origin (Windows bitmaps style). */ + int align; /**< Alignment of image rows (4 or 8). + OpenCV ignores it and uses widthStep instead. */ + int width; /**< Image width in pixels. */ + int height; /**< Image height in pixels. */ + struct _IplROI *roi; /**< Image ROI. If NULL, the whole image is selected. */ + struct _IplImage *maskROI; /**< Must be NULL. */ + void *imageId; /**< " " */ + struct _IplTileInfo *tileInfo; /**< " " */ + int imageSize; /**< Image data size in bytes + (==image->height*image->widthStep + in case of interleaved data)*/ + char *imageData; /**< Pointer to aligned image data. */ + int widthStep; /**< Size of aligned image row in bytes. */ + int BorderMode[4]; /**< Ignored by OpenCV. */ + int BorderConst[4]; /**< Ditto. */ + char *imageDataOrigin; /**< Pointer to very origin of image data + (not necessarily aligned) - + needed for correct deallocation */ + +#ifdef __cplusplus + _IplImage() {} + _IplImage(const cv::Mat& m); +#endif +} +IplImage; + +typedef struct _IplTileInfo IplTileInfo; + +typedef struct _IplROI +{ + int coi; /**< 0 - no COI (all channels are selected), 1 - 0th channel is selected ...*/ + int xOffset; + int yOffset; + int width; + int height; +} +IplROI; + +typedef struct _IplConvKernel +{ + int nCols; + int nRows; + int anchorX; + int anchorY; + int *values; + int nShiftR; +} +IplConvKernel; + +typedef struct _IplConvKernelFP +{ + int nCols; + int nRows; + int anchorX; + int anchorY; + float *values; +} +IplConvKernelFP; + +#define IPL_IMAGE_HEADER 1 +#define IPL_IMAGE_DATA 2 +#define IPL_IMAGE_ROI 4 + +#endif/*HAVE_IPL*/ + +/** extra border mode */ +#define IPL_BORDER_REFLECT_101 4 +#define IPL_BORDER_TRANSPARENT 5 + +#define IPL_IMAGE_MAGIC_VAL ((int)sizeof(IplImage)) +#define CV_TYPE_NAME_IMAGE "opencv-image" + +#define CV_IS_IMAGE_HDR(img) \ + ((img) != NULL && ((const IplImage*)(img))->nSize == sizeof(IplImage)) + +#define CV_IS_IMAGE(img) \ + (CV_IS_IMAGE_HDR(img) && ((IplImage*)img)->imageData != NULL) + +/** for storing double-precision + floating point data in IplImage's */ +#define IPL_DEPTH_64F 64 + +/** get reference to pixel at (col,row), + for multi-channel images (col) should be multiplied by number of channels */ +#define CV_IMAGE_ELEM( image, elemtype, row, col ) \ + (((elemtype*)((image)->imageData + (image)->widthStep*(row)))[(col)]) + +/****************************************************************************************\ +* Matrix type (CvMat) * +\****************************************************************************************/ + +#define CV_AUTO_STEP 0x7fffffff +#define CV_WHOLE_ARR cvSlice( 0, 0x3fffffff ) + +#define CV_MAGIC_MASK 0xFFFF0000 +#define CV_MAT_MAGIC_VAL 0x42420000 +#define CV_TYPE_NAME_MAT "opencv-matrix" + +/** Matrix elements are stored row by row. Element (i, j) (i - 0-based row index, j - 0-based column +index) of a matrix can be retrieved or modified using CV_MAT_ELEM macro: + + uchar pixval = CV_MAT_ELEM(grayimg, uchar, i, j) + CV_MAT_ELEM(cameraMatrix, float, 0, 2) = image.width*0.5f; + +To access multiple-channel matrices, you can use +CV_MAT_ELEM(matrix, type, i, j\*nchannels + channel_idx). + +@deprecated CvMat is now obsolete; consider using Mat instead. + */ +typedef struct CvMat +{ + int type; + int step; + + /* for internal use only */ + int* refcount; + int hdr_refcount; + + union + { + uchar* ptr; + short* s; + int* i; + float* fl; + double* db; + } data; + +#ifdef __cplusplus + union + { + int rows; + int height; + }; + + union + { + int cols; + int width; + }; +#else + int rows; + int cols; +#endif + + +#ifdef __cplusplus + CvMat() {} + CvMat(const CvMat& m) { memcpy(this, &m, sizeof(CvMat));} + CvMat(const cv::Mat& m); +#endif + +} +CvMat; + + +#define CV_IS_MAT_HDR(mat) \ + ((mat) != NULL && \ + (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \ + ((const CvMat*)(mat))->cols > 0 && ((const CvMat*)(mat))->rows > 0) + +#define CV_IS_MAT_HDR_Z(mat) \ + ((mat) != NULL && \ + (((const CvMat*)(mat))->type & CV_MAGIC_MASK) == CV_MAT_MAGIC_VAL && \ + ((const CvMat*)(mat))->cols >= 0 && ((const CvMat*)(mat))->rows >= 0) + +#define CV_IS_MAT(mat) \ + (CV_IS_MAT_HDR(mat) && ((const CvMat*)(mat))->data.ptr != NULL) + +#define CV_IS_MASK_ARR(mat) \ + (((mat)->type & (CV_MAT_TYPE_MASK & ~CV_8SC1)) == 0) + +#define CV_ARE_TYPES_EQ(mat1, mat2) \ + ((((mat1)->type ^ (mat2)->type) & CV_MAT_TYPE_MASK) == 0) + +#define CV_ARE_CNS_EQ(mat1, mat2) \ + ((((mat1)->type ^ (mat2)->type) & CV_MAT_CN_MASK) == 0) + +#define CV_ARE_DEPTHS_EQ(mat1, mat2) \ + ((((mat1)->type ^ (mat2)->type) & CV_MAT_DEPTH_MASK) == 0) + +#define CV_ARE_SIZES_EQ(mat1, mat2) \ + ((mat1)->rows == (mat2)->rows && (mat1)->cols == (mat2)->cols) + +#define CV_IS_MAT_CONST(mat) \ + (((mat)->rows|(mat)->cols) == 1) + +#define IPL2CV_DEPTH(depth) \ + ((((CV_8U)+(CV_16U<<4)+(CV_32F<<8)+(CV_64F<<16)+(CV_8S<<20)+ \ + (CV_16S<<24)+(CV_32S<<28)) >> ((((depth) & 0xF0) >> 2) + \ + (((depth) & IPL_DEPTH_SIGN) ? 20 : 0))) & 15) + +/** Inline constructor. No data is allocated internally!!! + * (Use together with cvCreateData, or use cvCreateMat instead to + * get a matrix with allocated data): + */ +CV_INLINE CvMat cvMat( int rows, int cols, int type, void* data CV_DEFAULT(NULL)) +{ + CvMat m; + + assert( (unsigned)CV_MAT_DEPTH(type) <= CV_64F ); + type = CV_MAT_TYPE(type); + m.type = CV_MAT_MAGIC_VAL | CV_MAT_CONT_FLAG | type; + m.cols = cols; + m.rows = rows; + m.step = m.cols*CV_ELEM_SIZE(type); + m.data.ptr = (uchar*)data; + m.refcount = NULL; + m.hdr_refcount = 0; + + return m; +} + +#ifdef __cplusplus +inline CvMat::CvMat(const cv::Mat& m) +{ + CV_DbgAssert(m.dims <= 2); + *this = cvMat(m.rows, m.dims == 1 ? 1 : m.cols, m.type(), m.data); + step = (int)m.step[0]; + type = (type & ~cv::Mat::CONTINUOUS_FLAG) | (m.flags & cv::Mat::CONTINUOUS_FLAG); +} +#endif + + +#define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size ) \ + (assert( (unsigned)(row) < (unsigned)(mat).rows && \ + (unsigned)(col) < (unsigned)(mat).cols ), \ + (mat).data.ptr + (size_t)(mat).step*(row) + (pix_size)*(col)) + +#define CV_MAT_ELEM_PTR( mat, row, col ) \ + CV_MAT_ELEM_PTR_FAST( mat, row, col, CV_ELEM_SIZE((mat).type) ) + +#define CV_MAT_ELEM( mat, elemtype, row, col ) \ + (*(elemtype*)CV_MAT_ELEM_PTR_FAST( mat, row, col, sizeof(elemtype))) + +/** @brief Returns the particular element of single-channel floating-point matrix. + +The function is a fast replacement for cvGetReal2D in the case of single-channel floating-point +matrices. It is faster because it is inline, it does fewer checks for array type and array element +type, and it checks for the row and column ranges only in debug mode. +@param mat Input matrix +@param row The zero-based index of row +@param col The zero-based index of column + */ +CV_INLINE double cvmGet( const CvMat* mat, int row, int col ) +{ + int type; + + type = CV_MAT_TYPE(mat->type); + assert( (unsigned)row < (unsigned)mat->rows && + (unsigned)col < (unsigned)mat->cols ); + + if( type == CV_32FC1 ) + return ((float*)(void*)(mat->data.ptr + (size_t)mat->step*row))[col]; + else + { + assert( type == CV_64FC1 ); + return ((double*)(void*)(mat->data.ptr + (size_t)mat->step*row))[col]; + } +} + +/** @brief Sets a specific element of a single-channel floating-point matrix. + +The function is a fast replacement for cvSetReal2D in the case of single-channel floating-point +matrices. It is faster because it is inline, it does fewer checks for array type and array element +type, and it checks for the row and column ranges only in debug mode. +@param mat The matrix +@param row The zero-based index of row +@param col The zero-based index of column +@param value The new value of the matrix element + */ +CV_INLINE void cvmSet( CvMat* mat, int row, int col, double value ) +{ + int type; + type = CV_MAT_TYPE(mat->type); + assert( (unsigned)row < (unsigned)mat->rows && + (unsigned)col < (unsigned)mat->cols ); + + if( type == CV_32FC1 ) + ((float*)(void*)(mat->data.ptr + (size_t)mat->step*row))[col] = (float)value; + else + { + assert( type == CV_64FC1 ); + ((double*)(void*)(mat->data.ptr + (size_t)mat->step*row))[col] = value; + } +} + + +CV_INLINE int cvIplDepth( int type ) +{ + int depth = CV_MAT_DEPTH(type); + return CV_ELEM_SIZE1(depth)*8 | (depth == CV_8S || depth == CV_16S || + depth == CV_32S ? IPL_DEPTH_SIGN : 0); +} + + +/****************************************************************************************\ +* Multi-dimensional dense array (CvMatND) * +\****************************************************************************************/ + +#define CV_MATND_MAGIC_VAL 0x42430000 +#define CV_TYPE_NAME_MATND "opencv-nd-matrix" + +#define CV_MAX_DIM 32 +#define CV_MAX_DIM_HEAP 1024 + +/** + @deprecated consider using cv::Mat instead + */ +typedef struct +#ifdef __cplusplus + CV_EXPORTS +#endif +CvMatND +{ + int type; + int dims; + + int* refcount; + int hdr_refcount; + + union + { + uchar* ptr; + float* fl; + double* db; + int* i; + short* s; + } data; + + struct + { + int size; + int step; + } + dim[CV_MAX_DIM]; + +#ifdef __cplusplus + CvMatND() {} + CvMatND(const cv::Mat& m); +#endif +} +CvMatND; + +#define CV_IS_MATND_HDR(mat) \ + ((mat) != NULL && (((const CvMatND*)(mat))->type & CV_MAGIC_MASK) == CV_MATND_MAGIC_VAL) + +#define CV_IS_MATND(mat) \ + (CV_IS_MATND_HDR(mat) && ((const CvMatND*)(mat))->data.ptr != NULL) + + +/****************************************************************************************\ +* Multi-dimensional sparse array (CvSparseMat) * +\****************************************************************************************/ + +#define CV_SPARSE_MAT_MAGIC_VAL 0x42440000 +#define CV_TYPE_NAME_SPARSE_MAT "opencv-sparse-matrix" + +struct CvSet; + +typedef struct +#ifdef __cplusplus + CV_EXPORTS +#endif +CvSparseMat +{ + int type; + int dims; + int* refcount; + int hdr_refcount; + + struct CvSet* heap; + void** hashtable; + int hashsize; + int valoffset; + int idxoffset; + int size[CV_MAX_DIM]; + +#ifdef __cplusplus + void copyToSparseMat(cv::SparseMat& m) const; +#endif +} +CvSparseMat; + +#ifdef __cplusplus + CV_EXPORTS CvSparseMat* cvCreateSparseMat(const cv::SparseMat& m); +#endif + +#define CV_IS_SPARSE_MAT_HDR(mat) \ + ((mat) != NULL && \ + (((const CvSparseMat*)(mat))->type & CV_MAGIC_MASK) == CV_SPARSE_MAT_MAGIC_VAL) + +#define CV_IS_SPARSE_MAT(mat) \ + CV_IS_SPARSE_MAT_HDR(mat) + +/**************** iteration through a sparse array *****************/ + +typedef struct CvSparseNode +{ + unsigned hashval; + struct CvSparseNode* next; +} +CvSparseNode; + +typedef struct CvSparseMatIterator +{ + CvSparseMat* mat; + CvSparseNode* node; + int curidx; +} +CvSparseMatIterator; + +#define CV_NODE_VAL(mat,node) ((void*)((uchar*)(node) + (mat)->valoffset)) +#define CV_NODE_IDX(mat,node) ((int*)((uchar*)(node) + (mat)->idxoffset)) + +/****************************************************************************************\ +* Histogram * +\****************************************************************************************/ + +typedef int CvHistType; + +#define CV_HIST_MAGIC_VAL 0x42450000 +#define CV_HIST_UNIFORM_FLAG (1 << 10) + +/** indicates whether bin ranges are set already or not */ +#define CV_HIST_RANGES_FLAG (1 << 11) + +#define CV_HIST_ARRAY 0 +#define CV_HIST_SPARSE 1 +#define CV_HIST_TREE CV_HIST_SPARSE + +/** should be used as a parameter only, + it turns to CV_HIST_UNIFORM_FLAG of hist->type */ +#define CV_HIST_UNIFORM 1 + +typedef struct CvHistogram +{ + int type; + CvArr* bins; + float thresh[CV_MAX_DIM][2]; /**< For uniform histograms. */ + float** thresh2; /**< For non-uniform histograms. */ + CvMatND mat; /**< Embedded matrix header for array histograms. */ +} +CvHistogram; + +#define CV_IS_HIST( hist ) \ + ((hist) != NULL && \ + (((CvHistogram*)(hist))->type & CV_MAGIC_MASK) == CV_HIST_MAGIC_VAL && \ + (hist)->bins != NULL) + +#define CV_IS_UNIFORM_HIST( hist ) \ + (((hist)->type & CV_HIST_UNIFORM_FLAG) != 0) + +#define CV_IS_SPARSE_HIST( hist ) \ + CV_IS_SPARSE_MAT((hist)->bins) + +#define CV_HIST_HAS_RANGES( hist ) \ + (((hist)->type & CV_HIST_RANGES_FLAG) != 0) + +/****************************************************************************************\ +* Other supplementary data type definitions * +\****************************************************************************************/ + +/*************************************** CvRect *****************************************/ +/** @sa Rect_ */ +typedef struct CvRect +{ + int x; + int y; + int width; + int height; + +#ifdef __cplusplus + CvRect(int _x = 0, int _y = 0, int w = 0, int h = 0): x(_x), y(_y), width(w), height(h) {} + template + CvRect(const cv::Rect_<_Tp>& r): x(cv::saturate_cast(r.x)), y(cv::saturate_cast(r.y)), width(cv::saturate_cast(r.width)), height(cv::saturate_cast(r.height)) {} + template + operator cv::Rect_<_Tp>() const { return cv::Rect_<_Tp>((_Tp)x, (_Tp)y, (_Tp)width, (_Tp)height); } +#endif +} +CvRect; + +/** constructs CvRect structure. */ +CV_INLINE CvRect cvRect( int x, int y, int width, int height ) +{ + CvRect r; + + r.x = x; + r.y = y; + r.width = width; + r.height = height; + + return r; +} + + +CV_INLINE IplROI cvRectToROI( CvRect rect, int coi ) +{ + IplROI roi; + roi.xOffset = rect.x; + roi.yOffset = rect.y; + roi.width = rect.width; + roi.height = rect.height; + roi.coi = coi; + + return roi; +} + + +CV_INLINE CvRect cvROIToRect( IplROI roi ) +{ + return cvRect( roi.xOffset, roi.yOffset, roi.width, roi.height ); +} + +/*********************************** CvTermCriteria *************************************/ + +#define CV_TERMCRIT_ITER 1 +#define CV_TERMCRIT_NUMBER CV_TERMCRIT_ITER +#define CV_TERMCRIT_EPS 2 + +/** @sa TermCriteria + */ +typedef struct CvTermCriteria +{ + int type; /**< may be combination of + CV_TERMCRIT_ITER + CV_TERMCRIT_EPS */ + int max_iter; + double epsilon; + +#ifdef __cplusplus + CvTermCriteria(int _type = 0, int _iter = 0, double _eps = 0) : type(_type), max_iter(_iter), epsilon(_eps) {} + CvTermCriteria(const cv::TermCriteria& t) : type(t.type), max_iter(t.maxCount), epsilon(t.epsilon) {} + operator cv::TermCriteria() const { return cv::TermCriteria(type, max_iter, epsilon); } +#endif + +} +CvTermCriteria; + +CV_INLINE CvTermCriteria cvTermCriteria( int type, int max_iter, double epsilon ) +{ + CvTermCriteria t; + + t.type = type; + t.max_iter = max_iter; + t.epsilon = (float)epsilon; + + return t; +} + + +/******************************* CvPoint and variants ***********************************/ + +typedef struct CvPoint +{ + int x; + int y; + +#ifdef __cplusplus + CvPoint(int _x = 0, int _y = 0): x(_x), y(_y) {} + template + CvPoint(const cv::Point_<_Tp>& pt): x((int)pt.x), y((int)pt.y) {} + template + operator cv::Point_<_Tp>() const { return cv::Point_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y)); } +#endif +} +CvPoint; + +/** constructs CvPoint structure. */ +CV_INLINE CvPoint cvPoint( int x, int y ) +{ + CvPoint p; + + p.x = x; + p.y = y; + + return p; +} + + +typedef struct CvPoint2D32f +{ + float x; + float y; + +#ifdef __cplusplus + CvPoint2D32f(float _x = 0, float _y = 0): x(_x), y(_y) {} + template + CvPoint2D32f(const cv::Point_<_Tp>& pt): x((float)pt.x), y((float)pt.y) {} + template + operator cv::Point_<_Tp>() const { return cv::Point_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y)); } +#endif +} +CvPoint2D32f; + +/** constructs CvPoint2D32f structure. */ +CV_INLINE CvPoint2D32f cvPoint2D32f( double x, double y ) +{ + CvPoint2D32f p; + + p.x = (float)x; + p.y = (float)y; + + return p; +} + +/** converts CvPoint to CvPoint2D32f. */ +CV_INLINE CvPoint2D32f cvPointTo32f( CvPoint point ) +{ + return cvPoint2D32f( (float)point.x, (float)point.y ); +} + +/** converts CvPoint2D32f to CvPoint. */ +CV_INLINE CvPoint cvPointFrom32f( CvPoint2D32f point ) +{ + CvPoint ipt; + ipt.x = cvRound(point.x); + ipt.y = cvRound(point.y); + + return ipt; +} + + +typedef struct CvPoint3D32f +{ + float x; + float y; + float z; + +#ifdef __cplusplus + CvPoint3D32f(float _x = 0, float _y = 0, float _z = 0): x(_x), y(_y), z(_z) {} + template + CvPoint3D32f(const cv::Point3_<_Tp>& pt): x((float)pt.x), y((float)pt.y), z((float)pt.z) {} + template + operator cv::Point3_<_Tp>() const { return cv::Point3_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y), cv::saturate_cast<_Tp>(z)); } +#endif +} +CvPoint3D32f; + +/** constructs CvPoint3D32f structure. */ +CV_INLINE CvPoint3D32f cvPoint3D32f( double x, double y, double z ) +{ + CvPoint3D32f p; + + p.x = (float)x; + p.y = (float)y; + p.z = (float)z; + + return p; +} + + +typedef struct CvPoint2D64f +{ + double x; + double y; +} +CvPoint2D64f; + +/** constructs CvPoint2D64f structure.*/ +CV_INLINE CvPoint2D64f cvPoint2D64f( double x, double y ) +{ + CvPoint2D64f p; + + p.x = x; + p.y = y; + + return p; +} + + +typedef struct CvPoint3D64f +{ + double x; + double y; + double z; +} +CvPoint3D64f; + +/** constructs CvPoint3D64f structure. */ +CV_INLINE CvPoint3D64f cvPoint3D64f( double x, double y, double z ) +{ + CvPoint3D64f p; + + p.x = x; + p.y = y; + p.z = z; + + return p; +} + + +/******************************** CvSize's & CvBox **************************************/ + +typedef struct CvSize +{ + int width; + int height; + +#ifdef __cplusplus + CvSize(int w = 0, int h = 0): width(w), height(h) {} + template + CvSize(const cv::Size_<_Tp>& sz): width(cv::saturate_cast(sz.width)), height(cv::saturate_cast(sz.height)) {} + template + operator cv::Size_<_Tp>() const { return cv::Size_<_Tp>(cv::saturate_cast<_Tp>(width), cv::saturate_cast<_Tp>(height)); } +#endif +} +CvSize; + +/** constructs CvSize structure. */ +CV_INLINE CvSize cvSize( int width, int height ) +{ + CvSize s; + + s.width = width; + s.height = height; + + return s; +} + +typedef struct CvSize2D32f +{ + float width; + float height; + +#ifdef __cplusplus + CvSize2D32f(float w = 0, float h = 0): width(w), height(h) {} + template + CvSize2D32f(const cv::Size_<_Tp>& sz): width(cv::saturate_cast(sz.width)), height(cv::saturate_cast(sz.height)) {} + template + operator cv::Size_<_Tp>() const { return cv::Size_<_Tp>(cv::saturate_cast<_Tp>(width), cv::saturate_cast<_Tp>(height)); } +#endif +} +CvSize2D32f; + +/** constructs CvSize2D32f structure. */ +CV_INLINE CvSize2D32f cvSize2D32f( double width, double height ) +{ + CvSize2D32f s; + + s.width = (float)width; + s.height = (float)height; + + return s; +} + +/** @sa RotatedRect + */ +typedef struct CvBox2D +{ + CvPoint2D32f center; /**< Center of the box. */ + CvSize2D32f size; /**< Box width and length. */ + float angle; /**< Angle between the horizontal axis */ + /**< and the first side (i.e. length) in degrees */ + +#ifdef __cplusplus + CvBox2D(CvPoint2D32f c = CvPoint2D32f(), CvSize2D32f s = CvSize2D32f(), float a = 0) : center(c), size(s), angle(a) {} + CvBox2D(const cv::RotatedRect& rr) : center(rr.center), size(rr.size), angle(rr.angle) {} + operator cv::RotatedRect() const { return cv::RotatedRect(center, size, angle); } +#endif +} +CvBox2D; + + +/** Line iterator state: */ +typedef struct CvLineIterator +{ + /** Pointer to the current point: */ + uchar* ptr; + + /* Bresenham algorithm state: */ + int err; + int plus_delta; + int minus_delta; + int plus_step; + int minus_step; +} +CvLineIterator; + + + +/************************************* CvSlice ******************************************/ +#define CV_WHOLE_SEQ_END_INDEX 0x3fffffff +#define CV_WHOLE_SEQ cvSlice(0, CV_WHOLE_SEQ_END_INDEX) + +typedef struct CvSlice +{ + int start_index, end_index; + +#if defined(__cplusplus) && !defined(__CUDACC__) + CvSlice(int start = 0, int end = 0) : start_index(start), end_index(end) {} + CvSlice(const cv::Range& r) { *this = (r.start != INT_MIN && r.end != INT_MAX) ? CvSlice(r.start, r.end) : CvSlice(0, CV_WHOLE_SEQ_END_INDEX); } + operator cv::Range() const { return (start_index == 0 && end_index == CV_WHOLE_SEQ_END_INDEX ) ? cv::Range::all() : cv::Range(start_index, end_index); } +#endif +} +CvSlice; + +CV_INLINE CvSlice cvSlice( int start, int end ) +{ + CvSlice slice; + slice.start_index = start; + slice.end_index = end; + + return slice; +} + + + +/************************************* CvScalar *****************************************/ +/** @sa Scalar_ + */ +typedef struct CvScalar +{ + double val[4]; + +#ifdef __cplusplus + CvScalar() {} + CvScalar(double d0, double d1 = 0, double d2 = 0, double d3 = 0) { val[0] = d0; val[1] = d1; val[2] = d2; val[3] = d3; } + template + CvScalar(const cv::Scalar_<_Tp>& s) { val[0] = s.val[0]; val[1] = s.val[1]; val[2] = s.val[2]; val[3] = s.val[3]; } + template + operator cv::Scalar_<_Tp>() const { return cv::Scalar_<_Tp>(cv::saturate_cast<_Tp>(val[0]), cv::saturate_cast<_Tp>(val[1]), cv::saturate_cast<_Tp>(val[2]), cv::saturate_cast<_Tp>(val[3])); } + template + CvScalar(const cv::Vec<_Tp, cn>& v) + { + int i; + for( i = 0; i < (cn < 4 ? cn : 4); i++ ) val[i] = v.val[i]; + for( ; i < 4; i++ ) val[i] = 0; + } +#endif +} +CvScalar; + +CV_INLINE CvScalar cvScalar( double val0, double val1 CV_DEFAULT(0), + double val2 CV_DEFAULT(0), double val3 CV_DEFAULT(0)) +{ + CvScalar scalar; + scalar.val[0] = val0; scalar.val[1] = val1; + scalar.val[2] = val2; scalar.val[3] = val3; + return scalar; +} + + +CV_INLINE CvScalar cvRealScalar( double val0 ) +{ + CvScalar scalar; + scalar.val[0] = val0; + scalar.val[1] = scalar.val[2] = scalar.val[3] = 0; + return scalar; +} + +CV_INLINE CvScalar cvScalarAll( double val0123 ) +{ + CvScalar scalar; + scalar.val[0] = val0123; + scalar.val[1] = val0123; + scalar.val[2] = val0123; + scalar.val[3] = val0123; + return scalar; +} + +/****************************************************************************************\ +* Dynamic Data structures * +\****************************************************************************************/ + +/******************************** Memory storage ****************************************/ + +typedef struct CvMemBlock +{ + struct CvMemBlock* prev; + struct CvMemBlock* next; +} +CvMemBlock; + +#define CV_STORAGE_MAGIC_VAL 0x42890000 + +typedef struct CvMemStorage +{ + int signature; + CvMemBlock* bottom; /**< First allocated block. */ + CvMemBlock* top; /**< Current memory block - top of the stack. */ + struct CvMemStorage* parent; /**< We get new blocks from parent as needed. */ + int block_size; /**< Block size. */ + int free_space; /**< Remaining free space in current block. */ +} +CvMemStorage; + +#define CV_IS_STORAGE(storage) \ + ((storage) != NULL && \ + (((CvMemStorage*)(storage))->signature & CV_MAGIC_MASK) == CV_STORAGE_MAGIC_VAL) + + +typedef struct CvMemStoragePos +{ + CvMemBlock* top; + int free_space; +} +CvMemStoragePos; + + +/*********************************** Sequence *******************************************/ + +typedef struct CvSeqBlock +{ + struct CvSeqBlock* prev; /**< Previous sequence block. */ + struct CvSeqBlock* next; /**< Next sequence block. */ + int start_index; /**< Index of the first element in the block + */ + /**< sequence->first->start_index. */ + int count; /**< Number of elements in the block. */ + schar* data; /**< Pointer to the first element of the block. */ +} +CvSeqBlock; + + +#define CV_TREE_NODE_FIELDS(node_type) \ + int flags; /**< Miscellaneous flags. */ \ + int header_size; /**< Size of sequence header. */ \ + struct node_type* h_prev; /**< Previous sequence. */ \ + struct node_type* h_next; /**< Next sequence. */ \ + struct node_type* v_prev; /**< 2nd previous sequence. */ \ + struct node_type* v_next /**< 2nd next sequence. */ + +/** + Read/Write sequence. + Elements can be dynamically inserted to or deleted from the sequence. +*/ +#define CV_SEQUENCE_FIELDS() \ + CV_TREE_NODE_FIELDS(CvSeq); \ + int total; /**< Total number of elements. */ \ + int elem_size; /**< Size of sequence element in bytes. */ \ + schar* block_max; /**< Maximal bound of the last block. */ \ + schar* ptr; /**< Current write pointer. */ \ + int delta_elems; /**< Grow seq this many at a time. */ \ + CvMemStorage* storage; /**< Where the seq is stored. */ \ + CvSeqBlock* free_blocks; /**< Free blocks list. */ \ + CvSeqBlock* first; /**< Pointer to the first sequence block. */ + +typedef struct CvSeq +{ + CV_SEQUENCE_FIELDS() +} +CvSeq; + +#define CV_TYPE_NAME_SEQ "opencv-sequence" +#define CV_TYPE_NAME_SEQ_TREE "opencv-sequence-tree" + +/*************************************** Set ********************************************/ +/** @brief Set + Order is not preserved. There can be gaps between sequence elements. + After the element has been inserted it stays in the same place all the time. + The MSB(most-significant or sign bit) of the first field (flags) is 0 iff the element exists. +*/ +#define CV_SET_ELEM_FIELDS(elem_type) \ + int flags; \ + struct elem_type* next_free; + +typedef struct CvSetElem +{ + CV_SET_ELEM_FIELDS(CvSetElem) +} +CvSetElem; + +#define CV_SET_FIELDS() \ + CV_SEQUENCE_FIELDS() \ + CvSetElem* free_elems; \ + int active_count; + +typedef struct CvSet +{ + CV_SET_FIELDS() +} +CvSet; + + +#define CV_SET_ELEM_IDX_MASK ((1 << 26) - 1) +#define CV_SET_ELEM_FREE_FLAG (1 << (sizeof(int)*8-1)) + +/** Checks whether the element pointed by ptr belongs to a set or not */ +#define CV_IS_SET_ELEM( ptr ) (((CvSetElem*)(ptr))->flags >= 0) + +/************************************* Graph ********************************************/ + +/** @name Graph + +We represent a graph as a set of vertices. Vertices contain their adjacency lists (more exactly, +pointers to first incoming or outcoming edge (or 0 if isolated vertex)). Edges are stored in +another set. There is a singly-linked list of incoming/outcoming edges for each vertex. + +Each edge consists of: + +- Two pointers to the starting and ending vertices (vtx[0] and vtx[1] respectively). + + A graph may be oriented or not. In the latter case, edges between vertex i to vertex j are not +distinguished during search operations. + +- Two pointers to next edges for the starting and ending vertices, where next[0] points to the +next edge in the vtx[0] adjacency list and next[1] points to the next edge in the vtx[1] +adjacency list. + +@see CvGraphEdge, CvGraphVtx, CvGraphVtx2D, CvGraph +@{ +*/ +#define CV_GRAPH_EDGE_FIELDS() \ + int flags; \ + float weight; \ + struct CvGraphEdge* next[2]; \ + struct CvGraphVtx* vtx[2]; + + +#define CV_GRAPH_VERTEX_FIELDS() \ + int flags; \ + struct CvGraphEdge* first; + + +typedef struct CvGraphEdge +{ + CV_GRAPH_EDGE_FIELDS() +} +CvGraphEdge; + +typedef struct CvGraphVtx +{ + CV_GRAPH_VERTEX_FIELDS() +} +CvGraphVtx; + +typedef struct CvGraphVtx2D +{ + CV_GRAPH_VERTEX_FIELDS() + CvPoint2D32f* ptr; +} +CvGraphVtx2D; + +/** + Graph is "derived" from the set (this is set a of vertices) + and includes another set (edges) +*/ +#define CV_GRAPH_FIELDS() \ + CV_SET_FIELDS() \ + CvSet* edges; + +typedef struct CvGraph +{ + CV_GRAPH_FIELDS() +} +CvGraph; + +#define CV_TYPE_NAME_GRAPH "opencv-graph" + +/** @} */ + +/*********************************** Chain/Countour *************************************/ + +typedef struct CvChain +{ + CV_SEQUENCE_FIELDS() + CvPoint origin; +} +CvChain; + +#define CV_CONTOUR_FIELDS() \ + CV_SEQUENCE_FIELDS() \ + CvRect rect; \ + int color; \ + int reserved[3]; + +typedef struct CvContour +{ + CV_CONTOUR_FIELDS() +} +CvContour; + +typedef CvContour CvPoint2DSeq; + +/****************************************************************************************\ +* Sequence types * +\****************************************************************************************/ + +#define CV_SEQ_MAGIC_VAL 0x42990000 + +#define CV_IS_SEQ(seq) \ + ((seq) != NULL && (((CvSeq*)(seq))->flags & CV_MAGIC_MASK) == CV_SEQ_MAGIC_VAL) + +#define CV_SET_MAGIC_VAL 0x42980000 +#define CV_IS_SET(set) \ + ((set) != NULL && (((CvSeq*)(set))->flags & CV_MAGIC_MASK) == CV_SET_MAGIC_VAL) + +#define CV_SEQ_ELTYPE_BITS 12 +#define CV_SEQ_ELTYPE_MASK ((1 << CV_SEQ_ELTYPE_BITS) - 1) + +#define CV_SEQ_ELTYPE_POINT CV_32SC2 /**< (x,y) */ +#define CV_SEQ_ELTYPE_CODE CV_8UC1 /**< freeman code: 0..7 */ +#define CV_SEQ_ELTYPE_GENERIC 0 +#define CV_SEQ_ELTYPE_PTR CV_USRTYPE1 +#define CV_SEQ_ELTYPE_PPOINT CV_SEQ_ELTYPE_PTR /**< &(x,y) */ +#define CV_SEQ_ELTYPE_INDEX CV_32SC1 /**< #(x,y) */ +#define CV_SEQ_ELTYPE_GRAPH_EDGE 0 /**< &next_o, &next_d, &vtx_o, &vtx_d */ +#define CV_SEQ_ELTYPE_GRAPH_VERTEX 0 /**< first_edge, &(x,y) */ +#define CV_SEQ_ELTYPE_TRIAN_ATR 0 /**< vertex of the binary tree */ +#define CV_SEQ_ELTYPE_CONNECTED_COMP 0 /**< connected component */ +#define CV_SEQ_ELTYPE_POINT3D CV_32FC3 /**< (x,y,z) */ + +#define CV_SEQ_KIND_BITS 2 +#define CV_SEQ_KIND_MASK (((1 << CV_SEQ_KIND_BITS) - 1)<flags & CV_SEQ_ELTYPE_MASK) +#define CV_SEQ_KIND( seq ) ((seq)->flags & CV_SEQ_KIND_MASK ) + +/** flag checking */ +#define CV_IS_SEQ_INDEX( seq ) ((CV_SEQ_ELTYPE(seq) == CV_SEQ_ELTYPE_INDEX) && \ + (CV_SEQ_KIND(seq) == CV_SEQ_KIND_GENERIC)) + +#define CV_IS_SEQ_CURVE( seq ) (CV_SEQ_KIND(seq) == CV_SEQ_KIND_CURVE) +#define CV_IS_SEQ_CLOSED( seq ) (((seq)->flags & CV_SEQ_FLAG_CLOSED) != 0) +#define CV_IS_SEQ_CONVEX( seq ) 0 +#define CV_IS_SEQ_HOLE( seq ) (((seq)->flags & CV_SEQ_FLAG_HOLE) != 0) +#define CV_IS_SEQ_SIMPLE( seq ) 1 + +/** type checking macros */ +#define CV_IS_SEQ_POINT_SET( seq ) \ + ((CV_SEQ_ELTYPE(seq) == CV_32SC2 || CV_SEQ_ELTYPE(seq) == CV_32FC2)) + +#define CV_IS_SEQ_POINT_SUBSET( seq ) \ + (CV_IS_SEQ_INDEX( seq ) || CV_SEQ_ELTYPE(seq) == CV_SEQ_ELTYPE_PPOINT) + +#define CV_IS_SEQ_POLYLINE( seq ) \ + (CV_SEQ_KIND(seq) == CV_SEQ_KIND_CURVE && CV_IS_SEQ_POINT_SET(seq)) + +#define CV_IS_SEQ_POLYGON( seq ) \ + (CV_IS_SEQ_POLYLINE(seq) && CV_IS_SEQ_CLOSED(seq)) + +#define CV_IS_SEQ_CHAIN( seq ) \ + (CV_SEQ_KIND(seq) == CV_SEQ_KIND_CURVE && (seq)->elem_size == 1) + +#define CV_IS_SEQ_CONTOUR( seq ) \ + (CV_IS_SEQ_CLOSED(seq) && (CV_IS_SEQ_POLYLINE(seq) || CV_IS_SEQ_CHAIN(seq))) + +#define CV_IS_SEQ_CHAIN_CONTOUR( seq ) \ + (CV_IS_SEQ_CHAIN( seq ) && CV_IS_SEQ_CLOSED( seq )) + +#define CV_IS_SEQ_POLYGON_TREE( seq ) \ + (CV_SEQ_ELTYPE (seq) == CV_SEQ_ELTYPE_TRIAN_ATR && \ + CV_SEQ_KIND( seq ) == CV_SEQ_KIND_BIN_TREE ) + +#define CV_IS_GRAPH( seq ) \ + (CV_IS_SET(seq) && CV_SEQ_KIND((CvSet*)(seq)) == CV_SEQ_KIND_GRAPH) + +#define CV_IS_GRAPH_ORIENTED( seq ) \ + (((seq)->flags & CV_GRAPH_FLAG_ORIENTED) != 0) + +#define CV_IS_SUBDIV2D( seq ) \ + (CV_IS_SET(seq) && CV_SEQ_KIND((CvSet*)(seq)) == CV_SEQ_KIND_SUBDIV2D) + +/****************************************************************************************/ +/* Sequence writer & reader */ +/****************************************************************************************/ + +#define CV_SEQ_WRITER_FIELDS() \ + int header_size; \ + CvSeq* seq; /**< the sequence written */ \ + CvSeqBlock* block; /**< current block */ \ + schar* ptr; /**< pointer to free space */ \ + schar* block_min; /**< pointer to the beginning of block*/\ + schar* block_max; /**< pointer to the end of block */ + +typedef struct CvSeqWriter +{ + CV_SEQ_WRITER_FIELDS() +} +CvSeqWriter; + + +#define CV_SEQ_READER_FIELDS() \ + int header_size; \ + CvSeq* seq; /**< sequence, beign read */ \ + CvSeqBlock* block; /**< current block */ \ + schar* ptr; /**< pointer to element be read next */ \ + schar* block_min; /**< pointer to the beginning of block */\ + schar* block_max; /**< pointer to the end of block */ \ + int delta_index;/**< = seq->first->start_index */ \ + schar* prev_elem; /**< pointer to previous element */ + +typedef struct CvSeqReader +{ + CV_SEQ_READER_FIELDS() +} +CvSeqReader; + +/****************************************************************************************/ +/* Operations on sequences */ +/****************************************************************************************/ + +#define CV_SEQ_ELEM( seq, elem_type, index ) \ +/** assert gives some guarantee that parameter is valid */ \ +( assert(sizeof((seq)->first[0]) == sizeof(CvSeqBlock) && \ + (seq)->elem_size == sizeof(elem_type)), \ + (elem_type*)((seq)->first && (unsigned)index < \ + (unsigned)((seq)->first->count) ? \ + (seq)->first->data + (index) * sizeof(elem_type) : \ + cvGetSeqElem( (CvSeq*)(seq), (index) ))) +#define CV_GET_SEQ_ELEM( elem_type, seq, index ) CV_SEQ_ELEM( (seq), elem_type, (index) ) + +/** Add element to sequence: */ +#define CV_WRITE_SEQ_ELEM_VAR( elem_ptr, writer ) \ +{ \ + if( (writer).ptr >= (writer).block_max ) \ + { \ + cvCreateSeqBlock( &writer); \ + } \ + memcpy((writer).ptr, elem_ptr, (writer).seq->elem_size);\ + (writer).ptr += (writer).seq->elem_size; \ +} + +#define CV_WRITE_SEQ_ELEM( elem, writer ) \ +{ \ + assert( (writer).seq->elem_size == sizeof(elem)); \ + if( (writer).ptr >= (writer).block_max ) \ + { \ + cvCreateSeqBlock( &writer); \ + } \ + assert( (writer).ptr <= (writer).block_max - sizeof(elem));\ + memcpy((writer).ptr, &(elem), sizeof(elem)); \ + (writer).ptr += sizeof(elem); \ +} + + +/** Move reader position forward: */ +#define CV_NEXT_SEQ_ELEM( elem_size, reader ) \ +{ \ + if( ((reader).ptr += (elem_size)) >= (reader).block_max ) \ + { \ + cvChangeSeqBlock( &(reader), 1 ); \ + } \ +} + + +/** Move reader position backward: */ +#define CV_PREV_SEQ_ELEM( elem_size, reader ) \ +{ \ + if( ((reader).ptr -= (elem_size)) < (reader).block_min ) \ + { \ + cvChangeSeqBlock( &(reader), -1 ); \ + } \ +} + +/** Read element and move read position forward: */ +#define CV_READ_SEQ_ELEM( elem, reader ) \ +{ \ + assert( (reader).seq->elem_size == sizeof(elem)); \ + memcpy( &(elem), (reader).ptr, sizeof((elem))); \ + CV_NEXT_SEQ_ELEM( sizeof(elem), reader ) \ +} + +/** Read element and move read position backward: */ +#define CV_REV_READ_SEQ_ELEM( elem, reader ) \ +{ \ + assert( (reader).seq->elem_size == sizeof(elem)); \ + memcpy(&(elem), (reader).ptr, sizeof((elem))); \ + CV_PREV_SEQ_ELEM( sizeof(elem), reader ) \ +} + + +#define CV_READ_CHAIN_POINT( _pt, reader ) \ +{ \ + (_pt) = (reader).pt; \ + if( (reader).ptr ) \ + { \ + CV_READ_SEQ_ELEM( (reader).code, (reader)); \ + assert( ((reader).code & ~7) == 0 ); \ + (reader).pt.x += (reader).deltas[(int)(reader).code][0]; \ + (reader).pt.y += (reader).deltas[(int)(reader).code][1]; \ + } \ +} + +#define CV_CURRENT_POINT( reader ) (*((CvPoint*)((reader).ptr))) +#define CV_PREV_POINT( reader ) (*((CvPoint*)((reader).prev_elem))) + +#define CV_READ_EDGE( pt1, pt2, reader ) \ +{ \ + assert( sizeof(pt1) == sizeof(CvPoint) && \ + sizeof(pt2) == sizeof(CvPoint) && \ + reader.seq->elem_size == sizeof(CvPoint)); \ + (pt1) = CV_PREV_POINT( reader ); \ + (pt2) = CV_CURRENT_POINT( reader ); \ + (reader).prev_elem = (reader).ptr; \ + CV_NEXT_SEQ_ELEM( sizeof(CvPoint), (reader)); \ +} + +/************ Graph macros ************/ + +/** Return next graph edge for given vertex: */ +#define CV_NEXT_GRAPH_EDGE( edge, vertex ) \ + (assert((edge)->vtx[0] == (vertex) || (edge)->vtx[1] == (vertex)), \ + (edge)->next[(edge)->vtx[1] == (vertex)]) + + + +/****************************************************************************************\ +* Data structures for persistence (a.k.a serialization) functionality * +\****************************************************************************************/ + +/** "black box" file storage */ +typedef struct CvFileStorage CvFileStorage; + +/** Storage flags: */ +#define CV_STORAGE_READ 0 +#define CV_STORAGE_WRITE 1 +#define CV_STORAGE_WRITE_TEXT CV_STORAGE_WRITE +#define CV_STORAGE_WRITE_BINARY CV_STORAGE_WRITE +#define CV_STORAGE_APPEND 2 +#define CV_STORAGE_MEMORY 4 +#define CV_STORAGE_FORMAT_MASK (7<<3) +#define CV_STORAGE_FORMAT_AUTO 0 +#define CV_STORAGE_FORMAT_XML 8 +#define CV_STORAGE_FORMAT_YAML 16 + +/** @brief List of attributes. : + +In the current implementation, attributes are used to pass extra parameters when writing user +objects (see cvWrite). XML attributes inside tags are not supported, aside from the object type +specification (type_id attribute). +@see cvAttrList, cvAttrValue + */ +typedef struct CvAttrList +{ + const char** attr; /**< NULL-terminated array of (attribute_name,attribute_value) pairs. */ + struct CvAttrList* next; /**< Pointer to next chunk of the attributes list. */ +} +CvAttrList; + +/** initializes CvAttrList structure */ +CV_INLINE CvAttrList cvAttrList( const char** attr CV_DEFAULT(NULL), + CvAttrList* next CV_DEFAULT(NULL) ) +{ + CvAttrList l; + l.attr = attr; + l.next = next; + + return l; +} + +struct CvTypeInfo; + +#define CV_NODE_NONE 0 +#define CV_NODE_INT 1 +#define CV_NODE_INTEGER CV_NODE_INT +#define CV_NODE_REAL 2 +#define CV_NODE_FLOAT CV_NODE_REAL +#define CV_NODE_STR 3 +#define CV_NODE_STRING CV_NODE_STR +#define CV_NODE_REF 4 /**< not used */ +#define CV_NODE_SEQ 5 +#define CV_NODE_MAP 6 +#define CV_NODE_TYPE_MASK 7 + +#define CV_NODE_TYPE(flags) ((flags) & CV_NODE_TYPE_MASK) + +/** file node flags */ +#define CV_NODE_FLOW 8 /**= CV_NODE_SEQ) +#define CV_NODE_IS_FLOW(flags) (((flags) & CV_NODE_FLOW) != 0) +#define CV_NODE_IS_EMPTY(flags) (((flags) & CV_NODE_EMPTY) != 0) +#define CV_NODE_IS_USER(flags) (((flags) & CV_NODE_USER) != 0) +#define CV_NODE_HAS_NAME(flags) (((flags) & CV_NODE_NAMED) != 0) + +#define CV_NODE_SEQ_SIMPLE 256 +#define CV_NODE_SEQ_IS_SIMPLE(seq) (((seq)->flags & CV_NODE_SEQ_SIMPLE) != 0) + +typedef struct CvString +{ + int len; + char* ptr; +} +CvString; + +/** All the keys (names) of elements in the readed file storage + are stored in the hash to speed up the lookup operations: */ +typedef struct CvStringHashNode +{ + unsigned hashval; + CvString str; + struct CvStringHashNode* next; +} +CvStringHashNode; + +typedef struct CvGenericHash CvFileNodeHash; + +/** Basic element of the file storage - scalar or collection: */ +typedef struct CvFileNode +{ + int tag; + struct CvTypeInfo* info; /**< type information + (only for user-defined object, for others it is 0) */ + union + { + double f; /**< scalar floating-point number */ + int i; /**< scalar integer number */ + CvString str; /**< text string */ + CvSeq* seq; /**< sequence (ordered collection of file nodes) */ + CvFileNodeHash* map; /**< map (collection of named file nodes) */ + } data; +} +CvFileNode; + +#ifdef __cplusplus +extern "C" { +#endif +typedef int (CV_CDECL *CvIsInstanceFunc)( const void* struct_ptr ); +typedef void (CV_CDECL *CvReleaseFunc)( void** struct_dblptr ); +typedef void* (CV_CDECL *CvReadFunc)( CvFileStorage* storage, CvFileNode* node ); +typedef void (CV_CDECL *CvWriteFunc)( CvFileStorage* storage, const char* name, + const void* struct_ptr, CvAttrList attributes ); +typedef void* (CV_CDECL *CvCloneFunc)( const void* struct_ptr ); +#ifdef __cplusplus +} +#endif + +/** @brief Type information + +The structure contains information about one of the standard or user-defined types. Instances of the +type may or may not contain a pointer to the corresponding CvTypeInfo structure. In any case, there +is a way to find the type info structure for a given object using the cvTypeOf function. +Alternatively, type info can be found by type name using cvFindType, which is used when an object +is read from file storage. The user can register a new type with cvRegisterType that adds the type +information structure into the beginning of the type list. Thus, it is possible to create +specialized types from generic standard types and override the basic methods. + */ +typedef struct CvTypeInfo +{ + int flags; /**< not used */ + int header_size; /**< sizeof(CvTypeInfo) */ + struct CvTypeInfo* prev; /**< previous registered type in the list */ + struct CvTypeInfo* next; /**< next registered type in the list */ + const char* type_name; /**< type name, written to file storage */ + CvIsInstanceFunc is_instance; /**< checks if the passed object belongs to the type */ + CvReleaseFunc release; /**< releases object (memory etc.) */ + CvReadFunc read; /**< reads object from file storage */ + CvWriteFunc write; /**< writes object to file storage */ + CvCloneFunc clone; /**< creates a copy of the object */ +} +CvTypeInfo; + + +/**** System data types ******/ + +typedef struct CvPluginFuncInfo +{ + void** func_addr; + void* default_func_addr; + const char* func_names; + int search_modules; + int loaded_from; +} +CvPluginFuncInfo; + +typedef struct CvModuleInfo +{ + struct CvModuleInfo* next; + const char* name; + const char* version; + CvPluginFuncInfo* func_tab; +} +CvModuleInfo; + +/** @} */ + +#endif /*__OPENCV_CORE_TYPES_H__*/ + +/* End of file. */ diff --git a/include/opencv2/core/utility.hpp b/include/opencv2/core/utility.hpp new file mode 100644 index 0000000..3ec0660 --- /dev/null +++ b/include/opencv2/core/utility.hpp @@ -0,0 +1,889 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_CORE_UTILITY_H__ +#define __OPENCV_CORE_UTILITY_H__ + +#ifndef __cplusplus +# error utility.hpp header must be compiled as C++ +#endif + +#include "opencv2/core.hpp" + +namespace cv +{ + +#ifdef CV_COLLECT_IMPL_DATA +CV_EXPORTS void setImpl(int flags); // set implementation flags and reset storage arrays +CV_EXPORTS void addImpl(int flag, const char* func = 0); // add implementation and function name to storage arrays +// Get stored implementation flags and fucntions names arrays +// Each implementation entry correspond to function name entry, so you can find which implementation was executed in which fucntion +CV_EXPORTS int getImpl(std::vector &impl, std::vector &funName); + +CV_EXPORTS bool useCollection(); // return implementation collection state +CV_EXPORTS void setUseCollection(bool flag); // set implementation collection state + +#define CV_IMPL_PLAIN 0x01 // native CPU OpenCV implementation +#define CV_IMPL_OCL 0x02 // OpenCL implementation +#define CV_IMPL_IPP 0x04 // IPP implementation +#define CV_IMPL_MT 0x10 // multithreaded implementation + +#define CV_IMPL_ADD(impl) \ + if(cv::useCollection()) \ + { \ + cv::addImpl(impl, CV_Func); \ + } +#else +#define CV_IMPL_ADD(impl) +#endif + +//! @addtogroup core_utils +//! @{ + +/** @brief Automatically Allocated Buffer Class + + The class is used for temporary buffers in functions and methods. + If a temporary buffer is usually small (a few K's of memory), + but its size depends on the parameters, it makes sense to create a small + fixed-size array on stack and use it if it's large enough. If the required buffer size + is larger than the fixed size, another buffer of sufficient size is allocated dynamically + and released after the processing. Therefore, in typical cases, when the buffer size is small, + there is no overhead associated with malloc()/free(). + At the same time, there is no limit on the size of processed data. + + This is what AutoBuffer does. The template takes 2 parameters - type of the buffer elements and + the number of stack-allocated elements. Here is how the class is used: + + \code + void my_func(const cv::Mat& m) + { + cv::AutoBuffer buf; // create automatic buffer containing 1000 floats + + buf.allocate(m.rows); // if m.rows <= 1000, the pre-allocated buffer is used, + // otherwise the buffer of "m.rows" floats will be allocated + // dynamically and deallocated in cv::AutoBuffer destructor + ... + } + \endcode +*/ +template class AutoBuffer +{ +public: + typedef _Tp value_type; + + //! the default constructor + AutoBuffer(); + //! constructor taking the real buffer size + AutoBuffer(size_t _size); + + //! the copy constructor + AutoBuffer(const AutoBuffer<_Tp, fixed_size>& buf); + //! the assignment operator + AutoBuffer<_Tp, fixed_size>& operator = (const AutoBuffer<_Tp, fixed_size>& buf); + + //! destructor. calls deallocate() + ~AutoBuffer(); + + //! allocates the new buffer of size _size. if the _size is small enough, stack-allocated buffer is used + void allocate(size_t _size); + //! deallocates the buffer if it was dynamically allocated + void deallocate(); + //! resizes the buffer and preserves the content + void resize(size_t _size); + //! returns the current buffer size + size_t size() const; + //! returns pointer to the real buffer, stack-allocated or head-allocated + operator _Tp* (); + //! returns read-only pointer to the real buffer, stack-allocated or head-allocated + operator const _Tp* () const; + +protected: + //! pointer to the real buffer, can point to buf if the buffer is small enough + _Tp* ptr; + //! size of the real buffer + size_t sz; + //! pre-allocated buffer. At least 1 element to confirm C++ standard reqirements + _Tp buf[(fixed_size > 0) ? fixed_size : 1]; +}; + +/** @brief Sets/resets the break-on-error mode. + +When the break-on-error mode is set, the default error handler issues a hardware exception, which +can make debugging more convenient. + +\return the previous state + */ +CV_EXPORTS bool setBreakOnError(bool flag); + +extern "C" typedef int (*ErrorCallback)( int status, const char* func_name, + const char* err_msg, const char* file_name, + int line, void* userdata ); + + +/** @brief Sets the new error handler and the optional user data. + + The function sets the new error handler, called from cv::error(). + + \param errCallback the new error handler. If NULL, the default error handler is used. + \param userdata the optional user data pointer, passed to the callback. + \param prevUserdata the optional output parameter where the previous user data pointer is stored + + \return the previous error handler +*/ +CV_EXPORTS ErrorCallback redirectError( ErrorCallback errCallback, void* userdata=0, void** prevUserdata=0); + +/** @brief Returns a text string formatted using the printf-like expression. + +The function acts like sprintf but forms and returns an STL string. It can be used to form an error +message in the Exception constructor. +@param fmt printf-compatible formatting specifiers. + */ +CV_EXPORTS String format( const char* fmt, ... ); +CV_EXPORTS String tempfile( const char* suffix = 0); +CV_EXPORTS void glob(String pattern, std::vector& result, bool recursive = false); + +/** @brief OpenCV will try to set the number of threads for the next parallel region. + +If threads == 0, OpenCV will disable threading optimizations and run all it's functions +sequentially. Passing threads \< 0 will reset threads number to system default. This function must +be called outside of parallel region. + +OpenCV will try to run it's functions with specified threads number, but some behaviour differs from +framework: +- `TBB` – User-defined parallel constructions will run with the same threads number, if + another does not specified. If late on user creates own scheduler, OpenCV will be use it. +- `OpenMP` – No special defined behaviour. +- `Concurrency` – If threads == 1, OpenCV will disable threading optimizations and run it's + functions sequentially. +- `GCD` – Supports only values \<= 0. +- `C=` – No special defined behaviour. +@param nthreads Number of threads used by OpenCV. +@sa getNumThreads, getThreadNum + */ +CV_EXPORTS void setNumThreads(int nthreads); + +/** @brief Returns the number of threads used by OpenCV for parallel regions. + +Always returns 1 if OpenCV is built without threading support. + +The exact meaning of return value depends on the threading framework used by OpenCV library: +- `TBB` – The number of threads, that OpenCV will try to use for parallel regions. If there is + any tbb::thread_scheduler_init in user code conflicting with OpenCV, then function returns + default number of threads used by TBB library. +- `OpenMP` – An upper bound on the number of threads that could be used to form a new team. +- `Concurrency` – The number of threads, that OpenCV will try to use for parallel regions. +- `GCD` – Unsupported; returns the GCD thread pool limit (512) for compatibility. +- `C=` – The number of threads, that OpenCV will try to use for parallel regions, if before + called setNumThreads with threads \> 0, otherwise returns the number of logical CPUs, + available for the process. +@sa setNumThreads, getThreadNum + */ +CV_EXPORTS int getNumThreads(); + +/** @brief Returns the index of the currently executed thread within the current parallel region. Always +returns 0 if called outside of parallel region. + +The exact meaning of return value depends on the threading framework used by OpenCV library: +- `TBB` – Unsupported with current 4.1 TBB release. May be will be supported in future. +- `OpenMP` – The thread number, within the current team, of the calling thread. +- `Concurrency` – An ID for the virtual processor that the current context is executing on (0 + for master thread and unique number for others, but not necessary 1,2,3,...). +- `GCD` – System calling thread's ID. Never returns 0 inside parallel region. +- `C=` – The index of the current parallel task. +@sa setNumThreads, getNumThreads + */ +CV_EXPORTS int getThreadNum(); + +/** @brief Returns full configuration time cmake output. + +Returned value is raw cmake output including version control system revision, compiler version, +compiler flags, enabled modules and third party libraries, etc. Output format depends on target +architecture. + */ +CV_EXPORTS_W const String& getBuildInformation(); + +/** @brief Returns the number of ticks. + +The function returns the number of ticks after the certain event (for example, when the machine was +turned on). It can be used to initialize RNG or to measure a function execution time by reading the +tick count before and after the function call. See also the tick frequency. + */ +CV_EXPORTS_W int64 getTickCount(); + +/** @brief Returns the number of ticks per second. + +The function returns the number of ticks per second. That is, the following code computes the +execution time in seconds: +@code + double t = (double)getTickCount(); + // do something ... + t = ((double)getTickCount() - t)/getTickFrequency(); +@endcode + */ +CV_EXPORTS_W double getTickFrequency(); + +/** @brief Returns the number of CPU ticks. + +The function returns the current number of CPU ticks on some architectures (such as x86, x64, +PowerPC). On other platforms the function is equivalent to getTickCount. It can also be used for +very accurate time measurements, as well as for RNG initialization. Note that in case of multi-CPU +systems a thread, from which getCPUTickCount is called, can be suspended and resumed at another CPU +with its own counter. So, theoretically (and practically) the subsequent calls to the function do +not necessary return the monotonously increasing values. Also, since a modern CPU varies the CPU +frequency depending on the load, the number of CPU clocks spent in some code cannot be directly +converted to time units. Therefore, getTickCount is generally a preferable solution for measuring +execution time. + */ +CV_EXPORTS_W int64 getCPUTickCount(); + +/** @brief Available CPU features. + +remember to keep this list identical to the one in cvdef.h +*/ +enum CpuFeatures { + CPU_MMX = 1, + CPU_SSE = 2, + CPU_SSE2 = 3, + CPU_SSE3 = 4, + CPU_SSSE3 = 5, + CPU_SSE4_1 = 6, + CPU_SSE4_2 = 7, + CPU_POPCNT = 8, + + CPU_AVX = 10, + CPU_AVX2 = 11, + CPU_FMA3 = 12, + + CPU_AVX_512F = 13, + CPU_AVX_512BW = 14, + CPU_AVX_512CD = 15, + CPU_AVX_512DQ = 16, + CPU_AVX_512ER = 17, + CPU_AVX_512IFMA512 = 18, + CPU_AVX_512PF = 19, + CPU_AVX_512VBMI = 20, + CPU_AVX_512VL = 21, + + CPU_NEON = 100 +}; + +/** @brief Returns true if the specified feature is supported by the host hardware. + +The function returns true if the host hardware supports the specified feature. When user calls +setUseOptimized(false), the subsequent calls to checkHardwareSupport() will return false until +setUseOptimized(true) is called. This way user can dynamically switch on and off the optimized code +in OpenCV. +@param feature The feature of interest, one of cv::CpuFeatures + */ +CV_EXPORTS_W bool checkHardwareSupport(int feature); + +/** @brief Returns the number of logical CPUs available for the process. + */ +CV_EXPORTS_W int getNumberOfCPUs(); + + +/** @brief Aligns a pointer to the specified number of bytes. + +The function returns the aligned pointer of the same type as the input pointer: +\f[\texttt{(\_Tp*)(((size\_t)ptr + n-1) \& -n)}\f] +@param ptr Aligned pointer. +@param n Alignment size that must be a power of two. + */ +template static inline _Tp* alignPtr(_Tp* ptr, int n=(int)sizeof(_Tp)) +{ + return (_Tp*)(((size_t)ptr + n-1) & -n); +} + +/** @brief Aligns a buffer size to the specified number of bytes. + +The function returns the minimum number that is greater or equal to sz and is divisible by n : +\f[\texttt{(sz + n-1) \& -n}\f] +@param sz Buffer size to align. +@param n Alignment size that must be a power of two. + */ +static inline size_t alignSize(size_t sz, int n) +{ + CV_DbgAssert((n & (n - 1)) == 0); // n is a power of 2 + return (sz + n-1) & -n; +} + +/** @brief Enables or disables the optimized code. + +The function can be used to dynamically turn on and off optimized code (code that uses SSE2, AVX, +and other instructions on the platforms that support it). It sets a global flag that is further +checked by OpenCV functions. Since the flag is not checked in the inner OpenCV loops, it is only +safe to call the function on the very top level in your application where you can be sure that no +other OpenCV function is currently executed. + +By default, the optimized code is enabled unless you disable it in CMake. The current status can be +retrieved using useOptimized. +@param onoff The boolean flag specifying whether the optimized code should be used (onoff=true) +or not (onoff=false). + */ +CV_EXPORTS_W void setUseOptimized(bool onoff); + +/** @brief Returns the status of optimized code usage. + +The function returns true if the optimized code is enabled. Otherwise, it returns false. + */ +CV_EXPORTS_W bool useOptimized(); + +static inline size_t getElemSize(int type) { return CV_ELEM_SIZE(type); } + +/////////////////////////////// Parallel Primitives ////////////////////////////////// + +/** @brief Base class for parallel data processors +*/ +class CV_EXPORTS ParallelLoopBody +{ +public: + virtual ~ParallelLoopBody(); + virtual void operator() (const Range& range) const = 0; +}; + +/** @brief Parallel data processor +*/ +CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.); + +/////////////////////////////// forEach method of cv::Mat //////////////////////////// +template inline +void Mat::forEach_impl(const Functor& operation) { + if (false) { + operation(*reinterpret_cast<_Tp*>(0), reinterpret_cast(NULL)); + // If your compiler fail in this line. + // Please check that your functor signature is + // (_Tp&, const int*) <- multidimential + // or (_Tp&, void*) <- in case of you don't need current idx. + } + + CV_Assert(this->total() / this->size[this->dims - 1] <= INT_MAX); + const int LINES = static_cast(this->total() / this->size[this->dims - 1]); + + class PixelOperationWrapper :public ParallelLoopBody + { + public: + PixelOperationWrapper(Mat_<_Tp>* const frame, const Functor& _operation) + : mat(frame), op(_operation) {}; + virtual ~PixelOperationWrapper(){}; + // ! Overloaded virtual operator + // convert range call to row call. + virtual void operator()(const Range &range) const { + const int DIMS = mat->dims; + const int COLS = mat->size[DIMS - 1]; + if (DIMS <= 2) { + for (int row = range.start; row < range.end; ++row) { + this->rowCall2(row, COLS); + } + } else { + std::vector idx(COLS); /// idx is modified in this->rowCall + idx[DIMS - 2] = range.start - 1; + + for (int line_num = range.start; line_num < range.end; ++line_num) { + idx[DIMS - 2]++; + for (int i = DIMS - 2; i >= 0; --i) { + if (idx[i] >= mat->size[i]) { + idx[i - 1] += idx[i] / mat->size[i]; + idx[i] %= mat->size[i]; + continue; // carry-over; + } + else { + break; + } + } + this->rowCall(&idx[0], COLS, DIMS); + } + } + }; + private: + Mat_<_Tp>* const mat; + const Functor op; + // ! Call operator for each elements in this row. + inline void rowCall(int* const idx, const int COLS, const int DIMS) const { + int &col = idx[DIMS - 1]; + col = 0; + _Tp* pixel = &(mat->template at<_Tp>(idx)); + + while (col < COLS) { + op(*pixel, const_cast(idx)); + pixel++; col++; + } + col = 0; + } + // ! Call operator for each elements in this row. 2d mat special version. + inline void rowCall2(const int row, const int COLS) const { + union Index{ + int body[2]; + operator const int*() const { + return reinterpret_cast(this); + } + int& operator[](const int i) { + return body[i]; + } + } idx = {{row, 0}}; + // Special union is needed to avoid + // "error: array subscript is above array bounds [-Werror=array-bounds]" + // when call the functor `op` such that access idx[3]. + + _Tp* pixel = &(mat->template at<_Tp>(idx)); + const _Tp* const pixel_end = pixel + COLS; + while(pixel < pixel_end) { + op(*pixel++, static_cast(idx)); + idx[1]++; + } + }; + PixelOperationWrapper& operator=(const PixelOperationWrapper &) { + CV_Assert(false); + // We can not remove this implementation because Visual Studio warning C4822. + return *this; + }; + }; + + parallel_for_(cv::Range(0, LINES), PixelOperationWrapper(reinterpret_cast*>(this), operation)); +} + +/////////////////////////// Synchronization Primitives /////////////////////////////// + +class CV_EXPORTS Mutex +{ +public: + Mutex(); + ~Mutex(); + Mutex(const Mutex& m); + Mutex& operator = (const Mutex& m); + + void lock(); + bool trylock(); + void unlock(); + + struct Impl; +protected: + Impl* impl; +}; + +class CV_EXPORTS AutoLock +{ +public: + AutoLock(Mutex& m) : mutex(&m) { mutex->lock(); } + ~AutoLock() { mutex->unlock(); } +protected: + Mutex* mutex; +private: + AutoLock(const AutoLock&); + AutoLock& operator = (const AutoLock&); +}; + +class CV_EXPORTS TLSDataContainer +{ +private: + int key_; +protected: + TLSDataContainer(); + virtual ~TLSDataContainer(); +public: + virtual void* createDataInstance() const = 0; + virtual void deleteDataInstance(void* data) const = 0; + + void* getData() const; +}; + +template +class TLSData : protected TLSDataContainer +{ +public: + inline TLSData() {} + inline ~TLSData() {} + inline T* get() const { return (T*)getData(); } +private: + virtual void* createDataInstance() const { return new T; } + virtual void deleteDataInstance(void* data) const { delete (T*)data; } +}; + +/** @brief Designed for command line parsing + +The sample below demonstrates how to use CommandLineParser: +@code + CommandLineParser parser(argc, argv, keys); + parser.about("Application name v1.0.0"); + + if (parser.has("help")) + { + parser.printMessage(); + return 0; + } + + int N = parser.get("N"); + double fps = parser.get("fps"); + String path = parser.get("path"); + + use_time_stamp = parser.has("timestamp"); + + String img1 = parser.get(0); + String img2 = parser.get(1); + + int repeat = parser.get(2); + + if (!parser.check()) + { + parser.printErrors(); + return 0; + } +@endcode + +### Keys syntax + +The keys parameter is a string containing several blocks, each one is enclosed in curley braces and +describes one argument. Each argument contains three parts separated by the `|` symbol: + +-# argument names is a space-separated list of option synonyms (to mark argument as positional, prefix it with the `@` symbol) +-# default value will be used if the argument was not provided (can be empty) +-# help message (can be empty) + +For example: + +@code{.cpp} + const String keys = + "{help h usage ? | | print this message }" + "{@image1 | | image1 for compare }" + "{@image2 | | image2 for compare }" + "{@repeat |1 | number }" + "{path |. | path to file }" + "{fps | -1.0 | fps for output video }" + "{N count |100 | count of objects }" + "{ts timestamp | | use time stamp }" + ; +} +@endcode + +### Usage + +For the described keys: + +@code{.sh} + # Good call (3 positional parameters: image1, image2 and repeat; N is 200, ts is true) + $ ./app -N=200 1.png 2.jpg 19 -ts + + # Bad call + $ ./app -fps=aaa + ERRORS: + Exception: can not convert: [aaa] to [double] +@endcode + */ +class CV_EXPORTS CommandLineParser +{ +public: + + /** @brief Constructor + + Initializes command line parser object + + @param argc number of command line arguments (from main()) + @param argv array of command line arguments (from main()) + @param keys string describing acceptable command line parameters (see class description for syntax) + */ + CommandLineParser(int argc, const char* const argv[], const String& keys); + + /** @brief Copy constructor */ + CommandLineParser(const CommandLineParser& parser); + + /** @brief Assignment operator */ + CommandLineParser& operator = (const CommandLineParser& parser); + + /** @brief Destructor */ + ~CommandLineParser(); + + /** @brief Returns application path + + This method returns the path to the executable from the command line (`argv[0]`). + + For example, if the application has been started with such command: + @code{.sh} + $ ./bin/my-executable + @endcode + this method will return `./bin`. + */ + String getPathToApplication() const; + + /** @brief Access arguments by name + + Returns argument converted to selected type. If the argument is not known or can not be + converted to selected type, the error flag is set (can be checked with @ref check). + + For example, define: + @code{.cpp} + String keys = "{N count||}"; + @endcode + + Call: + @code{.sh} + $ ./my-app -N=20 + # or + $ ./my-app --count=20 + @endcode + + Access: + @code{.cpp} + int N = parser.get("N"); + @endcode + + @param name name of the argument + @param space_delete remove spaces from the left and right of the string + @tparam T the argument will be converted to this type if possible + + @note You can access positional arguments by their `@`-prefixed name: + @code{.cpp} + parser.get("@image"); + @endcode + */ + template + T get(const String& name, bool space_delete = true) const + { + T val = T(); + getByName(name, space_delete, ParamType::type, (void*)&val); + return val; + } + + /** @brief Access positional arguments by index + + Returns argument converted to selected type. Indexes are counted from zero. + + For example, define: + @code{.cpp} + String keys = "{@arg1||}{@arg2||}" + @endcode + + Call: + @code{.sh} + ./my-app abc qwe + @endcode + + Access arguments: + @code{.cpp} + String val_1 = parser.get(0); // returns "abc", arg1 + String val_2 = parser.get(1); // returns "qwe", arg2 + @endcode + + @param index index of the argument + @param space_delete remove spaces from the left and right of the string + @tparam T the argument will be converted to this type if possible + */ + template + T get(int index, bool space_delete = true) const + { + T val = T(); + getByIndex(index, space_delete, ParamType::type, (void*)&val); + return val; + } + + /** @brief Check if field was provided in the command line + + @param name argument name to check + */ + bool has(const String& name) const; + + /** @brief Check for parsing errors + + Returns true if error occured while accessing the parameters (bad conversion, missing arguments, + etc.). Call @ref printErrors to print error messages list. + */ + bool check() const; + + /** @brief Set the about message + + The about message will be shown when @ref printMessage is called, right before arguments table. + */ + void about(const String& message); + + /** @brief Print help message + + This method will print standard help message containing the about message and arguments description. + + @sa about + */ + void printMessage() const; + + /** @brief Print list of errors occured + + @sa check + */ + void printErrors() const; + +protected: + void getByName(const String& name, bool space_delete, int type, void* dst) const; + void getByIndex(int index, bool space_delete, int type, void* dst) const; + + struct Impl; + Impl* impl; +}; + +//! @} core_utils + +//! @cond IGNORED + +/////////////////////////////// AutoBuffer implementation //////////////////////////////////////// + +template inline +AutoBuffer<_Tp, fixed_size>::AutoBuffer() +{ + ptr = buf; + sz = fixed_size; +} + +template inline +AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size) +{ + ptr = buf; + sz = fixed_size; + allocate(_size); +} + +template inline +AutoBuffer<_Tp, fixed_size>::AutoBuffer(const AutoBuffer<_Tp, fixed_size>& abuf ) +{ + ptr = buf; + sz = fixed_size; + allocate(abuf.size()); + for( size_t i = 0; i < sz; i++ ) + ptr[i] = abuf.ptr[i]; +} + +template inline AutoBuffer<_Tp, fixed_size>& +AutoBuffer<_Tp, fixed_size>::operator = (const AutoBuffer<_Tp, fixed_size>& abuf) +{ + if( this != &abuf ) + { + deallocate(); + allocate(abuf.size()); + for( size_t i = 0; i < sz; i++ ) + ptr[i] = abuf.ptr[i]; + } + return *this; +} + +template inline +AutoBuffer<_Tp, fixed_size>::~AutoBuffer() +{ deallocate(); } + +template inline void +AutoBuffer<_Tp, fixed_size>::allocate(size_t _size) +{ + if(_size <= sz) + { + sz = _size; + return; + } + deallocate(); + if(_size > fixed_size) + { + ptr = new _Tp[_size]; + sz = _size; + } +} + +template inline void +AutoBuffer<_Tp, fixed_size>::deallocate() +{ + if( ptr != buf ) + { + delete[] ptr; + ptr = buf; + sz = fixed_size; + } +} + +template inline void +AutoBuffer<_Tp, fixed_size>::resize(size_t _size) +{ + if(_size <= sz) + { + sz = _size; + return; + } + size_t i, prevsize = sz, minsize = MIN(prevsize, _size); + _Tp* prevptr = ptr; + + ptr = _size > fixed_size ? new _Tp[_size] : buf; + sz = _size; + + if( ptr != prevptr ) + for( i = 0; i < minsize; i++ ) + ptr[i] = prevptr[i]; + for( i = prevsize; i < _size; i++ ) + ptr[i] = _Tp(); + + if( prevptr != buf ) + delete[] prevptr; +} + +template inline size_t +AutoBuffer<_Tp, fixed_size>::size() const +{ return sz; } + +template inline +AutoBuffer<_Tp, fixed_size>::operator _Tp* () +{ return ptr; } + +template inline +AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const +{ return ptr; } + +#ifndef OPENCV_NOSTL +template<> inline std::string CommandLineParser::get(int index, bool space_delete) const +{ + return get(index, space_delete); +} +template<> inline std::string CommandLineParser::get(const String& name, bool space_delete) const +{ + return get(name, space_delete); +} +#endif // OPENCV_NOSTL + +//! @endcond + +} //namespace cv + +#ifndef DISABLE_OPENCV_24_COMPATIBILITY +#include "opencv2/core/core_c.h" +#endif + +#endif //__OPENCV_CORE_UTILITY_H__ diff --git a/include/opencv2/core/version.hpp b/include/opencv2/core/version.hpp new file mode 100644 index 0000000..e8662aa --- /dev/null +++ b/include/opencv2/core/version.hpp @@ -0,0 +1,71 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright( C) 2000-2015, Intel Corporation, all rights reserved. +// Copyright (C) 2011-2013, NVIDIA Corporation, all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +//(including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort(including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +/* + definition of the current version of OpenCV + Usefull to test in user programs +*/ + +#ifndef __OPENCV_VERSION_HPP__ +#define __OPENCV_VERSION_HPP__ + +#define CV_VERSION_MAJOR 3 +#define CV_VERSION_MINOR 0 +#define CV_VERSION_REVISION 0 +#define CV_VERSION_STATUS "" + +#define CVAUX_STR_EXP(__A) #__A +#define CVAUX_STR(__A) CVAUX_STR_EXP(__A) + +#define CVAUX_STRW_EXP(__A) L#__A +#define CVAUX_STRW(__A) CVAUX_STRW_EXP(__A) + +#define CV_VERSION CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) "." CVAUX_STR(CV_VERSION_REVISION) CV_VERSION_STATUS + +/* old style version constants*/ +#define CV_MAJOR_VERSION CV_VERSION_MAJOR +#define CV_MINOR_VERSION CV_VERSION_MINOR +#define CV_SUBMINOR_VERSION CV_VERSION_REVISION + +#endif diff --git a/include/opencv2/core/wimage.hpp b/include/opencv2/core/wimage.hpp new file mode 100644 index 0000000..ef9d398 --- /dev/null +++ b/include/opencv2/core/wimage.hpp @@ -0,0 +1,603 @@ +/*M////////////////////////////////////////////////////////////////////////////// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to +// this license. If you do not agree to this license, do not download, +// install, copy or use the software. +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2008, Google, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation or contributors may not be used to endorse +// or promote products derived from this software without specific +// prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" +// and any express or implied warranties, including, but not limited to, the +// implied warranties of merchantability and fitness for a particular purpose +// are disclaimed. In no event shall the Intel Corporation or contributors be +// liable for any direct, indirect, incidental, special, exemplary, or +// consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +///////////////////////////////////////////////////////////////////////////////// +//M*/ + +#ifndef __OPENCV_CORE_WIMAGE_HPP__ +#define __OPENCV_CORE_WIMAGE_HPP__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus + +namespace cv { + +//! @addtogroup core +//! @{ + +template class WImage; +template class WImageBuffer; +template class WImageView; + +template class WImageC; +template class WImageBufferC; +template class WImageViewC; + +// Commonly used typedefs. +typedef WImage WImage_b; +typedef WImageView WImageView_b; +typedef WImageBuffer WImageBuffer_b; + +typedef WImageC WImage1_b; +typedef WImageViewC WImageView1_b; +typedef WImageBufferC WImageBuffer1_b; + +typedef WImageC WImage3_b; +typedef WImageViewC WImageView3_b; +typedef WImageBufferC WImageBuffer3_b; + +typedef WImage WImage_f; +typedef WImageView WImageView_f; +typedef WImageBuffer WImageBuffer_f; + +typedef WImageC WImage1_f; +typedef WImageViewC WImageView1_f; +typedef WImageBufferC WImageBuffer1_f; + +typedef WImageC WImage3_f; +typedef WImageViewC WImageView3_f; +typedef WImageBufferC WImageBuffer3_f; + +// There isn't a standard for signed and unsigned short so be more +// explicit in the typename for these cases. +typedef WImage WImage_16s; +typedef WImageView WImageView_16s; +typedef WImageBuffer WImageBuffer_16s; + +typedef WImageC WImage1_16s; +typedef WImageViewC WImageView1_16s; +typedef WImageBufferC WImageBuffer1_16s; + +typedef WImageC WImage3_16s; +typedef WImageViewC WImageView3_16s; +typedef WImageBufferC WImageBuffer3_16s; + +typedef WImage WImage_16u; +typedef WImageView WImageView_16u; +typedef WImageBuffer WImageBuffer_16u; + +typedef WImageC WImage1_16u; +typedef WImageViewC WImageView1_16u; +typedef WImageBufferC WImageBuffer1_16u; + +typedef WImageC WImage3_16u; +typedef WImageViewC WImageView3_16u; +typedef WImageBufferC WImageBuffer3_16u; + +/** @brief Image class which provides a thin layer around an IplImage. + +The goals of the class design are: + + -# All the data has explicit ownership to avoid memory leaks + -# No hidden allocations or copies for performance. + -# Easy access to OpenCV methods (which will access IPP if available) + -# Can easily treat external data as an image + -# Easy to create images which are subsets of other images + -# Fast pixel access which can take advantage of number of channels if known at compile time. + +The WImage class is the image class which provides the data accessors. The 'W' comes from the fact +that it is also a wrapper around the popular but inconvenient IplImage class. A WImage can be +constructed either using a WImageBuffer class which allocates and frees the data, or using a +WImageView class which constructs a subimage or a view into external data. The view class does no +memory management. Each class actually has two versions, one when the number of channels is known +at compile time and one when it isn't. Using the one with the number of channels specified can +provide some compile time optimizations by using the fact that the number of channels is a +constant. + +We use the convention (c,r) to refer to column c and row r with (0,0) being the upper left corner. +This is similar to standard Euclidean coordinates with the first coordinate varying in the +horizontal direction and the second coordinate varying in the vertical direction. Thus (c,r) is +usually in the domain [0, width) X [0, height) + +Example usage: +@code +WImageBuffer3_b im(5,7); // Make a 5X7 3 channel image of type uchar +WImageView3_b sub_im(im, 2,2, 3,3); // 3X3 submatrix +vector vec(10, 3.0f); +WImageView1_f user_im(&vec[0], 2, 5); // 2X5 image w/ supplied data + +im.SetZero(); // same as cvSetZero(im.Ipl()) +*im(2, 3) = 15; // Modify the element at column 2, row 3 +MySetRand(&sub_im); + +// Copy the second row into the first. This can be done with no memory +// allocation and will use SSE if IPP is available. +int w = im.Width(); +im.View(0,0, w,1).CopyFrom(im.View(0,1, w,1)); + +// Doesn't care about source of data since using WImage +void MySetRand(WImage_b* im) { // Works with any number of channels +for (int r = 0; r < im->Height(); ++r) { + float* row = im->Row(r); + for (int c = 0; c < im->Width(); ++c) { + for (int ch = 0; ch < im->Channels(); ++ch, ++row) { + *row = uchar(rand() & 255); + } + } +} +} +@endcode + +Functions that are not part of the basic image allocation, viewing, and access should come from +OpenCV, except some useful functions that are not part of OpenCV can be found in wimage_util.h +*/ +template +class WImage +{ +public: + typedef T BaseType; + + // WImage is an abstract class with no other virtual methods so make the + // destructor virtual. + virtual ~WImage() = 0; + + // Accessors + IplImage* Ipl() {return image_; } + const IplImage* Ipl() const {return image_; } + T* ImageData() { return reinterpret_cast(image_->imageData); } + const T* ImageData() const { + return reinterpret_cast(image_->imageData); + } + + int Width() const {return image_->width; } + int Height() const {return image_->height; } + + // WidthStep is the number of bytes to go to the pixel with the next y coord + int WidthStep() const {return image_->widthStep; } + + int Channels() const {return image_->nChannels; } + int ChannelSize() const {return sizeof(T); } // number of bytes per channel + + // Number of bytes per pixel + int PixelSize() const {return Channels() * ChannelSize(); } + + // Return depth type (e.g. IPL_DEPTH_8U, IPL_DEPTH_32F) which is the number + // of bits per channel and with the signed bit set. + // This is known at compile time using specializations. + int Depth() const; + + inline const T* Row(int r) const { + return reinterpret_cast(image_->imageData + r*image_->widthStep); + } + + inline T* Row(int r) { + return reinterpret_cast(image_->imageData + r*image_->widthStep); + } + + // Pixel accessors which returns a pointer to the start of the channel + inline T* operator() (int c, int r) { + return reinterpret_cast(image_->imageData + r*image_->widthStep) + + c*Channels(); + } + + inline const T* operator() (int c, int r) const { + return reinterpret_cast(image_->imageData + r*image_->widthStep) + + c*Channels(); + } + + // Copy the contents from another image which is just a convenience to cvCopy + void CopyFrom(const WImage& src) { cvCopy(src.Ipl(), image_); } + + // Set contents to zero which is just a convenient to cvSetZero + void SetZero() { cvSetZero(image_); } + + // Construct a view into a region of this image + WImageView View(int c, int r, int width, int height); + +protected: + // Disallow copy and assignment + WImage(const WImage&); + void operator=(const WImage&); + + explicit WImage(IplImage* img) : image_(img) { + assert(!img || img->depth == Depth()); + } + + void SetIpl(IplImage* image) { + assert(!image || image->depth == Depth()); + image_ = image; + } + + IplImage* image_; +}; + + +/** Image class when both the pixel type and number of channels +are known at compile time. This wrapper will speed up some of the operations +like accessing individual pixels using the () operator. +*/ +template +class WImageC : public WImage +{ +public: + typedef typename WImage::BaseType BaseType; + enum { kChannels = C }; + + explicit WImageC(IplImage* img) : WImage(img) { + assert(!img || img->nChannels == Channels()); + } + + // Construct a view into a region of this image + WImageViewC View(int c, int r, int width, int height); + + // Copy the contents from another image which is just a convenience to cvCopy + void CopyFrom(const WImageC& src) { + cvCopy(src.Ipl(), WImage::image_); + } + + // WImageC is an abstract class with no other virtual methods so make the + // destructor virtual. + virtual ~WImageC() = 0; + + int Channels() const {return C; } + +protected: + // Disallow copy and assignment + WImageC(const WImageC&); + void operator=(const WImageC&); + + void SetIpl(IplImage* image) { + assert(!image || image->depth == WImage::Depth()); + WImage::SetIpl(image); + } +}; + +/** Image class which owns the data, so it can be allocated and is always +freed. It cannot be copied but can be explicity cloned. +*/ +template +class WImageBuffer : public WImage +{ +public: + typedef typename WImage::BaseType BaseType; + + // Default constructor which creates an object that can be + WImageBuffer() : WImage(0) {} + + WImageBuffer(int width, int height, int nchannels) : WImage(0) { + Allocate(width, height, nchannels); + } + + // Constructor which takes ownership of a given IplImage so releases + // the image on destruction. + explicit WImageBuffer(IplImage* img) : WImage(img) {} + + // Allocate an image. Does nothing if current size is the same as + // the new size. + void Allocate(int width, int height, int nchannels); + + // Set the data to point to an image, releasing the old data + void SetIpl(IplImage* img) { + ReleaseImage(); + WImage::SetIpl(img); + } + + // Clone an image which reallocates the image if of a different dimension. + void CloneFrom(const WImage& src) { + Allocate(src.Width(), src.Height(), src.Channels()); + CopyFrom(src); + } + + ~WImageBuffer() { + ReleaseImage(); + } + + // Release the image if it isn't null. + void ReleaseImage() { + if (WImage::image_) { + IplImage* image = WImage::image_; + cvReleaseImage(&image); + WImage::SetIpl(0); + } + } + + bool IsNull() const {return WImage::image_ == NULL; } + +private: + // Disallow copy and assignment + WImageBuffer(const WImageBuffer&); + void operator=(const WImageBuffer&); +}; + +/** Like a WImageBuffer class but when the number of channels is known at compile time. +*/ +template +class WImageBufferC : public WImageC +{ +public: + typedef typename WImage::BaseType BaseType; + enum { kChannels = C }; + + // Default constructor which creates an object that can be + WImageBufferC() : WImageC(0) {} + + WImageBufferC(int width, int height) : WImageC(0) { + Allocate(width, height); + } + + // Constructor which takes ownership of a given IplImage so releases + // the image on destruction. + explicit WImageBufferC(IplImage* img) : WImageC(img) {} + + // Allocate an image. Does nothing if current size is the same as + // the new size. + void Allocate(int width, int height); + + // Set the data to point to an image, releasing the old data + void SetIpl(IplImage* img) { + ReleaseImage(); + WImageC::SetIpl(img); + } + + // Clone an image which reallocates the image if of a different dimension. + void CloneFrom(const WImageC& src) { + Allocate(src.Width(), src.Height()); + CopyFrom(src); + } + + ~WImageBufferC() { + ReleaseImage(); + } + + // Release the image if it isn't null. + void ReleaseImage() { + if (WImage::image_) { + IplImage* image = WImage::image_; + cvReleaseImage(&image); + WImageC::SetIpl(0); + } + } + + bool IsNull() const {return WImage::image_ == NULL; } + +private: + // Disallow copy and assignment + WImageBufferC(const WImageBufferC&); + void operator=(const WImageBufferC&); +}; + +/** View into an image class which allows treating a subimage as an image or treating external data +as an image +*/ +template class WImageView : public WImage +{ +public: + typedef typename WImage::BaseType BaseType; + + // Construct a subimage. No checks are done that the subimage lies + // completely inside the original image. + WImageView(WImage* img, int c, int r, int width, int height); + + // Refer to external data. + // If not given width_step assumed to be same as width. + WImageView(T* data, int width, int height, int channels, int width_step = -1); + + // Refer to external data. This does NOT take ownership + // of the supplied IplImage. + WImageView(IplImage* img) : WImage(img) {} + + // Copy constructor + WImageView(const WImage& img) : WImage(0) { + header_ = *(img.Ipl()); + WImage::SetIpl(&header_); + } + + WImageView& operator=(const WImage& img) { + header_ = *(img.Ipl()); + WImage::SetIpl(&header_); + return *this; + } + +protected: + IplImage header_; +}; + + +template +class WImageViewC : public WImageC +{ +public: + typedef typename WImage::BaseType BaseType; + enum { kChannels = C }; + + // Default constructor needed for vectors of views. + WImageViewC(); + + virtual ~WImageViewC() {} + + // Construct a subimage. No checks are done that the subimage lies + // completely inside the original image. + WImageViewC(WImageC* img, + int c, int r, int width, int height); + + // Refer to external data + WImageViewC(T* data, int width, int height, int width_step = -1); + + // Refer to external data. This does NOT take ownership + // of the supplied IplImage. + WImageViewC(IplImage* img) : WImageC(img) {} + + // Copy constructor which does a shallow copy to allow multiple views + // of same data. gcc-4.1.1 gets confused if both versions of + // the constructor and assignment operator are not provided. + WImageViewC(const WImageC& img) : WImageC(0) { + header_ = *(img.Ipl()); + WImageC::SetIpl(&header_); + } + WImageViewC(const WImageViewC& img) : WImageC(0) { + header_ = *(img.Ipl()); + WImageC::SetIpl(&header_); + } + + WImageViewC& operator=(const WImageC& img) { + header_ = *(img.Ipl()); + WImageC::SetIpl(&header_); + return *this; + } + WImageViewC& operator=(const WImageViewC& img) { + header_ = *(img.Ipl()); + WImageC::SetIpl(&header_); + return *this; + } + +protected: + IplImage header_; +}; + + +// Specializations for depth +template<> +inline int WImage::Depth() const {return IPL_DEPTH_8U; } +template<> +inline int WImage::Depth() const {return IPL_DEPTH_8S; } +template<> +inline int WImage::Depth() const {return IPL_DEPTH_16S; } +template<> +inline int WImage::Depth() const {return IPL_DEPTH_16U; } +template<> +inline int WImage::Depth() const {return IPL_DEPTH_32S; } +template<> +inline int WImage::Depth() const {return IPL_DEPTH_32F; } +template<> +inline int WImage::Depth() const {return IPL_DEPTH_64F; } + +template inline WImage::~WImage() {} +template inline WImageC::~WImageC() {} + +template +inline void WImageBuffer::Allocate(int width, int height, int nchannels) +{ + if (IsNull() || WImage::Width() != width || + WImage::Height() != height || WImage::Channels() != nchannels) { + ReleaseImage(); + WImage::image_ = cvCreateImage(cvSize(width, height), + WImage::Depth(), nchannels); + } +} + +template +inline void WImageBufferC::Allocate(int width, int height) +{ + if (IsNull() || WImage::Width() != width || WImage::Height() != height) { + ReleaseImage(); + WImageC::SetIpl(cvCreateImage(cvSize(width, height),WImage::Depth(), C)); + } +} + +template +WImageView::WImageView(WImage* img, int c, int r, int width, int height) + : WImage(0) +{ + header_ = *(img->Ipl()); + header_.imageData = reinterpret_cast((*img)(c, r)); + header_.width = width; + header_.height = height; + WImage::SetIpl(&header_); +} + +template +WImageView::WImageView(T* data, int width, int height, int nchannels, int width_step) + : WImage(0) +{ + cvInitImageHeader(&header_, cvSize(width, height), WImage::Depth(), nchannels); + header_.imageData = reinterpret_cast(data); + if (width_step > 0) { + header_.widthStep = width_step; + } + WImage::SetIpl(&header_); +} + +template +WImageViewC::WImageViewC(WImageC* img, int c, int r, int width, int height) + : WImageC(0) +{ + header_ = *(img->Ipl()); + header_.imageData = reinterpret_cast((*img)(c, r)); + header_.width = width; + header_.height = height; + WImageC::SetIpl(&header_); +} + +template +WImageViewC::WImageViewC() : WImageC(0) { + cvInitImageHeader(&header_, cvSize(0, 0), WImage::Depth(), C); + header_.imageData = reinterpret_cast(0); + WImageC::SetIpl(&header_); +} + +template +WImageViewC::WImageViewC(T* data, int width, int height, int width_step) + : WImageC(0) +{ + cvInitImageHeader(&header_, cvSize(width, height), WImage::Depth(), C); + header_.imageData = reinterpret_cast(data); + if (width_step > 0) { + header_.widthStep = width_step; + } + WImageC::SetIpl(&header_); +} + +// Construct a view into a region of an image +template +WImageView WImage::View(int c, int r, int width, int height) { + return WImageView(this, c, r, width, height); +} + +template +WImageViewC WImageC::View(int c, int r, int width, int height) { + return WImageViewC(this, c, r, width, height); +} + +//! @} core + +} // end of namespace + +#endif // __cplusplus + +#endif diff --git a/include/opencv2/cvconfig.h b/include/opencv2/cvconfig.h new file mode 100644 index 0000000..5fd0d3b --- /dev/null +++ b/include/opencv2/cvconfig.h @@ -0,0 +1,183 @@ +/* OpenCV compiled as static or dynamic libs */ +/* #undef BUILD_SHARED_LIBS */ + +/* Compile for 'real' NVIDIA GPU architectures */ +#define CUDA_ARCH_BIN "" + +/* Create PTX or BIN for 1.0 compute capability */ +/* #undef CUDA_ARCH_BIN_OR_PTX_10 */ + +/* NVIDIA GPU features are used */ +#define CUDA_ARCH_FEATURES "" + +/* Compile for 'virtual' NVIDIA PTX architectures */ +#define CUDA_ARCH_PTX "" + +/* AVFoundation video libraries */ +/* #undef HAVE_AVFOUNDATION */ + +/* V4L capturing support */ +/* #undef HAVE_CAMV4L */ + +/* V4L2 capturing support */ +/* #undef HAVE_CAMV4L2 */ + +/* Carbon windowing environment */ +/* #undef HAVE_CARBON */ + +/* AMD's Basic Linear Algebra Subprograms Library*/ +#define HAVE_CLAMDBLAS + +/* AMD's OpenCL Fast Fourier Transform Library*/ +#define HAVE_CLAMDFFT + +/* Clp support */ +/* #undef HAVE_CLP */ + +/* Cocoa API */ +/* #undef HAVE_COCOA */ + +/* C= */ +/* #undef HAVE_CSTRIPES */ + +/* NVidia Cuda Basic Linear Algebra Subprograms (BLAS) API*/ +/* #undef HAVE_CUBLAS */ + +/* NVidia Cuda Runtime API*/ +/* #undef HAVE_CUDA */ + +/* NVidia Cuda Fast Fourier Transform (FFT) API*/ +/* #undef HAVE_CUFFT */ + +/* IEEE1394 capturing support */ +/* #undef HAVE_DC1394 */ + +/* IEEE1394 capturing support - libdc1394 v2.x */ +/* #undef HAVE_DC1394_2 */ + +/* DirectX */ +#define HAVE_DIRECTX +#define HAVE_D3D11 +#define HAVE_D3D10 +#define HAVE_D3D9 + +/* DirectShow Video Capture library */ +#define HAVE_DSHOW + +/* Eigen Matrix & Linear Algebra Library */ +/* #undef HAVE_EIGEN */ + +/* FFMpeg video library */ +#define HAVE_FFMPEG + +/* ffmpeg's libswscale */ +#define HAVE_FFMPEG_SWSCALE + +/* ffmpeg in Gentoo */ +#define HAVE_GENTOO_FFMPEG + +/* Geospatial Data Abstraction Library */ +/* #undef HAVE_GDAL */ + +/* GStreamer multimedia framework */ +/* #undef HAVE_GSTREAMER */ + +/* GTK+ 2.0 Thread support */ +/* #undef HAVE_GTHREAD */ + +/* GTK+ 2.x toolkit */ +/* #undef HAVE_GTK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_INTTYPES_H */ + +/* Intel Perceptual Computing SDK library */ +/* #undef HAVE_INTELPERC */ + +/* Intel Integrated Performance Primitives */ +#define HAVE_IPP +#define HAVE_IPP_ICV_ONLY + +/* Intel IPP Async */ +/* #undef HAVE_IPP_A */ + +/* JPEG-2000 codec */ +#define HAVE_JASPER + +/* IJG JPEG codec */ +#define HAVE_JPEG + +/* libpng/png.h needs to be included */ +/* #undef HAVE_LIBPNG_PNG_H */ + +/* V4L/V4L2 capturing support via libv4l */ +/* #undef HAVE_LIBV4L */ + +/* Microsoft Media Foundation Capture library */ +/* #undef HAVE_MSMF */ + +/* NVidia Video Decoding API*/ +/* #undef HAVE_NVCUVID */ + +/* OpenCL Support */ +#define HAVE_OPENCL +/* #undef HAVE_OPENCL_STATIC */ +/* #undef HAVE_OPENCL_SVM */ + +/* OpenEXR codec */ +#define HAVE_OPENEXR + +/* OpenGL support*/ +/* #undef HAVE_OPENGL */ + +/* OpenNI library */ +/* #undef HAVE_OPENNI */ + +/* OpenNI library */ +/* #undef HAVE_OPENNI2 */ + +/* PNG codec */ +#define HAVE_PNG + +/* Qt support */ +/* #undef HAVE_QT */ + +/* Qt OpenGL support */ +/* #undef HAVE_QT_OPENGL */ + +/* QuickTime video libraries */ +/* #undef HAVE_QUICKTIME */ + +/* QTKit video libraries */ +/* #undef HAVE_QTKIT */ + +/* Intel Threading Building Blocks */ +/* #undef HAVE_TBB */ + +/* TIFF codec */ +#define HAVE_TIFF + +/* Unicap video capture library */ +/* #undef HAVE_UNICAP */ + +/* Video for Windows support */ +#define HAVE_VFW + +/* V4L2 capturing support in videoio.h */ +/* #undef HAVE_VIDEOIO */ + +/* Win32 UI */ +#define HAVE_WIN32UI + +/* XIMEA camera support */ +/* #undef HAVE_XIMEA */ + +/* Xine video library */ +/* #undef HAVE_XINE */ + +/* Define if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* gPhoto2 library */ +/* #undef HAVE_GPHOTO2 */ diff --git a/include/opencv2/features2d.hpp b/include/opencv2/features2d.hpp new file mode 100644 index 0000000..cf95e7d --- /dev/null +++ b/include/opencv2/features2d.hpp @@ -0,0 +1,1299 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_FEATURES_2D_HPP__ +#define __OPENCV_FEATURES_2D_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/flann/miniflann.hpp" + +/** + @defgroup features2d 2D Features Framework + @{ + @defgroup features2d_main Feature Detection and Description + @defgroup features2d_match Descriptor Matchers + +Matchers of keypoint descriptors in OpenCV have wrappers with a common interface that enables you to +easily switch between different algorithms solving the same problem. This section is devoted to +matching descriptors that are represented as vectors in a multidimensional space. All objects that +implement vector descriptor matchers inherit the DescriptorMatcher interface. + +@note + - An example explaining keypoint matching can be found at + opencv_source_code/samples/cpp/descriptor_extractor_matcher.cpp + - An example on descriptor matching evaluation can be found at + opencv_source_code/samples/cpp/detector_descriptor_matcher_evaluation.cpp + - An example on one to many image matching can be found at + opencv_source_code/samples/cpp/matching_to_many_images.cpp + + @defgroup features2d_draw Drawing Function of Keypoints and Matches + @defgroup features2d_category Object Categorization + +This section describes approaches based on local 2D features and used to categorize objects. + +@note + - A complete Bag-Of-Words sample can be found at + opencv_source_code/samples/cpp/bagofwords_classification.cpp + - (Python) An example using the features2D framework to perform object categorization can be + found at opencv_source_code/samples/python2/find_obj.py + + @} + */ + +namespace cv +{ + +//! @addtogroup features2d +//! @{ + +// //! writes vector of keypoints to the file storage +// CV_EXPORTS void write(FileStorage& fs, const String& name, const std::vector& keypoints); +// //! reads vector of keypoints from the specified file storage node +// CV_EXPORTS void read(const FileNode& node, CV_OUT std::vector& keypoints); + +/** @brief A class filters a vector of keypoints. + + Because now it is difficult to provide a convenient interface for all usage scenarios of the + keypoints filter class, it has only several needed by now static methods. + */ +class CV_EXPORTS KeyPointsFilter +{ +public: + KeyPointsFilter(){} + + /* + * Remove keypoints within borderPixels of an image edge. + */ + static void runByImageBorder( std::vector& keypoints, Size imageSize, int borderSize ); + /* + * Remove keypoints of sizes out of range. + */ + static void runByKeypointSize( std::vector& keypoints, float minSize, + float maxSize=FLT_MAX ); + /* + * Remove keypoints from some image by mask for pixels of this image. + */ + static void runByPixelsMask( std::vector& keypoints, const Mat& mask ); + /* + * Remove duplicated keypoints. + */ + static void removeDuplicated( std::vector& keypoints ); + + /* + * Retain the specified number of the best keypoints (according to the response) + */ + static void retainBest( std::vector& keypoints, int npoints ); +}; + + +/************************************ Base Classes ************************************/ + +/** @brief Abstract base class for 2D image feature detectors and descriptor extractors +*/ +class CV_EXPORTS_W Feature2D : public virtual Algorithm +{ +public: + virtual ~Feature2D(); + + /** @brief Detects keypoints in an image (first variant) or image set (second variant). + + @param image Image. + @param keypoints The detected keypoints. In the second variant of the method keypoints[i] is a set + of keypoints detected in images[i] . + @param mask Mask specifying where to look for keypoints (optional). It must be a 8-bit integer + matrix with non-zero values in the region of interest. + */ + CV_WRAP virtual void detect( InputArray image, + CV_OUT std::vector& keypoints, + InputArray mask=noArray() ); + + /** @overload + @param images Image set. + @param keypoints The detected keypoints. In the second variant of the method keypoints[i] is a set + of keypoints detected in images[i] . + @param masks Masks for each input image specifying where to look for keypoints (optional). + masks[i] is a mask for images[i]. + */ + virtual void detect( InputArrayOfArrays images, + std::vector >& keypoints, + InputArrayOfArrays masks=noArray() ); + + /** @brief Computes the descriptors for a set of keypoints detected in an image (first variant) or image set + (second variant). + + @param image Image. + @param keypoints Input collection of keypoints. Keypoints for which a descriptor cannot be + computed are removed. Sometimes new keypoints can be added, for example: SIFT duplicates keypoint + with several dominant orientations (for each orientation). + @param descriptors Computed descriptors. In the second variant of the method descriptors[i] are + descriptors computed for a keypoints[i]. Row j is the keypoints (or keypoints[i]) is the + descriptor for keypoint j-th keypoint. + */ + CV_WRAP virtual void compute( InputArray image, + CV_OUT CV_IN_OUT std::vector& keypoints, + OutputArray descriptors ); + + /** @overload + + @param images Image set. + @param keypoints Input collection of keypoints. Keypoints for which a descriptor cannot be + computed are removed. Sometimes new keypoints can be added, for example: SIFT duplicates keypoint + with several dominant orientations (for each orientation). + @param descriptors Computed descriptors. In the second variant of the method descriptors[i] are + descriptors computed for a keypoints[i]. Row j is the keypoints (or keypoints[i]) is the + descriptor for keypoint j-th keypoint. + */ + virtual void compute( InputArrayOfArrays images, + std::vector >& keypoints, + OutputArrayOfArrays descriptors ); + + /** Detects keypoints and computes the descriptors */ + CV_WRAP virtual void detectAndCompute( InputArray image, InputArray mask, + CV_OUT std::vector& keypoints, + OutputArray descriptors, + bool useProvidedKeypoints=false ); + + CV_WRAP virtual int descriptorSize() const; + CV_WRAP virtual int descriptorType() const; + CV_WRAP virtual int defaultNorm() const; + + //! Return true if detector object is empty + CV_WRAP virtual bool empty() const; +}; + +/** Feature detectors in OpenCV have wrappers with a common interface that enables you to easily switch +between different algorithms solving the same problem. All objects that implement keypoint detectors +inherit the FeatureDetector interface. */ +typedef Feature2D FeatureDetector; + +/** Extractors of keypoint descriptors in OpenCV have wrappers with a common interface that enables you +to easily switch between different algorithms solving the same problem. This section is devoted to +computing descriptors represented as vectors in a multidimensional space. All objects that implement +the vector descriptor extractors inherit the DescriptorExtractor interface. + */ +typedef Feature2D DescriptorExtractor; + +//! @addtogroup features2d_main +//! @{ + +/** @brief Class implementing the BRISK keypoint detector and descriptor extractor, described in @cite LCS11 . + */ +class CV_EXPORTS_W BRISK : public Feature2D +{ +public: + /** @brief The BRISK constructor + + @param thresh AGAST detection threshold score. + @param octaves detection octaves. Use 0 to do single scale. + @param patternScale apply this scale to the pattern used for sampling the neighbourhood of a + keypoint. + */ + CV_WRAP static Ptr create(int thresh=30, int octaves=3, float patternScale=1.0f); + + /** @brief The BRISK constructor for a custom pattern + + @param radiusList defines the radii (in pixels) where the samples around a keypoint are taken (for + keypoint scale 1). + @param numberList defines the number of sampling points on the sampling circle. Must be the same + size as radiusList.. + @param dMax threshold for the short pairings used for descriptor formation (in pixels for keypoint + scale 1). + @param dMin threshold for the long pairings used for orientation determination (in pixels for + keypoint scale 1). + @param indexChange index remapping of the bits. */ + CV_WRAP static Ptr create(const std::vector &radiusList, const std::vector &numberList, + float dMax=5.85f, float dMin=8.2f, const std::vector& indexChange=std::vector()); +}; + +/** @brief Class implementing the ORB (*oriented BRIEF*) keypoint detector and descriptor extractor + +described in @cite RRKB11 . The algorithm uses FAST in pyramids to detect stable keypoints, selects +the strongest features using FAST or Harris response, finds their orientation using first-order +moments and computes the descriptors using BRIEF (where the coordinates of random point pairs (or +k-tuples) are rotated according to the measured orientation). + */ +class CV_EXPORTS_W ORB : public Feature2D +{ +public: + enum { kBytes = 32, HARRIS_SCORE=0, FAST_SCORE=1 }; + + /** @brief The ORB constructor + + @param nfeatures The maximum number of features to retain. + @param scaleFactor Pyramid decimation ratio, greater than 1. scaleFactor==2 means the classical + pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor + will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor + will mean that to cover certain scale range you will need more pyramid levels and so the speed + will suffer. + @param nlevels The number of pyramid levels. The smallest level will have linear size equal to + input_image_linear_size/pow(scaleFactor, nlevels). + @param edgeThreshold This is size of the border where the features are not detected. It should + roughly match the patchSize parameter. + @param firstLevel It should be 0 in the current implementation. + @param WTA_K The number of points that produce each element of the oriented BRIEF descriptor. The + default value 2 means the BRIEF where we take a random point pair and compare their brightnesses, + so we get 0/1 response. Other possible values are 3 and 4. For example, 3 means that we take 3 + random points (of course, those point coordinates are random, but they are generated from the + pre-defined seed, so each element of BRIEF descriptor is computed deterministically from the pixel + rectangle), find point of maximum brightness and output index of the winner (0, 1 or 2). Such + output will occupy 2 bits, and therefore it will need a special variant of Hamming distance, + denoted as NORM_HAMMING2 (2 bits per bin). When WTA_K=4, we take 4 random points to compute each + bin (that will also occupy 2 bits with possible values 0, 1, 2 or 3). + @param scoreType The default HARRIS_SCORE means that Harris algorithm is used to rank features + (the score is written to KeyPoint::score and is used to retain best nfeatures features); + FAST_SCORE is alternative value of the parameter that produces slightly less stable keypoints, + but it is a little faster to compute. + @param patchSize size of the patch used by the oriented BRIEF descriptor. Of course, on smaller + pyramid layers the perceived image area covered by a feature will be larger. + @param fastThreshold + */ + CV_WRAP static Ptr create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31, + int firstLevel=0, int WTA_K=2, int scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold=20); + + CV_WRAP virtual void setMaxFeatures(int maxFeatures) = 0; + CV_WRAP virtual int getMaxFeatures() const = 0; + + CV_WRAP virtual void setScaleFactor(double scaleFactor) = 0; + CV_WRAP virtual double getScaleFactor() const = 0; + + CV_WRAP virtual void setNLevels(int nlevels) = 0; + CV_WRAP virtual int getNLevels() const = 0; + + CV_WRAP virtual void setEdgeThreshold(int edgeThreshold) = 0; + CV_WRAP virtual int getEdgeThreshold() const = 0; + + CV_WRAP virtual void setFirstLevel(int firstLevel) = 0; + CV_WRAP virtual int getFirstLevel() const = 0; + + CV_WRAP virtual void setWTA_K(int wta_k) = 0; + CV_WRAP virtual int getWTA_K() const = 0; + + CV_WRAP virtual void setScoreType(int scoreType) = 0; + CV_WRAP virtual int getScoreType() const = 0; + + CV_WRAP virtual void setPatchSize(int patchSize) = 0; + CV_WRAP virtual int getPatchSize() const = 0; + + CV_WRAP virtual void setFastThreshold(int fastThreshold) = 0; + CV_WRAP virtual int getFastThreshold() const = 0; +}; + +/** @brief Maximally stable extremal region extractor. : + +The class encapsulates all the parameters of the MSER extraction algorithm (see +). Also see + for useful comments and parameters description. + +@note + - (Python) A complete example showing the use of the MSER detector can be found at + opencv_source_code/samples/python2/mser.py + */ +class CV_EXPORTS_W MSER : public Feature2D +{ +public: + //! the full constructor + CV_WRAP static Ptr create( int _delta=5, int _min_area=60, int _max_area=14400, + double _max_variation=0.25, double _min_diversity=.2, + int _max_evolution=200, double _area_threshold=1.01, + double _min_margin=0.003, int _edge_blur_size=5 ); + + CV_WRAP virtual void detectRegions( InputArray image, + CV_OUT std::vector >& msers, + std::vector& bboxes ) = 0; + + CV_WRAP virtual void setDelta(int delta) = 0; + CV_WRAP virtual int getDelta() const = 0; + + CV_WRAP virtual void setMinArea(int minArea) = 0; + CV_WRAP virtual int getMinArea() const = 0; + + CV_WRAP virtual void setMaxArea(int maxArea) = 0; + CV_WRAP virtual int getMaxArea() const = 0; + + CV_WRAP virtual void setPass2Only(bool f) = 0; + CV_WRAP virtual bool getPass2Only() const = 0; +}; + +/** @overload */ +CV_EXPORTS void FAST( InputArray image, CV_OUT std::vector& keypoints, + int threshold, bool nonmaxSuppression=true ); + +/** @brief Detects corners using the FAST algorithm + +@param image grayscale image where keypoints (corners) are detected. +@param keypoints keypoints detected on the image. +@param threshold threshold on difference between intensity of the central pixel and pixels of a +circle around this pixel. +@param nonmaxSuppression if true, non-maximum suppression is applied to detected corners +(keypoints). +@param type one of the three neighborhoods as defined in the paper: +FastFeatureDetector::TYPE_9_16, FastFeatureDetector::TYPE_7_12, +FastFeatureDetector::TYPE_5_8 + +Detects corners using the FAST algorithm by @cite Rosten06 . + +@note In Python API, types are given as cv2.FAST_FEATURE_DETECTOR_TYPE_5_8, +cv2.FAST_FEATURE_DETECTOR_TYPE_7_12 and cv2.FAST_FEATURE_DETECTOR_TYPE_9_16. For corner +detection, use cv2.FAST.detect() method. + */ +CV_EXPORTS void FAST( InputArray image, CV_OUT std::vector& keypoints, + int threshold, bool nonmaxSuppression, int type ); + +//! @} features2d_main + +//! @addtogroup features2d_main +//! @{ + +/** @brief Wrapping class for feature detection using the FAST method. : + */ +class CV_EXPORTS_W FastFeatureDetector : public Feature2D +{ +public: + enum + { + TYPE_5_8 = 0, TYPE_7_12 = 1, TYPE_9_16 = 2, + THRESHOLD = 10000, NONMAX_SUPPRESSION=10001, FAST_N=10002, + }; + + CV_WRAP static Ptr create( int threshold=10, + bool nonmaxSuppression=true, + int type=FastFeatureDetector::TYPE_9_16 ); + + CV_WRAP virtual void setThreshold(int threshold) = 0; + CV_WRAP virtual int getThreshold() const = 0; + + CV_WRAP virtual void setNonmaxSuppression(bool f) = 0; + CV_WRAP virtual bool getNonmaxSuppression() const = 0; + + CV_WRAP virtual void setType(int type) = 0; + CV_WRAP virtual int getType() const = 0; +}; + +/** @overload */ +CV_EXPORTS void AGAST( InputArray image, CV_OUT std::vector& keypoints, + int threshold, bool nonmaxSuppression=true ); + +/** @brief Detects corners using the AGAST algorithm + +@param image grayscale image where keypoints (corners) are detected. +@param keypoints keypoints detected on the image. +@param threshold threshold on difference between intensity of the central pixel and pixels of a +circle around this pixel. +@param nonmaxSuppression if true, non-maximum suppression is applied to detected corners +(keypoints). +@param type one of the four neighborhoods as defined in the paper: +AgastFeatureDetector::AGAST_5_8, AgastFeatureDetector::AGAST_7_12d, +AgastFeatureDetector::AGAST_7_12s, AgastFeatureDetector::OAST_9_16 + +Detects corners using the AGAST algorithm by @cite mair2010_agast . + + */ +CV_EXPORTS void AGAST( InputArray image, CV_OUT std::vector& keypoints, + int threshold, bool nonmaxSuppression, int type ); +//! @} features2d_main + +//! @addtogroup features2d_main +//! @{ + +/** @brief Wrapping class for feature detection using the AGAST method. : + */ +class CV_EXPORTS_W AgastFeatureDetector : public Feature2D +{ +public: + enum + { + AGAST_5_8 = 0, AGAST_7_12d = 1, AGAST_7_12s = 2, OAST_9_16 = 3, + THRESHOLD = 10000, NONMAX_SUPPRESSION = 10001, + }; + + CV_WRAP static Ptr create( int threshold=10, + bool nonmaxSuppression=true, + int type=AgastFeatureDetector::OAST_9_16 ); + + CV_WRAP virtual void setThreshold(int threshold) = 0; + CV_WRAP virtual int getThreshold() const = 0; + + CV_WRAP virtual void setNonmaxSuppression(bool f) = 0; + CV_WRAP virtual bool getNonmaxSuppression() const = 0; + + CV_WRAP virtual void setType(int type) = 0; + CV_WRAP virtual int getType() const = 0; +}; + +/** @brief Wrapping class for feature detection using the goodFeaturesToTrack function. : + */ +class CV_EXPORTS_W GFTTDetector : public Feature2D +{ +public: + CV_WRAP static Ptr create( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1, + int blockSize=3, bool useHarrisDetector=false, double k=0.04 ); + CV_WRAP virtual void setMaxFeatures(int maxFeatures) = 0; + CV_WRAP virtual int getMaxFeatures() const = 0; + + CV_WRAP virtual void setQualityLevel(double qlevel) = 0; + CV_WRAP virtual double getQualityLevel() const = 0; + + CV_WRAP virtual void setMinDistance(double minDistance) = 0; + CV_WRAP virtual double getMinDistance() const = 0; + + CV_WRAP virtual void setBlockSize(int blockSize) = 0; + CV_WRAP virtual int getBlockSize() const = 0; + + CV_WRAP virtual void setHarrisDetector(bool val) = 0; + CV_WRAP virtual bool getHarrisDetector() const = 0; + + CV_WRAP virtual void setK(double k) = 0; + CV_WRAP virtual double getK() const = 0; +}; + +/** @brief Class for extracting blobs from an image. : + +The class implements a simple algorithm for extracting blobs from an image: + +1. Convert the source image to binary images by applying thresholding with several thresholds from + minThreshold (inclusive) to maxThreshold (exclusive) with distance thresholdStep between + neighboring thresholds. +2. Extract connected components from every binary image by findContours and calculate their + centers. +3. Group centers from several binary images by their coordinates. Close centers form one group that + corresponds to one blob, which is controlled by the minDistBetweenBlobs parameter. +4. From the groups, estimate final centers of blobs and their radiuses and return as locations and + sizes of keypoints. + +This class performs several filtrations of returned blobs. You should set filterBy\* to true/false +to turn on/off corresponding filtration. Available filtrations: + +- **By color**. This filter compares the intensity of a binary image at the center of a blob to +blobColor. If they differ, the blob is filtered out. Use blobColor = 0 to extract dark blobs +and blobColor = 255 to extract light blobs. +- **By area**. Extracted blobs have an area between minArea (inclusive) and maxArea (exclusive). +- **By circularity**. Extracted blobs have circularity +(\f$\frac{4*\pi*Area}{perimeter * perimeter}\f$) between minCircularity (inclusive) and +maxCircularity (exclusive). +- **By ratio of the minimum inertia to maximum inertia**. Extracted blobs have this ratio +between minInertiaRatio (inclusive) and maxInertiaRatio (exclusive). +- **By convexity**. Extracted blobs have convexity (area / area of blob convex hull) between +minConvexity (inclusive) and maxConvexity (exclusive). + +Default values of parameters are tuned to extract dark circular blobs. + */ +class CV_EXPORTS_W SimpleBlobDetector : public Feature2D +{ +public: + struct CV_EXPORTS_W_SIMPLE Params + { + CV_WRAP Params(); + CV_PROP_RW float thresholdStep; + CV_PROP_RW float minThreshold; + CV_PROP_RW float maxThreshold; + CV_PROP_RW size_t minRepeatability; + CV_PROP_RW float minDistBetweenBlobs; + + CV_PROP_RW bool filterByColor; + CV_PROP_RW uchar blobColor; + + CV_PROP_RW bool filterByArea; + CV_PROP_RW float minArea, maxArea; + + CV_PROP_RW bool filterByCircularity; + CV_PROP_RW float minCircularity, maxCircularity; + + CV_PROP_RW bool filterByInertia; + CV_PROP_RW float minInertiaRatio, maxInertiaRatio; + + CV_PROP_RW bool filterByConvexity; + CV_PROP_RW float minConvexity, maxConvexity; + + void read( const FileNode& fn ); + void write( FileStorage& fs ) const; + }; + + CV_WRAP static Ptr + create(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params()); +}; + +//! @} features2d_main + +//! @addtogroup features2d_main +//! @{ + +/** @brief Class implementing the KAZE keypoint detector and descriptor extractor, described in @cite ABD12 . + +@note AKAZE descriptor can only be used with KAZE or AKAZE keypoints .. [ABD12] KAZE Features. Pablo +F. Alcantarilla, Adrien Bartoli and Andrew J. Davison. In European Conference on Computer Vision +(ECCV), Fiorenze, Italy, October 2012. +*/ +class CV_EXPORTS_W KAZE : public Feature2D +{ +public: + enum + { + DIFF_PM_G1 = 0, + DIFF_PM_G2 = 1, + DIFF_WEICKERT = 2, + DIFF_CHARBONNIER = 3 + }; + + /** @brief The KAZE constructor + + @param extended Set to enable extraction of extended (128-byte) descriptor. + @param upright Set to enable use of upright descriptors (non rotation-invariant). + @param threshold Detector response threshold to accept point + @param nOctaves Maximum octave evolution of the image + @param nOctaveLayers Default number of sublevels per scale level + @param diffusivity Diffusivity type. DIFF_PM_G1, DIFF_PM_G2, DIFF_WEICKERT or + DIFF_CHARBONNIER + */ + CV_WRAP static Ptr create(bool extended=false, bool upright=false, + float threshold = 0.001f, + int nOctaves = 4, int nOctaveLayers = 4, + int diffusivity = KAZE::DIFF_PM_G2); + + CV_WRAP virtual void setExtended(bool extended) = 0; + CV_WRAP virtual bool getExtended() const = 0; + + CV_WRAP virtual void setUpright(bool upright) = 0; + CV_WRAP virtual bool getUpright() const = 0; + + CV_WRAP virtual void setThreshold(double threshold) = 0; + CV_WRAP virtual double getThreshold() const = 0; + + CV_WRAP virtual void setNOctaves(int octaves) = 0; + CV_WRAP virtual int getNOctaves() const = 0; + + CV_WRAP virtual void setNOctaveLayers(int octaveLayers) = 0; + CV_WRAP virtual int getNOctaveLayers() const = 0; + + CV_WRAP virtual void setDiffusivity(int diff) = 0; + CV_WRAP virtual int getDiffusivity() const = 0; +}; + +/** @brief Class implementing the AKAZE keypoint detector and descriptor extractor, described in @cite ANB13 . : + +@note AKAZE descriptors can only be used with KAZE or AKAZE keypoints. Try to avoid using *extract* +and *detect* instead of *operator()* due to performance reasons. .. [ANB13] Fast Explicit Diffusion +for Accelerated Features in Nonlinear Scale Spaces. Pablo F. Alcantarilla, Jesús Nuevo and Adrien +Bartoli. In British Machine Vision Conference (BMVC), Bristol, UK, September 2013. + */ +class CV_EXPORTS_W AKAZE : public Feature2D +{ +public: + // AKAZE descriptor type + enum + { + DESCRIPTOR_KAZE_UPRIGHT = 2, ///< Upright descriptors, not invariant to rotation + DESCRIPTOR_KAZE = 3, + DESCRIPTOR_MLDB_UPRIGHT = 4, ///< Upright descriptors, not invariant to rotation + DESCRIPTOR_MLDB = 5 + }; + + /** @brief The AKAZE constructor + + @param descriptor_type Type of the extracted descriptor: DESCRIPTOR_KAZE, + DESCRIPTOR_KAZE_UPRIGHT, DESCRIPTOR_MLDB or DESCRIPTOR_MLDB_UPRIGHT. + @param descriptor_size Size of the descriptor in bits. 0 -\> Full size + @param descriptor_channels Number of channels in the descriptor (1, 2, 3) + @param threshold Detector response threshold to accept point + @param nOctaves Maximum octave evolution of the image + @param nOctaveLayers Default number of sublevels per scale level + @param diffusivity Diffusivity type. DIFF_PM_G1, DIFF_PM_G2, DIFF_WEICKERT or + DIFF_CHARBONNIER + */ + CV_WRAP static Ptr create(int descriptor_type=AKAZE::DESCRIPTOR_MLDB, + int descriptor_size = 0, int descriptor_channels = 3, + float threshold = 0.001f, int nOctaves = 4, + int nOctaveLayers = 4, int diffusivity = KAZE::DIFF_PM_G2); + + CV_WRAP virtual void setDescriptorType(int dtype) = 0; + CV_WRAP virtual int getDescriptorType() const = 0; + + CV_WRAP virtual void setDescriptorSize(int dsize) = 0; + CV_WRAP virtual int getDescriptorSize() const = 0; + + CV_WRAP virtual void setDescriptorChannels(int dch) = 0; + CV_WRAP virtual int getDescriptorChannels() const = 0; + + CV_WRAP virtual void setThreshold(double threshold) = 0; + CV_WRAP virtual double getThreshold() const = 0; + + CV_WRAP virtual void setNOctaves(int octaves) = 0; + CV_WRAP virtual int getNOctaves() const = 0; + + CV_WRAP virtual void setNOctaveLayers(int octaveLayers) = 0; + CV_WRAP virtual int getNOctaveLayers() const = 0; + + CV_WRAP virtual void setDiffusivity(int diff) = 0; + CV_WRAP virtual int getDiffusivity() const = 0; +}; + +//! @} features2d_main + +/****************************************************************************************\ +* Distance * +\****************************************************************************************/ + +template +struct CV_EXPORTS Accumulator +{ + typedef T Type; +}; + +template<> struct Accumulator { typedef float Type; }; +template<> struct Accumulator { typedef float Type; }; +template<> struct Accumulator { typedef float Type; }; +template<> struct Accumulator { typedef float Type; }; + +/* + * Squared Euclidean distance functor + */ +template +struct CV_EXPORTS SL2 +{ + enum { normType = NORM_L2SQR }; + typedef T ValueType; + typedef typename Accumulator::Type ResultType; + + ResultType operator()( const T* a, const T* b, int size ) const + { + return normL2Sqr(a, b, size); + } +}; + +/* + * Euclidean distance functor + */ +template +struct CV_EXPORTS L2 +{ + enum { normType = NORM_L2 }; + typedef T ValueType; + typedef typename Accumulator::Type ResultType; + + ResultType operator()( const T* a, const T* b, int size ) const + { + return (ResultType)std::sqrt((double)normL2Sqr(a, b, size)); + } +}; + +/* + * Manhattan distance (city block distance) functor + */ +template +struct CV_EXPORTS L1 +{ + enum { normType = NORM_L1 }; + typedef T ValueType; + typedef typename Accumulator::Type ResultType; + + ResultType operator()( const T* a, const T* b, int size ) const + { + return normL1(a, b, size); + } +}; + +/****************************************************************************************\ +* DescriptorMatcher * +\****************************************************************************************/ + +//! @addtogroup features2d_match +//! @{ + +/** @brief Abstract base class for matching keypoint descriptors. + +It has two groups of match methods: for matching descriptors of an image with another image or with +an image set. + */ +class CV_EXPORTS_W DescriptorMatcher : public Algorithm +{ +public: + virtual ~DescriptorMatcher(); + + /** @brief Adds descriptors to train a CPU(trainDescCollectionis) or GPU(utrainDescCollectionis) descriptor + collection. + + If the collection is not empty, the new descriptors are added to existing train descriptors. + + @param descriptors Descriptors to add. Each descriptors[i] is a set of descriptors from the same + train image. + */ + CV_WRAP virtual void add( InputArrayOfArrays descriptors ); + + /** @brief Returns a constant link to the train descriptor collection trainDescCollection . + */ + CV_WRAP const std::vector& getTrainDescriptors() const; + + /** @brief Clears the train descriptor collections. + */ + CV_WRAP virtual void clear(); + + /** @brief Returns true if there are no train descriptors in the both collections. + */ + CV_WRAP virtual bool empty() const; + + /** @brief Returns true if the descriptor matcher supports masking permissible matches. + */ + CV_WRAP virtual bool isMaskSupported() const = 0; + + /** @brief Trains a descriptor matcher + + Trains a descriptor matcher (for example, the flann index). In all methods to match, the method + train() is run every time before matching. Some descriptor matchers (for example, BruteForceMatcher) + have an empty implementation of this method. Other matchers really train their inner structures (for + example, FlannBasedMatcher trains flann::Index ). + */ + CV_WRAP virtual void train(); + + /** @brief Finds the best match for each descriptor from a query set. + + @param queryDescriptors Query set of descriptors. + @param trainDescriptors Train set of descriptors. This set is not added to the train descriptors + collection stored in the class object. + @param matches Matches. If a query descriptor is masked out in mask , no match is added for this + descriptor. So, matches size may be smaller than the query descriptors count. + @param mask Mask specifying permissible matches between an input query and train matrices of + descriptors. + + In the first variant of this method, the train descriptors are passed as an input argument. In the + second variant of the method, train descriptors collection that was set by DescriptorMatcher::add is + used. Optional mask (or masks) can be passed to specify which query and training descriptors can be + matched. Namely, queryDescriptors[i] can be matched with trainDescriptors[j] only if + mask.at\(i,j) is non-zero. + */ + CV_WRAP void match( InputArray queryDescriptors, InputArray trainDescriptors, + CV_OUT std::vector& matches, InputArray mask=noArray() ) const; + + /** @brief Finds the k best matches for each descriptor from a query set. + + @param queryDescriptors Query set of descriptors. + @param trainDescriptors Train set of descriptors. This set is not added to the train descriptors + collection stored in the class object. + @param mask Mask specifying permissible matches between an input query and train matrices of + descriptors. + @param matches Matches. Each matches[i] is k or less matches for the same query descriptor. + @param k Count of best matches found per each query descriptor or less if a query descriptor has + less than k possible matches in total. + @param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is + false, the matches vector has the same size as queryDescriptors rows. If compactResult is true, + the matches vector does not contain matches for fully masked-out query descriptors. + + These extended variants of DescriptorMatcher::match methods find several best matches for each query + descriptor. The matches are returned in the distance increasing order. See DescriptorMatcher::match + for the details about query and train descriptors. + */ + CV_WRAP void knnMatch( InputArray queryDescriptors, InputArray trainDescriptors, + CV_OUT std::vector >& matches, int k, + InputArray mask=noArray(), bool compactResult=false ) const; + + /** @brief For each query descriptor, finds the training descriptors not farther than the specified distance. + + @param queryDescriptors Query set of descriptors. + @param trainDescriptors Train set of descriptors. This set is not added to the train descriptors + collection stored in the class object. + @param matches Found matches. + @param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is + false, the matches vector has the same size as queryDescriptors rows. If compactResult is true, + the matches vector does not contain matches for fully masked-out query descriptors. + @param maxDistance Threshold for the distance between matched descriptors. Distance means here + metric distance (e.g. Hamming distance), not the distance between coordinates (which is measured + in Pixels)! + @param mask Mask specifying permissible matches between an input query and train matrices of + descriptors. + + For each query descriptor, the methods find such training descriptors that the distance between the + query descriptor and the training descriptor is equal or smaller than maxDistance. Found matches are + returned in the distance increasing order. + */ + void radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors, + std::vector >& matches, float maxDistance, + InputArray mask=noArray(), bool compactResult=false ) const; + + /** @overload + @param queryDescriptors Query set of descriptors. + @param matches Matches. If a query descriptor is masked out in mask , no match is added for this + descriptor. So, matches size may be smaller than the query descriptors count. + @param masks Set of masks. Each masks[i] specifies permissible matches between the input query + descriptors and stored train descriptors from the i-th image trainDescCollection[i]. + */ + CV_WRAP void match( InputArray queryDescriptors, CV_OUT std::vector& matches, + InputArrayOfArrays masks=noArray() ); + /** @overload + @param queryDescriptors Query set of descriptors. + @param matches Matches. Each matches[i] is k or less matches for the same query descriptor. + @param k Count of best matches found per each query descriptor or less if a query descriptor has + less than k possible matches in total. + @param masks Set of masks. Each masks[i] specifies permissible matches between the input query + descriptors and stored train descriptors from the i-th image trainDescCollection[i]. + @param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is + false, the matches vector has the same size as queryDescriptors rows. If compactResult is true, + the matches vector does not contain matches for fully masked-out query descriptors. + */ + CV_WRAP void knnMatch( InputArray queryDescriptors, CV_OUT std::vector >& matches, int k, + InputArrayOfArrays masks=noArray(), bool compactResult=false ); + /** @overload + @param queryDescriptors Query set of descriptors. + @param matches Found matches. + @param maxDistance Threshold for the distance between matched descriptors. Distance means here + metric distance (e.g. Hamming distance), not the distance between coordinates (which is measured + in Pixels)! + @param masks Set of masks. Each masks[i] specifies permissible matches between the input query + descriptors and stored train descriptors from the i-th image trainDescCollection[i]. + @param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is + false, the matches vector has the same size as queryDescriptors rows. If compactResult is true, + the matches vector does not contain matches for fully masked-out query descriptors. + */ + void radiusMatch( InputArray queryDescriptors, std::vector >& matches, float maxDistance, + InputArrayOfArrays masks=noArray(), bool compactResult=false ); + + // Reads matcher object from a file node + virtual void read( const FileNode& ); + // Writes matcher object to a file storage + virtual void write( FileStorage& ) const; + + /** @brief Clones the matcher. + + @param emptyTrainData If emptyTrainData is false, the method creates a deep copy of the object, + that is, copies both parameters and train data. If emptyTrainData is true, the method creates an + object copy with the current parameters but with empty train data. + */ + virtual Ptr clone( bool emptyTrainData=false ) const = 0; + + /** @brief Creates a descriptor matcher of a given type with the default parameters (using default + constructor). + + @param descriptorMatcherType Descriptor matcher type. Now the following matcher types are + supported: + - `BruteForce` (it uses L2 ) + - `BruteForce-L1` + - `BruteForce-Hamming` + - `BruteForce-Hamming(2)` + - `FlannBased` + */ + CV_WRAP static Ptr create( const String& descriptorMatcherType ); +protected: + /** + * Class to work with descriptors from several images as with one merged matrix. + * It is used e.g. in FlannBasedMatcher. + */ + class CV_EXPORTS DescriptorCollection + { + public: + DescriptorCollection(); + DescriptorCollection( const DescriptorCollection& collection ); + virtual ~DescriptorCollection(); + + // Vector of matrices "descriptors" will be merged to one matrix "mergedDescriptors" here. + void set( const std::vector& descriptors ); + virtual void clear(); + + const Mat& getDescriptors() const; + const Mat getDescriptor( int imgIdx, int localDescIdx ) const; + const Mat getDescriptor( int globalDescIdx ) const; + void getLocalIdx( int globalDescIdx, int& imgIdx, int& localDescIdx ) const; + + int size() const; + + protected: + Mat mergedDescriptors; + std::vector startIdxs; + }; + + //! In fact the matching is implemented only by the following two methods. These methods suppose + //! that the class object has been trained already. Public match methods call these methods + //! after calling train(). + virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, + InputArrayOfArrays masks=noArray(), bool compactResult=false ) = 0; + virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, + InputArrayOfArrays masks=noArray(), bool compactResult=false ) = 0; + + static bool isPossibleMatch( InputArray mask, int queryIdx, int trainIdx ); + static bool isMaskedOut( InputArrayOfArrays masks, int queryIdx ); + + static Mat clone_op( Mat m ) { return m.clone(); } + void checkMasks( InputArrayOfArrays masks, int queryDescriptorsCount ) const; + + //! Collection of descriptors from train images. + std::vector trainDescCollection; + std::vector utrainDescCollection; +}; + +/** @brief Brute-force descriptor matcher. + +For each descriptor in the first set, this matcher finds the closest descriptor in the second set +by trying each one. This descriptor matcher supports masking permissible matches of descriptor +sets. + */ +class CV_EXPORTS_W BFMatcher : public DescriptorMatcher +{ +public: + /** @brief Brute-force matcher constructor. + + @param normType One of NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2. L1 and L2 norms are + preferable choices for SIFT and SURF descriptors, NORM_HAMMING should be used with ORB, BRISK and + BRIEF, NORM_HAMMING2 should be used with ORB when WTA_K==3 or 4 (see ORB::ORB constructor + description). + @param crossCheck If it is false, this is will be default BFMatcher behaviour when it finds the k + nearest neighbors for each query descriptor. If crossCheck==true, then the knnMatch() method with + k=1 will only return pairs (i,j) such that for i-th query descriptor the j-th descriptor in the + matcher's collection is the nearest and vice versa, i.e. the BFMatcher will only return consistent + pairs. Such technique usually produces best results with minimal number of outliers when there are + enough matches. This is alternative to the ratio test, used by D. Lowe in SIFT paper. + */ + CV_WRAP BFMatcher( int normType=NORM_L2, bool crossCheck=false ); + virtual ~BFMatcher() {} + + virtual bool isMaskSupported() const { return true; } + + virtual Ptr clone( bool emptyTrainData=false ) const; +protected: + virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, + InputArrayOfArrays masks=noArray(), bool compactResult=false ); + virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, + InputArrayOfArrays masks=noArray(), bool compactResult=false ); + + int normType; + bool crossCheck; +}; + + +/** @brief Flann-based descriptor matcher. + +This matcher trains flann::Index_ on a train descriptor collection and calls its nearest search +methods to find the best matches. So, this matcher may be faster when matching a large train +collection than the brute force matcher. FlannBasedMatcher does not support masking permissible +matches of descriptor sets because flann::Index does not support this. : + */ +class CV_EXPORTS_W FlannBasedMatcher : public DescriptorMatcher +{ +public: + CV_WRAP FlannBasedMatcher( const Ptr& indexParams=makePtr(), + const Ptr& searchParams=makePtr() ); + + virtual void add( InputArrayOfArrays descriptors ); + virtual void clear(); + + // Reads matcher object from a file node + virtual void read( const FileNode& ); + // Writes matcher object to a file storage + virtual void write( FileStorage& ) const; + + virtual void train(); + virtual bool isMaskSupported() const; + + virtual Ptr clone( bool emptyTrainData=false ) const; +protected: + static void convertToDMatches( const DescriptorCollection& descriptors, + const Mat& indices, const Mat& distances, + std::vector >& matches ); + + virtual void knnMatchImpl( InputArray queryDescriptors, std::vector >& matches, int k, + InputArrayOfArrays masks=noArray(), bool compactResult=false ); + virtual void radiusMatchImpl( InputArray queryDescriptors, std::vector >& matches, float maxDistance, + InputArrayOfArrays masks=noArray(), bool compactResult=false ); + + Ptr indexParams; + Ptr searchParams; + Ptr flannIndex; + + DescriptorCollection mergedDescriptors; + int addedDescCount; +}; + +//! @} features2d_match + +/****************************************************************************************\ +* Drawing functions * +\****************************************************************************************/ + +//! @addtogroup features2d_draw +//! @{ + +struct CV_EXPORTS DrawMatchesFlags +{ + enum{ DEFAULT = 0, //!< Output image matrix will be created (Mat::create), + //!< i.e. existing memory of output image may be reused. + //!< Two source image, matches and single keypoints will be drawn. + //!< For each keypoint only the center point will be drawn (without + //!< the circle around keypoint with keypoint size and orientation). + DRAW_OVER_OUTIMG = 1, //!< Output image matrix will not be created (Mat::create). + //!< Matches will be drawn on existing content of output image. + NOT_DRAW_SINGLE_POINTS = 2, //!< Single keypoints will not be drawn. + DRAW_RICH_KEYPOINTS = 4 //!< For each keypoint the circle around keypoint with keypoint size and + //!< orientation will be drawn. + }; +}; + +/** @brief Draws keypoints. + +@param image Source image. +@param keypoints Keypoints from the source image. +@param outImage Output image. Its content depends on the flags value defining what is drawn in the +output image. See possible flags bit values below. +@param color Color of keypoints. +@param flags Flags setting drawing features. Possible flags bit values are defined by +DrawMatchesFlags. See details above in drawMatches . + +@note +For Python API, flags are modified as cv2.DRAW_MATCHES_FLAGS_DEFAULT, +cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS, cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG, +cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS + */ +CV_EXPORTS_W void drawKeypoints( InputArray image, const std::vector& keypoints, InputOutputArray outImage, + const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT ); + +/** @brief Draws the found matches of keypoints from two images. + +@param img1 First source image. +@param keypoints1 Keypoints from the first source image. +@param img2 Second source image. +@param keypoints2 Keypoints from the second source image. +@param matches1to2 Matches from the first image to the second one, which means that keypoints1[i] +has a corresponding point in keypoints2[matches[i]] . +@param outImg Output image. Its content depends on the flags value defining what is drawn in the +output image. See possible flags bit values below. +@param matchColor Color of matches (lines and connected keypoints). If matchColor==Scalar::all(-1) +, the color is generated randomly. +@param singlePointColor Color of single keypoints (circles), which means that keypoints do not +have the matches. If singlePointColor==Scalar::all(-1) , the color is generated randomly. +@param matchesMask Mask determining which matches are drawn. If the mask is empty, all matches are +drawn. +@param flags Flags setting drawing features. Possible flags bit values are defined by +DrawMatchesFlags. + +This function draws matches of keypoints from two images in the output image. Match is a line +connecting two keypoints (circles). See cv::DrawMatchesFlags. + */ +CV_EXPORTS_W void drawMatches( InputArray img1, const std::vector& keypoints1, + InputArray img2, const std::vector& keypoints2, + const std::vector& matches1to2, InputOutputArray outImg, + const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), + const std::vector& matchesMask=std::vector(), int flags=DrawMatchesFlags::DEFAULT ); + +/** @overload */ +CV_EXPORTS_AS(drawMatchesKnn) void drawMatches( InputArray img1, const std::vector& keypoints1, + InputArray img2, const std::vector& keypoints2, + const std::vector >& matches1to2, InputOutputArray outImg, + const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), + const std::vector >& matchesMask=std::vector >(), int flags=DrawMatchesFlags::DEFAULT ); + +//! @} features2d_draw + +/****************************************************************************************\ +* Functions to evaluate the feature detectors and [generic] descriptor extractors * +\****************************************************************************************/ + +CV_EXPORTS void evaluateFeatureDetector( const Mat& img1, const Mat& img2, const Mat& H1to2, + std::vector* keypoints1, std::vector* keypoints2, + float& repeatability, int& correspCount, + const Ptr& fdetector=Ptr() ); + +CV_EXPORTS void computeRecallPrecisionCurve( const std::vector >& matches1to2, + const std::vector >& correctMatches1to2Mask, + std::vector& recallPrecisionCurve ); + +CV_EXPORTS float getRecall( const std::vector& recallPrecisionCurve, float l_precision ); +CV_EXPORTS int getNearestPoint( const std::vector& recallPrecisionCurve, float l_precision ); + +/****************************************************************************************\ +* Bag of visual words * +\****************************************************************************************/ + +//! @addtogroup features2d_category +//! @{ + +/** @brief Abstract base class for training the *bag of visual words* vocabulary from a set of descriptors. + +For details, see, for example, *Visual Categorization with Bags of Keypoints* by Gabriella Csurka, +Christopher R. Dance, Lixin Fan, Jutta Willamowski, Cedric Bray, 2004. : + */ +class CV_EXPORTS_W BOWTrainer +{ +public: + BOWTrainer(); + virtual ~BOWTrainer(); + + /** @brief Adds descriptors to a training set. + + @param descriptors Descriptors to add to a training set. Each row of the descriptors matrix is a + descriptor. + + The training set is clustered using clustermethod to construct the vocabulary. + */ + CV_WRAP void add( const Mat& descriptors ); + + /** @brief Returns a training set of descriptors. + */ + CV_WRAP const std::vector& getDescriptors() const; + + /** @brief Returns the count of all descriptors stored in the training set. + */ + CV_WRAP int descriptorsCount() const; + + CV_WRAP virtual void clear(); + + /** @overload */ + CV_WRAP virtual Mat cluster() const = 0; + + /** @brief Clusters train descriptors. + + @param descriptors Descriptors to cluster. Each row of the descriptors matrix is a descriptor. + Descriptors are not added to the inner train descriptor set. + + The vocabulary consists of cluster centers. So, this method returns the vocabulary. In the first + variant of the method, train descriptors stored in the object are clustered. In the second variant, + input descriptors are clustered. + */ + CV_WRAP virtual Mat cluster( const Mat& descriptors ) const = 0; + +protected: + std::vector descriptors; + int size; +}; + +/** @brief kmeans -based class to train visual vocabulary using the *bag of visual words* approach. : + */ +class CV_EXPORTS_W BOWKMeansTrainer : public BOWTrainer +{ +public: + /** @brief The constructor. + + @see cv::kmeans + */ + CV_WRAP BOWKMeansTrainer( int clusterCount, const TermCriteria& termcrit=TermCriteria(), + int attempts=3, int flags=KMEANS_PP_CENTERS ); + virtual ~BOWKMeansTrainer(); + + // Returns trained vocabulary (i.e. cluster centers). + CV_WRAP virtual Mat cluster() const; + CV_WRAP virtual Mat cluster( const Mat& descriptors ) const; + +protected: + + int clusterCount; + TermCriteria termcrit; + int attempts; + int flags; +}; + +/** @brief Class to compute an image descriptor using the *bag of visual words*. + +Such a computation consists of the following steps: + +1. Compute descriptors for a given image and its keypoints set. +2. Find the nearest visual words from the vocabulary for each keypoint descriptor. +3. Compute the bag-of-words image descriptor as is a normalized histogram of vocabulary words +encountered in the image. The i-th bin of the histogram is a frequency of i-th word of the +vocabulary in the given image. + */ +class CV_EXPORTS_W BOWImgDescriptorExtractor +{ +public: + /** @brief The constructor. + + @param dextractor Descriptor extractor that is used to compute descriptors for an input image and + its keypoints. + @param dmatcher Descriptor matcher that is used to find the nearest word of the trained vocabulary + for each keypoint descriptor of the image. + */ + CV_WRAP BOWImgDescriptorExtractor( const Ptr& dextractor, + const Ptr& dmatcher ); + /** @overload */ + BOWImgDescriptorExtractor( const Ptr& dmatcher ); + virtual ~BOWImgDescriptorExtractor(); + + /** @brief Sets a visual vocabulary. + + @param vocabulary Vocabulary (can be trained using the inheritor of BOWTrainer ). Each row of the + vocabulary is a visual word (cluster center). + */ + CV_WRAP void setVocabulary( const Mat& vocabulary ); + + /** @brief Returns the set vocabulary. + */ + CV_WRAP const Mat& getVocabulary() const; + + /** @brief Computes an image descriptor using the set visual vocabulary. + + @param image Image, for which the descriptor is computed. + @param keypoints Keypoints detected in the input image. + @param imgDescriptor Computed output image descriptor. + @param pointIdxsOfClusters Indices of keypoints that belong to the cluster. This means that + pointIdxsOfClusters[i] are keypoint indices that belong to the i -th cluster (word of vocabulary) + returned if it is non-zero. + @param descriptors Descriptors of the image keypoints that are returned if they are non-zero. + */ + void compute( InputArray image, std::vector& keypoints, OutputArray imgDescriptor, + std::vector >* pointIdxsOfClusters=0, Mat* descriptors=0 ); + /** @overload + @param keypointDescriptors Computed descriptors to match with vocabulary. + @param imgDescriptor Computed output image descriptor. + @param pointIdxsOfClusters Indices of keypoints that belong to the cluster. This means that + pointIdxsOfClusters[i] are keypoint indices that belong to the i -th cluster (word of vocabulary) + returned if it is non-zero. + */ + void compute( InputArray keypointDescriptors, OutputArray imgDescriptor, + std::vector >* pointIdxsOfClusters=0 ); + // compute() is not constant because DescriptorMatcher::match is not constant + + CV_WRAP_AS(compute) void compute2( const Mat& image, std::vector& keypoints, CV_OUT Mat& imgDescriptor ) + { compute(image,keypoints,imgDescriptor); } + + /** @brief Returns an image descriptor size if the vocabulary is set. Otherwise, it returns 0. + */ + CV_WRAP int descriptorSize() const; + + /** @brief Returns an image descriptor type. + */ + CV_WRAP int descriptorType() const; + +protected: + Mat vocabulary; + Ptr dextractor; + Ptr dmatcher; +}; + +//! @} features2d_category + +//! @} features2d + +} /* namespace cv */ + +#endif diff --git a/include/opencv2/features2d/features2d.hpp b/include/opencv2/features2d/features2d.hpp new file mode 100644 index 0000000..e81df0a --- /dev/null +++ b/include/opencv2/features2d/features2d.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/features2d.hpp" diff --git a/include/opencv2/flann.hpp b/include/opencv2/flann.hpp new file mode 100644 index 0000000..4f92d57 --- /dev/null +++ b/include/opencv2/flann.hpp @@ -0,0 +1,561 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef _OPENCV_FLANN_HPP_ +#define _OPENCV_FLANN_HPP_ + +#include "opencv2/core.hpp" +#include "opencv2/flann/miniflann.hpp" +#include "opencv2/flann/flann_base.hpp" + +/** +@defgroup flann Clustering and Search in Multi-Dimensional Spaces + +This section documents OpenCV's interface to the FLANN library. FLANN (Fast Library for Approximate +Nearest Neighbors) is a library that contains a collection of algorithms optimized for fast nearest +neighbor search in large datasets and for high dimensional features. More information about FLANN +can be found in @cite Muja2009 . +*/ + +namespace cvflann +{ + CV_EXPORTS flann_distance_t flann_distance_type(); + FLANN_DEPRECATED CV_EXPORTS void set_distance_type(flann_distance_t distance_type, int order); +} + + +namespace cv +{ +namespace flann +{ + + +//! @addtogroup flann +//! @{ + +template struct CvType {}; +template <> struct CvType { static int type() { return CV_8U; } }; +template <> struct CvType { static int type() { return CV_8S; } }; +template <> struct CvType { static int type() { return CV_16U; } }; +template <> struct CvType { static int type() { return CV_16S; } }; +template <> struct CvType { static int type() { return CV_32S; } }; +template <> struct CvType { static int type() { return CV_32F; } }; +template <> struct CvType { static int type() { return CV_64F; } }; + + +// bring the flann parameters into this namespace +using ::cvflann::get_param; +using ::cvflann::print_params; + +// bring the flann distances into this namespace +using ::cvflann::L2_Simple; +using ::cvflann::L2; +using ::cvflann::L1; +using ::cvflann::MinkowskiDistance; +using ::cvflann::MaxDistance; +using ::cvflann::HammingLUT; +using ::cvflann::Hamming; +using ::cvflann::Hamming2; +using ::cvflann::HistIntersectionDistance; +using ::cvflann::HellingerDistance; +using ::cvflann::ChiSquareDistance; +using ::cvflann::KL_Divergence; + + +/** @brief The FLANN nearest neighbor index class. This class is templated with the type of elements for which +the index is built. + */ +template +class GenericIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + /** @brief Constructs a nearest neighbor search index for a given dataset. + + @param features Matrix of containing the features(points) to index. The size of the matrix is + num_features x feature_dimensionality and the data type of the elements in the matrix must + coincide with the type of the index. + @param params Structure containing the index parameters. The type of index that will be + constructed depends on the type of this parameter. See the description. + @param distance + + The method constructs a fast search structure from a set of features using the specified algorithm + with specified parameters, as defined by params. params is a reference to one of the following class + IndexParams descendants: + + - **LinearIndexParams** When passing an object of this type, the index will perform a linear, + brute-force search. : + @code + struct LinearIndexParams : public IndexParams + { + }; + @endcode + - **KDTreeIndexParams** When passing an object of this type the index constructed will consist of + a set of randomized kd-trees which will be searched in parallel. : + @code + struct KDTreeIndexParams : public IndexParams + { + KDTreeIndexParams( int trees = 4 ); + }; + @endcode + - **KMeansIndexParams** When passing an object of this type the index constructed will be a + hierarchical k-means tree. : + @code + struct KMeansIndexParams : public IndexParams + { + KMeansIndexParams( + int branching = 32, + int iterations = 11, + flann_centers_init_t centers_init = CENTERS_RANDOM, + float cb_index = 0.2 ); + }; + @endcode + - **CompositeIndexParams** When using a parameters object of this type the index created + combines the randomized kd-trees and the hierarchical k-means tree. : + @code + struct CompositeIndexParams : public IndexParams + { + CompositeIndexParams( + int trees = 4, + int branching = 32, + int iterations = 11, + flann_centers_init_t centers_init = CENTERS_RANDOM, + float cb_index = 0.2 ); + }; + @endcode + - **LshIndexParams** When using a parameters object of this type the index created uses + multi-probe LSH (by Multi-Probe LSH: Efficient Indexing for High-Dimensional Similarity Search + by Qin Lv, William Josephson, Zhe Wang, Moses Charikar, Kai Li., Proceedings of the 33rd + International Conference on Very Large Data Bases (VLDB). Vienna, Austria. September 2007) : + @code + struct LshIndexParams : public IndexParams + { + LshIndexParams( + unsigned int table_number, + unsigned int key_size, + unsigned int multi_probe_level ); + }; + @endcode + - **AutotunedIndexParams** When passing an object of this type the index created is + automatically tuned to offer the best performance, by choosing the optimal index type + (randomized kd-trees, hierarchical kmeans, linear) and parameters for the dataset provided. : + @code + struct AutotunedIndexParams : public IndexParams + { + AutotunedIndexParams( + float target_precision = 0.9, + float build_weight = 0.01, + float memory_weight = 0, + float sample_fraction = 0.1 ); + }; + @endcode + - **SavedIndexParams** This object type is used for loading a previously saved index from the + disk. : + @code + struct SavedIndexParams : public IndexParams + { + SavedIndexParams( String filename ); + }; + @endcode + */ + GenericIndex(const Mat& features, const ::cvflann::IndexParams& params, Distance distance = Distance()); + + ~GenericIndex(); + + /** @brief Performs a K-nearest neighbor search for a given query point using the index. + + @param query The query point + @param indices Vector that will contain the indices of the K-nearest neighbors found. It must have + at least knn size. + @param dists Vector that will contain the distances to the K-nearest neighbors found. It must have + at least knn size. + @param knn Number of nearest neighbors to search for. + @param params SearchParams + */ + void knnSearch(const std::vector& query, std::vector& indices, + std::vector& dists, int knn, const ::cvflann::SearchParams& params); + void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params); + + int radiusSearch(const std::vector& query, std::vector& indices, + std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& params); + int radiusSearch(const Mat& query, Mat& indices, Mat& dists, + DistanceType radius, const ::cvflann::SearchParams& params); + + void save(String filename) { nnIndex->save(filename); } + + int veclen() const { return nnIndex->veclen(); } + + int size() const { return nnIndex->size(); } + + ::cvflann::IndexParams getParameters() { return nnIndex->getParameters(); } + + FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters() { return nnIndex->getIndexParameters(); } + +private: + ::cvflann::Index* nnIndex; +}; + +//! @cond IGNORED + +#define FLANN_DISTANCE_CHECK \ + if ( ::cvflann::flann_distance_type() != cvflann::FLANN_DIST_L2) { \ + printf("[WARNING] You are using cv::flann::Index (or cv::flann::GenericIndex) and have also changed "\ + "the distance using cvflann::set_distance_type. This is no longer working as expected "\ + "(cv::flann::Index always uses L2). You should create the index templated on the distance, "\ + "for example for L1 distance use: GenericIndex< L1 > \n"); \ + } + + +template +GenericIndex::GenericIndex(const Mat& dataset, const ::cvflann::IndexParams& params, Distance distance) +{ + CV_Assert(dataset.type() == CvType::type()); + CV_Assert(dataset.isContinuous()); + ::cvflann::Matrix m_dataset((ElementType*)dataset.ptr(0), dataset.rows, dataset.cols); + + nnIndex = new ::cvflann::Index(m_dataset, params, distance); + + FLANN_DISTANCE_CHECK + + nnIndex->buildIndex(); +} + +template +GenericIndex::~GenericIndex() +{ + delete nnIndex; +} + +template +void GenericIndex::knnSearch(const std::vector& query, std::vector& indices, std::vector& dists, int knn, const ::cvflann::SearchParams& searchParams) +{ + ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size()); + ::cvflann::Matrix m_indices(&indices[0], 1, indices.size()); + ::cvflann::Matrix m_dists(&dists[0], 1, dists.size()); + + FLANN_DISTANCE_CHECK + + nnIndex->knnSearch(m_query,m_indices,m_dists,knn,searchParams); +} + + +template +void GenericIndex::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams) +{ + CV_Assert(queries.type() == CvType::type()); + CV_Assert(queries.isContinuous()); + ::cvflann::Matrix m_queries((ElementType*)queries.ptr(0), queries.rows, queries.cols); + + CV_Assert(indices.type() == CV_32S); + CV_Assert(indices.isContinuous()); + ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols); + + CV_Assert(dists.type() == CvType::type()); + CV_Assert(dists.isContinuous()); + ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols); + + FLANN_DISTANCE_CHECK + + nnIndex->knnSearch(m_queries,m_indices,m_dists,knn, searchParams); +} + +template +int GenericIndex::radiusSearch(const std::vector& query, std::vector& indices, std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams) +{ + ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size()); + ::cvflann::Matrix m_indices(&indices[0], 1, indices.size()); + ::cvflann::Matrix m_dists(&dists[0], 1, dists.size()); + + FLANN_DISTANCE_CHECK + + return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); +} + +template +int GenericIndex::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams) +{ + CV_Assert(query.type() == CvType::type()); + CV_Assert(query.isContinuous()); + ::cvflann::Matrix m_query((ElementType*)query.ptr(0), query.rows, query.cols); + + CV_Assert(indices.type() == CV_32S); + CV_Assert(indices.isContinuous()); + ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols); + + CV_Assert(dists.type() == CvType::type()); + CV_Assert(dists.isContinuous()); + ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols); + + FLANN_DISTANCE_CHECK + + return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); +} + +//! @endcond + +/** + * @deprecated Use GenericIndex class instead + */ +template +class +#ifndef _MSC_VER + FLANN_DEPRECATED +#endif + Index_ { +public: + typedef typename L2::ElementType ElementType; + typedef typename L2::ResultType DistanceType; + + Index_(const Mat& features, const ::cvflann::IndexParams& params); + + ~Index_(); + + void knnSearch(const std::vector& query, std::vector& indices, std::vector& dists, int knn, const ::cvflann::SearchParams& params); + void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params); + + int radiusSearch(const std::vector& query, std::vector& indices, std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& params); + int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& params); + + void save(String filename) + { + if (nnIndex_L1) nnIndex_L1->save(filename); + if (nnIndex_L2) nnIndex_L2->save(filename); + } + + int veclen() const + { + if (nnIndex_L1) return nnIndex_L1->veclen(); + if (nnIndex_L2) return nnIndex_L2->veclen(); + } + + int size() const + { + if (nnIndex_L1) return nnIndex_L1->size(); + if (nnIndex_L2) return nnIndex_L2->size(); + } + + ::cvflann::IndexParams getParameters() + { + if (nnIndex_L1) return nnIndex_L1->getParameters(); + if (nnIndex_L2) return nnIndex_L2->getParameters(); + + } + + FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters() + { + if (nnIndex_L1) return nnIndex_L1->getIndexParameters(); + if (nnIndex_L2) return nnIndex_L2->getIndexParameters(); + } + +private: + // providing backwards compatibility for L2 and L1 distances (most common) + ::cvflann::Index< L2 >* nnIndex_L2; + ::cvflann::Index< L1 >* nnIndex_L1; +}; + +#ifdef _MSC_VER +template +class FLANN_DEPRECATED Index_; +#endif + +//! @cond IGNORED + +template +Index_::Index_(const Mat& dataset, const ::cvflann::IndexParams& params) +{ + printf("[WARNING] The cv::flann::Index_ class is deperecated, use cv::flann::GenericIndex instead\n"); + + CV_Assert(dataset.type() == CvType::type()); + CV_Assert(dataset.isContinuous()); + ::cvflann::Matrix m_dataset((ElementType*)dataset.ptr(0), dataset.rows, dataset.cols); + + if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) { + nnIndex_L1 = NULL; + nnIndex_L2 = new ::cvflann::Index< L2 >(m_dataset, params); + } + else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) { + nnIndex_L1 = new ::cvflann::Index< L1 >(m_dataset, params); + nnIndex_L2 = NULL; + } + else { + printf("[ERROR] cv::flann::Index_ only provides backwards compatibility for the L1 and L2 distances. " + "For other distance types you must use cv::flann::GenericIndex\n"); + CV_Assert(0); + } + if (nnIndex_L1) nnIndex_L1->buildIndex(); + if (nnIndex_L2) nnIndex_L2->buildIndex(); +} + +template +Index_::~Index_() +{ + if (nnIndex_L1) delete nnIndex_L1; + if (nnIndex_L2) delete nnIndex_L2; +} + +template +void Index_::knnSearch(const std::vector& query, std::vector& indices, std::vector& dists, int knn, const ::cvflann::SearchParams& searchParams) +{ + ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size()); + ::cvflann::Matrix m_indices(&indices[0], 1, indices.size()); + ::cvflann::Matrix m_dists(&dists[0], 1, dists.size()); + + if (nnIndex_L1) nnIndex_L1->knnSearch(m_query,m_indices,m_dists,knn,searchParams); + if (nnIndex_L2) nnIndex_L2->knnSearch(m_query,m_indices,m_dists,knn,searchParams); +} + + +template +void Index_::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams) +{ + CV_Assert(queries.type() == CvType::type()); + CV_Assert(queries.isContinuous()); + ::cvflann::Matrix m_queries((ElementType*)queries.ptr(0), queries.rows, queries.cols); + + CV_Assert(indices.type() == CV_32S); + CV_Assert(indices.isContinuous()); + ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols); + + CV_Assert(dists.type() == CvType::type()); + CV_Assert(dists.isContinuous()); + ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols); + + if (nnIndex_L1) nnIndex_L1->knnSearch(m_queries,m_indices,m_dists,knn, searchParams); + if (nnIndex_L2) nnIndex_L2->knnSearch(m_queries,m_indices,m_dists,knn, searchParams); +} + +template +int Index_::radiusSearch(const std::vector& query, std::vector& indices, std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams) +{ + ::cvflann::Matrix m_query((ElementType*)&query[0], 1, query.size()); + ::cvflann::Matrix m_indices(&indices[0], 1, indices.size()); + ::cvflann::Matrix m_dists(&dists[0], 1, dists.size()); + + if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); + if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); +} + +template +int Index_::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams) +{ + CV_Assert(query.type() == CvType::type()); + CV_Assert(query.isContinuous()); + ::cvflann::Matrix m_query((ElementType*)query.ptr(0), query.rows, query.cols); + + CV_Assert(indices.type() == CV_32S); + CV_Assert(indices.isContinuous()); + ::cvflann::Matrix m_indices((int*)indices.ptr(0), indices.rows, indices.cols); + + CV_Assert(dists.type() == CvType::type()); + CV_Assert(dists.isContinuous()); + ::cvflann::Matrix m_dists((DistanceType*)dists.ptr(0), dists.rows, dists.cols); + + if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); + if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams); +} + +//! @endcond + +/** @brief Clusters features using hierarchical k-means algorithm. + +@param features The points to be clustered. The matrix must have elements of type +Distance::ElementType. +@param centers The centers of the clusters obtained. The matrix must have type +Distance::ResultType. The number of rows in this matrix represents the number of clusters desired, +however, because of the way the cut in the hierarchical tree is chosen, the number of clusters +computed will be the highest number of the form (branching-1)\*k+1 that's lower than the number of +clusters desired, where branching is the tree's branching factor (see description of the +KMeansIndexParams). +@param params Parameters used in the construction of the hierarchical k-means tree. +@param d Distance to be used for clustering. + +The method clusters the given feature vectors by constructing a hierarchical k-means tree and +choosing a cut in the tree that minimizes the cluster's variance. It returns the number of clusters +found. + */ +template +int hierarchicalClustering(const Mat& features, Mat& centers, const ::cvflann::KMeansIndexParams& params, + Distance d = Distance()) +{ + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + CV_Assert(features.type() == CvType::type()); + CV_Assert(features.isContinuous()); + ::cvflann::Matrix m_features((ElementType*)features.ptr(0), features.rows, features.cols); + + CV_Assert(centers.type() == CvType::type()); + CV_Assert(centers.isContinuous()); + ::cvflann::Matrix m_centers((DistanceType*)centers.ptr(0), centers.rows, centers.cols); + + return ::cvflann::hierarchicalClustering(m_features, m_centers, params, d); +} + +/** @deprecated +*/ +template +FLANN_DEPRECATED int hierarchicalClustering(const Mat& features, Mat& centers, const ::cvflann::KMeansIndexParams& params) +{ + printf("[WARNING] cv::flann::hierarchicalClustering is deprecated, use " + "cv::flann::hierarchicalClustering instead\n"); + + if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) { + return hierarchicalClustering< L2 >(features, centers, params); + } + else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) { + return hierarchicalClustering< L1 >(features, centers, params); + } + else { + printf("[ERROR] cv::flann::hierarchicalClustering only provides backwards " + "compatibility for the L1 and L2 distances. " + "For other distance types you must use cv::flann::hierarchicalClustering\n"); + CV_Assert(0); + } +} + +//! @} flann + +} } // namespace cv::flann + +#endif diff --git a/include/opencv2/flann/all_indices.h b/include/opencv2/flann/all_indices.h new file mode 100644 index 0000000..ff53fd8 --- /dev/null +++ b/include/opencv2/flann/all_indices.h @@ -0,0 +1,155 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + + +#ifndef OPENCV_FLANN_ALL_INDICES_H_ +#define OPENCV_FLANN_ALL_INDICES_H_ + +#include "general.h" + +#include "nn_index.h" +#include "kdtree_index.h" +#include "kdtree_single_index.h" +#include "kmeans_index.h" +#include "composite_index.h" +#include "linear_index.h" +#include "hierarchical_clustering_index.h" +#include "lsh_index.h" +#include "autotuned_index.h" + + +namespace cvflann +{ + +template +struct index_creator +{ + static NNIndex* create(const Matrix& dataset, const IndexParams& params, const Distance& distance) + { + flann_algorithm_t index_type = get_param(params, "algorithm"); + + NNIndex* nnIndex; + switch (index_type) { + case FLANN_INDEX_LINEAR: + nnIndex = new LinearIndex(dataset, params, distance); + break; + case FLANN_INDEX_KDTREE_SINGLE: + nnIndex = new KDTreeSingleIndex(dataset, params, distance); + break; + case FLANN_INDEX_KDTREE: + nnIndex = new KDTreeIndex(dataset, params, distance); + break; + case FLANN_INDEX_KMEANS: + nnIndex = new KMeansIndex(dataset, params, distance); + break; + case FLANN_INDEX_COMPOSITE: + nnIndex = new CompositeIndex(dataset, params, distance); + break; + case FLANN_INDEX_AUTOTUNED: + nnIndex = new AutotunedIndex(dataset, params, distance); + break; + case FLANN_INDEX_HIERARCHICAL: + nnIndex = new HierarchicalClusteringIndex(dataset, params, distance); + break; + case FLANN_INDEX_LSH: + nnIndex = new LshIndex(dataset, params, distance); + break; + default: + throw FLANNException("Unknown index type"); + } + + return nnIndex; + } +}; + +template +struct index_creator +{ + static NNIndex* create(const Matrix& dataset, const IndexParams& params, const Distance& distance) + { + flann_algorithm_t index_type = get_param(params, "algorithm"); + + NNIndex* nnIndex; + switch (index_type) { + case FLANN_INDEX_LINEAR: + nnIndex = new LinearIndex(dataset, params, distance); + break; + case FLANN_INDEX_KMEANS: + nnIndex = new KMeansIndex(dataset, params, distance); + break; + case FLANN_INDEX_HIERARCHICAL: + nnIndex = new HierarchicalClusteringIndex(dataset, params, distance); + break; + case FLANN_INDEX_LSH: + nnIndex = new LshIndex(dataset, params, distance); + break; + default: + throw FLANNException("Unknown index type"); + } + + return nnIndex; + } +}; + +template +struct index_creator +{ + static NNIndex* create(const Matrix& dataset, const IndexParams& params, const Distance& distance) + { + flann_algorithm_t index_type = get_param(params, "algorithm"); + + NNIndex* nnIndex; + switch (index_type) { + case FLANN_INDEX_LINEAR: + nnIndex = new LinearIndex(dataset, params, distance); + break; + case FLANN_INDEX_HIERARCHICAL: + nnIndex = new HierarchicalClusteringIndex(dataset, params, distance); + break; + case FLANN_INDEX_LSH: + nnIndex = new LshIndex(dataset, params, distance); + break; + default: + throw FLANNException("Unknown index type"); + } + + return nnIndex; + } +}; + +template +NNIndex* create_index_by_type(const Matrix& dataset, const IndexParams& params, const Distance& distance) +{ + return index_creator::create(dataset, params,distance); +} + +} + +#endif /* OPENCV_FLANN_ALL_INDICES_H_ */ diff --git a/include/opencv2/flann/allocator.h b/include/opencv2/flann/allocator.h new file mode 100644 index 0000000..26091d0 --- /dev/null +++ b/include/opencv2/flann/allocator.h @@ -0,0 +1,188 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_ALLOCATOR_H_ +#define OPENCV_FLANN_ALLOCATOR_H_ + +#include +#include + + +namespace cvflann +{ + +/** + * Allocates (using C's malloc) a generic type T. + * + * Params: + * count = number of instances to allocate. + * Returns: pointer (of type T*) to memory buffer + */ +template +T* allocate(size_t count = 1) +{ + T* mem = (T*) ::malloc(sizeof(T)*count); + return mem; +} + + +/** + * Pooled storage allocator + * + * The following routines allow for the efficient allocation of storage in + * small chunks from a specified pool. Rather than allowing each structure + * to be freed individually, an entire pool of storage is freed at once. + * This method has two advantages over just using malloc() and free(). First, + * it is far more efficient for allocating small objects, as there is + * no overhead for remembering all the information needed to free each + * object or consolidating fragmented memory. Second, the decision about + * how long to keep an object is made at the time of allocation, and there + * is no need to track down all the objects to free them. + * + */ + +const size_t WORDSIZE=16; +const size_t BLOCKSIZE=8192; + +class PooledAllocator +{ + /* We maintain memory alignment to word boundaries by requiring that all + allocations be in multiples of the machine wordsize. */ + /* Size of machine word in bytes. Must be power of 2. */ + /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */ + + + int remaining; /* Number of bytes left in current block of storage. */ + void* base; /* Pointer to base of current block of storage. */ + void* loc; /* Current location in block to next allocate memory. */ + int blocksize; + + +public: + int usedMemory; + int wastedMemory; + + /** + Default constructor. Initializes a new pool. + */ + PooledAllocator(int blockSize = BLOCKSIZE) + { + blocksize = blockSize; + remaining = 0; + base = NULL; + + usedMemory = 0; + wastedMemory = 0; + } + + /** + * Destructor. Frees all the memory allocated in this pool. + */ + ~PooledAllocator() + { + void* prev; + + while (base != NULL) { + prev = *((void**) base); /* Get pointer to prev block. */ + ::free(base); + base = prev; + } + } + + /** + * Returns a pointer to a piece of new memory of the given size in bytes + * allocated from the pool. + */ + void* allocateMemory(int size) + { + int blockSize; + + /* Round size up to a multiple of wordsize. The following expression + only works for WORDSIZE that is a power of 2, by masking last bits of + incremented size to zero. + */ + size = (size + (WORDSIZE - 1)) & ~(WORDSIZE - 1); + + /* Check whether a new block must be allocated. Note that the first word + of a block is reserved for a pointer to the previous block. + */ + if (size > remaining) { + + wastedMemory += remaining; + + /* Allocate new storage. */ + blockSize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ? + size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE; + + // use the standard C malloc to allocate memory + void* m = ::malloc(blockSize); + if (!m) { + fprintf(stderr,"Failed to allocate memory.\n"); + return NULL; + } + + /* Fill first word of new block with pointer to previous block. */ + ((void**) m)[0] = base; + base = m; + + int shift = 0; + //int shift = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1); + + remaining = blockSize - sizeof(void*) - shift; + loc = ((char*)m + sizeof(void*) + shift); + } + void* rloc = loc; + loc = (char*)loc + size; + remaining -= size; + + usedMemory += size; + + return rloc; + } + + /** + * Allocates (using this pool) a generic type T. + * + * Params: + * count = number of instances to allocate. + * Returns: pointer (of type T*) to memory buffer + */ + template + T* allocate(size_t count = 1) + { + T* mem = (T*) this->allocateMemory((int)(sizeof(T)*count)); + return mem; + } + +}; + +} + +#endif //OPENCV_FLANN_ALLOCATOR_H_ diff --git a/include/opencv2/flann/any.h b/include/opencv2/flann/any.h new file mode 100644 index 0000000..8c2edaa --- /dev/null +++ b/include/opencv2/flann/any.h @@ -0,0 +1,323 @@ +#ifndef OPENCV_FLANN_ANY_H_ +#define OPENCV_FLANN_ANY_H_ +/* + * (C) Copyright Christopher Diggins 2005-2011 + * (C) Copyright Pablo Aguilar 2005 + * (C) Copyright Kevlin Henney 2001 + * + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt + * + * Adapted for FLANN by Marius Muja + */ + +#include "defines.h" +#include +#include +#include + +namespace cvflann +{ + +namespace anyimpl +{ + +struct bad_any_cast +{ +}; + +struct empty_any +{ +}; + +inline std::ostream& operator <<(std::ostream& out, const empty_any&) +{ + out << "[empty_any]"; + return out; +} + +struct base_any_policy +{ + virtual void static_delete(void** x) = 0; + virtual void copy_from_value(void const* src, void** dest) = 0; + virtual void clone(void* const* src, void** dest) = 0; + virtual void move(void* const* src, void** dest) = 0; + virtual void* get_value(void** src) = 0; + virtual const void* get_value(void* const * src) = 0; + virtual ::size_t get_size() = 0; + virtual const std::type_info& type() = 0; + virtual void print(std::ostream& out, void* const* src) = 0; + virtual ~base_any_policy() {} +}; + +template +struct typed_base_any_policy : base_any_policy +{ + virtual ::size_t get_size() { return sizeof(T); } + virtual const std::type_info& type() { return typeid(T); } + +}; + +template +struct small_any_policy : typed_base_any_policy +{ + virtual void static_delete(void**) { } + virtual void copy_from_value(void const* src, void** dest) + { + new (dest) T(* reinterpret_cast(src)); + } + virtual void clone(void* const* src, void** dest) { *dest = *src; } + virtual void move(void* const* src, void** dest) { *dest = *src; } + virtual void* get_value(void** src) { return reinterpret_cast(src); } + virtual const void* get_value(void* const * src) { return reinterpret_cast(src); } + virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast(src); } +}; + +template +struct big_any_policy : typed_base_any_policy +{ + virtual void static_delete(void** x) + { + if (* x) delete (* reinterpret_cast(x)); *x = NULL; + } + virtual void copy_from_value(void const* src, void** dest) + { + *dest = new T(*reinterpret_cast(src)); + } + virtual void clone(void* const* src, void** dest) + { + *dest = new T(**reinterpret_cast(src)); + } + virtual void move(void* const* src, void** dest) + { + (*reinterpret_cast(dest))->~T(); + **reinterpret_cast(dest) = **reinterpret_cast(src); + } + virtual void* get_value(void** src) { return *src; } + virtual const void* get_value(void* const * src) { return *src; } + virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast(*src); } +}; + +template<> inline void big_any_policy::print(std::ostream& out, void* const* src) +{ + out << int(*reinterpret_cast(*src)); +} + +template<> inline void big_any_policy::print(std::ostream& out, void* const* src) +{ + out << int(*reinterpret_cast(*src)); +} + +template<> inline void big_any_policy::print(std::ostream& out, void* const* src) +{ + out << (*reinterpret_cast(*src)).c_str(); +} + +template +struct choose_policy +{ + typedef big_any_policy type; +}; + +template +struct choose_policy +{ + typedef small_any_policy type; +}; + +struct any; + +/// Choosing the policy for an any type is illegal, but should never happen. +/// This is designed to throw a compiler error. +template<> +struct choose_policy +{ + typedef void type; +}; + +/// Specializations for small types. +#define SMALL_POLICY(TYPE) \ + template<> \ + struct choose_policy { typedef small_any_policy type; \ + } + +SMALL_POLICY(signed char); +SMALL_POLICY(unsigned char); +SMALL_POLICY(signed short); +SMALL_POLICY(unsigned short); +SMALL_POLICY(signed int); +SMALL_POLICY(unsigned int); +SMALL_POLICY(signed long); +SMALL_POLICY(unsigned long); +SMALL_POLICY(float); +SMALL_POLICY(bool); + +#undef SMALL_POLICY + +template +class SinglePolicy +{ + SinglePolicy(); + SinglePolicy(const SinglePolicy& other); + SinglePolicy& operator=(const SinglePolicy& other); + +public: + static base_any_policy* get_policy(); + +private: + static typename choose_policy::type policy; +}; + +template +typename choose_policy::type SinglePolicy::policy; + +/// This function will return a different policy for each type. +template +inline base_any_policy* SinglePolicy::get_policy() { return &policy; } + +} // namespace anyimpl + +struct any +{ +private: + // fields + anyimpl::base_any_policy* policy; + void* object; + +public: + /// Initializing constructor. + template + any(const T& x) + : policy(anyimpl::SinglePolicy::get_policy()), object(NULL) + { + assign(x); + } + + /// Empty constructor. + any() + : policy(anyimpl::SinglePolicy::get_policy()), object(NULL) + { } + + /// Special initializing constructor for string literals. + any(const char* x) + : policy(anyimpl::SinglePolicy::get_policy()), object(NULL) + { + assign(x); + } + + /// Copy constructor. + any(const any& x) + : policy(anyimpl::SinglePolicy::get_policy()), object(NULL) + { + assign(x); + } + + /// Destructor. + ~any() + { + policy->static_delete(&object); + } + + /// Assignment function from another any. + any& assign(const any& x) + { + reset(); + policy = x.policy; + policy->clone(&x.object, &object); + return *this; + } + + /// Assignment function. + template + any& assign(const T& x) + { + reset(); + policy = anyimpl::SinglePolicy::get_policy(); + policy->copy_from_value(&x, &object); + return *this; + } + + /// Assignment operator. + template + any& operator=(const T& x) + { + return assign(x); + } + + /// Assignment operator, specialed for literal strings. + /// They have types like const char [6] which don't work as expected. + any& operator=(const char* x) + { + return assign(x); + } + + /// Utility functions + any& swap(any& x) + { + std::swap(policy, x.policy); + std::swap(object, x.object); + return *this; + } + + /// Cast operator. You can only cast to the original type. + template + T& cast() + { + if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast(); + T* r = reinterpret_cast(policy->get_value(&object)); + return *r; + } + + /// Cast operator. You can only cast to the original type. + template + const T& cast() const + { + if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast(); + const T* r = reinterpret_cast(policy->get_value(&object)); + return *r; + } + + /// Returns true if the any contains no value. + bool empty() const + { + return policy->type() == typeid(anyimpl::empty_any); + } + + /// Frees any allocated memory, and sets the value to NULL. + void reset() + { + policy->static_delete(&object); + policy = anyimpl::SinglePolicy::get_policy(); + } + + /// Returns true if the two types are the same. + bool compatible(const any& x) const + { + return policy->type() == x.policy->type(); + } + + /// Returns if the type is compatible with the policy + template + bool has_type() + { + return policy->type() == typeid(T); + } + + const std::type_info& type() const + { + return policy->type(); + } + + friend std::ostream& operator <<(std::ostream& out, const any& any_val); +}; + +inline std::ostream& operator <<(std::ostream& out, const any& any_val) +{ + any_val.policy->print(out,&any_val.object); + return out; +} + +} + +#endif // OPENCV_FLANN_ANY_H_ diff --git a/include/opencv2/flann/autotuned_index.h b/include/opencv2/flann/autotuned_index.h new file mode 100644 index 0000000..0670d19 --- /dev/null +++ b/include/opencv2/flann/autotuned_index.h @@ -0,0 +1,587 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ +#ifndef OPENCV_FLANN_AUTOTUNED_INDEX_H_ +#define OPENCV_FLANN_AUTOTUNED_INDEX_H_ + +#include "general.h" +#include "nn_index.h" +#include "ground_truth.h" +#include "index_testing.h" +#include "sampling.h" +#include "kdtree_index.h" +#include "kdtree_single_index.h" +#include "kmeans_index.h" +#include "composite_index.h" +#include "linear_index.h" +#include "logger.h" + +namespace cvflann +{ + +template +NNIndex* create_index_by_type(const Matrix& dataset, const IndexParams& params, const Distance& distance); + + +struct AutotunedIndexParams : public IndexParams +{ + AutotunedIndexParams(float target_precision = 0.8, float build_weight = 0.01, float memory_weight = 0, float sample_fraction = 0.1) + { + (*this)["algorithm"] = FLANN_INDEX_AUTOTUNED; + // precision desired (used for autotuning, -1 otherwise) + (*this)["target_precision"] = target_precision; + // build tree time weighting factor + (*this)["build_weight"] = build_weight; + // index memory weighting factor + (*this)["memory_weight"] = memory_weight; + // what fraction of the dataset to use for autotuning + (*this)["sample_fraction"] = sample_fraction; + } +}; + + +template +class AutotunedIndex : public NNIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + AutotunedIndex(const Matrix& inputData, const IndexParams& params = AutotunedIndexParams(), Distance d = Distance()) : + dataset_(inputData), distance_(d) + { + target_precision_ = get_param(params, "target_precision",0.8f); + build_weight_ = get_param(params,"build_weight", 0.01f); + memory_weight_ = get_param(params, "memory_weight", 0.0f); + sample_fraction_ = get_param(params,"sample_fraction", 0.1f); + bestIndex_ = NULL; + } + + AutotunedIndex(const AutotunedIndex&); + AutotunedIndex& operator=(const AutotunedIndex&); + + virtual ~AutotunedIndex() + { + if (bestIndex_ != NULL) { + delete bestIndex_; + bestIndex_ = NULL; + } + } + + /** + * Method responsible with building the index. + */ + virtual void buildIndex() + { + std::ostringstream stream; + bestParams_ = estimateBuildParams(); + print_params(bestParams_, stream); + Logger::info("----------------------------------------------------\n"); + Logger::info("Autotuned parameters:\n"); + Logger::info("%s", stream.str().c_str()); + Logger::info("----------------------------------------------------\n"); + + bestIndex_ = create_index_by_type(dataset_, bestParams_, distance_); + bestIndex_->buildIndex(); + speedup_ = estimateSearchParams(bestSearchParams_); + stream.str(std::string()); + print_params(bestSearchParams_, stream); + Logger::info("----------------------------------------------------\n"); + Logger::info("Search parameters:\n"); + Logger::info("%s", stream.str().c_str()); + Logger::info("----------------------------------------------------\n"); + } + + /** + * Saves the index to a stream + */ + virtual void saveIndex(FILE* stream) + { + save_value(stream, (int)bestIndex_->getType()); + bestIndex_->saveIndex(stream); + save_value(stream, get_param(bestSearchParams_, "checks")); + } + + /** + * Loads the index from a stream + */ + virtual void loadIndex(FILE* stream) + { + int index_type; + + load_value(stream, index_type); + IndexParams params; + params["algorithm"] = (flann_algorithm_t)index_type; + bestIndex_ = create_index_by_type(dataset_, params, distance_); + bestIndex_->loadIndex(stream); + int checks; + load_value(stream, checks); + bestSearchParams_["checks"] = checks; + } + + /** + * Method that searches for nearest-neighbors + */ + virtual void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& searchParams) + { + int checks = get_param(searchParams,"checks",FLANN_CHECKS_AUTOTUNED); + if (checks == FLANN_CHECKS_AUTOTUNED) { + bestIndex_->findNeighbors(result, vec, bestSearchParams_); + } + else { + bestIndex_->findNeighbors(result, vec, searchParams); + } + } + + + IndexParams getParameters() const + { + return bestIndex_->getParameters(); + } + + SearchParams getSearchParameters() const + { + return bestSearchParams_; + } + + float getSpeedup() const + { + return speedup_; + } + + + /** + * Number of features in this index. + */ + virtual size_t size() const + { + return bestIndex_->size(); + } + + /** + * The length of each vector in this index. + */ + virtual size_t veclen() const + { + return bestIndex_->veclen(); + } + + /** + * The amount of memory (in bytes) this index uses. + */ + virtual int usedMemory() const + { + return bestIndex_->usedMemory(); + } + + /** + * Algorithm name + */ + virtual flann_algorithm_t getType() const + { + return FLANN_INDEX_AUTOTUNED; + } + +private: + + struct CostData + { + float searchTimeCost; + float buildTimeCost; + float memoryCost; + float totalCost; + IndexParams params; + }; + + void evaluate_kmeans(CostData& cost) + { + StartStopTimer t; + int checks; + const int nn = 1; + + Logger::info("KMeansTree using params: max_iterations=%d, branching=%d\n", + get_param(cost.params,"iterations"), + get_param(cost.params,"branching")); + KMeansIndex kmeans(sampledDataset_, cost.params, distance_); + // measure index build time + t.start(); + kmeans.buildIndex(); + t.stop(); + float buildTime = (float)t.value; + + // measure search time + float searchTime = test_index_precision(kmeans, sampledDataset_, testDataset_, gt_matches_, target_precision_, checks, distance_, nn); + + float datasetMemory = float(sampledDataset_.rows * sampledDataset_.cols * sizeof(float)); + cost.memoryCost = (kmeans.usedMemory() + datasetMemory) / datasetMemory; + cost.searchTimeCost = searchTime; + cost.buildTimeCost = buildTime; + Logger::info("KMeansTree buildTime=%g, searchTime=%g, build_weight=%g\n", buildTime, searchTime, build_weight_); + } + + + void evaluate_kdtree(CostData& cost) + { + StartStopTimer t; + int checks; + const int nn = 1; + + Logger::info("KDTree using params: trees=%d\n", get_param(cost.params,"trees")); + KDTreeIndex kdtree(sampledDataset_, cost.params, distance_); + + t.start(); + kdtree.buildIndex(); + t.stop(); + float buildTime = (float)t.value; + + //measure search time + float searchTime = test_index_precision(kdtree, sampledDataset_, testDataset_, gt_matches_, target_precision_, checks, distance_, nn); + + float datasetMemory = float(sampledDataset_.rows * sampledDataset_.cols * sizeof(float)); + cost.memoryCost = (kdtree.usedMemory() + datasetMemory) / datasetMemory; + cost.searchTimeCost = searchTime; + cost.buildTimeCost = buildTime; + Logger::info("KDTree buildTime=%g, searchTime=%g\n", buildTime, searchTime); + } + + + // struct KMeansSimpleDownhillFunctor { + // + // Autotune& autotuner; + // KMeansSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {} + // + // float operator()(int* params) { + // + // float maxFloat = numeric_limits::max(); + // + // if (params[0]<2) return maxFloat; + // if (params[1]<0) return maxFloat; + // + // CostData c; + // c.params["algorithm"] = KMEANS; + // c.params["centers-init"] = CENTERS_RANDOM; + // c.params["branching"] = params[0]; + // c.params["max-iterations"] = params[1]; + // + // autotuner.evaluate_kmeans(c); + // + // return c.timeCost; + // + // } + // }; + // + // struct KDTreeSimpleDownhillFunctor { + // + // Autotune& autotuner; + // KDTreeSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {} + // + // float operator()(int* params) { + // float maxFloat = numeric_limits::max(); + // + // if (params[0]<1) return maxFloat; + // + // CostData c; + // c.params["algorithm"] = KDTREE; + // c.params["trees"] = params[0]; + // + // autotuner.evaluate_kdtree(c); + // + // return c.timeCost; + // + // } + // }; + + + + void optimizeKMeans(std::vector& costs) + { + Logger::info("KMEANS, Step 1: Exploring parameter space\n"); + + // explore kmeans parameters space using combinations of the parameters below + int maxIterations[] = { 1, 5, 10, 15 }; + int branchingFactors[] = { 16, 32, 64, 128, 256 }; + + int kmeansParamSpaceSize = FLANN_ARRAY_LEN(maxIterations) * FLANN_ARRAY_LEN(branchingFactors); + costs.reserve(costs.size() + kmeansParamSpaceSize); + + // evaluate kmeans for all parameter combinations + for (size_t i = 0; i < FLANN_ARRAY_LEN(maxIterations); ++i) { + for (size_t j = 0; j < FLANN_ARRAY_LEN(branchingFactors); ++j) { + CostData cost; + cost.params["algorithm"] = FLANN_INDEX_KMEANS; + cost.params["centers_init"] = FLANN_CENTERS_RANDOM; + cost.params["iterations"] = maxIterations[i]; + cost.params["branching"] = branchingFactors[j]; + + evaluate_kmeans(cost); + costs.push_back(cost); + } + } + + // Logger::info("KMEANS, Step 2: simplex-downhill optimization\n"); + // + // const int n = 2; + // // choose initial simplex points as the best parameters so far + // int kmeansNMPoints[n*(n+1)]; + // float kmeansVals[n+1]; + // for (int i=0;i& costs) + { + Logger::info("KD-TREE, Step 1: Exploring parameter space\n"); + + // explore kd-tree parameters space using the parameters below + int testTrees[] = { 1, 4, 8, 16, 32 }; + + // evaluate kdtree for all parameter combinations + for (size_t i = 0; i < FLANN_ARRAY_LEN(testTrees); ++i) { + CostData cost; + cost.params["trees"] = testTrees[i]; + + evaluate_kdtree(cost); + costs.push_back(cost); + } + + // Logger::info("KD-TREE, Step 2: simplex-downhill optimization\n"); + // + // const int n = 1; + // // choose initial simplex points as the best parameters so far + // int kdtreeNMPoints[n*(n+1)]; + // float kdtreeVals[n+1]; + // for (int i=0;i costs; + + int sampleSize = int(sample_fraction_ * dataset_.rows); + int testSampleSize = std::min(sampleSize / 10, 1000); + + Logger::info("Entering autotuning, dataset size: %d, sampleSize: %d, testSampleSize: %d, target precision: %g\n", dataset_.rows, sampleSize, testSampleSize, target_precision_); + + // For a very small dataset, it makes no sense to build any fancy index, just + // use linear search + if (testSampleSize < 10) { + Logger::info("Choosing linear, dataset too small\n"); + return LinearIndexParams(); + } + + // We use a fraction of the original dataset to speedup the autotune algorithm + sampledDataset_ = random_sample(dataset_, sampleSize); + // We use a cross-validation approach, first we sample a testset from the dataset + testDataset_ = random_sample(sampledDataset_, testSampleSize, true); + + // We compute the ground truth using linear search + Logger::info("Computing ground truth... \n"); + gt_matches_ = Matrix(new int[testDataset_.rows], testDataset_.rows, 1); + StartStopTimer t; + t.start(); + compute_ground_truth(sampledDataset_, testDataset_, gt_matches_, 0, distance_); + t.stop(); + + CostData linear_cost; + linear_cost.searchTimeCost = (float)t.value; + linear_cost.buildTimeCost = 0; + linear_cost.memoryCost = 0; + linear_cost.params["algorithm"] = FLANN_INDEX_LINEAR; + + costs.push_back(linear_cost); + + // Start parameter autotune process + Logger::info("Autotuning parameters...\n"); + + optimizeKMeans(costs); + optimizeKDTree(costs); + + float bestTimeCost = costs[0].searchTimeCost; + for (size_t i = 0; i < costs.size(); ++i) { + float timeCost = costs[i].buildTimeCost * build_weight_ + costs[i].searchTimeCost; + if (timeCost < bestTimeCost) { + bestTimeCost = timeCost; + } + } + + float bestCost = costs[0].searchTimeCost / bestTimeCost; + IndexParams bestParams = costs[0].params; + if (bestTimeCost > 0) { + for (size_t i = 0; i < costs.size(); ++i) { + float crtCost = (costs[i].buildTimeCost * build_weight_ + costs[i].searchTimeCost) / bestTimeCost + + memory_weight_ * costs[i].memoryCost; + if (crtCost < bestCost) { + bestCost = crtCost; + bestParams = costs[i].params; + } + } + } + + delete[] gt_matches_.data; + delete[] testDataset_.data; + delete[] sampledDataset_.data; + + return bestParams; + } + + + + /** + * Estimates the search time parameters needed to get the desired precision. + * Precondition: the index is built + * Postcondition: the searchParams will have the optimum params set, also the speedup obtained over linear search. + */ + float estimateSearchParams(SearchParams& searchParams) + { + const int nn = 1; + const size_t SAMPLE_COUNT = 1000; + + assert(bestIndex_ != NULL); // must have a valid index + + float speedup = 0; + + int samples = (int)std::min(dataset_.rows / 10, SAMPLE_COUNT); + if (samples > 0) { + Matrix testDataset = random_sample(dataset_, samples); + + Logger::info("Computing ground truth\n"); + + // we need to compute the ground truth first + Matrix gt_matches(new int[testDataset.rows], testDataset.rows, 1); + StartStopTimer t; + t.start(); + compute_ground_truth(dataset_, testDataset, gt_matches, 1, distance_); + t.stop(); + float linear = (float)t.value; + + int checks; + Logger::info("Estimating number of checks\n"); + + float searchTime; + float cb_index; + if (bestIndex_->getType() == FLANN_INDEX_KMEANS) { + Logger::info("KMeans algorithm, estimating cluster border factor\n"); + KMeansIndex* kmeans = (KMeansIndex*)bestIndex_; + float bestSearchTime = -1; + float best_cb_index = -1; + int best_checks = -1; + for (cb_index = 0; cb_index < 1.1f; cb_index += 0.2f) { + kmeans->set_cb_index(cb_index); + searchTime = test_index_precision(*kmeans, dataset_, testDataset, gt_matches, target_precision_, checks, distance_, nn, 1); + if ((searchTime < bestSearchTime) || (bestSearchTime == -1)) { + bestSearchTime = searchTime; + best_cb_index = cb_index; + best_checks = checks; + } + } + searchTime = bestSearchTime; + cb_index = best_cb_index; + checks = best_checks; + + kmeans->set_cb_index(best_cb_index); + Logger::info("Optimum cb_index: %g\n", cb_index); + bestParams_["cb_index"] = cb_index; + } + else { + searchTime = test_index_precision(*bestIndex_, dataset_, testDataset, gt_matches, target_precision_, checks, distance_, nn, 1); + } + + Logger::info("Required number of checks: %d \n", checks); + searchParams["checks"] = checks; + + speedup = linear / searchTime; + + delete[] gt_matches.data; + delete[] testDataset.data; + } + + return speedup; + } + +private: + NNIndex* bestIndex_; + + IndexParams bestParams_; + SearchParams bestSearchParams_; + + Matrix sampledDataset_; + Matrix testDataset_; + Matrix gt_matches_; + + float speedup_; + + /** + * The dataset used by this index + */ + const Matrix dataset_; + + /** + * Index parameters + */ + float target_precision_; + float build_weight_; + float memory_weight_; + float sample_fraction_; + + Distance distance_; + + +}; +} + +#endif /* OPENCV_FLANN_AUTOTUNED_INDEX_H_ */ diff --git a/include/opencv2/flann/composite_index.h b/include/opencv2/flann/composite_index.h new file mode 100644 index 0000000..527ca1a --- /dev/null +++ b/include/opencv2/flann/composite_index.h @@ -0,0 +1,194 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_COMPOSITE_INDEX_H_ +#define OPENCV_FLANN_COMPOSITE_INDEX_H_ + +#include "general.h" +#include "nn_index.h" +#include "kdtree_index.h" +#include "kmeans_index.h" + +namespace cvflann +{ + +/** + * Index parameters for the CompositeIndex. + */ +struct CompositeIndexParams : public IndexParams +{ + CompositeIndexParams(int trees = 4, int branching = 32, int iterations = 11, + flann_centers_init_t centers_init = FLANN_CENTERS_RANDOM, float cb_index = 0.2 ) + { + (*this)["algorithm"] = FLANN_INDEX_KMEANS; + // number of randomized trees to use (for kdtree) + (*this)["trees"] = trees; + // branching factor + (*this)["branching"] = branching; + // max iterations to perform in one kmeans clustering (kmeans tree) + (*this)["iterations"] = iterations; + // algorithm used for picking the initial cluster centers for kmeans tree + (*this)["centers_init"] = centers_init; + // cluster boundary index. Used when searching the kmeans tree + (*this)["cb_index"] = cb_index; + } +}; + + +/** + * This index builds a kd-tree index and a k-means index and performs nearest + * neighbour search both indexes. This gives a slight boost in search performance + * as some of the neighbours that are missed by one index are found by the other. + */ +template +class CompositeIndex : public NNIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + /** + * Index constructor + * @param inputData dataset containing the points to index + * @param params Index parameters + * @param d Distance functor + * @return + */ + CompositeIndex(const Matrix& inputData, const IndexParams& params = CompositeIndexParams(), + Distance d = Distance()) : index_params_(params) + { + kdtree_index_ = new KDTreeIndex(inputData, params, d); + kmeans_index_ = new KMeansIndex(inputData, params, d); + + } + + CompositeIndex(const CompositeIndex&); + CompositeIndex& operator=(const CompositeIndex&); + + virtual ~CompositeIndex() + { + delete kdtree_index_; + delete kmeans_index_; + } + + /** + * @return The index type + */ + flann_algorithm_t getType() const + { + return FLANN_INDEX_COMPOSITE; + } + + /** + * @return Size of the index + */ + size_t size() const + { + return kdtree_index_->size(); + } + + /** + * \returns The dimensionality of the features in this index. + */ + size_t veclen() const + { + return kdtree_index_->veclen(); + } + + /** + * \returns The amount of memory (in bytes) used by the index. + */ + int usedMemory() const + { + return kmeans_index_->usedMemory() + kdtree_index_->usedMemory(); + } + + /** + * \brief Builds the index + */ + void buildIndex() + { + Logger::info("Building kmeans tree...\n"); + kmeans_index_->buildIndex(); + Logger::info("Building kdtree tree...\n"); + kdtree_index_->buildIndex(); + } + + /** + * \brief Saves the index to a stream + * \param stream The stream to save the index to + */ + void saveIndex(FILE* stream) + { + kmeans_index_->saveIndex(stream); + kdtree_index_->saveIndex(stream); + } + + /** + * \brief Loads the index from a stream + * \param stream The stream from which the index is loaded + */ + void loadIndex(FILE* stream) + { + kmeans_index_->loadIndex(stream); + kdtree_index_->loadIndex(stream); + } + + /** + * \returns The index parameters + */ + IndexParams getParameters() const + { + return index_params_; + } + + /** + * \brief Method that searches for nearest-neighbours + */ + void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& searchParams) + { + kmeans_index_->findNeighbors(result, vec, searchParams); + kdtree_index_->findNeighbors(result, vec, searchParams); + } + +private: + /** The k-means index */ + KMeansIndex* kmeans_index_; + + /** The kd-tree index */ + KDTreeIndex* kdtree_index_; + + /** The index parameters */ + const IndexParams index_params_; +}; + +} + +#endif //OPENCV_FLANN_COMPOSITE_INDEX_H_ diff --git a/include/opencv2/flann/config.h b/include/opencv2/flann/config.h new file mode 100644 index 0000000..56832fd --- /dev/null +++ b/include/opencv2/flann/config.h @@ -0,0 +1,38 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + + +#ifndef OPENCV_FLANN_CONFIG_H_ +#define OPENCV_FLANN_CONFIG_H_ + +#ifdef FLANN_VERSION_ +#undef FLANN_VERSION_ +#endif +#define FLANN_VERSION_ "1.6.10" + +#endif /* OPENCV_FLANN_CONFIG_H_ */ diff --git a/include/opencv2/flann/defines.h b/include/opencv2/flann/defines.h new file mode 100644 index 0000000..f0264f7 --- /dev/null +++ b/include/opencv2/flann/defines.h @@ -0,0 +1,177 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + + +#ifndef OPENCV_FLANN_DEFINES_H_ +#define OPENCV_FLANN_DEFINES_H_ + +#include "config.h" + +#ifdef FLANN_EXPORT +#undef FLANN_EXPORT +#endif +#ifdef WIN32 +/* win32 dll export/import directives */ + #ifdef FLANN_EXPORTS + #define FLANN_EXPORT __declspec(dllexport) + #elif defined(FLANN_STATIC) + #define FLANN_EXPORT + #else + #define FLANN_EXPORT __declspec(dllimport) + #endif +#else +/* unix needs nothing */ + #define FLANN_EXPORT +#endif + + +#ifdef FLANN_DEPRECATED +#undef FLANN_DEPRECATED +#endif +#ifdef __GNUC__ +#define FLANN_DEPRECATED __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define FLANN_DEPRECATED __declspec(deprecated) +#else +#pragma message("WARNING: You need to implement FLANN_DEPRECATED for this compiler") +#define FLANN_DEPRECATED +#endif + + +#undef FLANN_PLATFORM_32_BIT +#undef FLANN_PLATFORM_64_BIT +#if defined __amd64__ || defined __x86_64__ || defined _WIN64 || defined _M_X64 +#define FLANN_PLATFORM_64_BIT +#else +#define FLANN_PLATFORM_32_BIT +#endif + + +#undef FLANN_ARRAY_LEN +#define FLANN_ARRAY_LEN(a) (sizeof(a)/sizeof(a[0])) + +namespace cvflann { + +/* Nearest neighbour index algorithms */ +enum flann_algorithm_t +{ + FLANN_INDEX_LINEAR = 0, + FLANN_INDEX_KDTREE = 1, + FLANN_INDEX_KMEANS = 2, + FLANN_INDEX_COMPOSITE = 3, + FLANN_INDEX_KDTREE_SINGLE = 4, + FLANN_INDEX_HIERARCHICAL = 5, + FLANN_INDEX_LSH = 6, + FLANN_INDEX_SAVED = 254, + FLANN_INDEX_AUTOTUNED = 255, + + // deprecated constants, should use the FLANN_INDEX_* ones instead + LINEAR = 0, + KDTREE = 1, + KMEANS = 2, + COMPOSITE = 3, + KDTREE_SINGLE = 4, + SAVED = 254, + AUTOTUNED = 255 +}; + + + +enum flann_centers_init_t +{ + FLANN_CENTERS_RANDOM = 0, + FLANN_CENTERS_GONZALES = 1, + FLANN_CENTERS_KMEANSPP = 2, + FLANN_CENTERS_GROUPWISE = 3, + + // deprecated constants, should use the FLANN_CENTERS_* ones instead + CENTERS_RANDOM = 0, + CENTERS_GONZALES = 1, + CENTERS_KMEANSPP = 2 +}; + +enum flann_log_level_t +{ + FLANN_LOG_NONE = 0, + FLANN_LOG_FATAL = 1, + FLANN_LOG_ERROR = 2, + FLANN_LOG_WARN = 3, + FLANN_LOG_INFO = 4 +}; + +enum flann_distance_t +{ + FLANN_DIST_EUCLIDEAN = 1, + FLANN_DIST_L2 = 1, + FLANN_DIST_MANHATTAN = 2, + FLANN_DIST_L1 = 2, + FLANN_DIST_MINKOWSKI = 3, + FLANN_DIST_MAX = 4, + FLANN_DIST_HIST_INTERSECT = 5, + FLANN_DIST_HELLINGER = 6, + FLANN_DIST_CHI_SQUARE = 7, + FLANN_DIST_CS = 7, + FLANN_DIST_KULLBACK_LEIBLER = 8, + FLANN_DIST_KL = 8, + FLANN_DIST_HAMMING = 9, + + // deprecated constants, should use the FLANN_DIST_* ones instead + EUCLIDEAN = 1, + MANHATTAN = 2, + MINKOWSKI = 3, + MAX_DIST = 4, + HIST_INTERSECT = 5, + HELLINGER = 6, + CS = 7, + KL = 8, + KULLBACK_LEIBLER = 8 +}; + +enum flann_datatype_t +{ + FLANN_INT8 = 0, + FLANN_INT16 = 1, + FLANN_INT32 = 2, + FLANN_INT64 = 3, + FLANN_UINT8 = 4, + FLANN_UINT16 = 5, + FLANN_UINT32 = 6, + FLANN_UINT64 = 7, + FLANN_FLOAT32 = 8, + FLANN_FLOAT64 = 9 +}; + +enum +{ + FLANN_CHECKS_UNLIMITED = -1, + FLANN_CHECKS_AUTOTUNED = -2 +}; + +} + +#endif /* OPENCV_FLANN_DEFINES_H_ */ diff --git a/include/opencv2/flann/dist.h b/include/opencv2/flann/dist.h new file mode 100644 index 0000000..9dbe527 --- /dev/null +++ b/include/opencv2/flann/dist.h @@ -0,0 +1,905 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_DIST_H_ +#define OPENCV_FLANN_DIST_H_ + +#include +#include +#include +#ifdef _MSC_VER +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif + +#include "defines.h" + +#if (defined WIN32 || defined _WIN32) && defined(_M_ARM) +# include +#endif + +#ifdef __ARM_NEON__ +# include "arm_neon.h" +#endif + +namespace cvflann +{ + +template +inline T abs(T x) { return (x<0) ? -x : x; } + +template<> +inline int abs(int x) { return ::abs(x); } + +template<> +inline float abs(float x) { return fabsf(x); } + +template<> +inline double abs(double x) { return fabs(x); } + +template +struct Accumulator { typedef T Type; }; +template<> +struct Accumulator { typedef float Type; }; +template<> +struct Accumulator { typedef float Type; }; +template<> +struct Accumulator { typedef float Type; }; +template<> +struct Accumulator { typedef float Type; }; +template<> +struct Accumulator { typedef float Type; }; +template<> +struct Accumulator { typedef float Type; }; + +#undef True +#undef False + +class True +{ +}; + +class False +{ +}; + + +/** + * Squared Euclidean distance functor. + * + * This is the simpler, unrolled version. This is preferable for + * very low dimensionality data (eg 3D points) + */ +template +struct L2_Simple +{ + typedef True is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const + { + ResultType result = ResultType(); + ResultType diff; + for(size_t i = 0; i < size; ++i ) { + diff = *a++ - *b++; + result += diff*diff; + } + return result; + } + + template + inline ResultType accum_dist(const U& a, const V& b, int) const + { + return (a-b)*(a-b); + } +}; + + + +/** + * Squared Euclidean distance functor, optimized version + */ +template +struct L2 +{ + typedef True is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + /** + * Compute the squared Euclidean distance between two vectors. + * + * This is highly optimised, with loop unrolling, as it is one + * of the most expensive inner loops. + * + * The computation of squared root at the end is omitted for + * efficiency. + */ + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const + { + ResultType result = ResultType(); + ResultType diff0, diff1, diff2, diff3; + Iterator1 last = a + size; + Iterator1 lastgroup = last - 3; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + diff0 = (ResultType)(a[0] - b[0]); + diff1 = (ResultType)(a[1] - b[1]); + diff2 = (ResultType)(a[2] - b[2]); + diff3 = (ResultType)(a[3] - b[3]); + result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; + a += 4; + b += 4; + + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (a < last) { + diff0 = (ResultType)(*a++ - *b++); + result += diff0 * diff0; + } + return result; + } + + /** + * Partial euclidean distance, using just one dimension. This is used by the + * kd-tree when computing partial distances while traversing the tree. + * + * Squared root is omitted for efficiency. + */ + template + inline ResultType accum_dist(const U& a, const V& b, int) const + { + return (a-b)*(a-b); + } +}; + + +/* + * Manhattan distance functor, optimized version + */ +template +struct L1 +{ + typedef True is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + /** + * Compute the Manhattan (L_1) distance between two vectors. + * + * This is highly optimised, with loop unrolling, as it is one + * of the most expensive inner loops. + */ + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const + { + ResultType result = ResultType(); + ResultType diff0, diff1, diff2, diff3; + Iterator1 last = a + size; + Iterator1 lastgroup = last - 3; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + diff0 = (ResultType)abs(a[0] - b[0]); + diff1 = (ResultType)abs(a[1] - b[1]); + diff2 = (ResultType)abs(a[2] - b[2]); + diff3 = (ResultType)abs(a[3] - b[3]); + result += diff0 + diff1 + diff2 + diff3; + a += 4; + b += 4; + + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (a < last) { + diff0 = (ResultType)abs(*a++ - *b++); + result += diff0; + } + return result; + } + + /** + * Partial distance, used by the kd-tree. + */ + template + inline ResultType accum_dist(const U& a, const V& b, int) const + { + return abs(a-b); + } +}; + + + +template +struct MinkowskiDistance +{ + typedef True is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + int order; + + MinkowskiDistance(int order_) : order(order_) {} + + /** + * Compute the Minkowsky (L_p) distance between two vectors. + * + * This is highly optimised, with loop unrolling, as it is one + * of the most expensive inner loops. + * + * The computation of squared root at the end is omitted for + * efficiency. + */ + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const + { + ResultType result = ResultType(); + ResultType diff0, diff1, diff2, diff3; + Iterator1 last = a + size; + Iterator1 lastgroup = last - 3; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + diff0 = (ResultType)abs(a[0] - b[0]); + diff1 = (ResultType)abs(a[1] - b[1]); + diff2 = (ResultType)abs(a[2] - b[2]); + diff3 = (ResultType)abs(a[3] - b[3]); + result += pow(diff0,order) + pow(diff1,order) + pow(diff2,order) + pow(diff3,order); + a += 4; + b += 4; + + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (a < last) { + diff0 = (ResultType)abs(*a++ - *b++); + result += pow(diff0,order); + } + return result; + } + + /** + * Partial distance, used by the kd-tree. + */ + template + inline ResultType accum_dist(const U& a, const V& b, int) const + { + return pow(static_cast(abs(a-b)),order); + } +}; + + + +template +struct MaxDistance +{ + typedef False is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + /** + * Compute the max distance (L_infinity) between two vectors. + * + * This distance is not a valid kdtree distance, it's not dimensionwise additive. + */ + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const + { + ResultType result = ResultType(); + ResultType diff0, diff1, diff2, diff3; + Iterator1 last = a + size; + Iterator1 lastgroup = last - 3; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + diff0 = abs(a[0] - b[0]); + diff1 = abs(a[1] - b[1]); + diff2 = abs(a[2] - b[2]); + diff3 = abs(a[3] - b[3]); + if (diff0>result) {result = diff0; } + if (diff1>result) {result = diff1; } + if (diff2>result) {result = diff2; } + if (diff3>result) {result = diff3; } + a += 4; + b += 4; + + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (a < last) { + diff0 = abs(*a++ - *b++); + result = (diff0>result) ? diff0 : result; + } + return result; + } + + /* This distance functor is not dimension-wise additive, which + * makes it an invalid kd-tree distance, not implementing the accum_dist method */ + +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor + * bit count of A exclusive XOR'ed with B + */ +struct HammingLUT +{ + typedef False is_kdtree_distance; + typedef False is_vector_space_distance; + + typedef unsigned char ElementType; + typedef int ResultType; + + /** this will count the bits in a ^ b + */ + ResultType operator()(const unsigned char* a, const unsigned char* b, size_t size) const + { + static const uchar popCountTable[] = + { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 + }; + ResultType result = 0; + for (size_t i = 0; i < size; i++) { + result += popCountTable[a[i] ^ b[i]]; + } + return result; + } +}; + +/** + * Hamming distance functor (pop count between two binary vectors, i.e. xor them and count the number of bits set) + * That code was taken from brief.cpp in OpenCV + */ +template +struct Hamming +{ + typedef False is_kdtree_distance; + typedef False is_vector_space_distance; + + + typedef T ElementType; + typedef int ResultType; + + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const + { + ResultType result = 0; +#ifdef __ARM_NEON__ + { + uint32x4_t bits = vmovq_n_u32(0); + for (size_t i = 0; i < size; i += 16) { + uint8x16_t A_vec = vld1q_u8 (a + i); + uint8x16_t B_vec = vld1q_u8 (b + i); + uint8x16_t AxorB = veorq_u8 (A_vec, B_vec); + uint8x16_t bitsSet = vcntq_u8 (AxorB); + uint16x8_t bitSet8 = vpaddlq_u8 (bitsSet); + uint32x4_t bitSet4 = vpaddlq_u16 (bitSet8); + bits = vaddq_u32(bits, bitSet4); + } + uint64x2_t bitSet2 = vpaddlq_u32 (bits); + result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0); + result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2); + } +#elif __GNUC__ + { + //for portability just use unsigned long -- and use the __builtin_popcountll (see docs for __builtin_popcountll) + typedef unsigned long long pop_t; + const size_t modulo = size % sizeof(pop_t); + const pop_t* a2 = reinterpret_cast (a); + const pop_t* b2 = reinterpret_cast (b); + const pop_t* a2_end = a2 + (size / sizeof(pop_t)); + + for (; a2 != a2_end; ++a2, ++b2) result += __builtin_popcountll((*a2) ^ (*b2)); + + if (modulo) { + //in the case where size is not dividable by sizeof(size_t) + //need to mask off the bits at the end + pop_t a_final = 0, b_final = 0; + memcpy(&a_final, a2, modulo); + memcpy(&b_final, b2, modulo); + result += __builtin_popcountll(a_final ^ b_final); + } + } +#else // NO NEON and NOT GNUC + typedef unsigned long long pop_t; + HammingLUT lut; + result = lut(reinterpret_cast (a), + reinterpret_cast (b), size * sizeof(pop_t)); +#endif + return result; + } +}; + +template +struct Hamming2 +{ + typedef False is_kdtree_distance; + typedef False is_vector_space_distance; + + typedef T ElementType; + typedef int ResultType; + + /** This is popcount_3() from: + * http://en.wikipedia.org/wiki/Hamming_weight */ + unsigned int popcnt32(uint32_t n) const + { + n -= ((n >> 1) & 0x55555555); + n = (n & 0x33333333) + ((n >> 2) & 0x33333333); + return (((n + (n >> 4))& 0xF0F0F0F)* 0x1010101) >> 24; + } + +#ifdef FLANN_PLATFORM_64_BIT + unsigned int popcnt64(uint64_t n) const + { + n -= ((n >> 1) & 0x5555555555555555); + n = (n & 0x3333333333333333) + ((n >> 2) & 0x3333333333333333); + return (((n + (n >> 4))& 0x0f0f0f0f0f0f0f0f)* 0x0101010101010101) >> 56; + } +#endif + + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const + { +#ifdef FLANN_PLATFORM_64_BIT + const uint64_t* pa = reinterpret_cast(a); + const uint64_t* pb = reinterpret_cast(b); + ResultType result = 0; + size /= (sizeof(uint64_t)/sizeof(unsigned char)); + for(size_t i = 0; i < size; ++i ) { + result += popcnt64(*pa ^ *pb); + ++pa; + ++pb; + } +#else + const uint32_t* pa = reinterpret_cast(a); + const uint32_t* pb = reinterpret_cast(b); + ResultType result = 0; + size /= (sizeof(uint32_t)/sizeof(unsigned char)); + for(size_t i = 0; i < size; ++i ) { + result += popcnt32(*pa ^ *pb); + ++pa; + ++pb; + } +#endif + return result; + } +}; + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +struct HistIntersectionDistance +{ + typedef True is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + /** + * Compute the histogram intersection distance + */ + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const + { + ResultType result = ResultType(); + ResultType min0, min1, min2, min3; + Iterator1 last = a + size; + Iterator1 lastgroup = last - 3; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + min0 = (ResultType)(a[0] < b[0] ? a[0] : b[0]); + min1 = (ResultType)(a[1] < b[1] ? a[1] : b[1]); + min2 = (ResultType)(a[2] < b[2] ? a[2] : b[2]); + min3 = (ResultType)(a[3] < b[3] ? a[3] : b[3]); + result += min0 + min1 + min2 + min3; + a += 4; + b += 4; + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (a < last) { + min0 = (ResultType)(*a < *b ? *a : *b); + result += min0; + ++a; + ++b; + } + return result; + } + + /** + * Partial distance, used by the kd-tree. + */ + template + inline ResultType accum_dist(const U& a, const V& b, int) const + { + return a +struct HellingerDistance +{ + typedef True is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + /** + * Compute the Hellinger distance + */ + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const + { + ResultType result = ResultType(); + ResultType diff0, diff1, diff2, diff3; + Iterator1 last = a + size; + Iterator1 lastgroup = last - 3; + + /* Process 4 items with each loop for efficiency. */ + while (a < lastgroup) { + diff0 = sqrt(static_cast(a[0])) - sqrt(static_cast(b[0])); + diff1 = sqrt(static_cast(a[1])) - sqrt(static_cast(b[1])); + diff2 = sqrt(static_cast(a[2])) - sqrt(static_cast(b[2])); + diff3 = sqrt(static_cast(a[3])) - sqrt(static_cast(b[3])); + result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; + a += 4; + b += 4; + } + while (a < last) { + diff0 = sqrt(static_cast(*a++)) - sqrt(static_cast(*b++)); + result += diff0 * diff0; + } + return result; + } + + /** + * Partial distance, used by the kd-tree. + */ + template + inline ResultType accum_dist(const U& a, const V& b, int) const + { + ResultType diff = sqrt(static_cast(a)) - sqrt(static_cast(b)); + return diff * diff; + } +}; + + +template +struct ChiSquareDistance +{ + typedef True is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + /** + * Compute the chi-square distance + */ + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const + { + ResultType result = ResultType(); + ResultType sum, diff; + Iterator1 last = a + size; + + while (a < last) { + sum = (ResultType)(*a + *b); + if (sum>0) { + diff = (ResultType)(*a - *b); + result += diff*diff/sum; + } + ++a; + ++b; + + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + return result; + } + + /** + * Partial distance, used by the kd-tree. + */ + template + inline ResultType accum_dist(const U& a, const V& b, int) const + { + ResultType result = ResultType(); + ResultType sum, diff; + + sum = (ResultType)(a+b); + if (sum>0) { + diff = (ResultType)(a-b); + result = diff*diff/sum; + } + return result; + } +}; + + +template +struct KL_Divergence +{ + typedef True is_kdtree_distance; + typedef True is_vector_space_distance; + + typedef T ElementType; + typedef typename Accumulator::Type ResultType; + + /** + * Compute the Kullback–Leibler divergence + */ + template + ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const + { + ResultType result = ResultType(); + Iterator1 last = a + size; + + while (a < last) { + if (* b != 0) { + ResultType ratio = (ResultType)(*a / *b); + if (ratio>0) { + result += *a * log(ratio); + } + } + ++a; + ++b; + + if ((worst_dist>0)&&(result>worst_dist)) { + return result; + } + } + return result; + } + + /** + * Partial distance, used by the kd-tree. + */ + template + inline ResultType accum_dist(const U& a, const V& b, int) const + { + ResultType result = ResultType(); + if( *b != 0 ) { + ResultType ratio = (ResultType)(a / b); + if (ratio>0) { + result = a * log(ratio); + } + } + return result; + } +}; + + + +/* + * This is a "zero iterator". It basically behaves like a zero filled + * array to all algorithms that use arrays as iterators (STL style). + * It's useful when there's a need to compute the distance between feature + * and origin it and allows for better compiler optimisation than using a + * zero-filled array. + */ +template +struct ZeroIterator +{ + + T operator*() + { + return 0; + } + + T operator[](int) + { + return 0; + } + + const ZeroIterator& operator ++() + { + return *this; + } + + ZeroIterator operator ++(int) + { + return *this; + } + + ZeroIterator& operator+=(int) + { + return *this; + } + +}; + + +/* + * Depending on processed distances, some of them are already squared (e.g. L2) + * and some are not (e.g.Hamming). In KMeans++ for instance we want to be sure + * we are working on ^2 distances, thus following templates to ensure that. + */ +template +struct squareDistance +{ + typedef typename Distance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist*dist; } +}; + + +template +struct squareDistance, ElementType> +{ + typedef typename L2_Simple::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + +template +struct squareDistance, ElementType> +{ + typedef typename L2::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + + +template +struct squareDistance, ElementType> +{ + typedef typename MinkowskiDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + +template +struct squareDistance, ElementType> +{ + typedef typename HellingerDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + +template +struct squareDistance, ElementType> +{ + typedef typename ChiSquareDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + + +template +typename Distance::ResultType ensureSquareDistance( typename Distance::ResultType dist ) +{ + typedef typename Distance::ElementType ElementType; + + squareDistance dummy; + return dummy( dist ); +} + + +/* + * ...and a template to ensure the user that he will process the normal distance, + * and not squared distance, without loosing processing time calling sqrt(ensureSquareDistance) + * that will result in doing actually sqrt(dist*dist) for L1 distance for instance. + */ +template +struct simpleDistance +{ + typedef typename Distance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + + +template +struct simpleDistance, ElementType> +{ + typedef typename L2_Simple::ResultType ResultType; + ResultType operator()( ResultType dist ) { return sqrt(dist); } +}; + +template +struct simpleDistance, ElementType> +{ + typedef typename L2::ResultType ResultType; + ResultType operator()( ResultType dist ) { return sqrt(dist); } +}; + + +template +struct simpleDistance, ElementType> +{ + typedef typename MinkowskiDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return sqrt(dist); } +}; + +template +struct simpleDistance, ElementType> +{ + typedef typename HellingerDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return sqrt(dist); } +}; + +template +struct simpleDistance, ElementType> +{ + typedef typename ChiSquareDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return sqrt(dist); } +}; + + +template +typename Distance::ResultType ensureSimpleDistance( typename Distance::ResultType dist ) +{ + typedef typename Distance::ElementType ElementType; + + simpleDistance dummy; + return dummy( dist ); +} + +} + +#endif //OPENCV_FLANN_DIST_H_ diff --git a/include/opencv2/flann/dummy.h b/include/opencv2/flann/dummy.h new file mode 100644 index 0000000..26bd3fa --- /dev/null +++ b/include/opencv2/flann/dummy.h @@ -0,0 +1,16 @@ + +#ifndef OPENCV_FLANN_DUMMY_H_ +#define OPENCV_FLANN_DUMMY_H_ + +namespace cvflann +{ + +#if (defined WIN32 || defined _WIN32 || defined WINCE) && defined CVAPI_EXPORTS +__declspec(dllexport) +#endif +void dummyfunc(); + +} + + +#endif /* OPENCV_FLANN_DUMMY_H_ */ diff --git a/include/opencv2/flann/dynamic_bitset.h b/include/opencv2/flann/dynamic_bitset.h new file mode 100644 index 0000000..d795b5d --- /dev/null +++ b/include/opencv2/flann/dynamic_bitset.h @@ -0,0 +1,159 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +/*********************************************************************** + * Author: Vincent Rabaud + *************************************************************************/ + +#ifndef OPENCV_FLANN_DYNAMIC_BITSET_H_ +#define OPENCV_FLANN_DYNAMIC_BITSET_H_ + +#ifndef FLANN_USE_BOOST +# define FLANN_USE_BOOST 0 +#endif +//#define FLANN_USE_BOOST 1 +#if FLANN_USE_BOOST +#include +typedef boost::dynamic_bitset<> DynamicBitset; +#else + +#include + +#include "dist.h" + +namespace cvflann { + +/** Class re-implementing the boost version of it + * This helps not depending on boost, it also does not do the bound checks + * and has a way to reset a block for speed + */ +class DynamicBitset +{ +public: + /** default constructor + */ + DynamicBitset() + { + } + + /** only constructor we use in our code + * @param sz the size of the bitset (in bits) + */ + DynamicBitset(size_t sz) + { + resize(sz); + reset(); + } + + /** Sets all the bits to 0 + */ + void clear() + { + std::fill(bitset_.begin(), bitset_.end(), 0); + } + + /** @brief checks if the bitset is empty + * @return true if the bitset is empty + */ + bool empty() const + { + return bitset_.empty(); + } + + /** set all the bits to 0 + */ + void reset() + { + std::fill(bitset_.begin(), bitset_.end(), 0); + } + + /** @brief set one bit to 0 + * @param index + */ + void reset(size_t index) + { + bitset_[index / cell_bit_size_] &= ~(size_t(1) << (index % cell_bit_size_)); + } + + /** @brief sets a specific bit to 0, and more bits too + * This function is useful when resetting a given set of bits so that the + * whole bitset ends up being 0: if that's the case, we don't care about setting + * other bits to 0 + * @param index + */ + void reset_block(size_t index) + { + bitset_[index / cell_bit_size_] = 0; + } + + /** resize the bitset so that it contains at least sz bits + * @param sz + */ + void resize(size_t sz) + { + size_ = sz; + bitset_.resize(sz / cell_bit_size_ + 1); + } + + /** set a bit to true + * @param index the index of the bit to set to 1 + */ + void set(size_t index) + { + bitset_[index / cell_bit_size_] |= size_t(1) << (index % cell_bit_size_); + } + + /** gives the number of contained bits + */ + size_t size() const + { + return size_; + } + + /** check if a bit is set + * @param index the index of the bit to check + * @return true if the bit is set + */ + bool test(size_t index) const + { + return (bitset_[index / cell_bit_size_] & (size_t(1) << (index % cell_bit_size_))) != 0; + } + +private: + std::vector bitset_; + size_t size_; + static const unsigned int cell_bit_size_ = CHAR_BIT * sizeof(size_t); +}; + +} // namespace cvflann + +#endif + +#endif // OPENCV_FLANN_DYNAMIC_BITSET_H_ diff --git a/include/opencv2/flann/flann.hpp b/include/opencv2/flann/flann.hpp new file mode 100644 index 0000000..227683f --- /dev/null +++ b/include/opencv2/flann/flann.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/flann.hpp" diff --git a/include/opencv2/flann/flann_base.hpp b/include/opencv2/flann/flann_base.hpp new file mode 100644 index 0000000..98c33cf --- /dev/null +++ b/include/opencv2/flann/flann_base.hpp @@ -0,0 +1,290 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_BASE_HPP_ +#define OPENCV_FLANN_BASE_HPP_ + +#include +#include +#include + +#include "general.h" +#include "matrix.h" +#include "params.h" +#include "saving.h" + +#include "all_indices.h" + +namespace cvflann +{ + +/** + * Sets the log level used for all flann functions + * @param level Verbosity level + */ +inline void log_verbosity(int level) +{ + if (level >= 0) { + Logger::setLevel(level); + } +} + +/** + * (Deprecated) Index parameters for creating a saved index. + */ +struct SavedIndexParams : public IndexParams +{ + SavedIndexParams(cv::String filename) + { + (* this)["algorithm"] = FLANN_INDEX_SAVED; + (*this)["filename"] = filename; + } +}; + + +template +NNIndex* load_saved_index(const Matrix& dataset, const cv::String& filename, Distance distance) +{ + typedef typename Distance::ElementType ElementType; + + FILE* fin = fopen(filename.c_str(), "rb"); + if (fin == NULL) { + return NULL; + } + IndexHeader header = load_header(fin); + if (header.data_type != Datatype::type()) { + throw FLANNException("Datatype of saved index is different than of the one to be created."); + } + if ((size_t(header.rows) != dataset.rows)||(size_t(header.cols) != dataset.cols)) { + throw FLANNException("The index saved belongs to a different dataset"); + } + + IndexParams params; + params["algorithm"] = header.index_type; + NNIndex* nnIndex = create_index_by_type(dataset, params, distance); + nnIndex->loadIndex(fin); + fclose(fin); + + return nnIndex; +} + + +template +class Index : public NNIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + Index(const Matrix& features, const IndexParams& params, Distance distance = Distance() ) + : index_params_(params) + { + flann_algorithm_t index_type = get_param(params,"algorithm"); + loaded_ = false; + + if (index_type == FLANN_INDEX_SAVED) { + nnIndex_ = load_saved_index(features, get_param(params,"filename"), distance); + loaded_ = true; + } + else { + nnIndex_ = create_index_by_type(features, params, distance); + } + } + + ~Index() + { + delete nnIndex_; + } + + /** + * Builds the index. + */ + void buildIndex() + { + if (!loaded_) { + nnIndex_->buildIndex(); + } + } + + void save(cv::String filename) + { + FILE* fout = fopen(filename.c_str(), "wb"); + if (fout == NULL) { + throw FLANNException("Cannot open file"); + } + save_header(fout, *nnIndex_); + saveIndex(fout); + fclose(fout); + } + + /** + * \brief Saves the index to a stream + * \param stream The stream to save the index to + */ + virtual void saveIndex(FILE* stream) + { + nnIndex_->saveIndex(stream); + } + + /** + * \brief Loads the index from a stream + * \param stream The stream from which the index is loaded + */ + virtual void loadIndex(FILE* stream) + { + nnIndex_->loadIndex(stream); + } + + /** + * \returns number of features in this index. + */ + size_t veclen() const + { + return nnIndex_->veclen(); + } + + /** + * \returns The dimensionality of the features in this index. + */ + size_t size() const + { + return nnIndex_->size(); + } + + /** + * \returns The index type (kdtree, kmeans,...) + */ + flann_algorithm_t getType() const + { + return nnIndex_->getType(); + } + + /** + * \returns The amount of memory (in bytes) used by the index. + */ + virtual int usedMemory() const + { + return nnIndex_->usedMemory(); + } + + + /** + * \returns The index parameters + */ + IndexParams getParameters() const + { + return nnIndex_->getParameters(); + } + + /** + * \brief Perform k-nearest neighbor search + * \param[in] queries The query points for which to find the nearest neighbors + * \param[out] indices The indices of the nearest neighbors found + * \param[out] dists Distances to the nearest neighbors found + * \param[in] knn Number of nearest neighbors to return + * \param[in] params Search parameters + */ + void knnSearch(const Matrix& queries, Matrix& indices, Matrix& dists, int knn, const SearchParams& params) + { + nnIndex_->knnSearch(queries, indices, dists, knn, params); + } + + /** + * \brief Perform radius search + * \param[in] query The query point + * \param[out] indices The indinces of the neighbors found within the given radius + * \param[out] dists The distances to the nearest neighbors found + * \param[in] radius The radius used for search + * \param[in] params Search parameters + * \returns Number of neighbors found + */ + int radiusSearch(const Matrix& query, Matrix& indices, Matrix& dists, float radius, const SearchParams& params) + { + return nnIndex_->radiusSearch(query, indices, dists, radius, params); + } + + /** + * \brief Method that searches for nearest-neighbours + */ + void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& searchParams) + { + nnIndex_->findNeighbors(result, vec, searchParams); + } + + /** + * \brief Returns actual index + */ + FLANN_DEPRECATED NNIndex* getIndex() + { + return nnIndex_; + } + + /** + * \brief Returns index parameters. + * \deprecated use getParameters() instead. + */ + FLANN_DEPRECATED const IndexParams* getIndexParameters() + { + return &index_params_; + } + +private: + /** Pointer to actual index class */ + NNIndex* nnIndex_; + /** Indices if the index was loaded from a file */ + bool loaded_; + /** Parameters passed to the index */ + IndexParams index_params_; +}; + +/** + * Performs a hierarchical clustering of the points passed as argument and then takes a cut in the + * the clustering tree to return a flat clustering. + * @param[in] points Points to be clustered + * @param centers The computed cluster centres. Matrix should be preallocated and centers.rows is the + * number of clusters requested. + * @param params Clustering parameters (The same as for cvflann::KMeansIndex) + * @param d Distance to be used for clustering (eg: cvflann::L2) + * @return number of clusters computed (can be different than clusters.rows and is the highest number + * of the form (branching-1)*K+1 smaller than clusters.rows). + */ +template +int hierarchicalClustering(const Matrix& points, Matrix& centers, + const KMeansIndexParams& params, Distance d = Distance()) +{ + KMeansIndex kmeans(points, params, d); + kmeans.buildIndex(); + + int clusterNum = kmeans.getClusterCenters(centers); + return clusterNum; +} + +} +#endif /* OPENCV_FLANN_BASE_HPP_ */ diff --git a/include/opencv2/flann/general.h b/include/opencv2/flann/general.h new file mode 100644 index 0000000..9d5402a --- /dev/null +++ b/include/opencv2/flann/general.h @@ -0,0 +1,50 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_GENERAL_H_ +#define OPENCV_FLANN_GENERAL_H_ + +#include "opencv2/core.hpp" + +namespace cvflann +{ + +class FLANNException : public cv::Exception +{ +public: + FLANNException(const char* message) : cv::Exception(0, message, "", __FILE__, __LINE__) { } + + FLANNException(const cv::String& message) : cv::Exception(0, message, "", __FILE__, __LINE__) { } +}; + +} + + +#endif /* OPENCV_FLANN_GENERAL_H_ */ diff --git a/include/opencv2/flann/ground_truth.h b/include/opencv2/flann/ground_truth.h new file mode 100644 index 0000000..fd8f3ae --- /dev/null +++ b/include/opencv2/flann/ground_truth.h @@ -0,0 +1,94 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_GROUND_TRUTH_H_ +#define OPENCV_FLANN_GROUND_TRUTH_H_ + +#include "dist.h" +#include "matrix.h" + + +namespace cvflann +{ + +template +void find_nearest(const Matrix& dataset, typename Distance::ElementType* query, int* matches, int nn, + int skip = 0, Distance distance = Distance()) +{ + typedef typename Distance::ResultType DistanceType; + int n = nn + skip; + + std::vector match(n); + std::vector dists(n); + + dists[0] = distance(dataset[0], query, dataset.cols); + match[0] = 0; + int dcnt = 1; + + for (size_t i=1; i=1 && dists[j] +void compute_ground_truth(const Matrix& dataset, const Matrix& testset, Matrix& matches, + int skip=0, Distance d = Distance()) +{ + for (size_t i=0; i(dataset, testset[i], matches[i], (int)matches.cols, skip, d); + } +} + + +} + +#endif //OPENCV_FLANN_GROUND_TRUTH_H_ diff --git a/include/opencv2/flann/hdf5.h b/include/opencv2/flann/hdf5.h new file mode 100644 index 0000000..80d23b9 --- /dev/null +++ b/include/opencv2/flann/hdf5.h @@ -0,0 +1,231 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + + +#ifndef OPENCV_FLANN_HDF5_H_ +#define OPENCV_FLANN_HDF5_H_ + +#include + +#include "matrix.h" + + +namespace cvflann +{ + +namespace +{ + +template +hid_t get_hdf5_type() +{ + throw FLANNException("Unsupported type for IO operations"); +} + +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_CHAR; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_UCHAR; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_SHORT; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_USHORT; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_INT; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_UINT; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_LONG; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_ULONG; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_FLOAT; } +template<> +hid_t get_hdf5_type() { return H5T_NATIVE_DOUBLE; } +} + + +#define CHECK_ERROR(x,y) if ((x)<0) throw FLANNException((y)); + +template +void save_to_file(const cvflann::Matrix& dataset, const String& filename, const String& name) +{ + +#if H5Eset_auto_vers == 2 + H5Eset_auto( H5E_DEFAULT, NULL, NULL ); +#else + H5Eset_auto( NULL, NULL ); +#endif + + herr_t status; + hid_t file_id; + file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT); + if (file_id < 0) { + file_id = H5Fcreate(filename.c_str(), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); + } + CHECK_ERROR(file_id,"Error creating hdf5 file."); + + hsize_t dimsf[2]; // dataset dimensions + dimsf[0] = dataset.rows; + dimsf[1] = dataset.cols; + + hid_t space_id = H5Screate_simple(2, dimsf, NULL); + hid_t memspace_id = H5Screate_simple(2, dimsf, NULL); + + hid_t dataset_id; +#if H5Dcreate_vers == 2 + dataset_id = H5Dcreate2(file_id, name.c_str(), get_hdf5_type(), space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); +#else + dataset_id = H5Dcreate(file_id, name.c_str(), get_hdf5_type(), space_id, H5P_DEFAULT); +#endif + + if (dataset_id<0) { +#if H5Dopen_vers == 2 + dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT); +#else + dataset_id = H5Dopen(file_id, name.c_str()); +#endif + } + CHECK_ERROR(dataset_id,"Error creating or opening dataset in file."); + + status = H5Dwrite(dataset_id, get_hdf5_type(), memspace_id, space_id, H5P_DEFAULT, dataset.data ); + CHECK_ERROR(status, "Error writing to dataset"); + + H5Sclose(memspace_id); + H5Sclose(space_id); + H5Dclose(dataset_id); + H5Fclose(file_id); + +} + + +template +void load_from_file(cvflann::Matrix& dataset, const String& filename, const String& name) +{ + herr_t status; + hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT); + CHECK_ERROR(file_id,"Error opening hdf5 file."); + + hid_t dataset_id; +#if H5Dopen_vers == 2 + dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT); +#else + dataset_id = H5Dopen(file_id, name.c_str()); +#endif + CHECK_ERROR(dataset_id,"Error opening dataset in file."); + + hid_t space_id = H5Dget_space(dataset_id); + + hsize_t dims_out[2]; + H5Sget_simple_extent_dims(space_id, dims_out, NULL); + + dataset = cvflann::Matrix(new T[dims_out[0]*dims_out[1]], dims_out[0], dims_out[1]); + + status = H5Dread(dataset_id, get_hdf5_type(), H5S_ALL, H5S_ALL, H5P_DEFAULT, dataset[0]); + CHECK_ERROR(status, "Error reading dataset"); + + H5Sclose(space_id); + H5Dclose(dataset_id); + H5Fclose(file_id); +} + + +#ifdef HAVE_MPI + +namespace mpi +{ +/** + * Loads a the hyperslice corresponding to this processor from a hdf5 file. + * @param flann_dataset Dataset where the data is loaded + * @param filename HDF5 file name + * @param name Name of dataset inside file + */ +template +void load_from_file(cvflann::Matrix& dataset, const String& filename, const String& name) +{ + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Info info = MPI_INFO_NULL; + + int mpi_size, mpi_rank; + MPI_Comm_size(comm, &mpi_size); + MPI_Comm_rank(comm, &mpi_rank); + + herr_t status; + + hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS); + H5Pset_fapl_mpio(plist_id, comm, info); + hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, plist_id); + CHECK_ERROR(file_id,"Error opening hdf5 file."); + H5Pclose(plist_id); + hid_t dataset_id; +#if H5Dopen_vers == 2 + dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT); +#else + dataset_id = H5Dopen(file_id, name.c_str()); +#endif + CHECK_ERROR(dataset_id,"Error opening dataset in file."); + + hid_t space_id = H5Dget_space(dataset_id); + hsize_t dims[2]; + H5Sget_simple_extent_dims(space_id, dims, NULL); + + hsize_t count[2]; + hsize_t offset[2]; + + hsize_t item_cnt = dims[0]/mpi_size+(dims[0]%mpi_size==0 ? 0 : 1); + hsize_t cnt = (mpi_rank(), memspace_id, space_id, plist_id, dataset.data); + CHECK_ERROR(status, "Error reading dataset"); + + H5Pclose(plist_id); + H5Sclose(space_id); + H5Sclose(memspace_id); + H5Dclose(dataset_id); + H5Fclose(file_id); +} +} +#endif // HAVE_MPI +} // namespace cvflann::mpi + +#endif /* OPENCV_FLANN_HDF5_H_ */ diff --git a/include/opencv2/flann/heap.h b/include/opencv2/flann/heap.h new file mode 100644 index 0000000..92a6ea6 --- /dev/null +++ b/include/opencv2/flann/heap.h @@ -0,0 +1,165 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_HEAP_H_ +#define OPENCV_FLANN_HEAP_H_ + +#include +#include + +namespace cvflann +{ + +/** + * Priority Queue Implementation + * + * The priority queue is implemented with a heap. A heap is a complete + * (full) binary tree in which each parent is less than both of its + * children, but the order of the children is unspecified. + */ +template +class Heap +{ + + /** + * Storage array for the heap. + * Type T must be comparable. + */ + std::vector heap; + int length; + + /** + * Number of element in the heap + */ + int count; + + + +public: + /** + * Constructor. + * + * Params: + * sz = heap size + */ + + Heap(int sz) + { + length = sz; + heap.reserve(length); + count = 0; + } + + /** + * + * Returns: heap size + */ + int size() + { + return count; + } + + /** + * Tests if the heap is empty + * + * Returns: true is heap empty, false otherwise + */ + bool empty() + { + return size()==0; + } + + /** + * Clears the heap. + */ + void clear() + { + heap.clear(); + count = 0; + } + + struct CompareT + { + bool operator()(const T& t_1, const T& t_2) const + { + return t_2 < t_1; + } + }; + + /** + * Insert a new element in the heap. + * + * We select the next empty leaf node, and then keep moving any larger + * parents down until the right location is found to store this element. + * + * Params: + * value = the new element to be inserted in the heap + */ + void insert(T value) + { + /* If heap is full, then return without adding this element. */ + if (count == length) { + return; + } + + heap.push_back(value); + static CompareT compareT; + std::push_heap(heap.begin(), heap.end(), compareT); + ++count; + } + + + + /** + * Returns the node of minimum value from the heap (top of the heap). + * + * Params: + * value = out parameter used to return the min element + * Returns: false if heap empty + */ + bool popMin(T& value) + { + if (count == 0) { + return false; + } + + value = heap[0]; + static CompareT compareT; + std::pop_heap(heap.begin(), heap.end(), compareT); + heap.pop_back(); + --count; + + return true; /* Return old last node. */ + } +}; + +} + +#endif //OPENCV_FLANN_HEAP_H_ diff --git a/include/opencv2/flann/hierarchical_clustering_index.h b/include/opencv2/flann/hierarchical_clustering_index.h new file mode 100644 index 0000000..9d890d4 --- /dev/null +++ b/include/opencv2/flann/hierarchical_clustering_index.h @@ -0,0 +1,848 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_ +#define OPENCV_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_ + +#include +#include +#include +#include +#include + +#include "general.h" +#include "nn_index.h" +#include "dist.h" +#include "matrix.h" +#include "result_set.h" +#include "heap.h" +#include "allocator.h" +#include "random.h" +#include "saving.h" + + +namespace cvflann +{ + +struct HierarchicalClusteringIndexParams : public IndexParams +{ + HierarchicalClusteringIndexParams(int branching = 32, + flann_centers_init_t centers_init = FLANN_CENTERS_RANDOM, + int trees = 4, int leaf_size = 100) + { + (*this)["algorithm"] = FLANN_INDEX_HIERARCHICAL; + // The branching factor used in the hierarchical clustering + (*this)["branching"] = branching; + // Algorithm used for picking the initial cluster centers + (*this)["centers_init"] = centers_init; + // number of parallel trees to build + (*this)["trees"] = trees; + // maximum leaf size + (*this)["leaf_size"] = leaf_size; + } +}; + + +/** + * Hierarchical index + * + * Contains a tree constructed through a hierarchical clustering + * and other information for indexing a set of points for nearest-neighbour matching. + */ +template +class HierarchicalClusteringIndex : public NNIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + +private: + + + typedef void (HierarchicalClusteringIndex::* centersAlgFunction)(int, int*, int, int*, int&); + + /** + * The function used for choosing the cluster centers. + */ + centersAlgFunction chooseCenters; + + + + /** + * Chooses the initial centers in the k-means clustering in a random manner. + * + * Params: + * k = number of centers + * vecs = the dataset of points + * indices = indices in the dataset + * indices_length = length of indices vector + * + */ + void chooseCentersRandom(int k, int* dsindices, int indices_length, int* centers, int& centers_length) + { + UniqueRandom r(indices_length); + + int index; + for (index=0; index=0 && rnd < n); + + centers[0] = dsindices[rnd]; + + int index; + for (index=1; indexbest_val) { + best_val = dist; + best_index = j; + } + } + if (best_index!=-1) { + centers[index] = dsindices[best_index]; + } + else { + break; + } + } + centers_length = index; + } + + + /** + * Chooses the initial centers in the k-means using the algorithm + * proposed in the KMeans++ paper: + * Arthur, David; Vassilvitskii, Sergei - k-means++: The Advantages of Careful Seeding + * + * Implementation of this function was converted from the one provided in Arthur's code. + * + * Params: + * k = number of centers + * vecs = the dataset of points + * indices = indices in the dataset + * Returns: + */ + void chooseCentersKMeanspp(int k, int* dsindices, int indices_length, int* centers, int& centers_length) + { + int n = indices_length; + + double currentPot = 0; + DistanceType* closestDistSq = new DistanceType[n]; + + // Choose one random center and set the closestDistSq values + int index = rand_int(n); + assert(index >=0 && index < n); + centers[0] = dsindices[index]; + + // Computing distance^2 will have the advantage of even higher probability further to pick new centers + // far from previous centers (and this complies to "k-means++: the advantages of careful seeding" article) + for (int i = 0; i < n; i++) { + closestDistSq[i] = distance(dataset[dsindices[i]], dataset[dsindices[index]], dataset.cols); + closestDistSq[i] = ensureSquareDistance( closestDistSq[i] ); + currentPot += closestDistSq[i]; + } + + + const int numLocalTries = 1; + + // Choose each center + int centerCount; + for (centerCount = 1; centerCount < k; centerCount++) { + + // Repeat several trials + double bestNewPot = -1; + int bestNewIndex = 0; + for (int localTrial = 0; localTrial < numLocalTries; localTrial++) { + + // Choose our center - have to be slightly careful to return a valid answer even accounting + // for possible rounding errors + double randVal = rand_double(currentPot); + for (index = 0; index < n-1; index++) { + if (randVal <= closestDistSq[index]) break; + else randVal -= closestDistSq[index]; + } + + // Compute the new potential + double newPot = 0; + for (int i = 0; i < n; i++) { + DistanceType dist = distance(dataset[dsindices[i]], dataset[dsindices[index]], dataset.cols); + newPot += std::min( ensureSquareDistance(dist), closestDistSq[i] ); + } + + // Store the best result + if ((bestNewPot < 0)||(newPot < bestNewPot)) { + bestNewPot = newPot; + bestNewIndex = index; + } + } + + // Add the appropriate center + centers[centerCount] = dsindices[bestNewIndex]; + currentPot = bestNewPot; + for (int i = 0; i < n; i++) { + DistanceType dist = distance(dataset[dsindices[i]], dataset[dsindices[bestNewIndex]], dataset.cols); + closestDistSq[i] = std::min( ensureSquareDistance(dist), closestDistSq[i] ); + } + } + + centers_length = centerCount; + + delete[] closestDistSq; + } + + + /** + * Chooses the initial centers in a way inspired by Gonzales (by Pierre-Emmanuel Viel): + * select the first point of the list as a candidate, then parse the points list. If another + * point is further than current candidate from the other centers, test if it is a good center + * of a local aggregation. If it is, replace current candidate by this point. And so on... + * + * Used with KMeansIndex that computes centers coordinates by averaging positions of clusters points, + * this doesn't make a real difference with previous methods. But used with HierarchicalClusteringIndex + * class that pick centers among existing points instead of computing the barycenters, there is a real + * improvement. + * + * Params: + * k = number of centers + * vecs = the dataset of points + * indices = indices in the dataset + * Returns: + */ + void GroupWiseCenterChooser(int k, int* dsindices, int indices_length, int* centers, int& centers_length) + { + const float kSpeedUpFactor = 1.3f; + + int n = indices_length; + + DistanceType* closestDistSq = new DistanceType[n]; + + // Choose one random center and set the closestDistSq values + int index = rand_int(n); + assert(index >=0 && index < n); + centers[0] = dsindices[index]; + + for (int i = 0; i < n; i++) { + closestDistSq[i] = distance(dataset[dsindices[i]], dataset[dsindices[index]], dataset.cols); + } + + + // Choose each center + int centerCount; + for (centerCount = 1; centerCount < k; centerCount++) { + + // Repeat several trials + double bestNewPot = -1; + int bestNewIndex = 0; + DistanceType furthest = 0; + for (index = 0; index < n; index++) { + + // We will test only the potential of the points further than current candidate + if( closestDistSq[index] > kSpeedUpFactor * (float)furthest ) { + + // Compute the new potential + double newPot = 0; + for (int i = 0; i < n; i++) { + newPot += std::min( distance(dataset[dsindices[i]], dataset[dsindices[index]], dataset.cols) + , closestDistSq[i] ); + } + + // Store the best result + if ((bestNewPot < 0)||(newPot <= bestNewPot)) { + bestNewPot = newPot; + bestNewIndex = index; + furthest = closestDistSq[index]; + } + } + } + + // Add the appropriate center + centers[centerCount] = dsindices[bestNewIndex]; + for (int i = 0; i < n; i++) { + closestDistSq[i] = std::min( distance(dataset[dsindices[i]], dataset[dsindices[bestNewIndex]], dataset.cols) + , closestDistSq[i] ); + } + } + + centers_length = centerCount; + + delete[] closestDistSq; + } + + +public: + + + /** + * Index constructor + * + * Params: + * inputData = dataset with the input features + * params = parameters passed to the hierarchical k-means algorithm + */ + HierarchicalClusteringIndex(const Matrix& inputData, const IndexParams& index_params = HierarchicalClusteringIndexParams(), + Distance d = Distance()) + : dataset(inputData), params(index_params), root(NULL), indices(NULL), distance(d) + { + memoryCounter = 0; + + size_ = dataset.rows; + veclen_ = dataset.cols; + + branching_ = get_param(params,"branching",32); + centers_init_ = get_param(params,"centers_init", FLANN_CENTERS_RANDOM); + trees_ = get_param(params,"trees",4); + leaf_size_ = get_param(params,"leaf_size",100); + + if (centers_init_==FLANN_CENTERS_RANDOM) { + chooseCenters = &HierarchicalClusteringIndex::chooseCentersRandom; + } + else if (centers_init_==FLANN_CENTERS_GONZALES) { + chooseCenters = &HierarchicalClusteringIndex::chooseCentersGonzales; + } + else if (centers_init_==FLANN_CENTERS_KMEANSPP) { + chooseCenters = &HierarchicalClusteringIndex::chooseCentersKMeanspp; + } + else if (centers_init_==FLANN_CENTERS_GROUPWISE) { + chooseCenters = &HierarchicalClusteringIndex::GroupWiseCenterChooser; + } + else { + throw FLANNException("Unknown algorithm for choosing initial centers."); + } + + trees_ = get_param(params,"trees",4); + root = new NodePtr[trees_]; + indices = new int*[trees_]; + + for (int i=0; i(); + computeClustering(root[i], indices[i], (int)size_, branching_,0); + } + } + + + flann_algorithm_t getType() const + { + return FLANN_INDEX_HIERARCHICAL; + } + + + void saveIndex(FILE* stream) + { + save_value(stream, branching_); + save_value(stream, trees_); + save_value(stream, centers_init_); + save_value(stream, leaf_size_); + save_value(stream, memoryCounter); + for (int i=0; i& result, const ElementType* vec, const SearchParams& searchParams) + { + + int maxChecks = get_param(searchParams,"checks",32); + + // Priority queue storing intermediate branches in the best-bin-first search + Heap* heap = new Heap((int)size_); + + std::vector checked(size_,false); + int checks = 0; + for (int i=0; ipopMin(branch) && (checks BranchSt; + + + + void save_tree(FILE* stream, NodePtr node, int num) + { + save_value(stream, *node); + if (node->childs==NULL) { + int indices_offset = (int)(node->indices - indices[num]); + save_value(stream, indices_offset); + } + else { + for(int i=0; ichilds[i], num); + } + } + } + + + void load_tree(FILE* stream, NodePtr& node, int num) + { + node = pool.allocate(); + load_value(stream, *node); + if (node->childs==NULL) { + int indices_offset; + load_value(stream, indices_offset); + node->indices = indices[num] + indices_offset; + } + else { + node->childs = pool.allocate(branching_); + for(int i=0; ichilds[i], num); + } + } + } + + + + + void computeLabels(int* dsindices, int indices_length, int* centers, int centers_length, int* labels, DistanceType& cost) + { + cost = 0; + for (int i=0; inew_dist) { + labels[i] = j; + dist = new_dist; + } + } + cost += dist; + } + } + + /** + * The method responsible with actually doing the recursive hierarchical + * clustering + * + * Params: + * node = the node to cluster + * indices = indices of the points belonging to the current node + * branching = the branching factor to use in the clustering + * + * TODO: for 1-sized clusters don't store a cluster center (it's the same as the single cluster point) + */ + void computeClustering(NodePtr node, int* dsindices, int indices_length, int branching, int level) + { + node->size = indices_length; + node->level = level; + + if (indices_length < leaf_size_) { // leaf node + node->indices = dsindices; + std::sort(node->indices,node->indices+indices_length); + node->childs = NULL; + return; + } + + std::vector centers(branching); + std::vector labels(indices_length); + + int centers_length; + (this->*chooseCenters)(branching, dsindices, indices_length, ¢ers[0], centers_length); + + if (centers_lengthindices = dsindices; + std::sort(node->indices,node->indices+indices_length); + node->childs = NULL; + return; + } + + + // assign points to clusters + DistanceType cost; + computeLabels(dsindices, indices_length, ¢ers[0], centers_length, &labels[0], cost); + + node->childs = pool.allocate(branching); + int start = 0; + int end = start; + for (int i=0; ichilds[i] = pool.allocate(); + node->childs[i]->pivot = centers[i]; + node->childs[i]->indices = NULL; + computeClustering(node->childs[i],dsindices+start, end-start, branching, level+1); + start=end; + } + } + + + + /** + * Performs one descent in the hierarchical k-means tree. The branches not + * visited are stored in a priority queue. + * + * Params: + * node = node to explore + * result = container for the k-nearest neighbors found + * vec = query points + * checks = how many points in the dataset have been checked so far + * maxChecks = maximum dataset points to checks + */ + + + void findNN(NodePtr node, ResultSet& result, const ElementType* vec, int& checks, int maxChecks, + Heap* heap, std::vector& checked) + { + if (node->childs==NULL) { + if (checks>=maxChecks) { + if (result.full()) return; + } + for (int i=0; isize; ++i) { + int index = node->indices[i]; + if (!checked[index]) { + DistanceType dist = distance(dataset[index], vec, veclen_); + result.addPoint(dist, index); + checked[index] = true; + ++checks; + } + } + } + else { + DistanceType* domain_distances = new DistanceType[branching_]; + int best_index = 0; + domain_distances[best_index] = distance(vec, dataset[node->childs[best_index]->pivot], veclen_); + for (int i=1; ichilds[i]->pivot], veclen_); + if (domain_distances[i]insert(BranchSt(node->childs[i],domain_distances[i])); + } + } + delete[] domain_distances; + findNN(node->childs[best_index],result,vec, checks, maxChecks, heap, checked); + } + } + +private: + + + /** + * The dataset used by this index + */ + const Matrix dataset; + + /** + * Parameters used by this index + */ + IndexParams params; + + + /** + * Number of features in the dataset. + */ + size_t size_; + + /** + * Length of each feature. + */ + size_t veclen_; + + /** + * The root node in the tree. + */ + NodePtr* root; + + /** + * Array of indices to vectors in the dataset. + */ + int** indices; + + + /** + * The distance + */ + Distance distance; + + /** + * Pooled memory allocator. + * + * Using a pooled memory allocator is more efficient + * than allocating memory directly when there is a large + * number small of memory allocations. + */ + PooledAllocator pool; + + /** + * Memory occupied by the index. + */ + int memoryCounter; + + /** index parameters */ + int branching_; + int trees_; + flann_centers_init_t centers_init_; + int leaf_size_; + + +}; + +} + +#endif /* OPENCV_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_ */ diff --git a/include/opencv2/flann/index_testing.h b/include/opencv2/flann/index_testing.h new file mode 100644 index 0000000..d764004 --- /dev/null +++ b/include/opencv2/flann/index_testing.h @@ -0,0 +1,318 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_INDEX_TESTING_H_ +#define OPENCV_FLANN_INDEX_TESTING_H_ + +#include +#include +#include + +#include "matrix.h" +#include "nn_index.h" +#include "result_set.h" +#include "logger.h" +#include "timer.h" + + +namespace cvflann +{ + +inline int countCorrectMatches(int* neighbors, int* groundTruth, int n) +{ + int count = 0; + for (int i=0; i +typename Distance::ResultType computeDistanceRaport(const Matrix& inputData, typename Distance::ElementType* target, + int* neighbors, int* groundTruth, int veclen, int n, const Distance& distance) +{ + typedef typename Distance::ResultType DistanceType; + + DistanceType ret = 0; + for (int i=0; i +float search_with_ground_truth(NNIndex& index, const Matrix& inputData, + const Matrix& testData, const Matrix& matches, int nn, int checks, + float& time, typename Distance::ResultType& dist, const Distance& distance, int skipMatches) +{ + typedef typename Distance::ResultType DistanceType; + + if (matches.cols resultSet(nn+skipMatches); + SearchParams searchParams(checks); + + std::vector indices(nn+skipMatches); + std::vector dists(nn+skipMatches); + int* neighbors = &indices[skipMatches]; + + int correct = 0; + DistanceType distR = 0; + StartStopTimer t; + int repeats = 0; + while (t.value<0.2) { + repeats++; + t.start(); + correct = 0; + distR = 0; + for (size_t i = 0; i < testData.rows; i++) { + resultSet.init(&indices[0], &dists[0]); + index.findNeighbors(resultSet, testData[i], searchParams); + + correct += countCorrectMatches(neighbors,matches[i], nn); + distR += computeDistanceRaport(inputData, testData[i], neighbors, matches[i], (int)testData.cols, nn, distance); + } + t.stop(); + } + time = float(t.value/repeats); + + float precicion = (float)correct/(nn*testData.rows); + + dist = distR/(testData.rows*nn); + + Logger::info("%8d %10.4g %10.5g %10.5g %10.5g\n", + checks, precicion, time, 1000.0 * time / testData.rows, dist); + + return precicion; +} + + +template +float test_index_checks(NNIndex& index, const Matrix& inputData, + const Matrix& testData, const Matrix& matches, + int checks, float& precision, const Distance& distance, int nn = 1, int skipMatches = 0) +{ + typedef typename Distance::ResultType DistanceType; + + Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n"); + Logger::info("---------------------------------------------------------\n"); + + float time = 0; + DistanceType dist = 0; + precision = search_with_ground_truth(index, inputData, testData, matches, nn, checks, time, dist, distance, skipMatches); + + return time; +} + +template +float test_index_precision(NNIndex& index, const Matrix& inputData, + const Matrix& testData, const Matrix& matches, + float precision, int& checks, const Distance& distance, int nn = 1, int skipMatches = 0) +{ + typedef typename Distance::ResultType DistanceType; + const float SEARCH_EPS = 0.001f; + + Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n"); + Logger::info("---------------------------------------------------------\n"); + + int c2 = 1; + float p2; + int c1 = 1; + //float p1; + float time; + DistanceType dist; + + p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches); + + if (p2>precision) { + Logger::info("Got as close as I can\n"); + checks = c2; + return time; + } + + while (p2SEARCH_EPS) { + Logger::info("Start linear estimation\n"); + // after we got to values in the vecinity of the desired precision + // use linear approximation get a better estimation + + cx = (c1+c2)/2; + realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches); + while (fabs(realPrecision-precision)>SEARCH_EPS) { + + if (realPrecision +void test_index_precisions(NNIndex& index, const Matrix& inputData, + const Matrix& testData, const Matrix& matches, + float* precisions, int precisions_length, const Distance& distance, int nn = 1, int skipMatches = 0, float maxTime = 0) +{ + typedef typename Distance::ResultType DistanceType; + + const float SEARCH_EPS = 0.001; + + // make sure precisions array is sorted + std::sort(precisions, precisions+precisions_length); + + int pindex = 0; + float precision = precisions[pindex]; + + Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n"); + Logger::info("---------------------------------------------------------\n"); + + int c2 = 1; + float p2; + + int c1 = 1; + float p1; + + float time; + DistanceType dist; + + p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches); + + // if precision for 1 run down the tree is already + // better then some of the requested precisions, then + // skip those + while (precisions[pindex] 0)&&(time > maxTime)&&(p2SEARCH_EPS) { + Logger::info("Start linear estimation\n"); + // after we got to values in the vecinity of the desired precision + // use linear approximation get a better estimation + + cx = (c1+c2)/2; + realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches); + while (fabs(realPrecision-precision)>SEARCH_EPS) { + + if (realPrecision +#include +#include +#include + +#include "general.h" +#include "nn_index.h" +#include "dynamic_bitset.h" +#include "matrix.h" +#include "result_set.h" +#include "heap.h" +#include "allocator.h" +#include "random.h" +#include "saving.h" + + +namespace cvflann +{ + +struct KDTreeIndexParams : public IndexParams +{ + KDTreeIndexParams(int trees = 4) + { + (*this)["algorithm"] = FLANN_INDEX_KDTREE; + (*this)["trees"] = trees; + } +}; + + +/** + * Randomized kd-tree index + * + * Contains the k-d trees and other information for indexing a set of points + * for nearest-neighbor matching. + */ +template +class KDTreeIndex : public NNIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + + /** + * KDTree constructor + * + * Params: + * inputData = dataset with the input features + * params = parameters passed to the kdtree algorithm + */ + KDTreeIndex(const Matrix& inputData, const IndexParams& params = KDTreeIndexParams(), + Distance d = Distance() ) : + dataset_(inputData), index_params_(params), distance_(d) + { + size_ = dataset_.rows; + veclen_ = dataset_.cols; + + trees_ = get_param(index_params_,"trees",4); + tree_roots_ = new NodePtr[trees_]; + + // Create a permutable array of indices to the input vectors. + vind_.resize(size_); + for (size_t i = 0; i < size_; ++i) { + vind_[i] = int(i); + } + + mean_ = new DistanceType[veclen_]; + var_ = new DistanceType[veclen_]; + } + + + KDTreeIndex(const KDTreeIndex&); + KDTreeIndex& operator=(const KDTreeIndex&); + + /** + * Standard destructor + */ + ~KDTreeIndex() + { + if (tree_roots_!=NULL) { + delete[] tree_roots_; + } + delete[] mean_; + delete[] var_; + } + + /** + * Builds the index + */ + void buildIndex() + { + /* Construct the randomized trees. */ + for (int i = 0; i < trees_; i++) { + /* Randomize the order of vectors to allow for unbiased sampling. */ + std::random_shuffle(vind_.begin(), vind_.end()); + tree_roots_[i] = divideTree(&vind_[0], int(size_) ); + } + } + + + flann_algorithm_t getType() const + { + return FLANN_INDEX_KDTREE; + } + + + void saveIndex(FILE* stream) + { + save_value(stream, trees_); + for (int i=0; i& result, const ElementType* vec, const SearchParams& searchParams) + { + int maxChecks = get_param(searchParams,"checks", 32); + float epsError = 1+get_param(searchParams,"eps",0.0f); + + if (maxChecks==FLANN_CHECKS_UNLIMITED) { + getExactNeighbors(result, vec, epsError); + } + else { + getNeighbors(result, vec, maxChecks, epsError); + } + } + + IndexParams getParameters() const + { + return index_params_; + } + +private: + + + /*--------------------- Internal Data Structures --------------------------*/ + struct Node + { + /** + * Dimension used for subdivision. + */ + int divfeat; + /** + * The values used for subdivision. + */ + DistanceType divval; + /** + * The child nodes. + */ + Node* child1, * child2; + }; + typedef Node* NodePtr; + typedef BranchStruct BranchSt; + typedef BranchSt* Branch; + + + + void save_tree(FILE* stream, NodePtr tree) + { + save_value(stream, *tree); + if (tree->child1!=NULL) { + save_tree(stream, tree->child1); + } + if (tree->child2!=NULL) { + save_tree(stream, tree->child2); + } + } + + + void load_tree(FILE* stream, NodePtr& tree) + { + tree = pool_.allocate(); + load_value(stream, *tree); + if (tree->child1!=NULL) { + load_tree(stream, tree->child1); + } + if (tree->child2!=NULL) { + load_tree(stream, tree->child2); + } + } + + + /** + * Create a tree node that subdivides the list of vecs from vind[first] + * to vind[last]. The routine is called recursively on each sublist. + * Place a pointer to this new tree node in the location pTree. + * + * Params: pTree = the new node to create + * first = index of the first vector + * last = index of the last vector + */ + NodePtr divideTree(int* ind, int count) + { + NodePtr node = pool_.allocate(); // allocate memory + + /* If too few exemplars remain, then make this a leaf node. */ + if ( count == 1) { + node->child1 = node->child2 = NULL; /* Mark as leaf node. */ + node->divfeat = *ind; /* Store index of this vec. */ + } + else { + int idx; + int cutfeat; + DistanceType cutval; + meanSplit(ind, count, idx, cutfeat, cutval); + + node->divfeat = cutfeat; + node->divval = cutval; + node->child1 = divideTree(ind, idx); + node->child2 = divideTree(ind+idx, count-idx); + } + + return node; + } + + + /** + * Choose which feature to use in order to subdivide this set of vectors. + * Make a random choice among those with the highest variance, and use + * its variance as the threshold value. + */ + void meanSplit(int* ind, int count, int& index, int& cutfeat, DistanceType& cutval) + { + memset(mean_,0,veclen_*sizeof(DistanceType)); + memset(var_,0,veclen_*sizeof(DistanceType)); + + /* Compute mean values. Only the first SAMPLE_MEAN values need to be + sampled to get a good estimate. + */ + int cnt = std::min((int)SAMPLE_MEAN+1, count); + for (int j = 0; j < cnt; ++j) { + ElementType* v = dataset_[ind[j]]; + for (size_t k=0; kcount/2) index = lim1; + else if (lim2 v[topind[num-1]])) { + /* Put this element at end of topind. */ + if (num < RAND_DIM) { + topind[num++] = i; /* Add to list. */ + } + else { + topind[num-1] = i; /* Replace last element. */ + } + /* Bubble end value down to right location by repeated swapping. */ + int j = num - 1; + while (j > 0 && v[topind[j]] > v[topind[j-1]]) { + std::swap(topind[j], topind[j-1]); + --j; + } + } + } + /* Select a random integer in range [0,num-1], and return that index. */ + int rnd = rand_int(num); + return (int)topind[rnd]; + } + + + /** + * Subdivide the list of points by a plane perpendicular on axe corresponding + * to the 'cutfeat' dimension at 'cutval' position. + * + * On return: + * dataset[ind[0..lim1-1]][cutfeat]cutval + */ + void planeSplit(int* ind, int count, int cutfeat, DistanceType cutval, int& lim1, int& lim2) + { + /* Move vector indices for left subtree to front of list. */ + int left = 0; + int right = count-1; + for (;; ) { + while (left<=right && dataset_[ind[left]][cutfeat]=cutval) --right; + if (left>right) break; + std::swap(ind[left], ind[right]); ++left; --right; + } + lim1 = left; + right = count-1; + for (;; ) { + while (left<=right && dataset_[ind[left]][cutfeat]<=cutval) ++left; + while (left<=right && dataset_[ind[right]][cutfeat]>cutval) --right; + if (left>right) break; + std::swap(ind[left], ind[right]); ++left; --right; + } + lim2 = left; + } + + /** + * Performs an exact nearest neighbor search. The exact search performs a full + * traversal of the tree. + */ + void getExactNeighbors(ResultSet& result, const ElementType* vec, float epsError) + { + // checkID -= 1; /* Set a different unique ID for each search. */ + + if (trees_ > 1) { + fprintf(stderr,"It doesn't make any sense to use more than one tree for exact search"); + } + if (trees_>0) { + searchLevelExact(result, vec, tree_roots_[0], 0.0, epsError); + } + assert(result.full()); + } + + /** + * Performs the approximate nearest-neighbor search. The search is approximate + * because the tree traversal is abandoned after a given number of descends in + * the tree. + */ + void getNeighbors(ResultSet& result, const ElementType* vec, int maxCheck, float epsError) + { + int i; + BranchSt branch; + + int checkCount = 0; + Heap* heap = new Heap((int)size_); + DynamicBitset checked(size_); + + /* Search once through each tree down to root. */ + for (i = 0; i < trees_; ++i) { + searchLevel(result, vec, tree_roots_[i], 0, checkCount, maxCheck, epsError, heap, checked); + } + + /* Keep searching other branches from heap until finished. */ + while ( heap->popMin(branch) && (checkCount < maxCheck || !result.full() )) { + searchLevel(result, vec, branch.node, branch.mindist, checkCount, maxCheck, epsError, heap, checked); + } + + delete heap; + + assert(result.full()); + } + + + /** + * Search starting from a given node of the tree. Based on any mismatches at + * higher levels, all exemplars below this level must have a distance of + * at least "mindistsq". + */ + void searchLevel(ResultSet& result_set, const ElementType* vec, NodePtr node, DistanceType mindist, int& checkCount, int maxCheck, + float epsError, Heap* heap, DynamicBitset& checked) + { + if (result_set.worstDist()child1 == NULL)&&(node->child2 == NULL)) { + /* Do not check same node more than once when searching multiple trees. + Once a vector is checked, we set its location in vind to the + current checkID. + */ + int index = node->divfeat; + if ( checked.test(index) || ((checkCount>=maxCheck)&& result_set.full()) ) return; + checked.set(index); + checkCount++; + + DistanceType dist = distance_(dataset_[index], vec, veclen_); + result_set.addPoint(dist,index); + + return; + } + + /* Which child branch should be taken first? */ + ElementType val = vec[node->divfeat]; + DistanceType diff = val - node->divval; + NodePtr bestChild = (diff < 0) ? node->child1 : node->child2; + NodePtr otherChild = (diff < 0) ? node->child2 : node->child1; + + /* Create a branch record for the branch not taken. Add distance + of this feature boundary (we don't attempt to correct for any + use of this feature in a parent node, which is unlikely to + happen and would have only a small effect). Don't bother + adding more branches to heap after halfway point, as cost of + adding exceeds their value. + */ + + DistanceType new_distsq = mindist + distance_.accum_dist(val, node->divval, node->divfeat); + // if (2 * checkCount < maxCheck || !result.full()) { + if ((new_distsq*epsError < result_set.worstDist())|| !result_set.full()) { + heap->insert( BranchSt(otherChild, new_distsq) ); + } + + /* Call recursively to search next level down. */ + searchLevel(result_set, vec, bestChild, mindist, checkCount, maxCheck, epsError, heap, checked); + } + + /** + * Performs an exact search in the tree starting from a node. + */ + void searchLevelExact(ResultSet& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist, const float epsError) + { + /* If this is a leaf node, then do check and return. */ + if ((node->child1 == NULL)&&(node->child2 == NULL)) { + int index = node->divfeat; + DistanceType dist = distance_(dataset_[index], vec, veclen_); + result_set.addPoint(dist,index); + return; + } + + /* Which child branch should be taken first? */ + ElementType val = vec[node->divfeat]; + DistanceType diff = val - node->divval; + NodePtr bestChild = (diff < 0) ? node->child1 : node->child2; + NodePtr otherChild = (diff < 0) ? node->child2 : node->child1; + + /* Create a branch record for the branch not taken. Add distance + of this feature boundary (we don't attempt to correct for any + use of this feature in a parent node, which is unlikely to + happen and would have only a small effect). Don't bother + adding more branches to heap after halfway point, as cost of + adding exceeds their value. + */ + + DistanceType new_distsq = mindist + distance_.accum_dist(val, node->divval, node->divfeat); + + /* Call recursively to search next level down. */ + searchLevelExact(result_set, vec, bestChild, mindist, epsError); + + if (new_distsq*epsError<=result_set.worstDist()) { + searchLevelExact(result_set, vec, otherChild, new_distsq, epsError); + } + } + + +private: + + enum + { + /** + * To improve efficiency, only SAMPLE_MEAN random values are used to + * compute the mean and variance at each level when building a tree. + * A value of 100 seems to perform as well as using all values. + */ + SAMPLE_MEAN = 100, + /** + * Top random dimensions to consider + * + * When creating random trees, the dimension on which to subdivide is + * selected at random from among the top RAND_DIM dimensions with the + * highest variance. A value of 5 works well. + */ + RAND_DIM=5 + }; + + + /** + * Number of randomized trees that are used + */ + int trees_; + + /** + * Array of indices to vectors in the dataset. + */ + std::vector vind_; + + /** + * The dataset used by this index + */ + const Matrix dataset_; + + IndexParams index_params_; + + size_t size_; + size_t veclen_; + + + DistanceType* mean_; + DistanceType* var_; + + + /** + * Array of k-d trees used to find neighbours. + */ + NodePtr* tree_roots_; + + /** + * Pooled memory allocator. + * + * Using a pooled memory allocator is more efficient + * than allocating memory directly when there is a large + * number small of memory allocations. + */ + PooledAllocator pool_; + + Distance distance_; + + +}; // class KDTreeForest + +} + +#endif //OPENCV_FLANN_KDTREE_INDEX_H_ diff --git a/include/opencv2/flann/kdtree_single_index.h b/include/opencv2/flann/kdtree_single_index.h new file mode 100644 index 0000000..30488ad --- /dev/null +++ b/include/opencv2/flann/kdtree_single_index.h @@ -0,0 +1,634 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_KDTREE_SINGLE_INDEX_H_ +#define OPENCV_FLANN_KDTREE_SINGLE_INDEX_H_ + +#include +#include +#include +#include + +#include "general.h" +#include "nn_index.h" +#include "matrix.h" +#include "result_set.h" +#include "heap.h" +#include "allocator.h" +#include "random.h" +#include "saving.h" + +namespace cvflann +{ + +struct KDTreeSingleIndexParams : public IndexParams +{ + KDTreeSingleIndexParams(int leaf_max_size = 10, bool reorder = true, int dim = -1) + { + (*this)["algorithm"] = FLANN_INDEX_KDTREE_SINGLE; + (*this)["leaf_max_size"] = leaf_max_size; + (*this)["reorder"] = reorder; + (*this)["dim"] = dim; + } +}; + + +/** + * Randomized kd-tree index + * + * Contains the k-d trees and other information for indexing a set of points + * for nearest-neighbor matching. + */ +template +class KDTreeSingleIndex : public NNIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + + /** + * KDTree constructor + * + * Params: + * inputData = dataset with the input features + * params = parameters passed to the kdtree algorithm + */ + KDTreeSingleIndex(const Matrix& inputData, const IndexParams& params = KDTreeSingleIndexParams(), + Distance d = Distance() ) : + dataset_(inputData), index_params_(params), distance_(d) + { + size_ = dataset_.rows; + dim_ = dataset_.cols; + int dim_param = get_param(params,"dim",-1); + if (dim_param>0) dim_ = dim_param; + leaf_max_size_ = get_param(params,"leaf_max_size",10); + reorder_ = get_param(params,"reorder",true); + + // Create a permutable array of indices to the input vectors. + vind_.resize(size_); + for (size_t i = 0; i < size_; i++) { + vind_[i] = (int)i; + } + } + + KDTreeSingleIndex(const KDTreeSingleIndex&); + KDTreeSingleIndex& operator=(const KDTreeSingleIndex&); + + /** + * Standard destructor + */ + ~KDTreeSingleIndex() + { + if (reorder_) delete[] data_.data; + } + + /** + * Builds the index + */ + void buildIndex() + { + computeBoundingBox(root_bbox_); + root_node_ = divideTree(0, (int)size_, root_bbox_ ); // construct the tree + + if (reorder_) { + delete[] data_.data; + data_ = cvflann::Matrix(new ElementType[size_*dim_], size_, dim_); + for (size_t i=0; i& queries, Matrix& indices, Matrix& dists, int knn, const SearchParams& params) + { + assert(queries.cols == veclen()); + assert(indices.rows >= queries.rows); + assert(dists.rows >= queries.rows); + assert(int(indices.cols) >= knn); + assert(int(dists.cols) >= knn); + + KNNSimpleResultSet resultSet(knn); + for (size_t i = 0; i < queries.rows; i++) { + resultSet.init(indices[i], dists[i]); + findNeighbors(resultSet, queries[i], params); + } + } + + IndexParams getParameters() const + { + return index_params_; + } + + /** + * Find set of nearest neighbors to vec. Their indices are stored inside + * the result object. + * + * Params: + * result = the result object in which the indices of the nearest-neighbors are stored + * vec = the vector for which to search the nearest neighbors + * maxCheck = the maximum number of restarts (in a best-bin-first manner) + */ + void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& searchParams) + { + float epsError = 1+get_param(searchParams,"eps",0.0f); + + std::vector dists(dim_,0); + DistanceType distsq = computeInitialDistances(vec, dists); + searchLevel(result, vec, root_node_, distsq, dists, epsError); + } + +private: + + + /*--------------------- Internal Data Structures --------------------------*/ + struct Node + { + /** + * Indices of points in leaf node + */ + int left, right; + /** + * Dimension used for subdivision. + */ + int divfeat; + /** + * The values used for subdivision. + */ + DistanceType divlow, divhigh; + /** + * The child nodes. + */ + Node* child1, * child2; + }; + typedef Node* NodePtr; + + + struct Interval + { + DistanceType low, high; + }; + + typedef std::vector BoundingBox; + + typedef BranchStruct BranchSt; + typedef BranchSt* Branch; + + + + + void save_tree(FILE* stream, NodePtr tree) + { + save_value(stream, *tree); + if (tree->child1!=NULL) { + save_tree(stream, tree->child1); + } + if (tree->child2!=NULL) { + save_tree(stream, tree->child2); + } + } + + + void load_tree(FILE* stream, NodePtr& tree) + { + tree = pool_.allocate(); + load_value(stream, *tree); + if (tree->child1!=NULL) { + load_tree(stream, tree->child1); + } + if (tree->child2!=NULL) { + load_tree(stream, tree->child2); + } + } + + + void computeBoundingBox(BoundingBox& bbox) + { + bbox.resize(dim_); + for (size_t i=0; ibbox[i].high) bbox[i].high = (DistanceType)dataset_[k][i]; + } + } + } + + + /** + * Create a tree node that subdivides the list of vecs from vind[first] + * to vind[last]. The routine is called recursively on each sublist. + * Place a pointer to this new tree node in the location pTree. + * + * Params: pTree = the new node to create + * first = index of the first vector + * last = index of the last vector + */ + NodePtr divideTree(int left, int right, BoundingBox& bbox) + { + NodePtr node = pool_.allocate(); // allocate memory + + /* If too few exemplars remain, then make this a leaf node. */ + if ( (right-left) <= leaf_max_size_) { + node->child1 = node->child2 = NULL; /* Mark as leaf node. */ + node->left = left; + node->right = right; + + // compute bounding-box of leaf points + for (size_t i=0; idataset_[vind_[k]][i]) bbox[i].low=(DistanceType)dataset_[vind_[k]][i]; + if (bbox[i].highdivfeat = cutfeat; + + BoundingBox left_bbox(bbox); + left_bbox[cutfeat].high = cutval; + node->child1 = divideTree(left, left+idx, left_bbox); + + BoundingBox right_bbox(bbox); + right_bbox[cutfeat].low = cutval; + node->child2 = divideTree(left+idx, right, right_bbox); + + node->divlow = left_bbox[cutfeat].high; + node->divhigh = right_bbox[cutfeat].low; + + for (size_t i=0; imax_elem) max_elem = val; + } + } + + void middleSplit(int* ind, int count, int& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox) + { + // find the largest span from the approximate bounding box + ElementType max_span = bbox[0].high-bbox[0].low; + cutfeat = 0; + cutval = (bbox[0].high+bbox[0].low)/2; + for (size_t i=1; imax_span) { + max_span = span; + cutfeat = i; + cutval = (bbox[i].high+bbox[i].low)/2; + } + } + + // compute exact span on the found dimension + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + cutval = (min_elem+max_elem)/2; + max_span = max_elem - min_elem; + + // check if a dimension of a largest span exists + size_t k = cutfeat; + for (size_t i=0; imax_span) { + computeMinMax(ind, count, i, min_elem, max_elem); + span = max_elem - min_elem; + if (span>max_span) { + max_span = span; + cutfeat = i; + cutval = (min_elem+max_elem)/2; + } + } + } + int lim1, lim2; + planeSplit(ind, count, cutfeat, cutval, lim1, lim2); + + if (lim1>count/2) index = lim1; + else if (lim2max_span) { + max_span = span; + } + } + DistanceType max_spread = -1; + cutfeat = 0; + for (size_t i=0; i(DistanceType)((1-EPS)*max_span)) { + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + DistanceType spread = (DistanceType)(max_elem-min_elem); + if (spread>max_spread) { + cutfeat = (int)i; + max_spread = spread; + } + } + } + // split in the middle + DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2; + ElementType min_elem, max_elem; + computeMinMax(ind, count, cutfeat, min_elem, max_elem); + + if (split_valmax_elem) cutval = (DistanceType)max_elem; + else cutval = split_val; + + int lim1, lim2; + planeSplit(ind, count, cutfeat, cutval, lim1, lim2); + + if (lim1>count/2) index = lim1; + else if (lim2cutval + */ + void planeSplit(int* ind, int count, int cutfeat, DistanceType cutval, int& lim1, int& lim2) + { + /* Move vector indices for left subtree to front of list. */ + int left = 0; + int right = count-1; + for (;; ) { + while (left<=right && dataset_[ind[left]][cutfeat]=cutval) --right; + if (left>right) break; + std::swap(ind[left], ind[right]); ++left; --right; + } + /* If either list is empty, it means that all remaining features + * are identical. Split in the middle to maintain a balanced tree. + */ + lim1 = left; + right = count-1; + for (;; ) { + while (left<=right && dataset_[ind[left]][cutfeat]<=cutval) ++left; + while (left<=right && dataset_[ind[right]][cutfeat]>cutval) --right; + if (left>right) break; + std::swap(ind[left], ind[right]); ++left; --right; + } + lim2 = left; + } + + DistanceType computeInitialDistances(const ElementType* vec, std::vector& dists) + { + DistanceType distsq = 0.0; + + for (size_t i = 0; i < dim_; ++i) { + if (vec[i] < root_bbox_[i].low) { + dists[i] = distance_.accum_dist(vec[i], root_bbox_[i].low, (int)i); + distsq += dists[i]; + } + if (vec[i] > root_bbox_[i].high) { + dists[i] = distance_.accum_dist(vec[i], root_bbox_[i].high, (int)i); + distsq += dists[i]; + } + } + + return distsq; + } + + /** + * Performs an exact search in the tree starting from a node. + */ + void searchLevel(ResultSet& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq, + std::vector& dists, const float epsError) + { + /* If this is a leaf node, then do check and return. */ + if ((node->child1 == NULL)&&(node->child2 == NULL)) { + DistanceType worst_dist = result_set.worstDist(); + for (int i=node->left; iright; ++i) { + int index = reorder_ ? i : vind_[i]; + DistanceType dist = distance_(vec, data_[index], dim_, worst_dist); + if (distdivfeat; + ElementType val = vec[idx]; + DistanceType diff1 = val - node->divlow; + DistanceType diff2 = val - node->divhigh; + + NodePtr bestChild; + NodePtr otherChild; + DistanceType cut_dist; + if ((diff1+diff2)<0) { + bestChild = node->child1; + otherChild = node->child2; + cut_dist = distance_.accum_dist(val, node->divhigh, idx); + } + else { + bestChild = node->child2; + otherChild = node->child1; + cut_dist = distance_.accum_dist( val, node->divlow, idx); + } + + /* Call recursively to search next level down. */ + searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError); + + DistanceType dst = dists[idx]; + mindistsq = mindistsq + cut_dist - dst; + dists[idx] = cut_dist; + if (mindistsq*epsError<=result_set.worstDist()) { + searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError); + } + dists[idx] = dst; + } + +private: + + /** + * The dataset used by this index + */ + const Matrix dataset_; + + IndexParams index_params_; + + int leaf_max_size_; + bool reorder_; + + + /** + * Array of indices to vectors in the dataset. + */ + std::vector vind_; + + Matrix data_; + + size_t size_; + size_t dim_; + + /** + * Array of k-d trees used to find neighbours. + */ + NodePtr root_node_; + + BoundingBox root_bbox_; + + /** + * Pooled memory allocator. + * + * Using a pooled memory allocator is more efficient + * than allocating memory directly when there is a large + * number small of memory allocations. + */ + PooledAllocator pool_; + + Distance distance_; +}; // class KDTree + +} + +#endif //OPENCV_FLANN_KDTREE_SINGLE_INDEX_H_ diff --git a/include/opencv2/flann/kmeans_index.h b/include/opencv2/flann/kmeans_index.h new file mode 100644 index 0000000..b49b8dd --- /dev/null +++ b/include/opencv2/flann/kmeans_index.h @@ -0,0 +1,1167 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_KMEANS_INDEX_H_ +#define OPENCV_FLANN_KMEANS_INDEX_H_ + +#include +#include +#include +#include +#include + +#include "general.h" +#include "nn_index.h" +#include "dist.h" +#include "matrix.h" +#include "result_set.h" +#include "heap.h" +#include "allocator.h" +#include "random.h" +#include "saving.h" +#include "logger.h" + + +namespace cvflann +{ + +struct KMeansIndexParams : public IndexParams +{ + KMeansIndexParams(int branching = 32, int iterations = 11, + flann_centers_init_t centers_init = FLANN_CENTERS_RANDOM, float cb_index = 0.2 ) + { + (*this)["algorithm"] = FLANN_INDEX_KMEANS; + // branching factor + (*this)["branching"] = branching; + // max iterations to perform in one kmeans clustering (kmeans tree) + (*this)["iterations"] = iterations; + // algorithm used for picking the initial cluster centers for kmeans tree + (*this)["centers_init"] = centers_init; + // cluster boundary index. Used when searching the kmeans tree + (*this)["cb_index"] = cb_index; + } +}; + + +/** + * Hierarchical kmeans index + * + * Contains a tree constructed through a hierarchical kmeans clustering + * and other information for indexing a set of points for nearest-neighbour matching. + */ +template +class KMeansIndex : public NNIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + + + typedef void (KMeansIndex::* centersAlgFunction)(int, int*, int, int*, int&); + + /** + * The function used for choosing the cluster centers. + */ + centersAlgFunction chooseCenters; + + + + /** + * Chooses the initial centers in the k-means clustering in a random manner. + * + * Params: + * k = number of centers + * vecs = the dataset of points + * indices = indices in the dataset + * indices_length = length of indices vector + * + */ + void chooseCentersRandom(int k, int* indices, int indices_length, int* centers, int& centers_length) + { + UniqueRandom r(indices_length); + + int index; + for (index=0; index=0 && rnd < n); + + centers[0] = indices[rnd]; + + int index; + for (index=1; indexbest_val) { + best_val = dist; + best_index = j; + } + } + if (best_index!=-1) { + centers[index] = indices[best_index]; + } + else { + break; + } + } + centers_length = index; + } + + + /** + * Chooses the initial centers in the k-means using the algorithm + * proposed in the KMeans++ paper: + * Arthur, David; Vassilvitskii, Sergei - k-means++: The Advantages of Careful Seeding + * + * Implementation of this function was converted from the one provided in Arthur's code. + * + * Params: + * k = number of centers + * vecs = the dataset of points + * indices = indices in the dataset + * Returns: + */ + void chooseCentersKMeanspp(int k, int* indices, int indices_length, int* centers, int& centers_length) + { + int n = indices_length; + + double currentPot = 0; + DistanceType* closestDistSq = new DistanceType[n]; + + // Choose one random center and set the closestDistSq values + int index = rand_int(n); + assert(index >=0 && index < n); + centers[0] = indices[index]; + + for (int i = 0; i < n; i++) { + closestDistSq[i] = distance_(dataset_[indices[i]], dataset_[indices[index]], dataset_.cols); + closestDistSq[i] = ensureSquareDistance( closestDistSq[i] ); + currentPot += closestDistSq[i]; + } + + + const int numLocalTries = 1; + + // Choose each center + int centerCount; + for (centerCount = 1; centerCount < k; centerCount++) { + + // Repeat several trials + double bestNewPot = -1; + int bestNewIndex = -1; + for (int localTrial = 0; localTrial < numLocalTries; localTrial++) { + + // Choose our center - have to be slightly careful to return a valid answer even accounting + // for possible rounding errors + double randVal = rand_double(currentPot); + for (index = 0; index < n-1; index++) { + if (randVal <= closestDistSq[index]) break; + else randVal -= closestDistSq[index]; + } + + // Compute the new potential + double newPot = 0; + for (int i = 0; i < n; i++) { + DistanceType dist = distance_(dataset_[indices[i]], dataset_[indices[index]], dataset_.cols); + newPot += std::min( ensureSquareDistance(dist), closestDistSq[i] ); + } + + // Store the best result + if ((bestNewPot < 0)||(newPot < bestNewPot)) { + bestNewPot = newPot; + bestNewIndex = index; + } + } + + // Add the appropriate center + centers[centerCount] = indices[bestNewIndex]; + currentPot = bestNewPot; + for (int i = 0; i < n; i++) { + DistanceType dist = distance_(dataset_[indices[i]], dataset_[indices[bestNewIndex]], dataset_.cols); + closestDistSq[i] = std::min( ensureSquareDistance(dist), closestDistSq[i] ); + } + } + + centers_length = centerCount; + + delete[] closestDistSq; + } + + + +public: + + flann_algorithm_t getType() const + { + return FLANN_INDEX_KMEANS; + } + + class KMeansDistanceComputer : public cv::ParallelLoopBody + { + public: + KMeansDistanceComputer(Distance _distance, const Matrix& _dataset, + const int _branching, const int* _indices, const Matrix& _dcenters, const size_t _veclen, + int* _count, int* _belongs_to, std::vector& _radiuses, bool& _converged, cv::Mutex& _mtx) + : distance(_distance) + , dataset(_dataset) + , branching(_branching) + , indices(_indices) + , dcenters(_dcenters) + , veclen(_veclen) + , count(_count) + , belongs_to(_belongs_to) + , radiuses(_radiuses) + , converged(_converged) + , mtx(_mtx) + { + } + + void operator()(const cv::Range& range) const + { + const int begin = range.start; + const int end = range.end; + + for( int i = begin; inew_sq_dist) { + new_centroid = j; + sq_dist = new_sq_dist; + } + } + if (sq_dist > radiuses[new_centroid]) { + radiuses[new_centroid] = sq_dist; + } + if (new_centroid != belongs_to[i]) { + count[belongs_to[i]]--; + count[new_centroid]++; + belongs_to[i] = new_centroid; + mtx.lock(); + converged = false; + mtx.unlock(); + } + } + } + + private: + Distance distance; + const Matrix& dataset; + const int branching; + const int* indices; + const Matrix& dcenters; + const size_t veclen; + int* count; + int* belongs_to; + std::vector& radiuses; + bool& converged; + cv::Mutex& mtx; + KMeansDistanceComputer& operator=( const KMeansDistanceComputer & ) { return *this; } + }; + + /** + * Index constructor + * + * Params: + * inputData = dataset with the input features + * params = parameters passed to the hierarchical k-means algorithm + */ + KMeansIndex(const Matrix& inputData, const IndexParams& params = KMeansIndexParams(), + Distance d = Distance()) + : dataset_(inputData), index_params_(params), root_(NULL), indices_(NULL), distance_(d) + { + memoryCounter_ = 0; + + size_ = dataset_.rows; + veclen_ = dataset_.cols; + + branching_ = get_param(params,"branching",32); + iterations_ = get_param(params,"iterations",11); + if (iterations_<0) { + iterations_ = (std::numeric_limits::max)(); + } + centers_init_ = get_param(params,"centers_init",FLANN_CENTERS_RANDOM); + + if (centers_init_==FLANN_CENTERS_RANDOM) { + chooseCenters = &KMeansIndex::chooseCentersRandom; + } + else if (centers_init_==FLANN_CENTERS_GONZALES) { + chooseCenters = &KMeansIndex::chooseCentersGonzales; + } + else if (centers_init_==FLANN_CENTERS_KMEANSPP) { + chooseCenters = &KMeansIndex::chooseCentersKMeanspp; + } + else { + throw FLANNException("Unknown algorithm for choosing initial centers."); + } + cb_index_ = 0.4f; + + } + + + KMeansIndex(const KMeansIndex&); + KMeansIndex& operator=(const KMeansIndex&); + + + /** + * Index destructor. + * + * Release the memory used by the index. + */ + virtual ~KMeansIndex() + { + if (root_ != NULL) { + free_centers(root_); + } + if (indices_!=NULL) { + delete[] indices_; + } + } + + /** + * Returns size of index. + */ + size_t size() const + { + return size_; + } + + /** + * Returns the length of an index feature. + */ + size_t veclen() const + { + return veclen_; + } + + + void set_cb_index( float index) + { + cb_index_ = index; + } + + /** + * Computes the inde memory usage + * Returns: memory used by the index + */ + int usedMemory() const + { + return pool_.usedMemory+pool_.wastedMemory+memoryCounter_; + } + + /** + * Builds the index + */ + void buildIndex() + { + if (branching_<2) { + throw FLANNException("Branching factor must be at least 2"); + } + + indices_ = new int[size_]; + for (size_t i=0; i(); + computeNodeStatistics(root_, indices_, (int)size_); + computeClustering(root_, indices_, (int)size_, branching_,0); + } + + + void saveIndex(FILE* stream) + { + save_value(stream, branching_); + save_value(stream, iterations_); + save_value(stream, memoryCounter_); + save_value(stream, cb_index_); + save_value(stream, *indices_, (int)size_); + + save_tree(stream, root_); + } + + + void loadIndex(FILE* stream) + { + load_value(stream, branching_); + load_value(stream, iterations_); + load_value(stream, memoryCounter_); + load_value(stream, cb_index_); + if (indices_!=NULL) { + delete[] indices_; + } + indices_ = new int[size_]; + load_value(stream, *indices_, size_); + + if (root_!=NULL) { + free_centers(root_); + } + load_tree(stream, root_); + + index_params_["algorithm"] = getType(); + index_params_["branching"] = branching_; + index_params_["iterations"] = iterations_; + index_params_["centers_init"] = centers_init_; + index_params_["cb_index"] = cb_index_; + + } + + + /** + * Find set of nearest neighbors to vec. Their indices are stored inside + * the result object. + * + * Params: + * result = the result object in which the indices of the nearest-neighbors are stored + * vec = the vector for which to search the nearest neighbors + * searchParams = parameters that influence the search algorithm (checks, cb_index) + */ + void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& searchParams) + { + + int maxChecks = get_param(searchParams,"checks",32); + + if (maxChecks==FLANN_CHECKS_UNLIMITED) { + findExactNN(root_, result, vec); + } + else { + // Priority queue storing intermediate branches in the best-bin-first search + Heap* heap = new Heap((int)size_); + + int checks = 0; + findNN(root_, result, vec, checks, maxChecks, heap); + + BranchSt branch; + while (heap->popMin(branch) && (checks& centers) + { + int numClusters = centers.rows; + if (numClusters<1) { + throw FLANNException("Number of clusters must be at least 1"); + } + + DistanceType variance; + KMeansNodePtr* clusters = new KMeansNodePtr[numClusters]; + + int clusterCount = getMinVarianceClusters(root_, clusters, numClusters, variance); + + Logger::info("Clusters requested: %d, returning %d\n",numClusters, clusterCount); + + for (int i=0; ipivot; + for (size_t j=0; j BranchSt; + + + + + void save_tree(FILE* stream, KMeansNodePtr node) + { + save_value(stream, *node); + save_value(stream, *(node->pivot), (int)veclen_); + if (node->childs==NULL) { + int indices_offset = (int)(node->indices - indices_); + save_value(stream, indices_offset); + } + else { + for(int i=0; ichilds[i]); + } + } + } + + + void load_tree(FILE* stream, KMeansNodePtr& node) + { + node = pool_.allocate(); + load_value(stream, *node); + node->pivot = new DistanceType[veclen_]; + load_value(stream, *(node->pivot), (int)veclen_); + if (node->childs==NULL) { + int indices_offset; + load_value(stream, indices_offset); + node->indices = indices_ + indices_offset; + } + else { + node->childs = pool_.allocate(branching_); + for(int i=0; ichilds[i]); + } + } + } + + + /** + * Helper function + */ + void free_centers(KMeansNodePtr node) + { + delete[] node->pivot; + if (node->childs!=NULL) { + for (int k=0; kchilds[k]); + } + } + } + + /** + * Computes the statistics of a node (mean, radius, variance). + * + * Params: + * node = the node to use + * indices = the indices of the points belonging to the node + */ + void computeNodeStatistics(KMeansNodePtr node, int* indices, int indices_length) + { + + DistanceType radius = 0; + DistanceType variance = 0; + DistanceType* mean = new DistanceType[veclen_]; + memoryCounter_ += int(veclen_*sizeof(DistanceType)); + + memset(mean,0,veclen_*sizeof(DistanceType)); + + for (size_t i=0; i(), veclen_); + } + for (size_t j=0; j(), veclen_); + + DistanceType tmp = 0; + for (int i=0; iradius) { + radius = tmp; + } + } + + node->variance = variance; + node->radius = radius; + node->pivot = mean; + } + + + /** + * The method responsible with actually doing the recursive hierarchical + * clustering + * + * Params: + * node = the node to cluster + * indices = indices of the points belonging to the current node + * branching = the branching factor to use in the clustering + * + * TODO: for 1-sized clusters don't store a cluster center (it's the same as the single cluster point) + */ + void computeClustering(KMeansNodePtr node, int* indices, int indices_length, int branching, int level) + { + node->size = indices_length; + node->level = level; + + if (indices_length < branching) { + node->indices = indices; + std::sort(node->indices,node->indices+indices_length); + node->childs = NULL; + return; + } + + cv::AutoBuffer centers_idx_buf(branching); + int* centers_idx = (int*)centers_idx_buf; + int centers_length; + (this->*chooseCenters)(branching, indices, indices_length, centers_idx, centers_length); + + if (centers_lengthindices = indices; + std::sort(node->indices,node->indices+indices_length); + node->childs = NULL; + return; + } + + + cv::AutoBuffer dcenters_buf(branching*veclen_); + Matrix dcenters((double*)dcenters_buf,branching,veclen_); + for (int i=0; i radiuses(branching); + cv::AutoBuffer count_buf(branching); + int* count = (int*)count_buf; + for (int i=0; i belongs_to_buf(indices_length); + int* belongs_to = (int*)belongs_to_buf; + for (int i=0; inew_sq_dist) { + belongs_to[i] = j; + sq_dist = new_sq_dist; + } + } + if (sq_dist>radiuses[belongs_to[i]]) { + radiuses[belongs_to[i]] = sq_dist; + } + count[belongs_to[i]]++; + } + + bool converged = false; + int iteration = 0; + while (!converged && iterationchilds = pool_.allocate(branching); + int start = 0; + int end = start; + for (int c=0; c(), veclen_); + variance += d; + mean_radius += sqrt(d); + std::swap(indices[i],indices[end]); + std::swap(belongs_to[i],belongs_to[end]); + end++; + } + } + variance /= s; + mean_radius /= s; + variance -= distance_(centers[c], ZeroIterator(), veclen_); + + node->childs[c] = pool_.allocate(); + node->childs[c]->radius = radiuses[c]; + node->childs[c]->pivot = centers[c]; + node->childs[c]->variance = variance; + node->childs[c]->mean_radius = mean_radius; + node->childs[c]->indices = NULL; + computeClustering(node->childs[c],indices+start, end-start, branching, level+1); + start=end; + } + } + + + + /** + * Performs one descent in the hierarchical k-means tree. The branches not + * visited are stored in a priority queue. + * + * Params: + * node = node to explore + * result = container for the k-nearest neighbors found + * vec = query points + * checks = how many points in the dataset have been checked so far + * maxChecks = maximum dataset points to checks + */ + + + void findNN(KMeansNodePtr node, ResultSet& result, const ElementType* vec, int& checks, int maxChecks, + Heap* heap) + { + // Ignore those clusters that are too far away + { + DistanceType bsq = distance_(vec, node->pivot, veclen_); + DistanceType rsq = node->radius; + DistanceType wsq = result.worstDist(); + + DistanceType val = bsq-rsq-wsq; + DistanceType val2 = val*val-4*rsq*wsq; + + //if (val>0) { + if ((val>0)&&(val2>0)) { + return; + } + } + + if (node->childs==NULL) { + if (checks>=maxChecks) { + if (result.full()) return; + } + checks += node->size; + for (int i=0; isize; ++i) { + int index = node->indices[i]; + DistanceType dist = distance_(dataset_[index], vec, veclen_); + result.addPoint(dist, index); + } + } + else { + DistanceType* domain_distances = new DistanceType[branching_]; + int closest_center = exploreNodeBranches(node, vec, domain_distances, heap); + delete[] domain_distances; + findNN(node->childs[closest_center],result,vec, checks, maxChecks, heap); + } + } + + /** + * Helper function that computes the nearest childs of a node to a given query point. + * Params: + * node = the node + * q = the query point + * distances = array with the distances to each child node. + * Returns: + */ + int exploreNodeBranches(KMeansNodePtr node, const ElementType* q, DistanceType* domain_distances, Heap* heap) + { + + int best_index = 0; + domain_distances[best_index] = distance_(q, node->childs[best_index]->pivot, veclen_); + for (int i=1; ichilds[i]->pivot, veclen_); + if (domain_distances[i]childs[best_index]->pivot; + for (int i=0; ichilds[i]->variance; + + // float dist_to_border = getDistanceToBorder(node.childs[i].pivot,best_center,q); + // if (domain_distances[i]insert(BranchSt(node->childs[i],domain_distances[i])); + } + } + + return best_index; + } + + + /** + * Function the performs exact nearest neighbor search by traversing the entire tree. + */ + void findExactNN(KMeansNodePtr node, ResultSet& result, const ElementType* vec) + { + // Ignore those clusters that are too far away + { + DistanceType bsq = distance_(vec, node->pivot, veclen_); + DistanceType rsq = node->radius; + DistanceType wsq = result.worstDist(); + + DistanceType val = bsq-rsq-wsq; + DistanceType val2 = val*val-4*rsq*wsq; + + // if (val>0) { + if ((val>0)&&(val2>0)) { + return; + } + } + + + if (node->childs==NULL) { + for (int i=0; isize; ++i) { + int index = node->indices[i]; + DistanceType dist = distance_(dataset_[index], vec, veclen_); + result.addPoint(dist, index); + } + } + else { + int* sort_indices = new int[branching_]; + + getCenterOrdering(node, vec, sort_indices); + + for (int i=0; ichilds[sort_indices[i]],result,vec); + } + + delete[] sort_indices; + } + } + + + /** + * Helper function. + * + * I computes the order in which to traverse the child nodes of a particular node. + */ + void getCenterOrdering(KMeansNodePtr node, const ElementType* q, int* sort_indices) + { + DistanceType* domain_distances = new DistanceType[branching_]; + for (int i=0; ichilds[i]->pivot, veclen_); + + int j=0; + while (domain_distances[j]j; --k) { + domain_distances[k] = domain_distances[k-1]; + sort_indices[k] = sort_indices[k-1]; + } + domain_distances[j] = dist; + sort_indices[j] = i; + } + delete[] domain_distances; + } + + /** + * Method that computes the squared distance from the query point q + * from inside region with center c to the border between this + * region and the region with center p + */ + DistanceType getDistanceToBorder(DistanceType* p, DistanceType* c, DistanceType* q) + { + DistanceType sum = 0; + DistanceType sum2 = 0; + + for (int i=0; ivariance*root->size; + + while (clusterCount::max)(); + int splitIndex = -1; + + for (int i=0; ichilds != NULL) { + + DistanceType variance = meanVariance - clusters[i]->variance*clusters[i]->size; + + for (int j=0; jchilds[j]->variance*clusters[i]->childs[j]->size; + } + if (variance clusters_length) break; + + meanVariance = minVariance; + + // split node + KMeansNodePtr toSplit = clusters[splitIndex]; + clusters[splitIndex] = toSplit->childs[0]; + for (int i=1; ichilds[i]; + } + } + + varianceValue = meanVariance/root->size; + return clusterCount; + } + +private: + /** The branching factor used in the hierarchical k-means clustering */ + int branching_; + + /** Maximum number of iterations to use when performing k-means clustering */ + int iterations_; + + /** Algorithm for choosing the cluster centers */ + flann_centers_init_t centers_init_; + + /** + * Cluster border index. This is used in the tree search phase when determining + * the closest cluster to explore next. A zero value takes into account only + * the cluster centres, a value greater then zero also take into account the size + * of the cluster. + */ + float cb_index_; + + /** + * The dataset used by this index + */ + const Matrix dataset_; + + /** Index parameters */ + IndexParams index_params_; + + /** + * Number of features in the dataset. + */ + size_t size_; + + /** + * Length of each feature. + */ + size_t veclen_; + + /** + * The root node in the tree. + */ + KMeansNodePtr root_; + + /** + * Array of indices to vectors in the dataset. + */ + int* indices_; + + /** + * The distance + */ + Distance distance_; + + /** + * Pooled memory allocator. + */ + PooledAllocator pool_; + + /** + * Memory occupied by the index. + */ + int memoryCounter_; +}; + +} + +#endif //OPENCV_FLANN_KMEANS_INDEX_H_ diff --git a/include/opencv2/flann/linear_index.h b/include/opencv2/flann/linear_index.h new file mode 100644 index 0000000..5aa7a5c --- /dev/null +++ b/include/opencv2/flann/linear_index.h @@ -0,0 +1,132 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_LINEAR_INDEX_H_ +#define OPENCV_FLANN_LINEAR_INDEX_H_ + +#include "general.h" +#include "nn_index.h" + +namespace cvflann +{ + +struct LinearIndexParams : public IndexParams +{ + LinearIndexParams() + { + (* this)["algorithm"] = FLANN_INDEX_LINEAR; + } +}; + +template +class LinearIndex : public NNIndex +{ +public: + + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + + LinearIndex(const Matrix& inputData, const IndexParams& params = LinearIndexParams(), + Distance d = Distance()) : + dataset_(inputData), index_params_(params), distance_(d) + { + } + + LinearIndex(const LinearIndex&); + LinearIndex& operator=(const LinearIndex&); + + flann_algorithm_t getType() const + { + return FLANN_INDEX_LINEAR; + } + + + size_t size() const + { + return dataset_.rows; + } + + size_t veclen() const + { + return dataset_.cols; + } + + + int usedMemory() const + { + return 0; + } + + void buildIndex() + { + /* nothing to do here for linear search */ + } + + void saveIndex(FILE*) + { + /* nothing to do here for linear search */ + } + + + void loadIndex(FILE*) + { + /* nothing to do here for linear search */ + + index_params_["algorithm"] = getType(); + } + + void findNeighbors(ResultSet& resultSet, const ElementType* vec, const SearchParams& /*searchParams*/) + { + ElementType* data = dataset_.data; + for (size_t i = 0; i < dataset_.rows; ++i, data += dataset_.cols) { + DistanceType dist = distance_(data, vec, dataset_.cols); + resultSet.addPoint(dist, (int)i); + } + } + + IndexParams getParameters() const + { + return index_params_; + } + +private: + /** The dataset */ + const Matrix dataset_; + /** Index parameters */ + IndexParams index_params_; + /** Index distance */ + Distance distance_; + +}; + +} + +#endif // OPENCV_FLANN_LINEAR_INDEX_H_ diff --git a/include/opencv2/flann/logger.h b/include/opencv2/flann/logger.h new file mode 100644 index 0000000..24f3fb6 --- /dev/null +++ b/include/opencv2/flann/logger.h @@ -0,0 +1,130 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_LOGGER_H +#define OPENCV_FLANN_LOGGER_H + +#include +#include + +#include "defines.h" + + +namespace cvflann +{ + +class Logger +{ + Logger() : stream(stdout), logLevel(FLANN_LOG_WARN) {} + + ~Logger() + { + if ((stream!=NULL)&&(stream!=stdout)) { + fclose(stream); + } + } + + static Logger& instance() + { + static Logger logger; + return logger; + } + + void _setDestination(const char* name) + { + if (name==NULL) { + stream = stdout; + } + else { + stream = fopen(name,"w"); + if (stream == NULL) { + stream = stdout; + } + } + } + + int _log(int level, const char* fmt, va_list arglist) + { + if (level > logLevel ) return -1; + int ret = vfprintf(stream, fmt, arglist); + return ret; + } + +public: + /** + * Sets the logging level. All messages with lower priority will be ignored. + * @param level Logging level + */ + static void setLevel(int level) { instance().logLevel = level; } + + /** + * Sets the logging destination + * @param name Filename or NULL for console + */ + static void setDestination(const char* name) { instance()._setDestination(name); } + + /** + * Print log message + * @param level Log level + * @param fmt Message format + * @return + */ + static int log(int level, const char* fmt, ...) + { + va_list arglist; + va_start(arglist, fmt); + int ret = instance()._log(level,fmt,arglist); + va_end(arglist); + return ret; + } + +#define LOG_METHOD(NAME,LEVEL) \ + static int NAME(const char* fmt, ...) \ + { \ + va_list ap; \ + va_start(ap, fmt); \ + int ret = instance()._log(LEVEL, fmt, ap); \ + va_end(ap); \ + return ret; \ + } + + LOG_METHOD(fatal, FLANN_LOG_FATAL) + LOG_METHOD(error, FLANN_LOG_ERROR) + LOG_METHOD(warn, FLANN_LOG_WARN) + LOG_METHOD(info, FLANN_LOG_INFO) + +private: + FILE* stream; + int logLevel; +}; + +} + +#endif //OPENCV_FLANN_LOGGER_H diff --git a/include/opencv2/flann/lsh_index.h b/include/opencv2/flann/lsh_index.h new file mode 100644 index 0000000..4d4670e --- /dev/null +++ b/include/opencv2/flann/lsh_index.h @@ -0,0 +1,392 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +/*********************************************************************** + * Author: Vincent Rabaud + *************************************************************************/ + +#ifndef OPENCV_FLANN_LSH_INDEX_H_ +#define OPENCV_FLANN_LSH_INDEX_H_ + +#include +#include +#include +#include +#include + +#include "general.h" +#include "nn_index.h" +#include "matrix.h" +#include "result_set.h" +#include "heap.h" +#include "lsh_table.h" +#include "allocator.h" +#include "random.h" +#include "saving.h" + +namespace cvflann +{ + +struct LshIndexParams : public IndexParams +{ + LshIndexParams(unsigned int table_number = 12, unsigned int key_size = 20, unsigned int multi_probe_level = 2) + { + (* this)["algorithm"] = FLANN_INDEX_LSH; + // The number of hash tables to use + (*this)["table_number"] = table_number; + // The length of the key in the hash tables + (*this)["key_size"] = key_size; + // Number of levels to use in multi-probe (0 for standard LSH) + (*this)["multi_probe_level"] = multi_probe_level; + } +}; + +/** + * Randomized kd-tree index + * + * Contains the k-d trees and other information for indexing a set of points + * for nearest-neighbor matching. + */ +template +class LshIndex : public NNIndex +{ +public: + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + + /** Constructor + * @param input_data dataset with the input features + * @param params parameters passed to the LSH algorithm + * @param d the distance used + */ + LshIndex(const Matrix& input_data, const IndexParams& params = LshIndexParams(), + Distance d = Distance()) : + dataset_(input_data), index_params_(params), distance_(d) + { + // cv::flann::IndexParams sets integer params as 'int', so it is used with get_param + // in place of 'unsigned int' + table_number_ = (unsigned int)get_param(index_params_,"table_number",12); + key_size_ = (unsigned int)get_param(index_params_,"key_size",20); + multi_probe_level_ = (unsigned int)get_param(index_params_,"multi_probe_level",2); + + feature_size_ = (unsigned)dataset_.cols; + fill_xor_mask(0, key_size_, multi_probe_level_, xor_masks_); + } + + + LshIndex(const LshIndex&); + LshIndex& operator=(const LshIndex&); + + /** + * Builds the index + */ + void buildIndex() + { + tables_.resize(table_number_); + for (unsigned int i = 0; i < table_number_; ++i) { + lsh::LshTable& table = tables_[i]; + table = lsh::LshTable(feature_size_, key_size_); + + // Add the features to the table + table.add(dataset_); + } + } + + flann_algorithm_t getType() const + { + return FLANN_INDEX_LSH; + } + + + void saveIndex(FILE* stream) + { + save_value(stream,table_number_); + save_value(stream,key_size_); + save_value(stream,multi_probe_level_); + save_value(stream, dataset_); + } + + void loadIndex(FILE* stream) + { + load_value(stream, table_number_); + load_value(stream, key_size_); + load_value(stream, multi_probe_level_); + load_value(stream, dataset_); + // Building the index is so fast we can afford not storing it + buildIndex(); + + index_params_["algorithm"] = getType(); + index_params_["table_number"] = table_number_; + index_params_["key_size"] = key_size_; + index_params_["multi_probe_level"] = multi_probe_level_; + } + + /** + * Returns size of index. + */ + size_t size() const + { + return dataset_.rows; + } + + /** + * Returns the length of an index feature. + */ + size_t veclen() const + { + return feature_size_; + } + + /** + * Computes the index memory usage + * Returns: memory used by the index + */ + int usedMemory() const + { + return (int)(dataset_.rows * sizeof(int)); + } + + + IndexParams getParameters() const + { + return index_params_; + } + + /** + * \brief Perform k-nearest neighbor search + * \param[in] queries The query points for which to find the nearest neighbors + * \param[out] indices The indices of the nearest neighbors found + * \param[out] dists Distances to the nearest neighbors found + * \param[in] knn Number of nearest neighbors to return + * \param[in] params Search parameters + */ + virtual void knnSearch(const Matrix& queries, Matrix& indices, Matrix& dists, int knn, const SearchParams& params) + { + assert(queries.cols == veclen()); + assert(indices.rows >= queries.rows); + assert(dists.rows >= queries.rows); + assert(int(indices.cols) >= knn); + assert(int(dists.cols) >= knn); + + + KNNUniqueResultSet resultSet(knn); + for (size_t i = 0; i < queries.rows; i++) { + resultSet.clear(); + std::fill_n(indices[i], knn, -1); + std::fill_n(dists[i], knn, std::numeric_limits::max()); + findNeighbors(resultSet, queries[i], params); + if (get_param(params,"sorted",true)) resultSet.sortAndCopy(indices[i], dists[i], knn); + else resultSet.copy(indices[i], dists[i], knn); + } + } + + + /** + * Find set of nearest neighbors to vec. Their indices are stored inside + * the result object. + * + * Params: + * result = the result object in which the indices of the nearest-neighbors are stored + * vec = the vector for which to search the nearest neighbors + * maxCheck = the maximum number of restarts (in a best-bin-first manner) + */ + void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& /*searchParams*/) + { + getNeighbors(vec, result); + } + +private: + /** Defines the comparator on score and index + */ + typedef std::pair ScoreIndexPair; + struct SortScoreIndexPairOnSecond + { + bool operator()(const ScoreIndexPair& left, const ScoreIndexPair& right) const + { + return left.second < right.second; + } + }; + + /** Fills the different xor masks to use when getting the neighbors in multi-probe LSH + * @param key the key we build neighbors from + * @param lowest_index the lowest index of the bit set + * @param level the multi-probe level we are at + * @param xor_masks all the xor mask + */ + void fill_xor_mask(lsh::BucketKey key, int lowest_index, unsigned int level, + std::vector& xor_masks) + { + xor_masks.push_back(key); + if (level == 0) return; + for (int index = lowest_index - 1; index >= 0; --index) { + // Create a new key + lsh::BucketKey new_key = key | (1 << index); + fill_xor_mask(new_key, index, level - 1, xor_masks); + } + } + + /** Performs the approximate nearest-neighbor search. + * @param vec the feature to analyze + * @param do_radius flag indicating if we check the radius too + * @param radius the radius if it is a radius search + * @param do_k flag indicating if we limit the number of nn + * @param k_nn the number of nearest neighbors + * @param checked_average used for debugging + */ + void getNeighbors(const ElementType* vec, bool /*do_radius*/, float radius, bool do_k, unsigned int k_nn, + float& /*checked_average*/) + { + static std::vector score_index_heap; + + if (do_k) { + unsigned int worst_score = std::numeric_limits::max(); + typename std::vector >::const_iterator table = tables_.begin(); + typename std::vector >::const_iterator table_end = tables_.end(); + for (; table != table_end; ++table) { + size_t key = table->getKey(vec); + std::vector::const_iterator xor_mask = xor_masks_.begin(); + std::vector::const_iterator xor_mask_end = xor_masks_.end(); + for (; xor_mask != xor_mask_end; ++xor_mask) { + size_t sub_key = key ^ (*xor_mask); + const lsh::Bucket* bucket = table->getBucketFromKey(sub_key); + if (bucket == 0) continue; + + // Go over each descriptor index + std::vector::const_iterator training_index = bucket->begin(); + std::vector::const_iterator last_training_index = bucket->end(); + DistanceType hamming_distance; + + // Process the rest of the candidates + for (; training_index < last_training_index; ++training_index) { + hamming_distance = distance_(vec, dataset_[*training_index], dataset_.cols); + + if (hamming_distance < worst_score) { + // Insert the new element + score_index_heap.push_back(ScoreIndexPair(hamming_distance, training_index)); + std::push_heap(score_index_heap.begin(), score_index_heap.end()); + + if (score_index_heap.size() > (unsigned int)k_nn) { + // Remove the highest distance value as we have too many elements + std::pop_heap(score_index_heap.begin(), score_index_heap.end()); + score_index_heap.pop_back(); + // Keep track of the worst score + worst_score = score_index_heap.front().first; + } + } + } + } + } + } + else { + typename std::vector >::const_iterator table = tables_.begin(); + typename std::vector >::const_iterator table_end = tables_.end(); + for (; table != table_end; ++table) { + size_t key = table->getKey(vec); + std::vector::const_iterator xor_mask = xor_masks_.begin(); + std::vector::const_iterator xor_mask_end = xor_masks_.end(); + for (; xor_mask != xor_mask_end; ++xor_mask) { + size_t sub_key = key ^ (*xor_mask); + const lsh::Bucket* bucket = table->getBucketFromKey(sub_key); + if (bucket == 0) continue; + + // Go over each descriptor index + std::vector::const_iterator training_index = bucket->begin(); + std::vector::const_iterator last_training_index = bucket->end(); + DistanceType hamming_distance; + + // Process the rest of the candidates + for (; training_index < last_training_index; ++training_index) { + // Compute the Hamming distance + hamming_distance = distance_(vec, dataset_[*training_index], dataset_.cols); + if (hamming_distance < radius) score_index_heap.push_back(ScoreIndexPair(hamming_distance, training_index)); + } + } + } + } + } + + /** Performs the approximate nearest-neighbor search. + * This is a slower version than the above as it uses the ResultSet + * @param vec the feature to analyze + */ + void getNeighbors(const ElementType* vec, ResultSet& result) + { + typename std::vector >::const_iterator table = tables_.begin(); + typename std::vector >::const_iterator table_end = tables_.end(); + for (; table != table_end; ++table) { + size_t key = table->getKey(vec); + std::vector::const_iterator xor_mask = xor_masks_.begin(); + std::vector::const_iterator xor_mask_end = xor_masks_.end(); + for (; xor_mask != xor_mask_end; ++xor_mask) { + size_t sub_key = key ^ (*xor_mask); + const lsh::Bucket* bucket = table->getBucketFromKey((lsh::BucketKey)sub_key); + if (bucket == 0) continue; + + // Go over each descriptor index + std::vector::const_iterator training_index = bucket->begin(); + std::vector::const_iterator last_training_index = bucket->end(); + DistanceType hamming_distance; + + // Process the rest of the candidates + for (; training_index < last_training_index; ++training_index) { + // Compute the Hamming distance + hamming_distance = distance_(vec, dataset_[*training_index], (int)dataset_.cols); + result.addPoint(hamming_distance, *training_index); + } + } + } + } + + /** The different hash tables */ + std::vector > tables_; + + /** The data the LSH tables where built from */ + Matrix dataset_; + + /** The size of the features (as ElementType[]) */ + unsigned int feature_size_; + + IndexParams index_params_; + + /** table number */ + unsigned int table_number_; + /** key size */ + unsigned int key_size_; + /** How far should we look for neighbors in multi-probe LSH */ + unsigned int multi_probe_level_; + + /** The XOR masks to apply to a key to get the neighboring buckets */ + std::vector xor_masks_; + + Distance distance_; +}; +} + +#endif //OPENCV_FLANN_LSH_INDEX_H_ diff --git a/include/opencv2/flann/lsh_table.h b/include/opencv2/flann/lsh_table.h new file mode 100644 index 0000000..582dcdb --- /dev/null +++ b/include/opencv2/flann/lsh_table.h @@ -0,0 +1,492 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +/*********************************************************************** + * Author: Vincent Rabaud + *************************************************************************/ + +#ifndef OPENCV_FLANN_LSH_TABLE_H_ +#define OPENCV_FLANN_LSH_TABLE_H_ + +#include +#include +#include +#include +// TODO as soon as we use C++0x, use the code in USE_UNORDERED_MAP +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define USE_UNORDERED_MAP 1 +#else +# define USE_UNORDERED_MAP 0 +#endif +#if USE_UNORDERED_MAP +#include +#else +#include +#endif +#include +#include + +#include "dynamic_bitset.h" +#include "matrix.h" + +namespace cvflann +{ + +namespace lsh +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** What is stored in an LSH bucket + */ +typedef uint32_t FeatureIndex; +/** The id from which we can get a bucket back in an LSH table + */ +typedef unsigned int BucketKey; + +/** A bucket in an LSH table + */ +typedef std::vector Bucket; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** POD for stats about an LSH table + */ +struct LshStats +{ + std::vector bucket_sizes_; + size_t n_buckets_; + size_t bucket_size_mean_; + size_t bucket_size_median_; + size_t bucket_size_min_; + size_t bucket_size_max_; + size_t bucket_size_std_dev; + /** Each contained vector contains three value: beginning/end for interval, number of elements in the bin + */ + std::vector > size_histogram_; +}; + +/** Overload the << operator for LshStats + * @param out the streams + * @param stats the stats to display + * @return the streams + */ +inline std::ostream& operator <<(std::ostream& out, const LshStats& stats) +{ + int w = 20; + out << "Lsh Table Stats:\n" << std::setw(w) << std::setiosflags(std::ios::right) << "N buckets : " + << stats.n_buckets_ << "\n" << std::setw(w) << std::setiosflags(std::ios::right) << "mean size : " + << std::setiosflags(std::ios::left) << stats.bucket_size_mean_ << "\n" << std::setw(w) + << std::setiosflags(std::ios::right) << "median size : " << stats.bucket_size_median_ << "\n" << std::setw(w) + << std::setiosflags(std::ios::right) << "min size : " << std::setiosflags(std::ios::left) + << stats.bucket_size_min_ << "\n" << std::setw(w) << std::setiosflags(std::ios::right) << "max size : " + << std::setiosflags(std::ios::left) << stats.bucket_size_max_; + + // Display the histogram + out << std::endl << std::setw(w) << std::setiosflags(std::ios::right) << "histogram : " + << std::setiosflags(std::ios::left); + for (std::vector >::const_iterator iterator = stats.size_histogram_.begin(), end = + stats.size_histogram_.end(); iterator != end; ++iterator) out << (*iterator)[0] << "-" << (*iterator)[1] << ": " << (*iterator)[2] << ", "; + + return out; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** Lsh hash table. As its key is a sub-feature, and as usually + * the size of it is pretty small, we keep it as a continuous memory array. + * The value is an index in the corpus of features (we keep it as an unsigned + * int for pure memory reasons, it could be a size_t) + */ +template +class LshTable +{ +public: + /** A container of all the feature indices. Optimized for space + */ +#if USE_UNORDERED_MAP + typedef std::unordered_map BucketsSpace; +#else + typedef std::map BucketsSpace; +#endif + + /** A container of all the feature indices. Optimized for speed + */ + typedef std::vector BucketsSpeed; + + /** Default constructor + */ + LshTable() + { + } + + /** Default constructor + * Create the mask and allocate the memory + * @param feature_size is the size of the feature (considered as a ElementType[]) + * @param key_size is the number of bits that are turned on in the feature + */ + LshTable(unsigned int feature_size, unsigned int key_size) + { + (void)feature_size; + (void)key_size; + std::cerr << "LSH is not implemented for that type" << std::endl; + assert(0); + } + + /** Add a feature to the table + * @param value the value to store for that feature + * @param feature the feature itself + */ + void add(unsigned int value, const ElementType* feature) + { + // Add the value to the corresponding bucket + BucketKey key = (lsh::BucketKey)getKey(feature); + + switch (speed_level_) { + case kArray: + // That means we get the buckets from an array + buckets_speed_[key].push_back(value); + break; + case kBitsetHash: + // That means we can check the bitset for the presence of a key + key_bitset_.set(key); + buckets_space_[key].push_back(value); + break; + case kHash: + { + // That means we have to check for the hash table for the presence of a key + buckets_space_[key].push_back(value); + break; + } + } + } + + /** Add a set of features to the table + * @param dataset the values to store + */ + void add(Matrix dataset) + { +#if USE_UNORDERED_MAP + buckets_space_.rehash((buckets_space_.size() + dataset.rows) * 1.2); +#endif + // Add the features to the table + for (unsigned int i = 0; i < dataset.rows; ++i) add(i, dataset[i]); + // Now that the table is full, optimize it for speed/space + optimize(); + } + + /** Get a bucket given the key + * @param key + * @return + */ + inline const Bucket* getBucketFromKey(BucketKey key) const + { + // Generate other buckets + switch (speed_level_) { + case kArray: + // That means we get the buckets from an array + return &buckets_speed_[key]; + break; + case kBitsetHash: + // That means we can check the bitset for the presence of a key + if (key_bitset_.test(key)) return &buckets_space_.find(key)->second; + else return 0; + break; + case kHash: + { + // That means we have to check for the hash table for the presence of a key + BucketsSpace::const_iterator bucket_it, bucket_end = buckets_space_.end(); + bucket_it = buckets_space_.find(key); + // Stop here if that bucket does not exist + if (bucket_it == bucket_end) return 0; + else return &bucket_it->second; + break; + } + } + return 0; + } + + /** Compute the sub-signature of a feature + */ + size_t getKey(const ElementType* /*feature*/) const + { + std::cerr << "LSH is not implemented for that type" << std::endl; + assert(0); + return 1; + } + + /** Get statistics about the table + * @return + */ + LshStats getStats() const; + +private: + /** defines the speed fo the implementation + * kArray uses a vector for storing data + * kBitsetHash uses a hash map but checks for the validity of a key with a bitset + * kHash uses a hash map only + */ + enum SpeedLevel + { + kArray, kBitsetHash, kHash + }; + + /** Initialize some variables + */ + void initialize(size_t key_size) + { + const size_t key_size_lower_bound = 1; + //a value (size_t(1) << key_size) must fit the size_t type so key_size has to be strictly less than size of size_t + const size_t key_size_upper_bound = std::min(sizeof(BucketKey) * CHAR_BIT + 1, sizeof(size_t) * CHAR_BIT); + if (key_size < key_size_lower_bound || key_size >= key_size_upper_bound) + { + CV_Error(cv::Error::StsBadArg, cv::format("Invalid key_size (=%d). Valid values for your system are %d <= key_size < %d.", (int)key_size, (int)key_size_lower_bound, (int)key_size_upper_bound)); + } + + speed_level_ = kHash; + key_size_ = (unsigned)key_size; + } + + /** Optimize the table for speed/space + */ + void optimize() + { + // If we are already using the fast storage, no need to do anything + if (speed_level_ == kArray) return; + + // Use an array if it will be more than half full + if (buckets_space_.size() > ((size_t(1) << key_size_) / 2)) { + speed_level_ = kArray; + // Fill the array version of it + buckets_speed_.resize(size_t(1) << key_size_); + for (BucketsSpace::const_iterator key_bucket = buckets_space_.begin(); key_bucket != buckets_space_.end(); ++key_bucket) buckets_speed_[key_bucket->first] = key_bucket->second; + + // Empty the hash table + buckets_space_.clear(); + return; + } + + // If the bitset is going to use less than 10% of the RAM of the hash map (at least 1 size_t for the key and two + // for the vector) or less than 512MB (key_size_ <= 30) + if (((std::max(buckets_space_.size(), buckets_speed_.size()) * CHAR_BIT * 3 * sizeof(BucketKey)) / 10 + >= (size_t(1) << key_size_)) || (key_size_ <= 32)) { + speed_level_ = kBitsetHash; + key_bitset_.resize(size_t(1) << key_size_); + key_bitset_.reset(); + // Try with the BucketsSpace + for (BucketsSpace::const_iterator key_bucket = buckets_space_.begin(); key_bucket != buckets_space_.end(); ++key_bucket) key_bitset_.set(key_bucket->first); + } + else { + speed_level_ = kHash; + key_bitset_.clear(); + } + } + + /** The vector of all the buckets if they are held for speed + */ + BucketsSpeed buckets_speed_; + + /** The hash table of all the buckets in case we cannot use the speed version + */ + BucketsSpace buckets_space_; + + /** What is used to store the data */ + SpeedLevel speed_level_; + + /** If the subkey is small enough, it will keep track of which subkeys are set through that bitset + * That is just a speedup so that we don't look in the hash table (which can be mush slower that checking a bitset) + */ + DynamicBitset key_bitset_; + + /** The size of the sub-signature in bits + */ + unsigned int key_size_; + + // Members only used for the unsigned char specialization + /** The mask to apply to a feature to get the hash key + * Only used in the unsigned char case + */ + std::vector mask_; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Specialization for unsigned char + +template<> +inline LshTable::LshTable(unsigned int feature_size, unsigned int subsignature_size) +{ + initialize(subsignature_size); + // Allocate the mask + mask_ = std::vector((size_t)ceil((float)(feature_size * sizeof(char)) / (float)sizeof(size_t)), 0); + + // A bit brutal but fast to code + std::vector indices(feature_size * CHAR_BIT); + for (size_t i = 0; i < feature_size * CHAR_BIT; ++i) indices[i] = i; + std::random_shuffle(indices.begin(), indices.end()); + + // Generate a random set of order of subsignature_size_ bits + for (unsigned int i = 0; i < key_size_; ++i) { + size_t index = indices[i]; + + // Set that bit in the mask + size_t divisor = CHAR_BIT * sizeof(size_t); + size_t idx = index / divisor; //pick the right size_t index + mask_[idx] |= size_t(1) << (index % divisor); //use modulo to find the bit offset + } + + // Set to 1 if you want to display the mask for debug +#if 0 + { + size_t bcount = 0; + BOOST_FOREACH(size_t mask_block, mask_){ + out << std::setw(sizeof(size_t) * CHAR_BIT / 4) << std::setfill('0') << std::hex << mask_block + << std::endl; + bcount += __builtin_popcountll(mask_block); + } + out << "bit count : " << std::dec << bcount << std::endl; + out << "mask size : " << mask_.size() << std::endl; + return out; + } +#endif +} + +/** Return the Subsignature of a feature + * @param feature the feature to analyze + */ +template<> +inline size_t LshTable::getKey(const unsigned char* feature) const +{ + // no need to check if T is dividable by sizeof(size_t) like in the Hamming + // distance computation as we have a mask + const size_t* feature_block_ptr = reinterpret_cast ((const void*)feature); + + // Figure out the subsignature of the feature + // Given the feature ABCDEF, and the mask 001011, the output will be + // 000CEF + size_t subsignature = 0; + size_t bit_index = 1; + + for (std::vector::const_iterator pmask_block = mask_.begin(); pmask_block != mask_.end(); ++pmask_block) { + // get the mask and signature blocks + size_t feature_block = *feature_block_ptr; + size_t mask_block = *pmask_block; + while (mask_block) { + // Get the lowest set bit in the mask block + size_t lowest_bit = mask_block & (-(ptrdiff_t)mask_block); + // Add it to the current subsignature if necessary + subsignature += (feature_block & lowest_bit) ? bit_index : 0; + // Reset the bit in the mask block + mask_block ^= lowest_bit; + // increment the bit index for the subsignature + bit_index <<= 1; + } + // Check the next feature block + ++feature_block_ptr; + } + return subsignature; +} + +template<> +inline LshStats LshTable::getStats() const +{ + LshStats stats; + stats.bucket_size_mean_ = 0; + if ((buckets_speed_.empty()) && (buckets_space_.empty())) { + stats.n_buckets_ = 0; + stats.bucket_size_median_ = 0; + stats.bucket_size_min_ = 0; + stats.bucket_size_max_ = 0; + return stats; + } + + if (!buckets_speed_.empty()) { + for (BucketsSpeed::const_iterator pbucket = buckets_speed_.begin(); pbucket != buckets_speed_.end(); ++pbucket) { + stats.bucket_sizes_.push_back((lsh::FeatureIndex)pbucket->size()); + stats.bucket_size_mean_ += pbucket->size(); + } + stats.bucket_size_mean_ /= buckets_speed_.size(); + stats.n_buckets_ = buckets_speed_.size(); + } + else { + for (BucketsSpace::const_iterator x = buckets_space_.begin(); x != buckets_space_.end(); ++x) { + stats.bucket_sizes_.push_back((lsh::FeatureIndex)x->second.size()); + stats.bucket_size_mean_ += x->second.size(); + } + stats.bucket_size_mean_ /= buckets_space_.size(); + stats.n_buckets_ = buckets_space_.size(); + } + + std::sort(stats.bucket_sizes_.begin(), stats.bucket_sizes_.end()); + + // BOOST_FOREACH(int size, stats.bucket_sizes_) + // std::cout << size << " "; + // std::cout << std::endl; + stats.bucket_size_median_ = stats.bucket_sizes_[stats.bucket_sizes_.size() / 2]; + stats.bucket_size_min_ = stats.bucket_sizes_.front(); + stats.bucket_size_max_ = stats.bucket_sizes_.back(); + + // TODO compute mean and std + /*float mean, stddev; + stats.bucket_size_mean_ = mean; + stats.bucket_size_std_dev = stddev;*/ + + // Include a histogram of the buckets + unsigned int bin_start = 0; + unsigned int bin_end = 20; + bool is_new_bin = true; + for (std::vector::iterator iterator = stats.bucket_sizes_.begin(), end = stats.bucket_sizes_.end(); iterator + != end; ) + if (*iterator < bin_end) { + if (is_new_bin) { + stats.size_histogram_.push_back(std::vector(3, 0)); + stats.size_histogram_.back()[0] = bin_start; + stats.size_histogram_.back()[1] = bin_end - 1; + is_new_bin = false; + } + ++stats.size_histogram_.back()[2]; + ++iterator; + } + else { + bin_start += 20; + bin_end += 20; + is_new_bin = true; + } + + return stats; +} + +// End the two namespaces +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif /* OPENCV_FLANN_LSH_TABLE_H_ */ diff --git a/include/opencv2/flann/matrix.h b/include/opencv2/flann/matrix.h new file mode 100644 index 0000000..51b6c63 --- /dev/null +++ b/include/opencv2/flann/matrix.h @@ -0,0 +1,116 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_DATASET_H_ +#define OPENCV_FLANN_DATASET_H_ + +#include + +#include "general.h" + +namespace cvflann +{ + +/** + * Class that implements a simple rectangular matrix stored in a memory buffer and + * provides convenient matrix-like access using the [] operators. + */ +template +class Matrix +{ +public: + typedef T type; + + size_t rows; + size_t cols; + size_t stride; + T* data; + + Matrix() : rows(0), cols(0), stride(0), data(NULL) + { + } + + Matrix(T* data_, size_t rows_, size_t cols_, size_t stride_ = 0) : + rows(rows_), cols(cols_), stride(stride_), data(data_) + { + if (stride==0) stride = cols; + } + + /** + * Convenience function for deallocating the storage data. + */ + FLANN_DEPRECATED void free() + { + fprintf(stderr, "The cvflann::Matrix::free() method is deprecated " + "and it does not do any memory deallocation any more. You are" + "responsible for deallocating the matrix memory (by doing" + "'delete[] matrix.data' for example)"); + } + + /** + * Operator that return a (pointer to a) row of the data. + */ + T* operator[](size_t index) const + { + return data+index*stride; + } +}; + + +class UntypedMatrix +{ +public: + size_t rows; + size_t cols; + void* data; + flann_datatype_t type; + + UntypedMatrix(void* data_, long rows_, long cols_) : + rows(rows_), cols(cols_), data(data_) + { + } + + ~UntypedMatrix() + { + } + + + template + Matrix as() + { + return Matrix((T*)data, rows, cols); + } +}; + + + +} + +#endif //OPENCV_FLANN_DATASET_H_ diff --git a/include/opencv2/flann/miniflann.hpp b/include/opencv2/flann/miniflann.hpp new file mode 100644 index 0000000..02fa236 --- /dev/null +++ b/include/opencv2/flann/miniflann.hpp @@ -0,0 +1,158 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef _OPENCV_MINIFLANN_HPP_ +#define _OPENCV_MINIFLANN_HPP_ + +#include "opencv2/core.hpp" +#include "opencv2/flann/defines.h" + +namespace cv +{ + +namespace flann +{ + +struct CV_EXPORTS IndexParams +{ + IndexParams(); + ~IndexParams(); + + String getString(const String& key, const String& defaultVal=String()) const; + int getInt(const String& key, int defaultVal=-1) const; + double getDouble(const String& key, double defaultVal=-1) const; + + void setString(const String& key, const String& value); + void setInt(const String& key, int value); + void setDouble(const String& key, double value); + void setFloat(const String& key, float value); + void setBool(const String& key, bool value); + void setAlgorithm(int value); + + void getAll(std::vector& names, + std::vector& types, + std::vector& strValues, + std::vector& numValues) const; + + void* params; +}; + +struct CV_EXPORTS KDTreeIndexParams : public IndexParams +{ + KDTreeIndexParams(int trees=4); +}; + +struct CV_EXPORTS LinearIndexParams : public IndexParams +{ + LinearIndexParams(); +}; + +struct CV_EXPORTS CompositeIndexParams : public IndexParams +{ + CompositeIndexParams(int trees = 4, int branching = 32, int iterations = 11, + cvflann::flann_centers_init_t centers_init = cvflann::FLANN_CENTERS_RANDOM, float cb_index = 0.2f ); +}; + +struct CV_EXPORTS AutotunedIndexParams : public IndexParams +{ + AutotunedIndexParams(float target_precision = 0.8f, float build_weight = 0.01f, + float memory_weight = 0, float sample_fraction = 0.1f); +}; + +struct CV_EXPORTS HierarchicalClusteringIndexParams : public IndexParams +{ + HierarchicalClusteringIndexParams(int branching = 32, + cvflann::flann_centers_init_t centers_init = cvflann::FLANN_CENTERS_RANDOM, int trees = 4, int leaf_size = 100 ); +}; + +struct CV_EXPORTS KMeansIndexParams : public IndexParams +{ + KMeansIndexParams(int branching = 32, int iterations = 11, + cvflann::flann_centers_init_t centers_init = cvflann::FLANN_CENTERS_RANDOM, float cb_index = 0.2f ); +}; + +struct CV_EXPORTS LshIndexParams : public IndexParams +{ + LshIndexParams(int table_number, int key_size, int multi_probe_level); +}; + +struct CV_EXPORTS SavedIndexParams : public IndexParams +{ + SavedIndexParams(const String& filename); +}; + +struct CV_EXPORTS SearchParams : public IndexParams +{ + SearchParams( int checks = 32, float eps = 0, bool sorted = true ); +}; + +class CV_EXPORTS_W Index +{ +public: + CV_WRAP Index(); + CV_WRAP Index(InputArray features, const IndexParams& params, cvflann::flann_distance_t distType=cvflann::FLANN_DIST_L2); + virtual ~Index(); + + CV_WRAP virtual void build(InputArray features, const IndexParams& params, cvflann::flann_distance_t distType=cvflann::FLANN_DIST_L2); + CV_WRAP virtual void knnSearch(InputArray query, OutputArray indices, + OutputArray dists, int knn, const SearchParams& params=SearchParams()); + + CV_WRAP virtual int radiusSearch(InputArray query, OutputArray indices, + OutputArray dists, double radius, int maxResults, + const SearchParams& params=SearchParams()); + + CV_WRAP virtual void save(const String& filename) const; + CV_WRAP virtual bool load(InputArray features, const String& filename); + CV_WRAP virtual void release(); + CV_WRAP cvflann::flann_distance_t getDistance() const; + CV_WRAP cvflann::flann_algorithm_t getAlgorithm() const; + +protected: + cvflann::flann_distance_t distType; + cvflann::flann_algorithm_t algo; + int featureType; + void* index; +}; + +} } // namespace cv::flann + +#endif diff --git a/include/opencv2/flann/nn_index.h b/include/opencv2/flann/nn_index.h new file mode 100644 index 0000000..381d4bc --- /dev/null +++ b/include/opencv2/flann/nn_index.h @@ -0,0 +1,177 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_NNINDEX_H +#define OPENCV_FLANN_NNINDEX_H + +#include "general.h" +#include "matrix.h" +#include "result_set.h" +#include "params.h" + +namespace cvflann +{ + +/** + * Nearest-neighbour index base class + */ +template +class NNIndex +{ + typedef typename Distance::ElementType ElementType; + typedef typename Distance::ResultType DistanceType; + +public: + + virtual ~NNIndex() {} + + /** + * \brief Builds the index + */ + virtual void buildIndex() = 0; + + /** + * \brief Perform k-nearest neighbor search + * \param[in] queries The query points for which to find the nearest neighbors + * \param[out] indices The indices of the nearest neighbors found + * \param[out] dists Distances to the nearest neighbors found + * \param[in] knn Number of nearest neighbors to return + * \param[in] params Search parameters + */ + virtual void knnSearch(const Matrix& queries, Matrix& indices, Matrix& dists, int knn, const SearchParams& params) + { + assert(queries.cols == veclen()); + assert(indices.rows >= queries.rows); + assert(dists.rows >= queries.rows); + assert(int(indices.cols) >= knn); + assert(int(dists.cols) >= knn); + +#if 0 + KNNResultSet resultSet(knn); + for (size_t i = 0; i < queries.rows; i++) { + resultSet.init(indices[i], dists[i]); + findNeighbors(resultSet, queries[i], params); + } +#else + KNNUniqueResultSet resultSet(knn); + for (size_t i = 0; i < queries.rows; i++) { + resultSet.clear(); + findNeighbors(resultSet, queries[i], params); + if (get_param(params,"sorted",true)) resultSet.sortAndCopy(indices[i], dists[i], knn); + else resultSet.copy(indices[i], dists[i], knn); + } +#endif + } + + /** + * \brief Perform radius search + * \param[in] query The query point + * \param[out] indices The indinces of the neighbors found within the given radius + * \param[out] dists The distances to the nearest neighbors found + * \param[in] radius The radius used for search + * \param[in] params Search parameters + * \returns Number of neighbors found + */ + virtual int radiusSearch(const Matrix& query, Matrix& indices, Matrix& dists, float radius, const SearchParams& params) + { + if (query.rows != 1) { + fprintf(stderr, "I can only search one feature at a time for range search\n"); + return -1; + } + assert(query.cols == veclen()); + assert(indices.cols == dists.cols); + + int n = 0; + int* indices_ptr = NULL; + DistanceType* dists_ptr = NULL; + if (indices.cols > 0) { + n = (int)indices.cols; + indices_ptr = indices[0]; + dists_ptr = dists[0]; + } + + RadiusUniqueResultSet resultSet((DistanceType)radius); + resultSet.clear(); + findNeighbors(resultSet, query[0], params); + if (n>0) { + if (get_param(params,"sorted",true)) resultSet.sortAndCopy(indices_ptr, dists_ptr, n); + else resultSet.copy(indices_ptr, dists_ptr, n); + } + + return (int)resultSet.size(); + } + + /** + * \brief Saves the index to a stream + * \param stream The stream to save the index to + */ + virtual void saveIndex(FILE* stream) = 0; + + /** + * \brief Loads the index from a stream + * \param stream The stream from which the index is loaded + */ + virtual void loadIndex(FILE* stream) = 0; + + /** + * \returns number of features in this index. + */ + virtual size_t size() const = 0; + + /** + * \returns The dimensionality of the features in this index. + */ + virtual size_t veclen() const = 0; + + /** + * \returns The amount of memory (in bytes) used by the index. + */ + virtual int usedMemory() const = 0; + + /** + * \returns The index type (kdtree, kmeans,...) + */ + virtual flann_algorithm_t getType() const = 0; + + /** + * \returns The index parameters + */ + virtual IndexParams getParameters() const = 0; + + + /** + * \brief Method that searches for nearest-neighbours + */ + virtual void findNeighbors(ResultSet& result, const ElementType* vec, const SearchParams& searchParams) = 0; +}; + +} + +#endif //OPENCV_FLANN_NNINDEX_H diff --git a/include/opencv2/flann/object_factory.h b/include/opencv2/flann/object_factory.h new file mode 100644 index 0000000..7f971c5 --- /dev/null +++ b/include/opencv2/flann/object_factory.h @@ -0,0 +1,91 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_OBJECT_FACTORY_H_ +#define OPENCV_FLANN_OBJECT_FACTORY_H_ + +#include + +namespace cvflann +{ + +class CreatorNotFound +{ +}; + +template +class ObjectFactory +{ + typedef ObjectFactory ThisClass; + typedef std::map ObjectRegistry; + + // singleton class, private constructor + ObjectFactory() {} + +public: + + bool subscribe(UniqueIdType id, ObjectCreator creator) + { + if (object_registry.find(id) != object_registry.end()) return false; + + object_registry[id] = creator; + return true; + } + + bool unregister(UniqueIdType id) + { + return object_registry.erase(id) == 1; + } + + ObjectCreator create(UniqueIdType id) + { + typename ObjectRegistry::const_iterator iter = object_registry.find(id); + + if (iter == object_registry.end()) { + throw CreatorNotFound(); + } + + return iter->second; + } + + static ThisClass& instance() + { + static ThisClass the_factory; + return the_factory; + } +private: + ObjectRegistry object_registry; +}; + +} + +#endif /* OPENCV_FLANN_OBJECT_FACTORY_H_ */ diff --git a/include/opencv2/flann/params.h b/include/opencv2/flann/params.h new file mode 100644 index 0000000..95ef4cd --- /dev/null +++ b/include/opencv2/flann/params.h @@ -0,0 +1,99 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + + +#ifndef OPENCV_FLANN_PARAMS_H_ +#define OPENCV_FLANN_PARAMS_H_ + +#include "any.h" +#include "general.h" +#include +#include + + +namespace cvflann +{ + +typedef std::map IndexParams; + +struct SearchParams : public IndexParams +{ + SearchParams(int checks = 32, float eps = 0, bool sorted = true ) + { + // how many leafs to visit when searching for neighbours (-1 for unlimited) + (*this)["checks"] = checks; + // search for eps-approximate neighbours (default: 0) + (*this)["eps"] = eps; + // only for radius search, require neighbours sorted by distance (default: true) + (*this)["sorted"] = sorted; + } +}; + + +template +T get_param(const IndexParams& params, cv::String name, const T& default_value) +{ + IndexParams::const_iterator it = params.find(name); + if (it != params.end()) { + return it->second.cast(); + } + else { + return default_value; + } +} + +template +T get_param(const IndexParams& params, cv::String name) +{ + IndexParams::const_iterator it = params.find(name); + if (it != params.end()) { + return it->second.cast(); + } + else { + throw FLANNException(cv::String("Missing parameter '")+name+cv::String("' in the parameters given")); + } +} + +inline void print_params(const IndexParams& params, std::ostream& stream) +{ + IndexParams::const_iterator it; + + for(it=params.begin(); it!=params.end(); ++it) { + stream << it->first << " : " << it->second << std::endl; + } +} + +inline void print_params(const IndexParams& params) +{ + print_params(params, std::cout); +} + +} + + +#endif /* OPENCV_FLANN_PARAMS_H_ */ diff --git a/include/opencv2/flann/random.h b/include/opencv2/flann/random.h new file mode 100644 index 0000000..a3cf5ec --- /dev/null +++ b/include/opencv2/flann/random.h @@ -0,0 +1,133 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_RANDOM_H +#define OPENCV_FLANN_RANDOM_H + +#include +#include +#include + +#include "general.h" + +namespace cvflann +{ + +/** + * Seeds the random number generator + * @param seed Random seed + */ +inline void seed_random(unsigned int seed) +{ + srand(seed); +} + +/* + * Generates a random double value. + */ +/** + * Generates a random double value. + * @param high Upper limit + * @param low Lower limit + * @return Random double value + */ +inline double rand_double(double high = 1.0, double low = 0) +{ + return low + ((high-low) * (std::rand() / (RAND_MAX + 1.0))); +} + +/** + * Generates a random integer value. + * @param high Upper limit + * @param low Lower limit + * @return Random integer value + */ +inline int rand_int(int high = RAND_MAX, int low = 0) +{ + return low + (int) ( double(high-low) * (std::rand() / (RAND_MAX + 1.0))); +} + +/** + * Random number generator that returns a distinct number from + * the [0,n) interval each time. + */ +class UniqueRandom +{ + std::vector vals_; + int size_; + int counter_; + +public: + /** + * Constructor. + * @param n Size of the interval from which to generate + * @return + */ + UniqueRandom(int n) + { + init(n); + } + + /** + * Initializes the number generator. + * @param n the size of the interval from which to generate random numbers. + */ + void init(int n) + { + // create and initialize an array of size n + vals_.resize(n); + size_ = n; + for (int i = 0; i < size_; ++i) vals_[i] = i; + + // shuffle the elements in the array + std::random_shuffle(vals_.begin(), vals_.end()); + + counter_ = 0; + } + + /** + * Return a distinct random integer in greater or equal to 0 and less + * than 'n' on each call. It should be called maximum 'n' times. + * Returns: a random integer + */ + int next() + { + if (counter_ == size_) { + return -1; + } + else { + return vals_[counter_++]; + } + } +}; + +} + +#endif //OPENCV_FLANN_RANDOM_H diff --git a/include/opencv2/flann/result_set.h b/include/opencv2/flann/result_set.h new file mode 100644 index 0000000..9750019 --- /dev/null +++ b/include/opencv2/flann/result_set.h @@ -0,0 +1,543 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_RESULTSET_H +#define OPENCV_FLANN_RESULTSET_H + +#include +#include +#include +#include +#include +#include + +namespace cvflann +{ + +/* This record represents a branch point when finding neighbors in + the tree. It contains a record of the minimum distance to the query + point, as well as the node at which the search resumes. + */ + +template +struct BranchStruct +{ + T node; /* Tree node at which search resumes */ + DistanceType mindist; /* Minimum distance to query for all nodes below. */ + + BranchStruct() {} + BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {} + + bool operator<(const BranchStruct& rhs) const + { + return mindist +class ResultSet +{ +public: + virtual ~ResultSet() {} + + virtual bool full() const = 0; + + virtual void addPoint(DistanceType dist, int index) = 0; + + virtual DistanceType worstDist() const = 0; + +}; + +/** + * KNNSimpleResultSet does not ensure that the element it holds are unique. + * Is used in those cases where the nearest neighbour algorithm used does not + * attempt to insert the same element multiple times. + */ +template +class KNNSimpleResultSet : public ResultSet +{ + int* indices; + DistanceType* dists; + int capacity; + int count; + DistanceType worst_distance_; + +public: + KNNSimpleResultSet(int capacity_) : capacity(capacity_), count(0) + { + } + + void init(int* indices_, DistanceType* dists_) + { + indices = indices_; + dists = dists_; + count = 0; + worst_distance_ = (std::numeric_limits::max)(); + dists[capacity-1] = worst_distance_; + } + + size_t size() const + { + return count; + } + + bool full() const + { + return count == capacity; + } + + + void addPoint(DistanceType dist, int index) + { + if (dist >= worst_distance_) return; + int i; + for (i=count; i>0; --i) { +#ifdef FLANN_FIRST_MATCH + if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) ) +#else + if (dists[i-1]>dist) +#endif + { + if (i +class KNNResultSet : public ResultSet +{ + int* indices; + DistanceType* dists; + int capacity; + int count; + DistanceType worst_distance_; + +public: + KNNResultSet(int capacity_) : capacity(capacity_), count(0) + { + } + + void init(int* indices_, DistanceType* dists_) + { + indices = indices_; + dists = dists_; + count = 0; + worst_distance_ = (std::numeric_limits::max)(); + dists[capacity-1] = worst_distance_; + } + + size_t size() const + { + return count; + } + + bool full() const + { + return count == capacity; + } + + + void addPoint(DistanceType dist, int index) + { + if (dist >= worst_distance_) return; + int i; + for (i = count; i > 0; --i) { +#ifdef FLANN_FIRST_MATCH + if ( (dists[i-1]<=dist) && ((dist!=dists[i-1])||(indices[i-1]<=index)) ) +#else + if (dists[i-1]<=dist) +#endif + { + // Check for duplicate indices + int j = i - 1; + while ((j >= 0) && (dists[j] == dist)) { + if (indices[j] == index) { + return; + } + --j; + } + break; + } + } + + if (count < capacity) ++count; + for (int j = count-1; j > i; --j) { + dists[j] = dists[j-1]; + indices[j] = indices[j-1]; + } + dists[i] = dist; + indices[i] = index; + worst_distance_ = dists[capacity-1]; + } + + DistanceType worstDist() const + { + return worst_distance_; + } +}; + + +/** + * A result-set class used when performing a radius based search. + */ +template +class RadiusResultSet : public ResultSet +{ + DistanceType radius; + int* indices; + DistanceType* dists; + size_t capacity; + size_t count; + +public: + RadiusResultSet(DistanceType radius_, int* indices_, DistanceType* dists_, int capacity_) : + radius(radius_), indices(indices_), dists(dists_), capacity(capacity_) + { + init(); + } + + ~RadiusResultSet() + { + } + + void init() + { + count = 0; + } + + size_t size() const + { + return count; + } + + bool full() const + { + return true; + } + + void addPoint(DistanceType dist, int index) + { + if (dist0)&&(count < capacity)) { + dists[count] = dist; + indices[count] = index; + } + count++; + } + } + + DistanceType worstDist() const + { + return radius; + } + +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** Class that holds the k NN neighbors + * Faster than KNNResultSet as it uses a binary heap and does not maintain two arrays + */ +template +class UniqueResultSet : public ResultSet +{ +public: + struct DistIndex + { + DistIndex(DistanceType dist, unsigned int index) : + dist_(dist), index_(index) + { + } + bool operator<(const DistIndex dist_index) const + { + return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_); + } + DistanceType dist_; + unsigned int index_; + }; + + /** Default cosntructor */ + UniqueResultSet() : + worst_distance_(std::numeric_limits::max()) + { + } + + /** Check the status of the set + * @return true if we have k NN + */ + inline bool full() const + { + return is_full_; + } + + /** Remove all elements in the set + */ + virtual void clear() = 0; + + /** Copy the set to two C arrays + * @param indices pointer to a C array of indices + * @param dist pointer to a C array of distances + * @param n_neighbors the number of neighbors to copy + */ + virtual void copy(int* indices, DistanceType* dist, int n_neighbors = -1) const + { + if (n_neighbors < 0) { + for (typename std::set::const_iterator dist_index = dist_indices_.begin(), dist_index_end = + dist_indices_.end(); dist_index != dist_index_end; ++dist_index, ++indices, ++dist) { + *indices = dist_index->index_; + *dist = dist_index->dist_; + } + } + else { + int i = 0; + for (typename std::set::const_iterator dist_index = dist_indices_.begin(), dist_index_end = + dist_indices_.end(); (dist_index != dist_index_end) && (i < n_neighbors); ++dist_index, ++indices, ++dist, ++i) { + *indices = dist_index->index_; + *dist = dist_index->dist_; + } + } + } + + /** Copy the set to two C arrays but sort it according to the distance first + * @param indices pointer to a C array of indices + * @param dist pointer to a C array of distances + * @param n_neighbors the number of neighbors to copy + */ + virtual void sortAndCopy(int* indices, DistanceType* dist, int n_neighbors = -1) const + { + copy(indices, dist, n_neighbors); + } + + /** The number of neighbors in the set + * @return + */ + size_t size() const + { + return dist_indices_.size(); + } + + /** The distance of the furthest neighbor + * If we don't have enough neighbors, it returns the max possible value + * @return + */ + inline DistanceType worstDist() const + { + return worst_distance_; + } +protected: + /** Flag to say if the set is full */ + bool is_full_; + + /** The worst distance found so far */ + DistanceType worst_distance_; + + /** The best candidates so far */ + std::set dist_indices_; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** Class that holds the k NN neighbors + * Faster than KNNResultSet as it uses a binary heap and does not maintain two arrays + */ +template +class KNNUniqueResultSet : public UniqueResultSet +{ +public: + /** Constructor + * @param capacity the number of neighbors to store at max + */ + KNNUniqueResultSet(unsigned int capacity) : capacity_(capacity) + { + this->is_full_ = false; + this->clear(); + } + + /** Add a possible candidate to the best neighbors + * @param dist distance for that neighbor + * @param index index of that neighbor + */ + inline void addPoint(DistanceType dist, int index) + { + // Don't do anything if we are worse than the worst + if (dist >= worst_distance_) return; + dist_indices_.insert(DistIndex(dist, index)); + + if (is_full_) { + if (dist_indices_.size() > capacity_) { + dist_indices_.erase(*dist_indices_.rbegin()); + worst_distance_ = dist_indices_.rbegin()->dist_; + } + } + else if (dist_indices_.size() == capacity_) { + is_full_ = true; + worst_distance_ = dist_indices_.rbegin()->dist_; + } + } + + /** Remove all elements in the set + */ + void clear() + { + dist_indices_.clear(); + worst_distance_ = std::numeric_limits::max(); + is_full_ = false; + } + +protected: + typedef typename UniqueResultSet::DistIndex DistIndex; + using UniqueResultSet::is_full_; + using UniqueResultSet::worst_distance_; + using UniqueResultSet::dist_indices_; + + /** The number of neighbors to keep */ + unsigned int capacity_; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** Class that holds the radius nearest neighbors + * It is more accurate than RadiusResult as it is not limited in the number of neighbors + */ +template +class RadiusUniqueResultSet : public UniqueResultSet +{ +public: + /** Constructor + * @param radius the maximum distance of a neighbor + */ + RadiusUniqueResultSet(DistanceType radius) : + radius_(radius) + { + is_full_ = true; + } + + /** Add a possible candidate to the best neighbors + * @param dist distance for that neighbor + * @param index index of that neighbor + */ + void addPoint(DistanceType dist, int index) + { + if (dist <= radius_) dist_indices_.insert(DistIndex(dist, index)); + } + + /** Remove all elements in the set + */ + inline void clear() + { + dist_indices_.clear(); + } + + + /** Check the status of the set + * @return alwys false + */ + inline bool full() const + { + return true; + } + + /** The distance of the furthest neighbor + * If we don't have enough neighbors, it returns the max possible value + * @return + */ + inline DistanceType worstDist() const + { + return radius_; + } +private: + typedef typename UniqueResultSet::DistIndex DistIndex; + using UniqueResultSet::dist_indices_; + using UniqueResultSet::is_full_; + + /** The furthest distance a neighbor can be */ + DistanceType radius_; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** Class that holds the k NN neighbors within a radius distance + */ +template +class KNNRadiusUniqueResultSet : public KNNUniqueResultSet +{ +public: + /** Constructor + * @param capacity the number of neighbors to store at max + * @param radius the maximum distance of a neighbor + */ + KNNRadiusUniqueResultSet(unsigned int capacity, DistanceType radius) + { + this->capacity_ = capacity; + this->radius_ = radius; + this->dist_indices_.reserve(capacity_); + this->clear(); + } + + /** Remove all elements in the set + */ + void clear() + { + dist_indices_.clear(); + worst_distance_ = radius_; + is_full_ = false; + } +private: + using KNNUniqueResultSet::dist_indices_; + using KNNUniqueResultSet::is_full_; + using KNNUniqueResultSet::worst_distance_; + + /** The maximum number of neighbors to consider */ + unsigned int capacity_; + + /** The maximum distance of a neighbor */ + DistanceType radius_; +}; +} + +#endif //OPENCV_FLANN_RESULTSET_H diff --git a/include/opencv2/flann/sampling.h b/include/opencv2/flann/sampling.h new file mode 100644 index 0000000..396f177 --- /dev/null +++ b/include/opencv2/flann/sampling.h @@ -0,0 +1,81 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + + +#ifndef OPENCV_FLANN_SAMPLING_H_ +#define OPENCV_FLANN_SAMPLING_H_ + +#include "matrix.h" +#include "random.h" + +namespace cvflann +{ + +template +Matrix random_sample(Matrix& srcMatrix, long size, bool remove = false) +{ + Matrix newSet(new T[size * srcMatrix.cols], size,srcMatrix.cols); + + T* src,* dest; + for (long i=0; i +Matrix random_sample(const Matrix& srcMatrix, size_t size) +{ + UniqueRandom rand((int)srcMatrix.rows); + Matrix newSet(new T[size * srcMatrix.cols], size,srcMatrix.cols); + + T* src,* dest; + for (size_t i=0; i +#include + +#include "general.h" +#include "nn_index.h" + +#ifdef FLANN_SIGNATURE_ +#undef FLANN_SIGNATURE_ +#endif +#define FLANN_SIGNATURE_ "FLANN_INDEX" + +namespace cvflann +{ + +template +struct Datatype {}; +template<> +struct Datatype { static flann_datatype_t type() { return FLANN_INT8; } }; +template<> +struct Datatype { static flann_datatype_t type() { return FLANN_INT16; } }; +template<> +struct Datatype { static flann_datatype_t type() { return FLANN_INT32; } }; +template<> +struct Datatype { static flann_datatype_t type() { return FLANN_UINT8; } }; +template<> +struct Datatype { static flann_datatype_t type() { return FLANN_UINT16; } }; +template<> +struct Datatype { static flann_datatype_t type() { return FLANN_UINT32; } }; +template<> +struct Datatype { static flann_datatype_t type() { return FLANN_FLOAT32; } }; +template<> +struct Datatype { static flann_datatype_t type() { return FLANN_FLOAT64; } }; + + +/** + * Structure representing the index header. + */ +struct IndexHeader +{ + char signature[16]; + char version[16]; + flann_datatype_t data_type; + flann_algorithm_t index_type; + size_t rows; + size_t cols; +}; + +/** + * Saves index header to stream + * + * @param stream - Stream to save to + * @param index - The index to save + */ +template +void save_header(FILE* stream, const NNIndex& index) +{ + IndexHeader header; + memset(header.signature, 0, sizeof(header.signature)); + strcpy(header.signature, FLANN_SIGNATURE_); + memset(header.version, 0, sizeof(header.version)); + strcpy(header.version, FLANN_VERSION_); + header.data_type = Datatype::type(); + header.index_type = index.getType(); + header.rows = index.size(); + header.cols = index.veclen(); + + std::fwrite(&header, sizeof(header),1,stream); +} + + +/** + * + * @param stream - Stream to load from + * @return Index header + */ +inline IndexHeader load_header(FILE* stream) +{ + IndexHeader header; + size_t read_size = fread(&header,sizeof(header),1,stream); + + if (read_size!=(size_t)1) { + throw FLANNException("Invalid index file, cannot read"); + } + + if (strcmp(header.signature,FLANN_SIGNATURE_)!=0) { + throw FLANNException("Invalid index file, wrong signature"); + } + + return header; + +} + + +template +void save_value(FILE* stream, const T& value, size_t count = 1) +{ + fwrite(&value, sizeof(value),count, stream); +} + +template +void save_value(FILE* stream, const cvflann::Matrix& value) +{ + fwrite(&value, sizeof(value),1, stream); + fwrite(value.data, sizeof(T),value.rows*value.cols, stream); +} + +template +void save_value(FILE* stream, const std::vector& value) +{ + size_t size = value.size(); + fwrite(&size, sizeof(size_t), 1, stream); + fwrite(&value[0], sizeof(T), size, stream); +} + +template +void load_value(FILE* stream, T& value, size_t count = 1) +{ + size_t read_cnt = fread(&value, sizeof(value), count, stream); + if (read_cnt != count) { + throw FLANNException("Cannot read from file"); + } +} + +template +void load_value(FILE* stream, cvflann::Matrix& value) +{ + size_t read_cnt = fread(&value, sizeof(value), 1, stream); + if (read_cnt != 1) { + throw FLANNException("Cannot read from file"); + } + value.data = new T[value.rows*value.cols]; + read_cnt = fread(value.data, sizeof(T), value.rows*value.cols, stream); + if (read_cnt != (size_t)(value.rows*value.cols)) { + throw FLANNException("Cannot read from file"); + } +} + + +template +void load_value(FILE* stream, std::vector& value) +{ + size_t size; + size_t read_cnt = fread(&size, sizeof(size_t), 1, stream); + if (read_cnt!=1) { + throw FLANNException("Cannot read from file"); + } + value.resize(size); + read_cnt = fread(&value[0], sizeof(T), size, stream); + if (read_cnt != size) { + throw FLANNException("Cannot read from file"); + } +} + +} + +#endif /* OPENCV_FLANN_SAVING_H_ */ diff --git a/include/opencv2/flann/simplex_downhill.h b/include/opencv2/flann/simplex_downhill.h new file mode 100644 index 0000000..145901a --- /dev/null +++ b/include/opencv2/flann/simplex_downhill.h @@ -0,0 +1,186 @@ +/*********************************************************************** + * Software License Agreement (BSD License) + * + * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. + * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. + * + * THE BSD LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *************************************************************************/ + +#ifndef OPENCV_FLANN_SIMPLEX_DOWNHILL_H_ +#define OPENCV_FLANN_SIMPLEX_DOWNHILL_H_ + +namespace cvflann +{ + +/** + Adds val to array vals (and point to array points) and keeping the arrays sorted by vals. + */ +template +void addValue(int pos, float val, float* vals, T* point, T* points, int n) +{ + vals[pos] = val; + for (int i=0; i0 && vals[j] +float optimizeSimplexDownhill(T* points, int n, F func, float* vals = NULL ) +{ + const int MAX_ITERATIONS = 10; + + assert(n>0); + + T* p_o = new T[n]; + T* p_r = new T[n]; + T* p_e = new T[n]; + + int alpha = 1; + + int iterations = 0; + + bool ownVals = false; + if (vals == NULL) { + ownVals = true; + vals = new float[n+1]; + for (int i=0; i MAX_ITERATIONS) break; + + // compute average of simplex points (except the highest point) + for (int j=0; j=vals[0])&&(val_r=vals[n]) { + for (int i=0; i +#include "opencv2/core.hpp" +#include "opencv2/core/utility.hpp" + +namespace cvflann +{ + +/** + * A start-stop timer class. + * + * Can be used to time portions of code. + */ +class StartStopTimer +{ + int64 startTime; + +public: + /** + * Value of the timer. + */ + double value; + + + /** + * Constructor. + */ + StartStopTimer() + { + reset(); + } + + /** + * Starts the timer. + */ + void start() + { + startTime = cv::getTickCount(); + } + + /** + * Stops the timer and updates timer value. + */ + void stop() + { + int64 stopTime = cv::getTickCount(); + value += ( (double)stopTime - startTime) / cv::getTickFrequency(); + } + + /** + * Resets the timer value to 0. + */ + void reset() + { + value = 0; + } + +}; + +} + +#endif // FLANN_TIMER_H diff --git a/include/opencv2/hal.hpp b/include/opencv2/hal.hpp new file mode 100644 index 0000000..95d1ac6 --- /dev/null +++ b/include/opencv2/hal.hpp @@ -0,0 +1,98 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HAL_HPP__ +#define __OPENCV_HAL_HPP__ + +#include "opencv2/hal/defs.h" + +/** + @defgroup hal Hardware Acceleration Layer +*/ + +namespace cv { namespace hal { + +namespace Error { + +enum +{ + Ok = 0, + Unknown = -1 +}; + +} + +int normHamming(const uchar* a, int n); +int normHamming(const uchar* a, const uchar* b, int n); + +int normHamming(const uchar* a, int n, int cellSize); +int normHamming(const uchar* a, const uchar* b, int n, int cellSize); + +//////////////////////////////// low-level functions //////////////////////////////// + +int LU(float* A, size_t astep, int m, float* b, size_t bstep, int n); +int LU(double* A, size_t astep, int m, double* b, size_t bstep, int n); +bool Cholesky(float* A, size_t astep, int m, float* b, size_t bstep, int n); +bool Cholesky(double* A, size_t astep, int m, double* b, size_t bstep, int n); + +int normL1_(const uchar* a, const uchar* b, int n); +float normL1_(const float* a, const float* b, int n); +float normL2Sqr_(const float* a, const float* b, int n); + +void exp(const float* src, float* dst, int n); +void exp(const double* src, double* dst, int n); +void log(const float* src, float* dst, int n); +void log(const double* src, double* dst, int n); + +void fastAtan2(const float* y, const float* x, float* dst, int n, bool angleInDegrees); +void magnitude(const float* x, const float* y, float* dst, int n); +void magnitude(const double* x, const double* y, double* dst, int n); +void sqrt(const float* src, float* dst, int len); +void sqrt(const double* src, double* dst, int len); +void invSqrt(const float* src, float* dst, int len); +void invSqrt(const double* src, double* dst, int len); + +}} //cv::hal + +#endif //__OPENCV_HAL_HPP__ diff --git a/include/opencv2/hal/defs.h b/include/opencv2/hal/defs.h new file mode 100644 index 0000000..1975339 --- /dev/null +++ b/include/opencv2/hal/defs.h @@ -0,0 +1,675 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_DEF_H__ +#define __OPENCV_DEF_H__ + +#if !defined _CRT_SECURE_NO_DEPRECATE && defined _MSC_VER && _MSC_VER > 1300 +# define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio warnings */ +#endif + +#include + +#if defined __ICL +# define CV_ICC __ICL +#elif defined __ICC +# define CV_ICC __ICC +#elif defined __ECL +# define CV_ICC __ECL +#elif defined __ECC +# define CV_ICC __ECC +#elif defined __INTEL_COMPILER +# define CV_ICC __INTEL_COMPILER +#endif + +#ifndef CV_INLINE +# if defined __cplusplus +# define CV_INLINE static inline +# elif defined _MSC_VER +# define CV_INLINE __inline +# else +# define CV_INLINE static +# endif +#endif + +#if defined CV_ICC && !defined CV_ENABLE_UNROLLED +# define CV_ENABLE_UNROLLED 0 +#else +# define CV_ENABLE_UNROLLED 1 +#endif + +#ifdef __GNUC__ +# define CV_DECL_ALIGNED(x) __attribute__ ((aligned (x))) +#elif defined _MSC_VER +# define CV_DECL_ALIGNED(x) __declspec(align(x)) +#else +# define CV_DECL_ALIGNED(x) +#endif + +/* CPU features and intrinsics support */ +#define CV_CPU_NONE 0 +#define CV_CPU_MMX 1 +#define CV_CPU_SSE 2 +#define CV_CPU_SSE2 3 +#define CV_CPU_SSE3 4 +#define CV_CPU_SSSE3 5 +#define CV_CPU_SSE4_1 6 +#define CV_CPU_SSE4_2 7 +#define CV_CPU_POPCNT 8 + +#define CV_CPU_AVX 10 +#define CV_CPU_AVX2 11 +#define CV_CPU_FMA3 12 + +#define CV_CPU_AVX_512F 13 +#define CV_CPU_AVX_512BW 14 +#define CV_CPU_AVX_512CD 15 +#define CV_CPU_AVX_512DQ 16 +#define CV_CPU_AVX_512ER 17 +#define CV_CPU_AVX_512IFMA512 18 +#define CV_CPU_AVX_512PF 19 +#define CV_CPU_AVX_512VBMI 20 +#define CV_CPU_AVX_512VL 21 + +#define CV_CPU_NEON 100 + +// when adding to this list remember to update the enum in core/utility.cpp +#define CV_HARDWARE_MAX_FEATURE 255 + +// do not include SSE/AVX/NEON headers for NVCC compiler +#ifndef __CUDACC__ + +#if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2) +# include +# define CV_MMX 1 +# define CV_SSE 1 +# define CV_SSE2 1 +# if defined __SSE3__ || (defined _MSC_VER && _MSC_VER >= 1500) +# include +# define CV_SSE3 1 +# endif +# if defined __SSSE3__ || (defined _MSC_VER && _MSC_VER >= 1500) +# include +# define CV_SSSE3 1 +# endif +# if defined __SSE4_1__ || (defined _MSC_VER && _MSC_VER >= 1500) +# include +# define CV_SSE4_1 1 +# endif +# if defined __SSE4_2__ || (defined _MSC_VER && _MSC_VER >= 1500) +# include +# define CV_SSE4_2 1 +# endif +# if defined __POPCNT__ || (defined _MSC_VER && _MSC_VER >= 1500) +# ifdef _MSC_VER +# include +# else +# include +# endif +# define CV_POPCNT 1 +# endif +# if defined __AVX__ || (defined _MSC_VER && _MSC_VER >= 1600 && 0) +// MS Visual Studio 2010 (2012?) has no macro pre-defined to identify the use of /arch:AVX +// See: http://connect.microsoft.com/VisualStudio/feedback/details/605858/arch-avx-should-define-a-predefined-macro-in-x64-and-set-a-unique-value-for-m-ix86-fp-in-win32 +# include +# define CV_AVX 1 +# if defined(_XCR_XFEATURE_ENABLED_MASK) +# define __xgetbv() _xgetbv(_XCR_XFEATURE_ENABLED_MASK) +# else +# define __xgetbv() 0 +# endif +# endif +# if defined __AVX2__ || (defined _MSC_VER && _MSC_VER >= 1800 && 0) +# include +# define CV_AVX2 1 +# if defined __FMA__ +# define CV_FMA3 1 +# endif +# endif +#endif + +#if (defined WIN32 || defined _WIN32) && defined(_M_ARM) +# include +# include "arm_neon.h" +# define CV_NEON 1 +# define CPU_HAS_NEON_FEATURE (true) +#elif defined(__ARM_NEON__) || (defined (__ARM_NEON) && defined(__aarch64__)) +# include +# define CV_NEON 1 +#endif + +#if defined __GNUC__ && defined __arm__ && (defined __ARM_PCS_VFP || defined __ARM_VFPV3__) +# define CV_VFP 1 +#endif + +#endif // __CUDACC__ + +#ifndef CV_POPCNT +#define CV_POPCNT 0 +#endif +#ifndef CV_MMX +# define CV_MMX 0 +#endif +#ifndef CV_SSE +# define CV_SSE 0 +#endif +#ifndef CV_SSE2 +# define CV_SSE2 0 +#endif +#ifndef CV_SSE3 +# define CV_SSE3 0 +#endif +#ifndef CV_SSSE3 +# define CV_SSSE3 0 +#endif +#ifndef CV_SSE4_1 +# define CV_SSE4_1 0 +#endif +#ifndef CV_SSE4_2 +# define CV_SSE4_2 0 +#endif +#ifndef CV_AVX +# define CV_AVX 0 +#endif +#ifndef CV_AVX2 +# define CV_AVX2 0 +#endif +#ifndef CV_FMA3 +# define CV_FMA3 0 +#endif +#ifndef CV_AVX_512F +# define CV_AVX_512F 0 +#endif +#ifndef CV_AVX_512BW +# define CV_AVX_512BW 0 +#endif +#ifndef CV_AVX_512CD +# define CV_AVX_512CD 0 +#endif +#ifndef CV_AVX_512DQ +# define CV_AVX_512DQ 0 +#endif +#ifndef CV_AVX_512ER +# define CV_AVX_512ER 0 +#endif +#ifndef CV_AVX_512IFMA512 +# define CV_AVX_512IFMA512 0 +#endif +#ifndef CV_AVX_512PF +# define CV_AVX_512PF 0 +#endif +#ifndef CV_AVX_512VBMI +# define CV_AVX_512VBMI 0 +#endif +#ifndef CV_AVX_512VL +# define CV_AVX_512VL 0 +#endif + +#ifndef CV_NEON +# define CV_NEON 0 +#endif + +#ifndef CV_VFP +# define CV_VFP 0 +#endif + +/* primitive types */ +/* + schar - signed 1 byte integer + uchar - unsigned 1 byte integer + short - signed 2 byte integer + ushort - unsigned 2 byte integer + int - signed 4 byte integer + uint - unsigned 4 byte integer + int64 - signed 8 byte integer + uint64 - unsigned 8 byte integer +*/ + +#if !defined _MSC_VER && !defined __BORLANDC__ +# if defined __cplusplus && __cplusplus >= 201103L +# include + typedef std::uint32_t uint; +# else +# include + typedef uint32_t uint; +# endif +#else + typedef unsigned uint; +#endif + +typedef signed char schar; + +#ifndef __IPL_H__ + typedef unsigned char uchar; + typedef unsigned short ushort; +#endif + +#if defined _MSC_VER || defined __BORLANDC__ + typedef __int64 int64; + typedef unsigned __int64 uint64; +# define CV_BIG_INT(n) n##I64 +# define CV_BIG_UINT(n) n##UI64 +#else + typedef int64_t int64; + typedef uint64_t uint64; +# define CV_BIG_INT(n) n##LL +# define CV_BIG_UINT(n) n##ULL +#endif + +/* fundamental constants */ +#define CV_PI 3.1415926535897932384626433832795 +#define CV_2PI 6.283185307179586476925286766559 +#define CV_LOG2 0.69314718055994530941723212145818 + +typedef union Cv32suf +{ + int i; + unsigned u; + float f; +} +Cv32suf; + +typedef union Cv64suf +{ + int64 i; + uint64 u; + double f; +} +Cv64suf; + + +/****************************************************************************************\ +* fast math * +\****************************************************************************************/ + +#if defined __BORLANDC__ +# include +#elif defined __cplusplus +# include +#else +# include +#endif + +#ifdef HAVE_TEGRA_OPTIMIZATION +# include "tegra_round.hpp" +#endif + +//! @addtogroup core_utils +//! @{ + +#if CV_VFP + // 1. general scheme + #define ARM_ROUND(_value, _asm_string) \ + int res; \ + float temp; \ + asm(_asm_string : [res] "=r" (res), [temp] "=w" (temp) : [value] "w" (_value)); \ + return res + // 2. version for double + #ifdef __clang__ + #define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %[value] \n vmov %[res], %[temp]") + #else + #define ARM_ROUND_DBL(value) ARM_ROUND(value, "vcvtr.s32.f64 %[temp], %P[value] \n vmov %[res], %[temp]") + #endif + // 3. version for float + #define ARM_ROUND_FLT(value) ARM_ROUND(value, "vcvtr.s32.f32 %[temp], %[value]\n vmov %[res], %[temp]") +#endif // CV_VFP + +/** @brief Rounds floating-point number to the nearest integer + + @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the + result is not defined. + */ +CV_INLINE int +cvRound( double value ) +{ +#if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ \ + && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__) + __m128d t = _mm_set_sd( value ); + return _mm_cvtsd_si32(t); +#elif defined _MSC_VER && defined _M_IX86 + int t; + __asm + { + fld value; + fistp t; + } + return t; +#elif ((defined _MSC_VER && defined _M_ARM) || defined CV_ICC || \ + defined __GNUC__) && defined HAVE_TEGRA_OPTIMIZATION + TEGRA_ROUND_DBL(value); +#elif defined CV_ICC || defined __GNUC__ +# if CV_VFP + ARM_ROUND_DBL(value); +# else + return (int)lrint(value); +# endif +#else + /* it's ok if round does not comply with IEEE754 standard; + the tests should allow +/-1 difference when the tested functions use round */ + return (int)(value + (value >= 0 ? 0.5 : -0.5)); +#endif +} + + +/** @brief Rounds floating-point number to the nearest integer not larger than the original. + + The function computes an integer i such that: + \f[i \le \texttt{value} < i+1\f] + @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the + result is not defined. + */ +CV_INLINE int cvFloor( double value ) +{ +#if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__) + __m128d t = _mm_set_sd( value ); + int i = _mm_cvtsd_si32(t); + return i - _mm_movemask_pd(_mm_cmplt_sd(t, _mm_cvtsi32_sd(t,i))); +#elif defined __GNUC__ + int i = (int)value; + return i - (i > value); +#else + int i = cvRound(value); + float diff = (float)(value - i); + return i - (diff < 0); +#endif +} + +/** @brief Rounds floating-point number to the nearest integer not larger than the original. + + The function computes an integer i such that: + \f[i \le \texttt{value} < i+1\f] + @param value floating-point number. If the value is outside of INT_MIN ... INT_MAX range, the + result is not defined. + */ +CV_INLINE int cvCeil( double value ) +{ +#if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__&& !defined __APPLE__)) && !defined(__CUDACC__) + __m128d t = _mm_set_sd( value ); + int i = _mm_cvtsd_si32(t); + return i + _mm_movemask_pd(_mm_cmplt_sd(_mm_cvtsi32_sd(t,i), t)); +#elif defined __GNUC__ + int i = (int)value; + return i + (i < value); +#else + int i = cvRound(value); + float diff = (float)(i - value); + return i + (diff < 0); +#endif +} + +/** @brief Determines if the argument is Not A Number. + + @param value The input floating-point value + + The function returns 1 if the argument is Not A Number (as defined by IEEE754 standard), 0 + otherwise. */ +CV_INLINE int cvIsNaN( double value ) +{ + Cv64suf ieee754; + ieee754.f = value; + return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) + + ((unsigned)ieee754.u != 0) > 0x7ff00000; +} + +/** @brief Determines if the argument is Infinity. + + @param value The input floating-point value + + The function returns 1 if the argument is a plus or minus infinity (as defined by IEEE754 standard) + and 0 otherwise. */ +CV_INLINE int cvIsInf( double value ) +{ + Cv64suf ieee754; + ieee754.f = value; + return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 && + (unsigned)ieee754.u == 0; +} + +#ifdef __cplusplus + +/** @overload */ +CV_INLINE int cvRound(float value) +{ +#if ((defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ && \ + defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__) + __m128 t = _mm_set_ss( value ); + return _mm_cvtss_si32(t); +#elif defined _MSC_VER && defined _M_IX86 + int t; + __asm + { + fld value; + fistp t; + } + return t; +#elif ((defined _MSC_VER && defined _M_ARM) || defined CV_ICC || \ + defined __GNUC__) && defined HAVE_TEGRA_OPTIMIZATION + TEGRA_ROUND_FLT(value); +#elif defined CV_ICC || defined __GNUC__ +# if CV_VFP + ARM_ROUND_FLT(value); +# else + return (int)lrintf(value); +# endif +#else + /* it's ok if round does not comply with IEEE754 standard; + the tests should allow +/-1 difference when the tested functions use round */ + return (int)(value + (value >= 0 ? 0.5f : -0.5f)); +#endif +} + +/** @overload */ +CV_INLINE int cvRound( int value ) +{ + return value; +} + +/** @overload */ +CV_INLINE int cvFloor( float value ) +{ +#if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__ && !defined __APPLE__)) && !defined(__CUDACC__) + __m128 t = _mm_set_ss( value ); + int i = _mm_cvtss_si32(t); + return i - _mm_movemask_ps(_mm_cmplt_ss(t, _mm_cvtsi32_ss(t,i))); +#elif defined __GNUC__ + int i = (int)value; + return i - (i > value); +#else + int i = cvRound(value); + float diff = (float)(value - i); + return i - (diff < 0); +#endif +} + +/** @overload */ +CV_INLINE int cvFloor( int value ) +{ + return value; +} + +/** @overload */ +CV_INLINE int cvCeil( float value ) +{ +#if (defined _MSC_VER && defined _M_X64 || (defined __GNUC__ && defined __SSE2__&& !defined __APPLE__)) && !defined(__CUDACC__) + __m128 t = _mm_set_ss( value ); + int i = _mm_cvtss_si32(t); + return i + _mm_movemask_ps(_mm_cmplt_ss(_mm_cvtsi32_ss(t,i), t)); +#elif defined __GNUC__ + int i = (int)value; + return i + (i < value); +#else + int i = cvRound(value); + float diff = (float)(i - value); + return i + (diff < 0); +#endif +} + +/** @overload */ +CV_INLINE int cvCeil( int value ) +{ + return value; +} + +/** @overload */ +CV_INLINE int cvIsNaN( float value ) +{ + Cv32suf ieee754; + ieee754.f = value; + return (ieee754.u & 0x7fffffff) > 0x7f800000; +} + +/** @overload */ +CV_INLINE int cvIsInf( float value ) +{ + Cv32suf ieee754; + ieee754.f = value; + return (ieee754.u & 0x7fffffff) == 0x7f800000; +} + +#include + +namespace cv +{ + +/////////////// saturate_cast (used in image & signal processing) /////////////////// + +/** + Template function for accurate conversion from one primitive type to another. + + The functions saturate_cast resemble the standard C++ cast operations, such as static_cast\() + and others. They perform an efficient and accurate conversion from one primitive type to another + (see the introduction chapter). saturate in the name means that when the input value v is out of the + range of the target type, the result is not formed just by taking low bits of the input, but instead + the value is clipped. For example: + @code + uchar a = saturate_cast(-100); // a = 0 (UCHAR_MIN) + short b = saturate_cast(33333.33333); // b = 32767 (SHRT_MAX) + @endcode + Such clipping is done when the target type is unsigned char , signed char , unsigned short or + signed short . For 32-bit integers, no clipping is done. + + When the parameter is a floating-point value and the target type is an integer (8-, 16- or 32-bit), + the floating-point value is first rounded to the nearest integer and then clipped if needed (when + the target type is 8- or 16-bit). + + This operation is used in the simplest or most complex image processing functions in OpenCV. + + @param v Function parameter. + @sa add, subtract, multiply, divide, Mat::convertTo + */ +template static inline _Tp saturate_cast(uchar v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(schar v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(ushort v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(short v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(unsigned v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(int v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(float v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(double v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(int64 v) { return _Tp(v); } +/** @overload */ +template static inline _Tp saturate_cast(uint64 v) { return _Tp(v); } + +//! @cond IGNORED + +template<> inline uchar saturate_cast(schar v) { return (uchar)std::max((int)v, 0); } +template<> inline uchar saturate_cast(ushort v) { return (uchar)std::min((unsigned)v, (unsigned)UCHAR_MAX); } +template<> inline uchar saturate_cast(int v) { return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); } +template<> inline uchar saturate_cast(short v) { return saturate_cast((int)v); } +template<> inline uchar saturate_cast(unsigned v) { return (uchar)std::min(v, (unsigned)UCHAR_MAX); } +template<> inline uchar saturate_cast(float v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline uchar saturate_cast(double v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline uchar saturate_cast(int64 v) { return (uchar)((uint64)v <= (uint64)UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); } +template<> inline uchar saturate_cast(uint64 v) { return (uchar)std::min(v, (uint64)UCHAR_MAX); } + +template<> inline schar saturate_cast(uchar v) { return (schar)std::min((int)v, SCHAR_MAX); } +template<> inline schar saturate_cast(ushort v) { return (schar)std::min((unsigned)v, (unsigned)SCHAR_MAX); } +template<> inline schar saturate_cast(int v) { return (schar)((unsigned)(v-SCHAR_MIN) <= (unsigned)UCHAR_MAX ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN); } +template<> inline schar saturate_cast(short v) { return saturate_cast((int)v); } +template<> inline schar saturate_cast(unsigned v) { return (schar)std::min(v, (unsigned)SCHAR_MAX); } +template<> inline schar saturate_cast(float v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline schar saturate_cast(double v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline schar saturate_cast(int64 v) { return (schar)((uint64)((int64)v-SCHAR_MIN) <= (uint64)UCHAR_MAX ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN); } +template<> inline schar saturate_cast(uint64 v) { return (schar)std::min(v, (uint64)SCHAR_MAX); } + +template<> inline ushort saturate_cast(schar v) { return (ushort)std::max((int)v, 0); } +template<> inline ushort saturate_cast(short v) { return (ushort)std::max((int)v, 0); } +template<> inline ushort saturate_cast(int v) { return (ushort)((unsigned)v <= (unsigned)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); } +template<> inline ushort saturate_cast(unsigned v) { return (ushort)std::min(v, (unsigned)USHRT_MAX); } +template<> inline ushort saturate_cast(float v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline ushort saturate_cast(double v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline ushort saturate_cast(int64 v) { return (ushort)((uint64)v <= (uint64)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); } +template<> inline ushort saturate_cast(uint64 v) { return (ushort)std::min(v, (uint64)USHRT_MAX); } + +template<> inline short saturate_cast(ushort v) { return (short)std::min((int)v, SHRT_MAX); } +template<> inline short saturate_cast(int v) { return (short)((unsigned)(v - SHRT_MIN) <= (unsigned)USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN); } +template<> inline short saturate_cast(unsigned v) { return (short)std::min(v, (unsigned)SHRT_MAX); } +template<> inline short saturate_cast(float v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline short saturate_cast(double v) { int iv = cvRound(v); return saturate_cast(iv); } +template<> inline short saturate_cast(int64 v) { return (short)((uint64)((int64)v - SHRT_MIN) <= (uint64)USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN); } +template<> inline short saturate_cast(uint64 v) { return (short)std::min(v, (uint64)SHRT_MAX); } + +template<> inline int saturate_cast(float v) { return cvRound(v); } +template<> inline int saturate_cast(double v) { return cvRound(v); } + +// we intentionally do not clip negative numbers, to make -1 become 0xffffffff etc. +template<> inline unsigned saturate_cast(float v) { return cvRound(v); } +template<> inline unsigned saturate_cast(double v) { return cvRound(v); } + +//! @endcond + +} + +#endif // __cplusplus + +//! @} core_utils + +#endif //__OPENCV_HAL_H__ diff --git a/include/opencv2/hal/intrin.hpp b/include/opencv2/hal/intrin.hpp new file mode 100644 index 0000000..767c578 --- /dev/null +++ b/include/opencv2/hal/intrin.hpp @@ -0,0 +1,292 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HAL_INTRIN_HPP__ +#define __OPENCV_HAL_INTRIN_HPP__ + +#include +#include +#include + +#define OPENCV_HAL_ADD(a, b) ((a) + (b)) +#define OPENCV_HAL_AND(a, b) ((a) & (b)) +#define OPENCV_HAL_NOP(a) (a) +#define OPENCV_HAL_1ST(a, b) (a) + +// unlike HAL API, which is in cv::hal, +// we put intrinsics into cv namespace to make its +// access from within opencv code more accessible +namespace cv { + +template struct V_TypeTraits +{ + typedef _Tp int_type; + typedef _Tp uint_type; + typedef _Tp abs_type; + typedef _Tp sum_type; + + enum { delta = 0, shift = 0 }; + + static int_type reinterpret_int(_Tp x) { return x; } + static uint_type reinterpet_uint(_Tp x) { return x; } + static _Tp reinterpret_from_int(int_type x) { return (_Tp)x; } +}; + +template<> struct V_TypeTraits +{ + typedef uchar value_type; + typedef schar int_type; + typedef uchar uint_type; + typedef uchar abs_type; + typedef int sum_type; + + typedef ushort w_type; + + enum { delta = 128, shift = 8 }; + + static int_type reinterpret_int(value_type x) { return (int_type)x; } + static uint_type reinterpret_uint(value_type x) { return (uint_type)x; } + static value_type reinterpret_from_int(int_type x) { return (value_type)x; } +}; + +template<> struct V_TypeTraits +{ + typedef schar value_type; + typedef schar int_type; + typedef uchar uint_type; + typedef uchar abs_type; + typedef int sum_type; + + typedef short w_type; + + enum { delta = 128, shift = 8 }; + + static int_type reinterpret_int(value_type x) { return (int_type)x; } + static uint_type reinterpret_uint(value_type x) { return (uint_type)x; } + static value_type reinterpret_from_int(int_type x) { return (value_type)x; } +}; + +template<> struct V_TypeTraits +{ + typedef ushort value_type; + typedef short int_type; + typedef ushort uint_type; + typedef ushort abs_type; + typedef int sum_type; + + typedef unsigned w_type; + typedef uchar nu_type; + + enum { delta = 32768, shift = 16 }; + + static int_type reinterpret_int(value_type x) { return (int_type)x; } + static uint_type reinterpret_uint(value_type x) { return (uint_type)x; } + static value_type reinterpret_from_int(int_type x) { return (value_type)x; } +}; + +template<> struct V_TypeTraits +{ + typedef short value_type; + typedef short int_type; + typedef ushort uint_type; + typedef ushort abs_type; + typedef int sum_type; + + typedef int w_type; + typedef uchar nu_type; + typedef schar n_type; + + enum { delta = 128, shift = 8 }; + + static int_type reinterpret_int(value_type x) { return (int_type)x; } + static uint_type reinterpret_uint(value_type x) { return (uint_type)x; } + static value_type reinterpret_from_int(int_type x) { return (value_type)x; } +}; + +template<> struct V_TypeTraits +{ + typedef unsigned value_type; + typedef int int_type; + typedef unsigned uint_type; + typedef unsigned abs_type; + typedef unsigned sum_type; + + typedef uint64 w_type; + typedef ushort nu_type; + + static int_type reinterpret_int(value_type x) { return (int_type)x; } + static uint_type reinterpret_uint(value_type x) { return (uint_type)x; } + static value_type reinterpret_from_int(int_type x) { return (value_type)x; } +}; + +template<> struct V_TypeTraits +{ + typedef int value_type; + typedef int int_type; + typedef unsigned uint_type; + typedef unsigned abs_type; + typedef int sum_type; + + typedef int64 w_type; + typedef short n_type; + typedef ushort nu_type; + + static int_type reinterpret_int(value_type x) { return (int_type)x; } + static uint_type reinterpret_uint(value_type x) { return (uint_type)x; } + static value_type reinterpret_from_int(int_type x) { return (value_type)x; } +}; + +template<> struct V_TypeTraits +{ + typedef uint64 value_type; + typedef int64 int_type; + typedef uint64 uint_type; + typedef uint64 abs_type; + typedef uint64 sum_type; + + typedef unsigned nu_type; + + static int_type reinterpret_int(value_type x) { return (int_type)x; } + static uint_type reinterpret_uint(value_type x) { return (uint_type)x; } + static value_type reinterpret_from_int(int_type x) { return (value_type)x; } +}; + +template<> struct V_TypeTraits +{ + typedef int64 value_type; + typedef int64 int_type; + typedef uint64 uint_type; + typedef uint64 abs_type; + typedef int64 sum_type; + + typedef int nu_type; + + static int_type reinterpret_int(value_type x) { return (int_type)x; } + static uint_type reinterpret_uint(value_type x) { return (uint_type)x; } + static value_type reinterpret_from_int(int_type x) { return (value_type)x; } +}; + + +template<> struct V_TypeTraits +{ + typedef float value_type; + typedef int int_type; + typedef unsigned uint_type; + typedef float abs_type; + typedef float sum_type; + + typedef double w_type; + + static int_type reinterpret_int(value_type x) + { + Cv32suf u; + u.f = x; + return u.i; + } + static uint_type reinterpet_uint(value_type x) + { + Cv32suf u; + u.f = x; + return u.u; + } + static value_type reinterpret_from_int(int_type x) + { + Cv32suf u; + u.i = x; + return u.f; + } +}; + +template<> struct V_TypeTraits +{ + typedef double value_type; + typedef int64 int_type; + typedef uint64 uint_type; + typedef double abs_type; + typedef double sum_type; + static int_type reinterpret_int(value_type x) + { + Cv64suf u; + u.f = x; + return u.i; + } + static uint_type reinterpet_uint(value_type x) + { + Cv64suf u; + u.f = x; + return u.u; + } + static value_type reinterpret_from_int(int_type x) + { + Cv64suf u; + u.i = x; + return u.f; + } +}; + +} + +#if CV_SSE2 + +#include "opencv2/hal/intrin_sse.hpp" + +#elif CV_NEON + +#include "opencv2/hal/intrin_neon.hpp" + +#else + +#include "opencv2/hal/intrin_cpp.hpp" + +#endif + +#ifndef CV_SIMD128 +#define CV_SIMD128 0 +#endif + +#ifndef CV_SIMD128_64F +#define CV_SIMD128_64F 0 +#endif + +#endif diff --git a/include/opencv2/hal/intrin_cpp.hpp b/include/opencv2/hal/intrin_cpp.hpp new file mode 100644 index 0000000..e0140a8 --- /dev/null +++ b/include/opencv2/hal/intrin_cpp.hpp @@ -0,0 +1,811 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HAL_INTRIN_CPP_HPP__ +#define __OPENCV_HAL_INTRIN_CPP_HPP__ + +namespace cv +{ + +template struct v_reg +{ + typedef _Tp lane_type; + typedef v_reg::int_type, n> int_vec; + typedef v_reg::abs_type, n> abs_vec; + enum { nlanes = n }; + + explicit v_reg(const _Tp* ptr) { for( int i = 0; i < n; i++ ) s[i] = ptr[i]; } + v_reg(_Tp s0, _Tp s1) { s[0] = s0; s[1] = s1; } + v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3) { s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; } + v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3, + _Tp s4, _Tp s5, _Tp s6, _Tp s7) + { + s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; + s[4] = s4; s[5] = s5; s[6] = s6; s[7] = s7; + } + v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3, + _Tp s4, _Tp s5, _Tp s6, _Tp s7, + _Tp s8, _Tp s9, _Tp s10, _Tp s11, + _Tp s12, _Tp s13, _Tp s14, _Tp s15) + { + s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; + s[4] = s4; s[5] = s5; s[6] = s6; s[7] = s7; + s[8] = s8; s[9] = s9; s[10] = s10; s[11] = s11; + s[12] = s12; s[13] = s13; s[14] = s14; s[15] = s15; + } + + v_reg() {} + v_reg(const v_reg<_Tp, n> & r) + { + for( int i = 0; i < n; i++ ) + s[i] = r.s[i]; + } + + _Tp get(const int i) const { return s[i]; } + _Tp get0() const { return s[0]; } + v_reg<_Tp, n> high() const + { + v_reg<_Tp, n> c; + int i; + for( i = 0; i < n/2; i++ ) + { + c.s[i] = s[i+(n/2)]; + c.s[i+(n/2)] = 0; + } + return c; + } + + static v_reg<_Tp, n> zero() + { + v_reg<_Tp, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = (_Tp)0; + return c; + } + + static v_reg<_Tp, n> all(_Tp s) + { + v_reg<_Tp, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = s; + return c; + } + + template v_reg<_Tp2, n2> reinterpret_as() const + { + size_t bytes = std::min(sizeof(_Tp2)*n2, sizeof(_Tp)*n); + v_reg<_Tp2, n2> c; + memcpy(&c.s[0], &s[0], bytes); + return c; + } + + _Tp s[n]; +}; + +#define OPENCV_HAL_IMPL_BIN_OP(bin_op) \ +template inline v_reg<_Tp, n> \ + operator bin_op (const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ +{ \ + v_reg<_Tp, n> c; \ + for( int i = 0; i < n; i++ ) \ + c.s[i] = saturate_cast<_Tp>(a.s[i] bin_op b.s[i]); \ + return c; \ +} \ +template inline v_reg<_Tp, n>& \ + operator bin_op##= (v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ +{ \ + for( int i = 0; i < n; i++ ) \ + a.s[i] = saturate_cast<_Tp>(a.s[i] bin_op b.s[i]); \ + return a; \ +} + +OPENCV_HAL_IMPL_BIN_OP(+) +OPENCV_HAL_IMPL_BIN_OP(-) +OPENCV_HAL_IMPL_BIN_OP(*) +OPENCV_HAL_IMPL_BIN_OP(/) + +#define OPENCV_HAL_IMPL_BIT_OP(bit_op) \ +template inline v_reg<_Tp, n> operator bit_op \ + (const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ +{ \ + v_reg<_Tp, n> c; \ + typedef typename V_TypeTraits<_Tp>::int_type itype; \ + for( int i = 0; i < n; i++ ) \ + c.s[i] = V_TypeTraits<_Tp>::reinterpret_from_int((itype)(V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) bit_op \ + V_TypeTraits<_Tp>::reinterpret_int(b.s[i]))); \ + return c; \ +} \ +template inline v_reg<_Tp, n>& operator \ + bit_op##= (v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ +{ \ + typedef typename V_TypeTraits<_Tp>::int_type itype; \ + for( int i = 0; i < n; i++ ) \ + a.s[i] = V_TypeTraits<_Tp>::reinterpret_from_int((itype)(V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) bit_op \ + V_TypeTraits<_Tp>::reinterpret_int(b.s[i]))); \ + return a; \ +} + +OPENCV_HAL_IMPL_BIT_OP(&) +OPENCV_HAL_IMPL_BIT_OP(|) +OPENCV_HAL_IMPL_BIT_OP(^) + +template inline v_reg<_Tp, n> operator ~ (const v_reg<_Tp, n>& a) +{ + v_reg<_Tp, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = V_TypeTraits<_Tp>::reinterpret_from_int(~V_TypeTraits<_Tp>::reinterpret_int(a.s[i])); + return c; +} + +#define OPENCV_HAL_IMPL_MATH_FUNC(func, cfunc, _Tp2) \ +template inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a) \ +{ \ + v_reg<_Tp2, n> c; \ + for( int i = 0; i < n; i++ ) \ + c.s[i] = cfunc(a.s[i]); \ + return c; \ +} + +OPENCV_HAL_IMPL_MATH_FUNC(v_sqrt, std::sqrt, _Tp) +OPENCV_HAL_IMPL_MATH_FUNC(v_sin, std::sin, _Tp) +OPENCV_HAL_IMPL_MATH_FUNC(v_cos, std::cos, _Tp) +OPENCV_HAL_IMPL_MATH_FUNC(v_exp, std::exp, _Tp) +OPENCV_HAL_IMPL_MATH_FUNC(v_log, std::log, _Tp) +OPENCV_HAL_IMPL_MATH_FUNC(v_abs, (typename V_TypeTraits<_Tp>::abs_type)std::abs, + typename V_TypeTraits<_Tp>::abs_type) +OPENCV_HAL_IMPL_MATH_FUNC(v_round, cvRound, int) +OPENCV_HAL_IMPL_MATH_FUNC(v_floor, cvFloor, int) +OPENCV_HAL_IMPL_MATH_FUNC(v_ceil, cvCeil, int) +OPENCV_HAL_IMPL_MATH_FUNC(v_trunc, int, int) + +#define OPENCV_HAL_IMPL_MINMAX_FUNC(func, hfunc, cfunc) \ +template inline v_reg<_Tp, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ +{ \ + v_reg<_Tp, n> c; \ + for( int i = 0; i < n; i++ ) \ + c.s[i] = cfunc(a.s[i], b.s[i]); \ + return c; \ +} \ +template inline _Tp hfunc(const v_reg<_Tp, n>& a) \ +{ \ + _Tp c = a.s[0]; \ + for( int i = 1; i < n; i++ ) \ + c = cfunc(c, a.s[i]); \ + return c; \ +} + +OPENCV_HAL_IMPL_MINMAX_FUNC(v_min, v_reduce_min, std::min) +OPENCV_HAL_IMPL_MINMAX_FUNC(v_max, v_reduce_max, std::max) + +template +inline void v_minmax( const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, + v_reg<_Tp, n>& minval, v_reg<_Tp, n>& maxval ) +{ + for( int i = 0; i < n; i++ ) + { + minval.s[i] = std::min(a.s[i], b.s[i]); + maxval.s[i] = std::max(a.s[i], b.s[i]); + } +} + + +#define OPENCV_HAL_IMPL_CMP_OP(cmp_op) \ +template \ +inline v_reg<_Tp, n> operator cmp_op(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ +{ \ + typedef typename V_TypeTraits<_Tp>::int_type itype; \ + v_reg<_Tp, n> c; \ + for( int i = 0; i < n; i++ ) \ + c.s[i] = V_TypeTraits<_Tp>::reinterpret_from_int((itype)-(int)(a.s[i] cmp_op b.s[i])); \ + return c; \ +} + +OPENCV_HAL_IMPL_CMP_OP(<) +OPENCV_HAL_IMPL_CMP_OP(>) +OPENCV_HAL_IMPL_CMP_OP(<=) +OPENCV_HAL_IMPL_CMP_OP(>=) +OPENCV_HAL_IMPL_CMP_OP(==) +OPENCV_HAL_IMPL_CMP_OP(!=) + +#define OPENCV_HAL_IMPL_ADD_SUB_OP(func, bin_op, cast_op, _Tp2) \ +template \ +inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ +{ \ + typedef _Tp2 rtype; \ + v_reg c; \ + for( int i = 0; i < n; i++ ) \ + c.s[i] = cast_op(a.s[i] bin_op b.s[i]); \ + return c; \ +} + +OPENCV_HAL_IMPL_ADD_SUB_OP(v_add_wrap, +, (_Tp), _Tp) +OPENCV_HAL_IMPL_ADD_SUB_OP(v_sub_wrap, -, (_Tp), _Tp) +OPENCV_HAL_IMPL_ADD_SUB_OP(v_absdiff, -, (rtype)std::abs, typename V_TypeTraits<_Tp>::abs_type) + +template +inline v_reg<_Tp, n> v_invsqrt(const v_reg<_Tp, n>& a) +{ + v_reg<_Tp, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = 1.f/std::sqrt(a.s[i]); + return c; +} + +template +inline v_reg<_Tp, n> v_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) +{ + v_reg<_Tp, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = std::sqrt(a.s[i]*a.s[i] + b.s[i]*b.s[i]); + return c; +} + + +template +inline v_reg<_Tp, n> v_sqr_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) +{ + v_reg<_Tp, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = a.s[i]*a.s[i] + b.s[i]*b.s[i]; + return c; +} + +template +inline v_reg<_Tp, n> v_muladd(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, + const v_reg<_Tp, n>& c) +{ + v_reg<_Tp, n> d; + for( int i = 0; i < n; i++ ) + d.s[i] = a.s[i]*b.s[i] + c.s[i]; + return d; +} + +template inline v_reg::w_type, n/2> + v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) +{ + typedef typename V_TypeTraits<_Tp>::w_type w_type; + v_reg c; + for( int i = 0; i < (n/2); i++ ) + c.s[i] = (w_type)a.s[i*2]*b.s[i*2] + (w_type)a.s[i*2+1]*b.s[i*2+1]; + return c; +} + +template inline void v_mul_expand(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, + v_reg::w_type, n/2>& c, + v_reg::w_type, n/2>& d) +{ + typedef typename V_TypeTraits<_Tp>::w_type w_type; + for( int i = 0; i < (n/2); i++ ) + { + c.s[i] = (w_type)a.s[i]*b.s[i]*2; + d.s[i] = (w_type)a.s[i+(n/2)]*b.s[i+(n/2)]; + } +} + +template inline void v_hsum(const v_reg<_Tp, n>& a, + v_reg::w_type, n/2>& c) +{ + typedef typename V_TypeTraits<_Tp>::w_type w_type; + for( int i = 0; i < (n/2); i++ ) + { + c.s[i] = (w_type)a.s[i*2] + a.s[i*2+1]; + } +} + +#define OPENCV_HAL_IMPL_SHIFT_OP(shift_op) \ +template inline v_reg<_Tp, n> operator shift_op(const v_reg<_Tp, n>& a, int imm) \ +{ \ + v_reg<_Tp, n> c; \ + for( int i = 0; i < n; i++ ) \ + c.s[i] = (_Tp)(a.s[i] shift_op imm); \ + return c; \ +} + +OPENCV_HAL_IMPL_SHIFT_OP(<<) +OPENCV_HAL_IMPL_SHIFT_OP(>>) + +template inline typename V_TypeTraits<_Tp>::sum_type v_reduce_sum(const v_reg<_Tp, n>& a) +{ + typename V_TypeTraits<_Tp>::sum_type c = a.s[0]; + for( int i = 1; i < n; i++ ) + c += a.s[i]; + return c; +} + +template inline int v_signmask(const v_reg<_Tp, n>& a) +{ + int mask = 0; + for( int i = 0; i < n; i++ ) + mask |= (V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) < 0) << i; + return mask; +} + +template inline bool v_check_all(const v_reg<_Tp, n>& a) +{ + for( int i = 0; i < n; i++ ) + if( V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) >= 0 ) + return false; + return true; +} + +template inline bool v_check_any(const v_reg<_Tp, n>& a) +{ + for( int i = 0; i < n; i++ ) + if( V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) < 0 ) + return true; + return false; +} + +template inline v_reg<_Tp, n> v_select(const v_reg<_Tp, n>& mask, + const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) +{ + v_reg<_Tp, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = V_TypeTraits<_Tp>::reinterpret_int(mask.s[i]) < 0 ? b.s[i] : a.s[i]; + return c; +} + +template inline void v_expand(const v_reg<_Tp, n>& a, + v_reg::w_type, n/2>& b0, + v_reg::w_type, n/2>& b1) +{ + for( int i = 0; i < (n/2); i++ ) + { + b0.s[i] = a.s[i]; + b1.s[i] = a.s[i+(n/2)]; + } +} + +template inline v_reg::int_type, n> + v_reinterpret_as_int(const v_reg<_Tp, n>& a) +{ + v_reg::int_type, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = V_TypeTraits<_Tp>::reinterpret_int(a.s[i]); + return c; +} + +template inline v_reg::uint_type, n> + v_reinterpret_as_uint(const v_reg<_Tp, n>& a) +{ + v_reg::uint_type, n> c; + for( int i = 0; i < n; i++ ) + c.s[i] = V_TypeTraits<_Tp>::reinterpret_uint(a.s[i]); + return c; +} + +template inline void v_zip( const v_reg<_Tp, n>& a0, const v_reg<_Tp, n>& a1, + v_reg<_Tp, n>& b0, v_reg<_Tp, n>& b1 ) +{ + int i; + for( i = 0; i < n/2; i++ ) + { + b0.s[i*2] = a0.s[i]; + b0.s[i*2+1] = a1.s[i]; + } + for( ; i < n; i++ ) + { + b1.s[i*2-n] = a0.s[i]; + b1.s[i*2-n+1] = a1.s[i]; + } +} + +template inline v_reg<_Tp, n> v_load(const _Tp* ptr) +{ + return v_reg<_Tp, n>(ptr); +} + +template inline v_reg<_Tp, n> v_load_aligned(const _Tp* ptr) +{ + return v_reg<_Tp, n>(ptr); +} + +template inline void v_load_halves(const _Tp* loptr, const _Tp* hiptr) +{ + v_reg<_Tp, n> c; + for( int i = 0; i < n/2; i++ ) + { + c.s[i] = loptr[i]; + c.s[i+n/2] = hiptr[i]; + } + return c; +} + +template inline v_reg::w_type, n> v_load_expand(const _Tp* ptr) +{ + typedef typename V_TypeTraits<_Tp>::w_type w_type; + v_reg c; + for( int i = 0; i < n; i++ ) + { + c.s[i] = ptr[i]; + } + return c; +} + +template inline v_reg::w_type>::w_type, n> v_load_expand_q(const _Tp* ptr) +{ + typedef typename V_TypeTraits::w_type>::w_type w_type; + v_reg c; + for( int i = 0; i < n; i++ ) + { + c.s[i] = ptr[i]; + } + return c; +} + +template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, + v_reg<_Tp, n>& b, v_reg<_Tp, n>& c) +{ + int i, i3; + for( i = i3 = 0; i < n; i++, i3 += 3 ) + { + a.s[i] = ptr[i3]; + b.s[i] = ptr[i3+1]; + c.s[i] = ptr[i3+2]; + } +} + +template +inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, + v_reg<_Tp, n>& b, v_reg<_Tp, n>& c, + v_reg<_Tp, n>& d) +{ + int i, i4; + for( i = i4 = 0; i < n; i++, i4 += 4 ) + { + a.s[i] = ptr[i4]; + b.s[i] = ptr[i4+1]; + c.s[i] = ptr[i4+2]; + d.s[i] = ptr[i4+3]; + } +} + +template +inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, + const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c) +{ + int i, i3; + for( i = i3 = 0; i < n; i++, i3 += 3 ) + { + ptr[i3] = a.s[i]; + ptr[i3+1] = b.s[i]; + ptr[i3+2] = c.s[i]; + } +} + +template inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, + const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c, + const v_reg<_Tp, n>& d) +{ + int i, i4; + for( i = i4 = 0; i < n; i++, i4 += 4 ) + { + ptr[i4] = a.s[i]; + ptr[i4+1] = b.s[i]; + ptr[i4+2] = c.s[i]; + ptr[i4+3] = d.s[i]; + } +} + +template +inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a) +{ + for( int i = 0; i < n; i++ ) + ptr[i] = a.s[i]; +} + +template +inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a) +{ + for( int i = 0; i < (n/2); i++ ) + ptr[i] = a.s[i]; +} + +template +inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a) +{ + for( int i = 0; i < (n/2); i++ ) + ptr[i] = a.s[i+(n/2)]; +} + +template +inline void v_store_aligned(_Tp* ptr, const v_reg<_Tp, n>& a) +{ + for( int i = 0; i < n; i++ ) + ptr[i] = a.s[i]; +} + +template +inline v_reg<_Tp, n> v_combine_low(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) +{ + v_reg<_Tp, n> c; + for( int i = 0; i < (n/2); i++ ) + { + c.s[i] = a.s[i]; + c.s[i+(n/2)] = b.s[i]; + } +} + +template +inline v_reg<_Tp, n> v_combine_high(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) +{ + v_reg<_Tp, n> c; + for( int i = 0; i < (n/2); i++ ) + { + c.s[i] = a.s[i+(n/2)]; + c.s[i+(n/2)] = b.s[i+(n/2)]; + } +} + +template +inline void v_recombine(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, + v_reg<_Tp, n>& low, v_reg<_Tp, n>& high) +{ + for( int i = 0; i < (n/2); i++ ) + { + low.s[i] = a.s[i]; + low.s[i+(n/2)] = b.s[i]; + high.s[i] = a.s[i+(n/2)]; + high.s[i+(n/2)] = b.s[i+(n/2)]; + } +} + +template inline v_reg v_round(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + c.s[i] = cvRound(a.s[i]); + return c; +} + +template inline v_reg v_floor(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + c.s[i] = cvFloor(a.s[i]); + return c; +} + +template inline v_reg v_ceil(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + c.s[i] = cvCeil(a.s[i]); + return c; +} + +template inline v_reg v_trunc(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + c.s[i] = (int)(a.s[i]); + return c; +} + +template inline v_reg v_round(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + { + c.s[i] = cvRound(a.s[i]); + c.s[i+n] = 0; + } + return c; +} + +template inline v_reg v_floor(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + { + c.s[i] = cvFloor(a.s[i]); + c.s[i+n] = 0; + } + return c; +} + +template inline v_reg v_ceil(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + { + c.s[i] = cvCeil(a.s[i]); + c.s[i+n] = 0; + } + return c; +} + +template inline v_reg v_trunc(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + { + c.s[i] = cvCeil(a.s[i]); + c.s[i+n] = 0; + } + return c; +} + +template inline v_reg v_cvt_f32(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + c.s[i] = (float)a.s[i]; + return c; +} + +template inline v_reg v_cvt_f64(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + c.s[i] = (double)a.s[i]; + return c; +} + +template inline v_reg v_cvt_f64(const v_reg& a) +{ + v_reg c; + for( int i = 0; i < n; i++ ) + c.s[i] = (double)a.s[i]; + return c; +} + +template +inline void v_transpose4x4( v_reg<_Tp, 4>& a0, const v_reg<_Tp, 4>& a1, + const v_reg<_Tp, 4>& a2, const v_reg<_Tp, 4>& a3, + v_reg<_Tp, 4>& b0, v_reg<_Tp, 4>& b1, + v_reg<_Tp, 4>& b2, v_reg<_Tp, 4>& b3 ) +{ + b0 = v_reg<_Tp, 4>(a0.s[0], a1.s[0], a2.s[0], a3.s[0]); + b1 = v_reg<_Tp, 4>(a0.s[1], a1.s[1], a2.s[1], a3.s[1]); + b2 = v_reg<_Tp, 4>(a0.s[2], a1.s[2], a2.s[2], a3.s[2]); + b3 = v_reg<_Tp, 4>(a0.s[3], a1.s[3], a2.s[3], a3.s[3]); +} + +typedef v_reg v_uint8x16; +typedef v_reg v_int8x16; +typedef v_reg v_uint16x8; +typedef v_reg v_int16x8; +typedef v_reg v_uint32x4; +typedef v_reg v_int32x4; +typedef v_reg v_float32x4; +typedef v_reg v_float32x8; +typedef v_reg v_float64x2; +typedef v_reg v_uint64x2; +typedef v_reg v_int64x2; + +#define OPENCV_HAL_IMPL_C_INIT(_Tpvec, _Tp, suffix) \ +inline _Tpvec v_setzero_##suffix() { return _Tpvec::zero(); } \ +inline _Tpvec v_setall_##suffix(_Tp val) { return _Tpvec::all(val); } \ +template inline _Tpvec \ + v_reinterpret_as_##suffix(const v_reg<_Tp0, n0>& a) \ +{ return a.template reinterpret_as<_Tp, _Tpvec::nlanes>(a); } + +OPENCV_HAL_IMPL_C_INIT(v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_C_INIT(v_int8x16, schar, s8) +OPENCV_HAL_IMPL_C_INIT(v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_C_INIT(v_int16x8, short, s16) +OPENCV_HAL_IMPL_C_INIT(v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_C_INIT(v_int32x4, int, s32) +OPENCV_HAL_IMPL_C_INIT(v_float32x4, float, f32) +OPENCV_HAL_IMPL_C_INIT(v_float64x2, double, f64) +OPENCV_HAL_IMPL_C_INIT(v_uint64x2, uint64, u64) +OPENCV_HAL_IMPL_C_INIT(v_uint64x2, int64, s64) + +#define OPENCV_HAL_IMPL_C_SHIFT(_Tpvec, _Tp) \ +template inline _Tpvec v_shl(const _Tpvec& a) \ +{ return a << n; } \ +template inline _Tpvec v_shr(const _Tpvec& a) \ +{ return a >> n; } \ +template inline _Tpvec v_rshr(const _Tpvec& a) \ +{ \ + _Tpvec c; \ + for( int i = 0; i < _Tpvec::nlanes; i++ ) \ + c.s[i] = (_Tp)((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \ + return c; \ +} + +OPENCV_HAL_IMPL_C_SHIFT(v_uint16x8, ushort) +OPENCV_HAL_IMPL_C_SHIFT(v_int16x8, short) +OPENCV_HAL_IMPL_C_SHIFT(v_uint32x4, unsigned) +OPENCV_HAL_IMPL_C_SHIFT(v_int32x4, int) +OPENCV_HAL_IMPL_C_SHIFT(v_uint64x2, uint64) +OPENCV_HAL_IMPL_C_SHIFT(v_int64x2, int64) + + +#define OPENCV_HAL_IMPL_C_PACK(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ +inline _Tpnvec v_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \ +{ \ + _Tpnvec c; \ + for( int i = 0; i < _Tpvec::nlanes; i++ ) \ + { \ + c.s[i] = saturate_cast<_Tpn>(a.s[i]); \ + c.s[i+_Tpvec::nlanes] = saturate_cast<_Tpn>(b.s[i]); \ + } \ + return c; \ +} \ +template inline _Tpnvec v_rshr_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \ +{ \ + _Tpnvec c; \ + for( int i = 0; i < _Tpvec::nlanes; i++ ) \ + { \ + c.s[i] = saturate_cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \ + c.s[i+_Tpvec::nlanes] = saturate_cast<_Tpn>((b.s[i] + ((_Tp)1 << (n - 1))) >> n); \ + } \ + return c; \ +} \ +inline void v_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \ +{ \ + for( int i = 0; i < _Tpvec::nlanes; i++ ) \ + ptr[i] = saturate_cast<_Tpn>(a.s[i]); \ +} \ +template inline void v_rshr_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \ +{ \ + for( int i = 0; i < _Tpvec::nlanes; i++ ) \ + ptr[i] = saturate_cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \ +} + +OPENCV_HAL_IMPL_C_PACK(v_uint16x8, ushort, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_PACK(v_int16x8, short, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_PACK(v_int16x8, short, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_PACK(v_uint32x4, unsigned, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_PACK(v_int32x4, int, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_PACK(v_int32x4, int, v_uint16x8, ushort, pack_u) +OPENCV_HAL_IMPL_C_PACK(v_uint64x2, uint64, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_PACK(v_int64x2, int64, v_int32x4, int, pack) + +inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, + const v_float32x4& m1, const v_float32x4& m2, + const v_float32x4& m3) +{ + return v_float32x4(v.s[0]*m0.s[0] + v.s[1]*m1.s[0] + v.s[2]*m2.s[0] + v.s[3]*m3.s[0], + v.s[0]*m0.s[1] + v.s[1]*m1.s[1] + v.s[2]*m2.s[1] + v.s[3]*m3.s[1], + v.s[0]*m0.s[2] + v.s[1]*m1.s[2] + v.s[2]*m2.s[2] + v.s[3]*m3.s[2], + v.s[0]*m0.s[3] + v.s[1]*m1.s[3] + v.s[2]*m2.s[3] + v.s[3]*m3.s[3]); +} + +} + +#endif diff --git a/include/opencv2/hal/intrin_neon.hpp b/include/opencv2/hal/intrin_neon.hpp new file mode 100644 index 0000000..2418566 --- /dev/null +++ b/include/opencv2/hal/intrin_neon.hpp @@ -0,0 +1,826 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HAL_INTRIN_NEON_HPP__ +#define __OPENCV_HAL_INTRIN_NEON_HPP__ + +namespace cv +{ + +#define CV_SIMD128 1 + +struct v_uint8x16 +{ + typedef uchar lane_type; + enum { nlanes = 16 }; + + v_uint8x16() {} + explicit v_uint8x16(uint8x16_t v) : val(v) {} + v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7, + uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) + { + uchar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; + val = vld1q_u8(v); + } + uchar get0() const + { + return vgetq_lane_u8(val, 0); + } + + uint8x16_t val; +}; + +struct v_int8x16 +{ + typedef schar lane_type; + enum { nlanes = 16 }; + + v_int8x16() {} + explicit v_int8x16(int8x16_t v) : val(v) {} + v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7, + schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) + { + schar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}; + val = vld1q_s8(v); + } + schar get0() const + { + return vgetq_lane_s8(val, 0); + } + + int8x16_t val; +}; + +struct v_uint16x8 +{ + typedef ushort lane_type; + enum { nlanes = 8 }; + + v_uint16x8() {} + explicit v_uint16x8(uint16x8_t v) : val(v) {} + v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) + { + ushort v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; + val = vld1q_u16(v); + } + ushort get0() const + { + return vgetq_lane_u16(val, 0); + } + + uint16x8_t val; +}; + +struct v_int16x8 +{ + typedef short lane_type; + enum { nlanes = 8 }; + + v_int16x8() {} + explicit v_int16x8(int16x8_t v) : val(v) {} + v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) + { + short v[] = {v0, v1, v2, v3, v4, v5, v6, v7}; + val = vld1q_s16(v); + } + short get0() const + { + return vgetq_lane_s16(val, 0); + } + + int16x8_t val; +}; + +struct v_uint32x4 +{ + typedef unsigned lane_type; + enum { nlanes = 4 }; + + v_uint32x4() {} + explicit v_uint32x4(uint32x4_t v) : val(v) {} + v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) + { + unsigned v[] = {v0, v1, v2, v3}; + val = vld1q_u32(v); + } + unsigned get0() const + { + return vgetq_lane_u32(val, 0); + } + + uint32x4_t val; +}; + +struct v_int32x4 +{ + typedef int lane_type; + enum { nlanes = 4 }; + + v_int32x4() {} + explicit v_int32x4(int32x4_t v) : val(v) {} + v_int32x4(int v0, int v1, int v2, int v3) + { + int v[] = {v0, v1, v2, v3}; + val = vld1q_s32(v); + } + int get0() const + { + return vgetq_lane_s32(val, 0); + } + int32x4_t val; +}; + +struct v_float32x4 +{ + typedef float lane_type; + enum { nlanes = 4 }; + + v_float32x4() {} + explicit v_float32x4(float32x4_t v) : val(v) {} + v_float32x4(float v0, float v1, float v2, float v3) + { + float v[] = {v0, v1, v2, v3}; + val = vld1q_f32(v); + } + float get0() const + { + return vgetq_lane_f32(val, 0); + } + float32x4_t val; +}; + +struct v_uint64x2 +{ + typedef uint64 lane_type; + enum { nlanes = 2 }; + + v_uint64x2() {} + explicit v_uint64x2(uint64x2_t v) : val(v) {} + v_uint64x2(unsigned v0, unsigned v1) + { + uint64 v[] = {v0, v1}; + val = vld1q_u64(v); + } + uint64 get0() const + { + return vgetq_lane_u64(val, 0); + } + uint64x2_t val; +}; + +struct v_int64x2 +{ + typedef int64 lane_type; + enum { nlanes = 2 }; + + v_int64x2() {} + explicit v_int64x2(int64x2_t v) : val(v) {} + v_int64x2(int v0, int v1) + { + int64 v[] = {v0, v1}; + val = vld1q_s64(v); + } + int64 get0() const + { + return vgetq_lane_s64(val, 0); + } + int64x2_t val; +}; + +#define OPENCV_HAL_IMPL_NEON_INIT(_Tpv, _Tp, suffix) \ +inline v_##_Tpv v_setzero_##suffix() { return v_##_Tpv(vdupq_n_##suffix((_Tp)0)); } \ +inline v_##_Tpv v_setall_##suffix(_Tp v) { return v_##_Tpv(vdupq_n_##suffix(v)); } \ +inline _Tpv##_t vreinterpretq_##suffix##_##suffix(_Tpv##_t v) { return v; } \ +inline v_uint8x16 v_reinterpret_as_u8(const v_##_Tpv& v) { return v_uint8x16(vreinterpretq_u8_##suffix(v.val)); } \ +inline v_int8x16 v_reinterpret_as_s8(const v_##_Tpv& v) { return v_int8x16(vreinterpretq_s8_##suffix(v.val)); } \ +inline v_uint16x8 v_reinterpret_as_u16(const v_##_Tpv& v) { return v_uint16x8(vreinterpretq_u16_##suffix(v.val)); } \ +inline v_int16x8 v_reinterpret_as_s16(const v_##_Tpv& v) { return v_int16x8(vreinterpretq_s16_##suffix(v.val)); } \ +inline v_uint32x4 v_reinterpret_as_u32(const v_##_Tpv& v) { return v_uint32x4(vreinterpretq_u32_##suffix(v.val)); } \ +inline v_int32x4 v_reinterpret_as_s32(const v_##_Tpv& v) { return v_int32x4(vreinterpretq_s32_##suffix(v.val)); } \ +inline v_uint64x2 v_reinterpret_as_u64(const v_##_Tpv& v) { return v_uint64x2(vreinterpretq_u64_##suffix(v.val)); } \ +inline v_int64x2 v_reinterpret_as_s64(const v_##_Tpv& v) { return v_int64x2(vreinterpretq_s64_##suffix(v.val)); } \ +inline v_float32x4 v_reinterpret_as_f32(const v_##_Tpv& v) { return v_float32x4(vreinterpretq_f32_##suffix(v.val)); } + +OPENCV_HAL_IMPL_NEON_INIT(uint8x16, uchar, u8) +OPENCV_HAL_IMPL_NEON_INIT(int8x16, schar, s8) +OPENCV_HAL_IMPL_NEON_INIT(uint16x8, ushort, u16) +OPENCV_HAL_IMPL_NEON_INIT(int16x8, short, s16) +OPENCV_HAL_IMPL_NEON_INIT(uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_NEON_INIT(int32x4, int, s32) +OPENCV_HAL_IMPL_NEON_INIT(uint64x2, uint64, u64) +OPENCV_HAL_IMPL_NEON_INIT(int64x2, int64, s64) +OPENCV_HAL_IMPL_NEON_INIT(float32x4, float, f32) + +#define OPENCV_HAL_IMPL_NEON_PACK(_Tpvec, _Tp, hreg, suffix, _Tpwvec, wsuffix, pack, op) \ +inline _Tpvec v_##pack(const _Tpwvec& a, const _Tpwvec& b) \ +{ \ + hreg a1 = vqmov##op##_##wsuffix(a.val), b1 = vqmov##op##_##wsuffix(b.val); \ + return _Tpvec(vcombine_##suffix(a1, b1)); \ +} \ +inline void v_##pack##_store(_Tp* ptr, const _Tpwvec& a) \ +{ \ + hreg a1 = vqmov##op##_##wsuffix(a.val); \ + vst1_##suffix(ptr, a1); \ +} \ +template inline \ +_Tpvec v_rshr_##pack(const _Tpwvec& a, const _Tpwvec& b) \ +{ \ + hreg a1 = vqrshr##op##_n_##wsuffix(a.val, n); \ + hreg b1 = vqrshr##op##_n_##wsuffix(b.val, n); \ + return _Tpvec(vcombine_##suffix(a1, b1)); \ +} \ +template inline \ +void v_rshr_##pack##_store(_Tp* ptr, const _Tpwvec& a) \ +{ \ + hreg a1 = vqrshr##op##_n_##wsuffix(a.val, n); \ + vst1_##suffix(ptr, a1); \ +} + +OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_uint16x8, u16, pack, n) +OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_int16x8, s16, pack_u, un) +OPENCV_HAL_IMPL_NEON_PACK(v_int8x16, schar, int8x8_t, s8, v_int16x8, s16, pack, n) +OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_uint32x4, u32, pack, n) +OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_int32x4, s32, pack_u, un) +OPENCV_HAL_IMPL_NEON_PACK(v_int16x8, short, int16x4_t, s16, v_int32x4, s32, pack, n) +OPENCV_HAL_IMPL_NEON_PACK(v_uint32x4, unsigned, uint32x2_t, u32, v_uint64x2, u64, pack, n) +OPENCV_HAL_IMPL_NEON_PACK(v_int32x4, int, int32x2_t, s32, v_int64x2, s64, pack, n) + +inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, + const v_float32x4& m1, const v_float32x4& m2, + const v_float32x4& m3) +{ + float32x2_t vl = vget_low_f32(v.val), vh = vget_high_f32(v.val); + float32x4_t res = vmulq_lane_f32(m0.val, vl, 0); + res = vmlaq_lane_f32(res, m1.val, vl, 1); + res = vmlaq_lane_f32(res, m2.val, vh, 0); + res = vmlaq_lane_f32(res, m3.val, vh, 1); + return v_float32x4(res); +} + +#define OPENCV_HAL_IMPL_NEON_BIN_OP(bin_op, _Tpvec, intrin) \ +inline _Tpvec operator bin_op (const _Tpvec& a, const _Tpvec& b) \ +{ \ + return _Tpvec(intrin(a.val, b.val)); \ +} \ +inline _Tpvec& operator bin_op##= (_Tpvec& a, const _Tpvec& b) \ +{ \ + a.val = intrin(a.val, b.val); \ + return a; \ +} + +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_uint8x16, vqaddq_u8) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_uint8x16, vqsubq_u8) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_int8x16, vqaddq_s8) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_int8x16, vqsubq_s8) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_uint16x8, vqaddq_u16) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_uint16x8, vqsubq_u16) +OPENCV_HAL_IMPL_NEON_BIN_OP(*, v_uint16x8, vmulq_u16) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_int16x8, vqaddq_s16) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_int16x8, vqsubq_s16) +OPENCV_HAL_IMPL_NEON_BIN_OP(*, v_int16x8, vmulq_s16) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_int32x4, vaddq_s32) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_int32x4, vsubq_s32) +OPENCV_HAL_IMPL_NEON_BIN_OP(*, v_int32x4, vmulq_s32) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_uint32x4, vaddq_u32) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_uint32x4, vsubq_u32) +OPENCV_HAL_IMPL_NEON_BIN_OP(*, v_uint32x4, vmulq_u32) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_float32x4, vaddq_f32) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_float32x4, vsubq_f32) +OPENCV_HAL_IMPL_NEON_BIN_OP(*, v_float32x4, vmulq_f32) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_int64x2, vaddq_s64) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_int64x2, vsubq_s64) +OPENCV_HAL_IMPL_NEON_BIN_OP(+, v_uint64x2, vaddq_u64) +OPENCV_HAL_IMPL_NEON_BIN_OP(-, v_uint64x2, vsubq_u64) + +inline v_float32x4 operator / (const v_float32x4& a, const v_float32x4& b) +{ + float32x4_t reciprocal = vrecpeq_f32(b.val); + reciprocal = vmulq_f32(vrecpsq_f32(b.val, reciprocal), reciprocal); + reciprocal = vmulq_f32(vrecpsq_f32(b.val, reciprocal), reciprocal); + return v_float32x4(vmulq_f32(a.val, reciprocal)); +} +inline v_float32x4& operator /= (v_float32x4& a, const v_float32x4& b) +{ + float32x4_t reciprocal = vrecpeq_f32(b.val); + reciprocal = vmulq_f32(vrecpsq_f32(b.val, reciprocal), reciprocal); + reciprocal = vmulq_f32(vrecpsq_f32(b.val, reciprocal), reciprocal); + a.val = vmulq_f32(a.val, reciprocal); + return a; +} + +inline void v_mul_expand(const v_int16x8& a, const v_int16x8& b, + v_int32x4& c, v_int32x4& d) +{ + c.val = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val)); + d.val = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val)); +} + +inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b, + v_uint32x4& c, v_uint32x4& d) +{ + c.val = vmull_u16(vget_low_u16(a.val), vget_low_u16(b.val)); + d.val = vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val)); +} + +inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b, + v_uint64x2& c, v_uint64x2& d) +{ + c.val = vmull_u32(vget_low_u32(a.val), vget_low_u32(b.val)); + d.val = vmull_u32(vget_high_u32(a.val), vget_high_u32(b.val)); +} + +inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b) +{ + int32x4_t c = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val)); + int32x4_t d = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val)); + int32x4x2_t cd = vtrnq_s32(c, d); + return v_int32x4(vaddq_s32(cd.val[0], cd.val[1])); +} + +#define OPENCV_HAL_IMPL_NEON_LOGIC_OP(_Tpvec, suffix) \ + OPENCV_HAL_IMPL_NEON_BIN_OP(&, _Tpvec, vandq_##suffix) \ + OPENCV_HAL_IMPL_NEON_BIN_OP(|, _Tpvec, vorrq_##suffix) \ + OPENCV_HAL_IMPL_NEON_BIN_OP(^, _Tpvec, veorq_##suffix) \ + inline _Tpvec operator ~ (const _Tpvec& a) \ + { \ + return _Tpvec(vreinterpretq_##suffix##_u8(vmvnq_u8(vreinterpretq_u8_##suffix(a.val)))); \ + } + +OPENCV_HAL_IMPL_NEON_LOGIC_OP(v_uint8x16, u8) +OPENCV_HAL_IMPL_NEON_LOGIC_OP(v_int8x16, s8) +OPENCV_HAL_IMPL_NEON_LOGIC_OP(v_uint16x8, u16) +OPENCV_HAL_IMPL_NEON_LOGIC_OP(v_int16x8, s16) +OPENCV_HAL_IMPL_NEON_LOGIC_OP(v_uint32x4, u32) +OPENCV_HAL_IMPL_NEON_LOGIC_OP(v_int32x4, s32) +OPENCV_HAL_IMPL_NEON_LOGIC_OP(v_uint64x2, u64) +OPENCV_HAL_IMPL_NEON_LOGIC_OP(v_int64x2, s64) + +#define OPENCV_HAL_IMPL_NEON_FLT_BIT_OP(bin_op, intrin) \ +inline v_float32x4 operator bin_op (const v_float32x4& a, const v_float32x4& b) \ +{ \ + return v_float32x4(vreinterpretq_f32_s32(intrin(vreinterpretq_s32_f32(a.val), vreinterpretq_s32_f32(b.val)))); \ +} \ +inline v_float32x4& operator bin_op##= (v_float32x4& a, const v_float32x4& b) \ +{ \ + a.val = vreinterpretq_f32_s32(intrin(vreinterpretq_s32_f32(a.val), vreinterpretq_s32_f32(b.val))); \ + return a; \ +} + +OPENCV_HAL_IMPL_NEON_FLT_BIT_OP(&, vandq_s32) +OPENCV_HAL_IMPL_NEON_FLT_BIT_OP(|, vorrq_s32) +OPENCV_HAL_IMPL_NEON_FLT_BIT_OP(^, veorq_s32) + +inline v_float32x4 operator ~ (const v_float32x4& a) +{ + return v_float32x4(vreinterpretq_f32_s32(vmvnq_s32(vreinterpretq_s32_f32(a.val)))); +} + +inline v_float32x4 v_sqrt(const v_float32x4& x) +{ + float32x4_t x1 = vmaxq_f32(x.val, vdupq_n_f32(FLT_MIN)); + float32x4_t e = vrsqrteq_f32(x1); + e = vmulq_f32(vrsqrtsq_f32(vmulq_f32(x1, e), e), e); + e = vmulq_f32(vrsqrtsq_f32(vmulq_f32(x1, e), e), e); + return v_float32x4(vmulq_f32(x.val, e)); +} + +inline v_float32x4 v_invsqrt(const v_float32x4& x) +{ + float32x4_t e = vrsqrteq_f32(x.val); + e = vmulq_f32(vrsqrtsq_f32(vmulq_f32(x.val, e), e), e); + e = vmulq_f32(vrsqrtsq_f32(vmulq_f32(x.val, e), e), e); + return v_float32x4(e); +} + +inline v_float32x4 v_abs(v_float32x4 x) +{ return v_float32x4(vabsq_f32(x.val)); } + +// TODO: exp, log, sin, cos + +#define OPENCV_HAL_IMPL_NEON_BIN_FUNC(_Tpvec, func, intrin) \ +inline _Tpvec func(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return _Tpvec(intrin(a.val, b.val)); \ +} + +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint8x16, v_min, vminq_u8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint8x16, v_max, vmaxq_u8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int8x16, v_min, vminq_s8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int8x16, v_max, vmaxq_s8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint16x8, v_min, vminq_u16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint16x8, v_max, vmaxq_u16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int16x8, v_min, vminq_s16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int16x8, v_max, vmaxq_s16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint32x4, v_min, vminq_u32) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint32x4, v_max, vmaxq_u32) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int32x4, v_min, vminq_s32) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int32x4, v_max, vmaxq_s32) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float32x4, v_min, vminq_f32) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float32x4, v_max, vmaxq_f32) + + +#define OPENCV_HAL_IMPL_NEON_INT_CMP_OP(_Tpvec, cast, suffix, not_suffix) \ +inline _Tpvec operator == (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(cast(vceqq_##suffix(a.val, b.val))); } \ +inline _Tpvec operator != (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(cast(vmvnq_##not_suffix(vceqq_##suffix(a.val, b.val)))); } \ +inline _Tpvec operator < (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(cast(vcltq_##suffix(a.val, b.val))); } \ +inline _Tpvec operator > (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(cast(vcgtq_##suffix(a.val, b.val))); } \ +inline _Tpvec operator <= (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(cast(vcleq_##suffix(a.val, b.val))); } \ +inline _Tpvec operator >= (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(cast(vcgeq_##suffix(a.val, b.val))); } + +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint8x16, OPENCV_HAL_NOP, u8, u8) +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int8x16, vreinterpretq_s8_u8, s8, u8) +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint16x8, OPENCV_HAL_NOP, u16, u16) +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int16x8, vreinterpretq_s16_u16, s16, u16) +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint32x4, OPENCV_HAL_NOP, u32, u32) +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int32x4, vreinterpretq_s32_u32, s32, u32) +OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float32x4, vreinterpretq_f32_u32, f32, u32) + +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint8x16, v_add_wrap, vaddq_u8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int8x16, v_add_wrap, vaddq_s8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint16x8, v_add_wrap, vaddq_u16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int16x8, v_add_wrap, vaddq_s16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint8x16, v_sub_wrap, vsubq_u8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int8x16, v_sub_wrap, vsubq_s8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint16x8, v_sub_wrap, vsubq_u16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_int16x8, v_sub_wrap, vsubq_s16) + +// TODO: absdiff for signed integers +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint8x16, v_absdiff, vabdq_u8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint16x8, v_absdiff, vabdq_u16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint32x4, v_absdiff, vabdq_u32) +OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float32x4, v_absdiff, vabdq_f32) + +inline v_float32x4 v_magnitude(const v_float32x4& a, const v_float32x4& b) +{ + v_float32x4 x(vmlaq_f32(vmulq_f32(a.val, a.val), b.val, b.val)); + return v_sqrt(x); +} + +inline v_float32x4 v_sqr_magnitude(const v_float32x4& a, const v_float32x4& b) +{ + return v_float32x4(vmlaq_f32(vmulq_f32(a.val, a.val), b.val, b.val)); +} + +inline v_float32x4 v_muladd(const v_float32x4& a, const v_float32x4& b, const v_float32x4& c) +{ + return v_float32x4(vmlaq_f32(c.val, a.val, b.val)); +} + +// trade efficiency for convenience +#define OPENCV_HAL_IMPL_NEON_SHIFT_OP(_Tpvec, suffix, _Tps, ssuffix) \ +inline _Tpvec operator << (const _Tpvec& a, int n) \ +{ return _Tpvec(vshlq_##suffix(a.val, vdupq_n_##ssuffix((_Tps)n))); } \ +inline _Tpvec operator >> (const _Tpvec& a, int n) \ +{ return _Tpvec(vshlq_##suffix(a.val, vdupq_n_##ssuffix((_Tps)-n))); } \ +template inline _Tpvec v_shl(const _Tpvec& a) \ +{ return _Tpvec(vshlq_n_##suffix(a.val, n)); } \ +template inline _Tpvec v_shr(const _Tpvec& a) \ +{ return _Tpvec(vshrq_n_##suffix(a.val, n)); } \ +template inline _Tpvec v_rshr(const _Tpvec& a) \ +{ return _Tpvec(vrshrq_n_##suffix(a.val, n)); } + +OPENCV_HAL_IMPL_NEON_SHIFT_OP(v_uint8x16, u8, schar, s8) +OPENCV_HAL_IMPL_NEON_SHIFT_OP(v_int8x16, s8, schar, s8) +OPENCV_HAL_IMPL_NEON_SHIFT_OP(v_uint16x8, u16, short, s16) +OPENCV_HAL_IMPL_NEON_SHIFT_OP(v_int16x8, s16, short, s16) +OPENCV_HAL_IMPL_NEON_SHIFT_OP(v_uint32x4, u32, int, s32) +OPENCV_HAL_IMPL_NEON_SHIFT_OP(v_int32x4, s32, int, s32) +OPENCV_HAL_IMPL_NEON_SHIFT_OP(v_uint64x2, u64, int64, s64) +OPENCV_HAL_IMPL_NEON_SHIFT_OP(v_int64x2, s64, int64, s64) + +#define OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(_Tpvec, _Tp, suffix) \ +inline _Tpvec v_load(const _Tp* ptr) \ +{ return _Tpvec(vld1q_##suffix(ptr)); } \ +inline _Tpvec v_load_aligned(const _Tp* ptr) \ +{ return _Tpvec(vld1q_##suffix(ptr)); } \ +inline _Tpvec v_load_halves(const _Tp* ptr0, const _Tp* ptr1) \ +{ return _Tpvec(vcombine_##suffix(vld1_##suffix(ptr0), vld1_##suffix(ptr1))); } \ +inline void v_store(_Tp* ptr, const _Tpvec& a) \ +{ vst1q_##suffix(ptr, a.val); } \ +inline void v_store_aligned(_Tp* ptr, const _Tpvec& a) \ +{ vst1q_##suffix(ptr, a.val); } \ +inline void v_store_low(_Tp* ptr, const _Tpvec& a) \ +{ vst1_##suffix(ptr, vget_low_##suffix(a.val)); } \ +inline void v_store_high(_Tp* ptr, const _Tpvec& a) \ +{ vst1_##suffix(ptr, vget_high_##suffix(a.val)); } + +OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_int8x16, schar, s8) +OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_int16x8, short, s16) +OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_int32x4, int, s32) +OPENCV_HAL_IMPL_NEON_LOADSTORE_OP(v_float32x4, float, f32) + +#define OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(_Tpvec, scalartype, func, scalar_func) \ +inline scalartype v_reduce_##func(const _Tpvec& a) \ +{ \ + scalartype CV_DECL_ALIGNED(16) buf[4]; \ + v_store_aligned(buf, a); \ + scalartype s0 = scalar_func(buf[0], buf[1]); \ + scalartype s1 = scalar_func(buf[2], buf[3]); \ + return scalar_func(s0, s1); \ +} + +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_uint32x4, unsigned, sum, OPENCV_HAL_ADD) +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_uint32x4, unsigned, max, std::max) +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_uint32x4, unsigned, min, std::min) +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_int32x4, int, sum, OPENCV_HAL_ADD) +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_int32x4, int, max, std::max) +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_int32x4, int, min, std::min) +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float, sum, OPENCV_HAL_ADD) +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float, max, std::max) +OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float, min, std::min) + +inline int v_signmask(const v_uint8x16& a) +{ + int8x8_t m0 = vcreate_s8(CV_BIG_UINT(0x0706050403020100)); + uint8x16_t v0 = vshlq_u8(vshrq_n_u8(a.val, 7), vcombine_s8(m0, m0)); + uint64x2_t v1 = vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(v0))); + return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 8); +} +inline int v_signmask(const v_int8x16& a) +{ return v_signmask(v_reinterpret_as_u8(a)); } + +inline int v_signmask(const v_uint16x8& a) +{ + int16x4_t m0 = vcreate_s16(CV_BIG_UINT(0x0003000200010000)); + uint16x8_t v0 = vshlq_u16(vshrq_n_u16(a.val, 15), vcombine_s16(m0, m0)); + uint64x2_t v1 = vpaddlq_u32(vpaddlq_u16(v0)); + return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 4); +} +inline int v_signmask(const v_int16x8& a) +{ return v_signmask(v_reinterpret_as_u16(a)); } + +inline int v_signmask(const v_uint32x4& a) +{ + int32x2_t m0 = vcreate_s32(CV_BIG_UINT(0x0000000100000000)); + uint32x4_t v0 = vshlq_u32(vshrq_n_u32(a.val, 31), vcombine_s32(m0, m0)); + uint64x2_t v1 = vpaddlq_u32(v0); + return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 2); +} +inline int v_signmask(const v_int32x4& a) +{ return v_signmask(v_reinterpret_as_u32(a)); } +inline int v_signmask(const v_float32x4& a) +{ return v_signmask(v_reinterpret_as_u32(a)); } + +#define OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(_Tpvec, suffix, shift) \ +inline bool v_check_all(const v_##_Tpvec& a) \ +{ \ + _Tpvec##_t v0 = vshrq_n_##suffix(vmvnq_##suffix(a.val), shift); \ + uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \ + return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) == 0; \ +} \ +inline bool v_check_any(const v_##_Tpvec& a) \ +{ \ + _Tpvec##_t v0 = vshrq_n_##suffix(a.val, shift); \ + uint64x2_t v1 = vreinterpretq_u64_##suffix(v0); \ + return (vgetq_lane_u64(v1, 0) | vgetq_lane_u64(v1, 1)) != 0; \ +} + +OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint8x16, u8, 7) +OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint16x8, u16, 15) +OPENCV_HAL_IMPL_NEON_CHECK_ALLANY(uint32x4, u32, 31) + +inline bool v_check_all(const v_int8x16& a) +{ return v_check_all(v_reinterpret_as_u8(a)); } +inline bool v_check_all(const v_int16x8& a) +{ return v_check_all(v_reinterpret_as_u16(a)); } +inline bool v_check_all(const v_int32x4& a) +{ return v_check_all(v_reinterpret_as_u32(a)); } +inline bool v_check_all(const v_float32x4& a) +{ return v_check_all(v_reinterpret_as_u32(a)); } + +inline bool v_check_any(const v_int8x16& a) +{ return v_check_all(v_reinterpret_as_u8(a)); } +inline bool v_check_any(const v_int16x8& a) +{ return v_check_all(v_reinterpret_as_u16(a)); } +inline bool v_check_any(const v_int32x4& a) +{ return v_check_all(v_reinterpret_as_u32(a)); } +inline bool v_check_any(const v_float32x4& a) +{ return v_check_all(v_reinterpret_as_u32(a)); } + +#define OPENCV_HAL_IMPL_NEON_SELECT(_Tpvec, suffix, usuffix) \ +inline _Tpvec v_select(const _Tpvec& mask, const _Tpvec& a, const _Tpvec& b) \ +{ \ + return _Tpvec(vbslq_##suffix(vreinterpretq_##usuffix##_##suffix(mask.val), a.val, b.val)); \ +} + +OPENCV_HAL_IMPL_NEON_SELECT(v_uint8x16, u8, u8) +OPENCV_HAL_IMPL_NEON_SELECT(v_int8x16, s8, u8) +OPENCV_HAL_IMPL_NEON_SELECT(v_uint16x8, u16, u16) +OPENCV_HAL_IMPL_NEON_SELECT(v_int16x8, s16, u16) +OPENCV_HAL_IMPL_NEON_SELECT(v_uint32x4, u32, u32) +OPENCV_HAL_IMPL_NEON_SELECT(v_int32x4, s32, u32) +OPENCV_HAL_IMPL_NEON_SELECT(v_float32x4, f32, u32) + +#define OPENCV_HAL_IMPL_NEON_EXPAND(_Tpvec, _Tpwvec, _Tp, suffix) \ +inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \ +{ \ + b0.val = vmovl_##suffix(vget_low_##suffix(a.val)); \ + b1.val = vmovl_##suffix(vget_high_##suffix(a.val)); \ +} \ +inline _Tpwvec v_load_expand(const _Tp* ptr) \ +{ \ + return _Tpwvec(vmovl_##suffix(vld1_##suffix(ptr))); \ +} + +OPENCV_HAL_IMPL_NEON_EXPAND(v_uint8x16, v_uint16x8, uchar, u8) +OPENCV_HAL_IMPL_NEON_EXPAND(v_int8x16, v_int16x8, schar, s8) +OPENCV_HAL_IMPL_NEON_EXPAND(v_uint16x8, v_uint32x4, ushort, u16) +OPENCV_HAL_IMPL_NEON_EXPAND(v_int16x8, v_int32x4, short, s16) + +inline v_uint32x4 v_load_expand_q(const uchar* ptr) +{ + uint8x8_t v0 = vcreate_u8(*(unsigned*)ptr); + uint16x4_t v1 = vget_low_u16(vmovl_u8(v0)); + return v_uint32x4(vmovl_u16(v1)); +} + +inline v_int32x4 v_load_expand_q(const schar* ptr) +{ + int8x8_t v0 = vcreate_s8(*(unsigned*)ptr); + int16x4_t v1 = vget_low_s16(vmovl_s8(v0)); + return v_int32x4(vmovl_s16(v1)); +} + +#define OPENCV_HAL_IMPL_NEON_UNPACKS(_Tpvec, suffix) \ +inline void v_zip(const v_##_Tpvec& a0, const v_##_Tpvec& a1, v_##_Tpvec& b0, v_##_Tpvec& b1) \ +{ \ + _Tpvec##x2_t p = vzipq_##suffix(a0.val, a1.val); \ + b0.val = p.val[0]; \ + b1.val = p.val[1]; \ +} \ +inline v_##_Tpvec v_combine_low(const v_##_Tpvec& a, const v_##_Tpvec& b) \ +{ \ + return v_##_Tpvec(vcombine_##suffix(vget_low_##suffix(a.val), vget_low_##suffix(b.val))); \ +} \ +inline v_##_Tpvec v_combine_high(const v_##_Tpvec& a, const v_##_Tpvec& b) \ +{ \ + return v_##_Tpvec(vcombine_##suffix(vget_high_##suffix(a.val), vget_high_##suffix(b.val))); \ +} \ +inline void v_recombine(const v_##_Tpvec& a, const v_##_Tpvec& b, v_##_Tpvec& c, v_##_Tpvec& d) \ +{ \ + c.val = vcombine_##suffix(vget_low_##suffix(a.val), vget_low_##suffix(b.val)); \ + d.val = vcombine_##suffix(vget_high_##suffix(a.val), vget_high_##suffix(b.val)); \ +} + +OPENCV_HAL_IMPL_NEON_UNPACKS(uint8x16, u8) +OPENCV_HAL_IMPL_NEON_UNPACKS(int8x16, s8) +OPENCV_HAL_IMPL_NEON_UNPACKS(uint16x8, u16) +OPENCV_HAL_IMPL_NEON_UNPACKS(int16x8, s16) +OPENCV_HAL_IMPL_NEON_UNPACKS(uint32x4, u32) +OPENCV_HAL_IMPL_NEON_UNPACKS(int32x4, s32) +OPENCV_HAL_IMPL_NEON_UNPACKS(float32x4, f32) + +inline v_int32x4 v_round(const v_float32x4& a) +{ + static const int32x4_t v_sign = vdupq_n_s32(1 << 31), + v_05 = vreinterpretq_s32_f32(vdupq_n_f32(0.5f)); + + int32x4_t v_addition = vorrq_s32(v_05, vandq_s32(v_sign, vreinterpretq_s32_f32(a.val))); + return v_int32x4(vcvtq_s32_f32(vaddq_f32(a.val, vreinterpretq_f32_s32(v_addition)))); +} + +inline v_int32x4 v_floor(const v_float32x4& a) +{ + int32x4_t a1 = vcvtq_s32_f32(a.val); + uint32x4_t mask = vcgtq_f32(vcvtq_f32_s32(a1), a.val); + return v_int32x4(vaddq_s32(a1, vreinterpretq_s32_u32(mask))); +} + +inline v_int32x4 v_ceil(const v_float32x4& a) +{ + int32x4_t a1 = vcvtq_s32_f32(a.val); + uint32x4_t mask = vcgtq_f32(a.val, vcvtq_f32_s32(a1)); + return v_int32x4(vsubq_s32(a1, vreinterpretq_s32_u32(mask))); +} + +inline v_int32x4 v_trunc(const v_float32x4& a) +{ return v_int32x4(vcvtq_s32_f32(a.val)); } + +#define OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(_Tpvec, suffix) \ +inline void transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \ + const v_##_Tpvec& a2, const v_##_Tpvec& a3, \ + v_##_Tpvec& b0, v_##_Tpvec& b1, \ + v_##_Tpvec& b2, v_##_Tpvec& b3) \ +{ \ + /* m00 m01 m02 m03 */ \ + /* m10 m11 m12 m13 */ \ + /* m20 m21 m22 m23 */ \ + /* m30 m31 m32 m33 */ \ + _Tpvec##x2_t t0 = vtrnq_##suffix(a0.val, a1.val); \ + _Tpvec##x2_t t1 = vtrnq_##suffix(a2.val, a3.val); \ + /* m00 m10 m02 m12 */ \ + /* m01 m11 m03 m13 */ \ + /* m20 m30 m22 m32 */ \ + /* m21 m31 m23 m33 */ \ + b0.val = vcombine_##suffix(vget_low_##suffix(t0.val[0]), vget_low_##suffix(t1.val[0])); \ + b1.val = vcombine_##suffix(vget_low_##suffix(t0.val[1]), vget_low_##suffix(t1.val[1])); \ + b2.val = vcombine_##suffix(vget_high_##suffix(t0.val[0]), vget_high_##suffix(t1.val[0])); \ + b3.val = vcombine_##suffix(vget_high_##suffix(t0.val[1]), vget_high_##suffix(t1.val[1])); \ +} + +OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(uint32x4, u32) +OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(int32x4, s32) +OPENCV_HAL_IMPL_NEON_TRANSPOSE4x4(float32x4, f32) + +#define OPENCV_HAL_IMPL_NEON_INTERLEAVED(_Tpvec, _Tp, suffix) \ +inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b, v_##_Tpvec& c) \ +{ \ + _Tpvec##x3_t v = vld3q_##suffix(ptr); \ + a.val = v.val[0]; \ + b.val = v.val[1]; \ + c.val = v.val[2]; \ +} \ +inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b, \ + v_##_Tpvec& c, v_##_Tpvec& d) \ +{ \ + _Tpvec##x4_t v = vld4q_##suffix(ptr); \ + a.val = v.val[0]; \ + b.val = v.val[1]; \ + c.val = v.val[2]; \ + d.val = v.val[3]; \ +} \ +inline void v_store_interleave( _Tp* ptr, const v_##_Tpvec& a, const v_##_Tpvec& b, const v_##_Tpvec& c) \ +{ \ + _Tpvec##x3_t v; \ + v.val[0] = a.val; \ + v.val[1] = b.val; \ + v.val[2] = c.val; \ + vst3q_##suffix(ptr, v); \ +} \ +inline void v_store_interleave( _Tp* ptr, const v_##_Tpvec& a, const v_##_Tpvec& b, \ + const v_##_Tpvec& c, const v_##_Tpvec& d) \ +{ \ + _Tpvec##x4_t v; \ + v.val[0] = a.val; \ + v.val[1] = b.val; \ + v.val[2] = c.val; \ + v.val[3] = d.val; \ + vst4q_##suffix(ptr, v); \ +} + +OPENCV_HAL_IMPL_NEON_INTERLEAVED(uint8x16, uchar, u8) +OPENCV_HAL_IMPL_NEON_INTERLEAVED(int8x16, schar, s8) +OPENCV_HAL_IMPL_NEON_INTERLEAVED(uint16x8, ushort, u16) +OPENCV_HAL_IMPL_NEON_INTERLEAVED(int16x8, short, s16) +OPENCV_HAL_IMPL_NEON_INTERLEAVED(uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_NEON_INTERLEAVED(int32x4, int, s32) +OPENCV_HAL_IMPL_NEON_INTERLEAVED(float32x4, float, f32) + +inline v_float32x4 v_cvt_f32(const v_int32x4& a) +{ + return v_float32x4(vcvtq_f32_s32(a.val)); +} + +} + +#endif diff --git a/include/opencv2/hal/intrin_sse.hpp b/include/opencv2/hal/intrin_sse.hpp new file mode 100644 index 0000000..69171e2 --- /dev/null +++ b/include/opencv2/hal/intrin_sse.hpp @@ -0,0 +1,1554 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HAL_SSE_HPP__ +#define __OPENCV_HAL_SSE_HPP__ + +#define CV_SIMD128 1 +#define CV_SIMD128_64F 1 + +namespace cv +{ + +struct v_uint8x16 +{ + typedef uchar lane_type; + enum { nlanes = 16 }; + + v_uint8x16() {} + explicit v_uint8x16(__m128i v) : val(v) {} + v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7, + uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15) + { + val = _mm_setr_epi8((char)v0, (char)v1, (char)v2, (char)v3, + (char)v4, (char)v5, (char)v6, (char)v7, + (char)v8, (char)v9, (char)v10, (char)v11, + (char)v12, (char)v13, (char)v14, (char)v15); + } + uchar get0() const + { + return (uchar)_mm_cvtsi128_si32(val); + } + + __m128i val; +}; + +struct v_int8x16 +{ + typedef schar lane_type; + enum { nlanes = 16 }; + + v_int8x16() {} + explicit v_int8x16(__m128i v) : val(v) {} + v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7, + schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15) + { + val = _mm_setr_epi8((char)v0, (char)v1, (char)v2, (char)v3, + (char)v4, (char)v5, (char)v6, (char)v7, + (char)v8, (char)v9, (char)v10, (char)v11, + (char)v12, (char)v13, (char)v14, (char)v15); + } + schar get0() const + { + return (schar)_mm_cvtsi128_si32(val); + } + + __m128i val; +}; + +struct v_uint16x8 +{ + typedef ushort lane_type; + enum { nlanes = 8 }; + + v_uint16x8() {} + explicit v_uint16x8(__m128i v) : val(v) {} + v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7) + { + val = _mm_setr_epi16((short)v0, (short)v1, (short)v2, (short)v3, + (short)v4, (short)v5, (short)v6, (short)v7); + } + ushort get0() const + { + return (ushort)_mm_cvtsi128_si32(val); + } + + __m128i val; +}; + +struct v_int16x8 +{ + typedef short lane_type; + enum { nlanes = 8 }; + + v_int16x8() {} + explicit v_int16x8(__m128i v) : val(v) {} + v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7) + { + val = _mm_setr_epi16((short)v0, (short)v1, (short)v2, (short)v3, + (short)v4, (short)v5, (short)v6, (short)v7); + } + short get0() const + { + return (short)_mm_cvtsi128_si32(val); + } + __m128i val; +}; + +struct v_uint32x4 +{ + typedef unsigned lane_type; + enum { nlanes = 4 }; + + v_uint32x4() {} + explicit v_uint32x4(__m128i v) : val(v) {} + v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) + { + val = _mm_setr_epi32((int)v0, (int)v1, (int)v2, (int)v3); + } + unsigned get0() const + { + return (unsigned)_mm_cvtsi128_si32(val); + } + __m128i val; +}; + +struct v_int32x4 +{ + typedef int lane_type; + enum { nlanes = 4 }; + + v_int32x4() {} + explicit v_int32x4(__m128i v) : val(v) {} + v_int32x4(int v0, int v1, int v2, int v3) + { + val = _mm_setr_epi32(v0, v1, v2, v3); + } + int get0() const + { + return _mm_cvtsi128_si32(val); + } + __m128i val; +}; + +struct v_float32x4 +{ + typedef float lane_type; + enum { nlanes = 4 }; + + v_float32x4() {} + explicit v_float32x4(__m128 v) : val(v) {} + v_float32x4(float v0, float v1, float v2, float v3) + { + val = _mm_setr_ps(v0, v1, v2, v3); + } + float get0() const + { + return _mm_cvtss_f32(val); + } + __m128 val; +}; + +struct v_uint64x2 +{ + typedef uint64 lane_type; + enum { nlanes = 2 }; + + v_uint64x2() {} + explicit v_uint64x2(__m128i v) : val(v) {} + v_uint64x2(uint64 v0, uint64 v1) + { + val = _mm_setr_epi32((int)v0, (int)(v0 >> 32), (int)v1, (int)(v1 >> 32)); + } + uint64 get0() const + { + int a = _mm_cvtsi128_si32(val); + int b = _mm_cvtsi128_si32(_mm_srli_epi64(val, 32)); + return (unsigned)a | ((uint64)(unsigned)b << 32); + } + __m128i val; +}; + +struct v_int64x2 +{ + typedef int64 lane_type; + enum { nlanes = 2 }; + + v_int64x2() {} + explicit v_int64x2(__m128i v) : val(v) {} + v_int64x2(int64 v0, int64 v1) + { + val = _mm_setr_epi32((int)v0, (int)(v0 >> 32), (int)v1, (int)(v1 >> 32)); + } + int64 get0() const + { + int a = _mm_cvtsi128_si32(val); + int b = _mm_cvtsi128_si32(_mm_srli_epi64(val, 32)); + return (int64)((unsigned)a | ((uint64)(unsigned)b << 32)); + } + __m128i val; +}; + +struct v_float64x2 +{ + typedef double lane_type; + enum { nlanes = 2 }; + + v_float64x2() {} + explicit v_float64x2(__m128d v) : val(v) {} + v_float64x2(double v0, double v1) + { + val = _mm_setr_pd(v0, v1); + } + double get0() const + { + return _mm_cvtsd_f64(val); + } + __m128d val; +}; + +#define OPENCV_HAL_IMPL_SSE_INITVEC(_Tpvec, _Tp, suffix, zsuffix, ssuffix, _Tps, cast) \ +inline _Tpvec v_setzero_##suffix() { return _Tpvec(_mm_setzero_##zsuffix()); } \ +inline _Tpvec v_setall_##suffix(_Tp v) { return _Tpvec(_mm_set1_##ssuffix((_Tps)v)); } \ +template inline _Tpvec v_reinterpret_as_##suffix(const _Tpvec0& a) \ +{ return _Tpvec(cast(a.val)); } + +OPENCV_HAL_IMPL_SSE_INITVEC(v_uint8x16, uchar, u8, si128, epi8, char, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_INITVEC(v_int8x16, schar, s8, si128, epi8, char, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_INITVEC(v_uint16x8, ushort, u16, si128, epi16, short, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_INITVEC(v_int16x8, short, s16, si128, epi16, short, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_INITVEC(v_uint32x4, unsigned, u32, si128, epi32, int, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_INITVEC(v_int32x4, int, s32, si128, epi32, int, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_INITVEC(v_float32x4, float, f32, ps, ps, float, _mm_castsi128_ps) +OPENCV_HAL_IMPL_SSE_INITVEC(v_float64x2, double, f64, pd, pd, double, _mm_castsi128_pd) + +inline v_uint64x2 v_setzero_u64() { return v_uint64x2(_mm_setzero_si128()); } +inline v_int64x2 v_setzero_s64() { return v_int64x2(_mm_setzero_si128()); } +inline v_uint64x2 v_setall_u64(uint64 val) { return v_uint64x2(val, val); } +inline v_int64x2 v_setall_s64(int64 val) { return v_int64x2(val, val); } + +template inline +v_uint64x2 v_reinterpret_as_u64(const _Tpvec& a) { return v_uint64x2(a.val); } +template inline +v_int64x2 v_reinterpret_as_s64(const _Tpvec& a) { return v_int64x2(a.val); } +inline v_float32x4 v_reinterpret_as_f32(const v_uint64x2& a) +{ return v_float32x4(_mm_castsi128_ps(a.val)); } +inline v_float32x4 v_reinterpret_as_f32(const v_int64x2& a) +{ return v_float32x4(_mm_castsi128_ps(a.val)); } +inline v_float64x2 v_reinterpret_as_f64(const v_uint64x2& a) +{ return v_float64x2(_mm_castsi128_pd(a.val)); } +inline v_float64x2 v_reinterpret_as_f64(const v_int64x2& a) +{ return v_float64x2(_mm_castsi128_pd(a.val)); } + +#define OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(_Tpvec, suffix) \ +inline _Tpvec v_reinterpret_as_##suffix(const v_float32x4& a) \ +{ return _Tpvec(_mm_castps_si128(a.val)); } \ +inline _Tpvec v_reinterpret_as_##suffix(const v_float64x2& a) \ +{ return _Tpvec(_mm_castpd_si128(a.val)); } + +OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_uint8x16, u8) +OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_int8x16, s8) +OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_uint16x8, u16) +OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_int16x8, s16) +OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_uint32x4, u32) +OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_int32x4, s32) +OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_uint64x2, u64) +OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_int64x2, s64) + +//////////////// PACK /////////////// +inline v_uint8x16 v_pack(const v_uint16x8& a, const v_uint16x8& b) +{ + __m128i delta = _mm_set1_epi16(255); + return v_uint8x16(_mm_packus_epi16(_mm_subs_epu16(a.val, _mm_subs_epu16(a.val, delta)), + _mm_subs_epu16(b.val, _mm_subs_epu16(b.val, delta)))); +} + +inline void v_pack_store(uchar* ptr, const v_uint16x8& a) +{ + __m128i delta = _mm_set1_epi16(255); + __m128i a1 = _mm_subs_epu16(a.val, _mm_subs_epu16(a.val, delta)); + _mm_storel_epi64((__m128i*)ptr, _mm_packus_epi16(a1, a1)); +} + +inline v_uint8x16 v_pack_u(const v_int16x8& a, const v_int16x8& b) +{ return v_uint8x16(_mm_packus_epi16(a.val, b.val)); } + +inline void v_pack_u_store(uchar* ptr, const v_int16x8& a) +{ _mm_storel_epi64((__m128i*)ptr, _mm_packus_epi16(a.val, a.val)); } + +template inline +v_uint8x16 v_rshr_pack(const v_uint16x8& a, const v_uint16x8& b) +{ + // we assume that n > 0, and so the shifted 16-bit values can be treated as signed numbers. + __m128i delta = _mm_set1_epi16((short)(1 << (n-1))); + return v_uint8x16(_mm_packus_epi16(_mm_srli_epi16(_mm_adds_epu16(a.val, delta), n), + _mm_srli_epi16(_mm_adds_epu16(b.val, delta), n))); +} + +template inline +void v_rshr_pack_store(uchar* ptr, const v_uint16x8& a) +{ + __m128i delta = _mm_set1_epi16((short)(1 << (n-1))); + __m128i a1 = _mm_srli_epi16(_mm_adds_epu16(a.val, delta), n); + _mm_storel_epi64((__m128i*)ptr, _mm_packus_epi16(a1, a1)); +} + +template inline +v_uint8x16 v_rshr_pack_u(const v_int16x8& a, const v_int16x8& b) +{ + __m128i delta = _mm_set1_epi16((short)(1 << (n-1))); + return v_uint8x16(_mm_packus_epi16(_mm_srai_epi16(_mm_adds_epi16(a.val, delta), n), + _mm_srai_epi16(_mm_adds_epi16(b.val, delta), n))); +} + +template inline +void v_rshr_pack_u_store(uchar* ptr, const v_int16x8& a) +{ + __m128i delta = _mm_set1_epi16((short)(1 << (n-1))); + __m128i a1 = _mm_srai_epi16(_mm_adds_epi16(a.val, delta), n); + _mm_storel_epi64((__m128i*)ptr, _mm_packus_epi16(a1, a1)); +} + +inline v_int8x16 v_pack(const v_int16x8& a, const v_int16x8& b) +{ return v_int8x16(_mm_packs_epi16(a.val, b.val)); } + +inline void v_pack_store(schar* ptr, v_int16x8& a) +{ _mm_storel_epi64((__m128i*)ptr, _mm_packs_epi16(a.val, a.val)); } + +template inline +v_int8x16 v_rshr_pack(const v_int16x8& a, const v_int16x8& b) +{ + // we assume that n > 0, and so the shifted 16-bit values can be treated as signed numbers. + __m128i delta = _mm_set1_epi16((short)(1 << (n-1))); + return v_int8x16(_mm_packs_epi16(_mm_srai_epi16(_mm_adds_epi16(a.val, delta), n), + _mm_srai_epi16(_mm_adds_epi16(b.val, delta), n))); +} +template inline +void v_rshr_pack_store(schar* ptr, const v_int16x8& a) +{ + // we assume that n > 0, and so the shifted 16-bit values can be treated as signed numbers. + __m128i delta = _mm_set1_epi16((short)(1 << (n-1))); + __m128i a1 = _mm_srai_epi16(_mm_adds_epi16(a.val, delta), n); + _mm_storel_epi64((__m128i*)ptr, _mm_packs_epi16(a1, a1)); +} + + +// bit-wise "mask ? a : b" +inline __m128i v_select_si128(__m128i mask, __m128i a, __m128i b) +{ + return _mm_xor_si128(b, _mm_and_si128(_mm_xor_si128(a, b), mask)); +} + +inline v_uint16x8 v_pack(const v_uint32x4& a, const v_uint32x4& b) +{ + __m128i z = _mm_setzero_si128(), maxval32 = _mm_set1_epi32(65535), delta32 = _mm_set1_epi32(32768); + __m128i a1 = _mm_sub_epi32(v_select_si128(_mm_cmpgt_epi32(z, a.val), maxval32, a.val), delta32); + __m128i b1 = _mm_sub_epi32(v_select_si128(_mm_cmpgt_epi32(z, b.val), maxval32, b.val), delta32); + __m128i r = _mm_packs_epi32(a1, b1); + return v_uint16x8(_mm_sub_epi16(r, _mm_set1_epi16(-32768))); +} + +inline void v_pack_store(ushort* ptr, const v_uint32x4& a) +{ + __m128i z = _mm_setzero_si128(), maxval32 = _mm_set1_epi32(65535), delta32 = _mm_set1_epi32(32768); + __m128i a1 = _mm_sub_epi32(v_select_si128(_mm_cmpgt_epi32(z, a.val), maxval32, a.val), delta32); + __m128i r = _mm_packs_epi32(a1, a1); + _mm_storel_epi64((__m128i*)ptr, _mm_sub_epi16(r, _mm_set1_epi16(-32768))); +} + +template inline +v_uint16x8 v_rshr_pack(const v_uint32x4& a, const v_uint32x4& b) +{ + __m128i delta = _mm_set1_epi32(1 << (n-1)), delta32 = _mm_set1_epi32(32768); + __m128i a1 = _mm_sub_epi32(_mm_srli_epi32(_mm_add_epi32(a.val, delta), n), delta32); + __m128i b1 = _mm_sub_epi32(_mm_srli_epi32(_mm_add_epi32(b.val, delta), n), delta32); + return v_uint16x8(_mm_sub_epi16(_mm_packs_epi32(a1, b1), _mm_set1_epi16(-32768))); +} + +template inline +void v_rshr_pack_store(ushort* ptr, const v_uint32x4& a) +{ + __m128i delta = _mm_set1_epi32(1 << (n-1)), delta32 = _mm_set1_epi32(32768); + __m128i a1 = _mm_sub_epi32(_mm_srli_epi32(_mm_add_epi32(a.val, delta), n), delta32); + __m128i a2 = _mm_sub_epi16(_mm_packs_epi32(a1, a1), _mm_set1_epi16(-32768)); + _mm_storel_epi64((__m128i*)ptr, a2); +} + +inline v_uint16x8 v_pack_u(const v_int32x4& a, const v_int32x4& b) +{ + __m128i delta32 = _mm_set1_epi32(32768); + __m128i r = _mm_packs_epi32(_mm_sub_epi32(a.val, delta32), _mm_sub_epi32(b.val, delta32)); + return v_uint16x8(_mm_sub_epi16(r, _mm_set1_epi16(-32768))); +} + +inline void v_pack_u_store(ushort* ptr, const v_int32x4& a) +{ + __m128i delta32 = _mm_set1_epi32(32768); + __m128i a1 = _mm_sub_epi32(a.val, delta32); + __m128i r = _mm_sub_epi16(_mm_packs_epi32(a1, a1), _mm_set1_epi16(-32768)); + _mm_storel_epi64((__m128i*)ptr, r); +} + +template inline +void v_rshr_pack_u_store(ushort* ptr, const v_int32x4& a) +{ + __m128i delta = _mm_set1_epi32(1 << (n-1)), delta32 = _mm_set1_epi32(32768); + __m128i a1 = _mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(a.val, delta), n), delta32); + __m128i a2 = _mm_sub_epi16(_mm_packs_epi32(a1, a1), _mm_set1_epi16(-32768)); + _mm_storel_epi64((__m128i*)ptr, a2); +} + +inline v_int16x8 v_pack(const v_int32x4& a, const v_int32x4& b) +{ return v_int16x8(_mm_packs_epi32(a.val, b.val)); } + +inline void v_pack_store(short* ptr, const v_int32x4& a) +{ + _mm_storel_epi64((__m128i*)ptr, _mm_packs_epi32(a.val, a.val)); +} + +template inline +v_int16x8 v_rshr_pack(const v_int32x4& a, const v_int32x4& b) +{ + __m128i delta = _mm_set1_epi32(1 << (n-1)); + return v_int16x8(_mm_packs_epi32(_mm_srai_epi32(_mm_add_epi32(a.val, delta), n), + _mm_srai_epi32(_mm_add_epi32(b.val, delta), n))); +} + +template inline +void v_rshr_pack_store(short* ptr, const v_int32x4& a) +{ + __m128i delta = _mm_set1_epi32(1 << (n-1)); + __m128i a1 = _mm_srai_epi32(_mm_add_epi32(a.val, delta), n); + _mm_storel_epi64((__m128i*)ptr, a1); +} + + +// [a0 0 | b0 0] [a1 0 | b1 0] +inline v_uint32x4 v_pack(const v_uint64x2& a, const v_uint64x2& b) +{ + __m128i v0 = _mm_unpacklo_epi32(a.val, b.val); // a0 a1 0 0 + __m128i v1 = _mm_unpackhi_epi32(a.val, b.val); // b0 b1 0 0 + return v_uint32x4(_mm_unpacklo_epi64(v0, v1)); +} + +inline void v_pack_store(unsigned* ptr, const v_uint64x2& a) +{ + __m128i a1 = _mm_shuffle_epi32(a.val, _MM_SHUFFLE(0, 2, 2, 0)); + _mm_storel_epi64((__m128i*)ptr, a1); +} + +// [a0 0 | b0 0] [a1 0 | b1 0] +inline v_int32x4 v_pack(const v_int64x2& a, const v_int64x2& b) +{ + __m128i v0 = _mm_unpacklo_epi32(a.val, b.val); // a0 a1 0 0 + __m128i v1 = _mm_unpackhi_epi32(a.val, b.val); // b0 b1 0 0 + return v_int32x4(_mm_unpacklo_epi64(v0, v1)); +} + +inline void v_pack_store(int* ptr, const v_int64x2& a) +{ + __m128i a1 = _mm_shuffle_epi32(a.val, _MM_SHUFFLE(0, 2, 2, 0)); + _mm_storel_epi64((__m128i*)ptr, a1); +} + +template inline +v_uint32x4 v_rshr_pack(const v_uint64x2& a, const v_uint64x2& b) +{ + uint64 delta = (uint64)1 << (n-1); + v_uint64x2 delta2(delta, delta); + __m128i a1 = _mm_srli_epi64(_mm_add_epi64(a.val, delta2.val), n); + __m128i b1 = _mm_srli_epi64(_mm_add_epi64(b.val, delta2.val), n); + __m128i v0 = _mm_unpacklo_epi32(a1, b1); // a0 a1 0 0 + __m128i v1 = _mm_unpackhi_epi32(a1, b1); // b0 b1 0 0 + return v_uint32x4(_mm_unpacklo_epi64(v0, v1)); +} + +template inline +void v_rshr_pack_store(unsigned* ptr, const v_uint64x2& a) +{ + uint64 delta = (uint64)1 << (n-1); + v_uint64x2 delta2(delta, delta); + __m128i a1 = _mm_srli_epi64(_mm_add_epi64(a.val, delta2.val), n); + __m128i a2 = _mm_shuffle_epi32(a1, _MM_SHUFFLE(0, 2, 2, 0)); + _mm_storel_epi64((__m128i*)ptr, a2); +} + +inline __m128i v_sign_epi64(__m128i a) +{ + return _mm_shuffle_epi32(_mm_srai_epi32(a, 31), _MM_SHUFFLE(3, 3, 1, 1)); // x m0 | x m1 +} + +inline __m128i v_srai_epi64(__m128i a, int imm) +{ + __m128i smask = v_sign_epi64(a); + return _mm_xor_si128(_mm_srli_epi64(_mm_xor_si128(a, smask), imm), smask); +} + +template inline +v_int32x4 v_rshr_pack(const v_int64x2& a, const v_int64x2& b) +{ + int64 delta = (int64)1 << (n-1); + v_int64x2 delta2(delta, delta); + __m128i a1 = v_srai_epi64(_mm_add_epi64(a.val, delta2.val), n); + __m128i b1 = v_srai_epi64(_mm_add_epi64(b.val, delta2.val), n); + __m128i v0 = _mm_unpacklo_epi32(a1, b1); // a0 a1 0 0 + __m128i v1 = _mm_unpackhi_epi32(a1, b1); // b0 b1 0 0 + return v_int32x4(_mm_unpacklo_epi64(v0, v1)); +} + +template inline +void v_rshr_pack_store(int* ptr, const v_int64x2& a) +{ + int64 delta = (int64)1 << (n-1); + v_int64x2 delta2(delta, delta); + __m128i a1 = v_srai_epi64(_mm_add_epi64(a.val, delta2.val), n); + __m128i a2 = _mm_shuffle_epi32(a1, _MM_SHUFFLE(0, 2, 2, 0)); + _mm_storel_epi64((__m128i*)ptr, a2); +} + +inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, + const v_float32x4& m1, const v_float32x4& m2, + const v_float32x4& m3) +{ + __m128 v0 = _mm_mul_ps(_mm_shuffle_ps(v.val, v.val, _MM_SHUFFLE(0, 0, 0, 0)), m0.val); + __m128 v1 = _mm_mul_ps(_mm_shuffle_ps(v.val, v.val, _MM_SHUFFLE(1, 1, 1, 1)), m1.val); + __m128 v2 = _mm_mul_ps(_mm_shuffle_ps(v.val, v.val, _MM_SHUFFLE(2, 2, 2, 2)), m2.val); + __m128 v3 = _mm_mul_ps(_mm_shuffle_ps(v.val, v.val, _MM_SHUFFLE(3, 3, 3, 3)), m3.val); + + return v_float32x4(_mm_add_ps(_mm_add_ps(v0, v1), _mm_add_ps(v2, v3))); +} + + +#define OPENCV_HAL_IMPL_SSE_BIN_OP(bin_op, _Tpvec, intrin) \ + inline _Tpvec operator bin_op (const _Tpvec& a, const _Tpvec& b) \ + { \ + return _Tpvec(intrin(a.val, b.val)); \ + } \ + inline _Tpvec& operator bin_op##= (_Tpvec& a, const _Tpvec& b) \ + { \ + a.val = intrin(a.val, b.val); \ + return a; \ + } + +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_uint8x16, _mm_adds_epu8) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_uint8x16, _mm_subs_epu8) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_int8x16, _mm_adds_epi8) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_int8x16, _mm_subs_epi8) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_uint16x8, _mm_adds_epu16) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_uint16x8, _mm_subs_epu16) +OPENCV_HAL_IMPL_SSE_BIN_OP(*, v_uint16x8, _mm_mullo_epi16) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_int16x8, _mm_adds_epi16) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_int16x8, _mm_subs_epi16) +OPENCV_HAL_IMPL_SSE_BIN_OP(*, v_int16x8, _mm_mullo_epi16) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_uint32x4, _mm_add_epi32) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_uint32x4, _mm_sub_epi32) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_int32x4, _mm_add_epi32) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_int32x4, _mm_sub_epi32) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_float32x4, _mm_add_ps) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_float32x4, _mm_sub_ps) +OPENCV_HAL_IMPL_SSE_BIN_OP(*, v_float32x4, _mm_mul_ps) +OPENCV_HAL_IMPL_SSE_BIN_OP(/, v_float32x4, _mm_div_ps) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_float64x2, _mm_add_pd) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_float64x2, _mm_sub_pd) +OPENCV_HAL_IMPL_SSE_BIN_OP(*, v_float64x2, _mm_mul_pd) +OPENCV_HAL_IMPL_SSE_BIN_OP(/, v_float64x2, _mm_div_pd) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_uint64x2, _mm_add_epi64) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_uint64x2, _mm_sub_epi64) +OPENCV_HAL_IMPL_SSE_BIN_OP(+, v_int64x2, _mm_add_epi64) +OPENCV_HAL_IMPL_SSE_BIN_OP(-, v_int64x2, _mm_sub_epi64) + +inline v_uint32x4 operator * (const v_uint32x4& a, const v_uint32x4& b) +{ + __m128i c0 = _mm_mul_epu32(a.val, b.val); + __m128i c1 = _mm_mul_epu32(_mm_srli_epi64(a.val, 32), _mm_srli_epi64(b.val, 32)); + __m128i d0 = _mm_unpacklo_epi32(c0, c1); + __m128i d1 = _mm_unpackhi_epi32(c0, c1); + return v_uint32x4(_mm_unpacklo_epi64(d0, d1)); +} +inline v_int32x4 operator * (const v_int32x4& a, const v_int32x4& b) +{ + __m128i c0 = _mm_mul_epu32(a.val, b.val); + __m128i c1 = _mm_mul_epu32(_mm_srli_epi64(a.val, 32), _mm_srli_epi64(b.val, 32)); + __m128i d0 = _mm_unpacklo_epi32(c0, c1); + __m128i d1 = _mm_unpackhi_epi32(c0, c1); + return v_int32x4(_mm_unpacklo_epi64(d0, d1)); +} +inline v_uint32x4& operator *= (v_uint32x4& a, const v_uint32x4& b) +{ + a = a * b; + return a; +} +inline v_int32x4& operator *= (v_int32x4& a, const v_int32x4& b) +{ + a = a * b; + return a; +} + +inline void v_mul_expand(const v_int16x8& a, const v_int16x8& b, + v_int32x4& c, v_int32x4& d) +{ + __m128i v0 = _mm_mullo_epi16(a.val, b.val); + __m128i v1 = _mm_mulhi_epi16(a.val, b.val); + c.val = _mm_unpacklo_epi32(v0, v1); + d.val = _mm_unpackhi_epi32(v0, v1); +} + +inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b, + v_uint32x4& c, v_uint32x4& d) +{ + __m128i v0 = _mm_mullo_epi16(a.val, b.val); + __m128i v1 = _mm_mulhi_epu16(a.val, b.val); + c.val = _mm_unpacklo_epi32(v0, v1); + d.val = _mm_unpackhi_epi32(v0, v1); +} + +inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b, + v_uint64x2& c, v_uint64x2& d) +{ + __m128i c0 = _mm_mul_epu32(a.val, b.val); + __m128i c1 = _mm_mul_epu32(_mm_srli_epi64(a.val, 32), _mm_srli_epi64(b.val, 32)); + c.val = _mm_unpacklo_epi64(c0, c1); + d.val = _mm_unpackhi_epi64(c0, c1); +} + +inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b) +{ + return v_int32x4(_mm_madd_epi16(a.val, b.val)); +} + +#define OPENCV_HAL_IMPL_SSE_LOGIC_OP(_Tpvec, suffix, not_const) \ + OPENCV_HAL_IMPL_SSE_BIN_OP(&, _Tpvec, _mm_and_##suffix) \ + OPENCV_HAL_IMPL_SSE_BIN_OP(|, _Tpvec, _mm_or_##suffix) \ + OPENCV_HAL_IMPL_SSE_BIN_OP(^, _Tpvec, _mm_xor_##suffix) \ + inline _Tpvec operator ~ (const _Tpvec& a) \ + { \ + return _Tpvec(_mm_xor_##suffix(a.val, not_const)); \ + } + +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_uint8x16, si128, _mm_set1_epi32(-1)) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_int8x16, si128, _mm_set1_epi32(-1)) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_uint16x8, si128, _mm_set1_epi32(-1)) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_int16x8, si128, _mm_set1_epi32(-1)) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_uint32x4, si128, _mm_set1_epi32(-1)) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_int32x4, si128, _mm_set1_epi32(-1)) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_uint64x2, si128, _mm_set1_epi32(-1)) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_int64x2, si128, _mm_set1_epi32(-1)) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_float32x4, ps, _mm_castsi128_ps(_mm_set1_epi32(-1))) +OPENCV_HAL_IMPL_SSE_LOGIC_OP(v_float64x2, pd, _mm_castsi128_pd(_mm_set1_epi32(-1))) + +inline v_float32x4 v_sqrt(const v_float32x4& x) +{ return v_float32x4(_mm_sqrt_ps(x.val)); } + +inline v_float32x4 v_invsqrt(const v_float32x4& x) +{ + static const __m128 _0_5 = _mm_set1_ps(0.5f), _1_5 = _mm_set1_ps(1.5f); + __m128 t = x.val; + __m128 h = _mm_mul_ps(t, _0_5); + t = _mm_rsqrt_ps(t); + t = _mm_mul_ps(t, _mm_sub_ps(_1_5, _mm_mul_ps(_mm_mul_ps(t, t), h))); + return v_float32x4(t); +} + +inline v_float64x2 v_sqrt(const v_float64x2& x) +{ return v_float64x2(_mm_sqrt_pd(x.val)); } + +inline v_float64x2 v_invsqrt(const v_float64x2& x) +{ + static const __m128d v_1 = _mm_set1_pd(1.); + return v_float64x2(_mm_div_pd(v_1, _mm_sqrt_pd(x.val))); +} + +inline v_float32x4 v_abs(const v_float32x4& x) +{ return v_float32x4(_mm_and_ps(x.val, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)))); } +inline v_float64x2 v_abs(const v_float64x2& x) +{ + return v_float64x2(_mm_and_pd(x.val, + _mm_castsi128_pd(_mm_srli_epi64(_mm_set1_epi32(-1), 1)))); +} + +// TODO: exp, log, sin, cos + +#define OPENCV_HAL_IMPL_SSE_BIN_FUNC(_Tpvec, func, intrin) \ +inline _Tpvec func(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return _Tpvec(intrin(a.val, b.val)); \ +} + +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_uint8x16, v_min, _mm_min_epu8) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_uint8x16, v_max, _mm_max_epu8) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_int16x8, v_min, _mm_min_epi16) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_int16x8, v_max, _mm_max_epi16) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_float32x4, v_min, _mm_min_ps) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_float32x4, v_max, _mm_max_ps) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_float64x2, v_min, _mm_min_pd) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_float64x2, v_max, _mm_max_pd) + +inline v_int8x16 v_min(const v_int8x16& a, const v_int8x16& b) +{ + __m128i delta = _mm_set1_epi8((char)-128); + return v_int8x16(_mm_xor_si128(delta, _mm_min_epu8(_mm_xor_si128(a.val, delta), + _mm_xor_si128(b.val, delta)))); +} +inline v_int8x16 v_max(const v_int8x16& a, const v_int8x16& b) +{ + __m128i delta = _mm_set1_epi8((char)-128); + return v_int8x16(_mm_xor_si128(delta, _mm_max_epu8(_mm_xor_si128(a.val, delta), + _mm_xor_si128(b.val, delta)))); +} +inline v_uint16x8 v_min(const v_uint16x8& a, const v_uint16x8& b) +{ + return v_uint16x8(_mm_subs_epu16(a.val, _mm_subs_epu16(a.val, b.val))); +} +inline v_uint16x8 v_max(const v_uint16x8& a, const v_uint16x8& b) +{ + return v_uint16x8(_mm_adds_epu16(_mm_subs_epu16(a.val, b.val), b.val)); +} +inline v_uint32x4 v_min(const v_uint32x4& a, const v_uint32x4& b) +{ + __m128i delta = _mm_set1_epi32((int)0x80000000); + __m128i mask = _mm_cmpgt_epi32(_mm_xor_si128(a.val, delta), _mm_xor_si128(b.val, delta)); + return v_uint32x4(v_select_si128(mask, b.val, a.val)); +} +inline v_uint32x4 v_max(const v_uint32x4& a, const v_uint32x4& b) +{ + __m128i delta = _mm_set1_epi32((int)0x80000000); + __m128i mask = _mm_cmpgt_epi32(_mm_xor_si128(a.val, delta), _mm_xor_si128(b.val, delta)); + return v_uint32x4(v_select_si128(mask, a.val, b.val)); +} +inline v_int32x4 v_min(const v_int32x4& a, const v_int32x4& b) +{ + return v_int32x4(v_select_si128(_mm_cmpgt_epi32(a.val, b.val), b.val, a.val)); +} +inline v_int32x4 v_max(const v_int32x4& a, const v_int32x4& b) +{ + return v_int32x4(v_select_si128(_mm_cmpgt_epi32(a.val, b.val), a.val, b.val)); +} + +#define OPENCV_HAL_IMPL_SSE_INT_CMP_OP(_Tpuvec, _Tpsvec, suffix, sbit) \ +inline _Tpuvec operator == (const _Tpuvec& a, const _Tpuvec& b) \ +{ return _Tpuvec(_mm_cmpeq_##suffix(a.val, b.val)); } \ +inline _Tpuvec operator != (const _Tpuvec& a, const _Tpuvec& b) \ +{ \ + __m128i not_mask = _mm_set1_epi32(-1); \ + return _Tpuvec(_mm_xor_si128(_mm_cmpeq_##suffix(a.val, b.val), not_mask)); \ +} \ +inline _Tpsvec operator == (const _Tpsvec& a, const _Tpsvec& b) \ +{ return _Tpsvec(_mm_cmpeq_##suffix(a.val, b.val)); } \ +inline _Tpsvec operator != (const _Tpsvec& a, const _Tpsvec& b) \ +{ \ + __m128i not_mask = _mm_set1_epi32(-1); \ + return _Tpsvec(_mm_xor_si128(_mm_cmpeq_##suffix(a.val, b.val), not_mask)); \ +} \ +inline _Tpuvec operator < (const _Tpuvec& a, const _Tpuvec& b) \ +{ \ + __m128i smask = _mm_set1_##suffix(sbit); \ + return _Tpuvec(_mm_cmpgt_##suffix(_mm_xor_si128(b.val, smask), _mm_xor_si128(a.val, smask))); \ +} \ +inline _Tpuvec operator > (const _Tpuvec& a, const _Tpuvec& b) \ +{ \ + __m128i smask = _mm_set1_##suffix(sbit); \ + return _Tpuvec(_mm_cmpgt_##suffix(_mm_xor_si128(a.val, smask), _mm_xor_si128(b.val, smask))); \ +} \ +inline _Tpuvec operator <= (const _Tpuvec& a, const _Tpuvec& b) \ +{ \ + __m128i smask = _mm_set1_##suffix(sbit); \ + __m128i not_mask = _mm_set1_epi32(-1); \ + __m128i res = _mm_cmpgt_##suffix(_mm_xor_si128(a.val, smask), _mm_xor_si128(b.val, smask)); \ + return _Tpuvec(_mm_xor_si128(res, not_mask)); \ +} \ +inline _Tpuvec operator >= (const _Tpuvec& a, const _Tpuvec& b) \ +{ \ + __m128i smask = _mm_set1_##suffix(sbit); \ + __m128i not_mask = _mm_set1_epi32(-1); \ + __m128i res = _mm_cmpgt_##suffix(_mm_xor_si128(b.val, smask), _mm_xor_si128(a.val, smask)); \ + return _Tpuvec(_mm_xor_si128(res, not_mask)); \ +} \ +inline _Tpsvec operator < (const _Tpsvec& a, const _Tpsvec& b) \ +{ \ + return _Tpsvec(_mm_cmpgt_##suffix(b.val, a.val)); \ +} \ +inline _Tpsvec operator > (const _Tpsvec& a, const _Tpsvec& b) \ +{ \ + return _Tpsvec(_mm_cmpgt_##suffix(a.val, b.val)); \ +} \ +inline _Tpsvec operator <= (const _Tpsvec& a, const _Tpsvec& b) \ +{ \ + __m128i not_mask = _mm_set1_epi32(-1); \ + return _Tpsvec(_mm_xor_si128(_mm_cmpgt_##suffix(a.val, b.val), not_mask)); \ +} \ +inline _Tpsvec operator >= (const _Tpsvec& a, const _Tpsvec& b) \ +{ \ + __m128i not_mask = _mm_set1_epi32(-1); \ + return _Tpsvec(_mm_xor_si128(_mm_cmpgt_##suffix(b.val, a.val), not_mask)); \ +} + +OPENCV_HAL_IMPL_SSE_INT_CMP_OP(v_uint8x16, v_int8x16, epi8, (char)-128) +OPENCV_HAL_IMPL_SSE_INT_CMP_OP(v_uint16x8, v_int16x8, epi16, (short)-32768) +OPENCV_HAL_IMPL_SSE_INT_CMP_OP(v_uint32x4, v_int32x4, epi32, (int)0x80000000) + +#define OPENCV_HAL_IMPL_SSE_FLT_CMP_OP(_Tpvec, suffix) \ +inline _Tpvec operator == (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(_mm_cmpeq_##suffix(a.val, b.val)); } \ +inline _Tpvec operator != (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(_mm_cmpneq_##suffix(a.val, b.val)); } \ +inline _Tpvec operator < (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(_mm_cmplt_##suffix(a.val, b.val)); } \ +inline _Tpvec operator > (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(_mm_cmpgt_##suffix(a.val, b.val)); } \ +inline _Tpvec operator <= (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(_mm_cmple_##suffix(a.val, b.val)); } \ +inline _Tpvec operator >= (const _Tpvec& a, const _Tpvec& b) \ +{ return _Tpvec(_mm_cmpge_##suffix(a.val, b.val)); } + +OPENCV_HAL_IMPL_SSE_FLT_CMP_OP(v_float32x4, ps) +OPENCV_HAL_IMPL_SSE_FLT_CMP_OP(v_float64x2, pd) + +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_uint8x16, v_add_wrap, _mm_add_epi8) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_int8x16, v_add_wrap, _mm_add_epi8) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_uint16x8, v_add_wrap, _mm_add_epi16) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_int16x8, v_add_wrap, _mm_add_epi16) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_uint8x16, v_sub_wrap, _mm_sub_epi8) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_int8x16, v_sub_wrap, _mm_sub_epi8) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_uint16x8, v_sub_wrap, _mm_sub_epi16) +OPENCV_HAL_IMPL_SSE_BIN_FUNC(v_int16x8, v_sub_wrap, _mm_sub_epi16) + +#define OPENCV_HAL_IMPL_SSE_ABSDIFF_8_16(_Tpuvec, _Tpsvec, bits, smask32) \ +inline _Tpuvec v_absdiff(const _Tpuvec& a, const _Tpuvec& b) \ +{ \ + return _Tpuvec(_mm_add_epi##bits(_mm_subs_epu##bits(a.val, b.val), _mm_subs_epu##bits(b.val, a.val))); \ +} \ +inline _Tpuvec v_absdiff(const _Tpsvec& a, const _Tpsvec& b) \ +{ \ + __m128i smask = _mm_set1_epi32(smask32); \ + __m128i a1 = _mm_xor_si128(a.val, smask); \ + __m128i b1 = _mm_xor_si128(b.val, smask); \ + return _Tpuvec(_mm_add_epi##bits(_mm_subs_epu##bits(a1, b1), _mm_subs_epu##bits(b1, a1))); \ +} + +OPENCV_HAL_IMPL_SSE_ABSDIFF_8_16(v_uint8x16, v_int8x16, 8, (int)0x80808080) +OPENCV_HAL_IMPL_SSE_ABSDIFF_8_16(v_uint16x8, v_int16x8, 16, (int)0x80008000) + +#define OPENCV_HAL_IMPL_SSE_MISC_FLT_OP(_Tpvec, _Tp, _Tpreg, suffix, absmask_vec) \ +inline _Tpvec v_absdiff(const _Tpvec& a, const _Tpvec& b) \ +{ \ + _Tpreg absmask = _mm_castsi128_##suffix(absmask_vec); \ + return _Tpvec(_mm_and_##suffix(_mm_sub_##suffix(a.val, b.val), absmask)); \ +} \ +inline _Tpvec v_magnitude(const _Tpvec& a, const _Tpvec& b) \ +{ \ + _Tpreg res = _mm_add_##suffix(_mm_mul_##suffix(a.val, a.val), _mm_mul_##suffix(b.val, b.val)); \ + return _Tpvec(_mm_sqrt_##suffix(res)); \ +} \ +inline _Tpvec v_sqr_magnitude(const _Tpvec& a, const _Tpvec& b) \ +{ \ + _Tpreg res = _mm_add_##suffix(_mm_mul_##suffix(a.val, a.val), _mm_mul_##suffix(b.val, b.val)); \ + return _Tpvec(res); \ +} \ +inline _Tpvec v_muladd(const _Tpvec& a, const _Tpvec& b, const _Tpvec& c) \ +{ \ + return _Tpvec(_mm_add_##suffix(_mm_mul_##suffix(a.val, b.val), c.val)); \ +} + +OPENCV_HAL_IMPL_SSE_MISC_FLT_OP(v_float32x4, float, __m128, ps, _mm_set1_epi32((int)0x7fffffff)) +OPENCV_HAL_IMPL_SSE_MISC_FLT_OP(v_float64x2, double, __m128d, pd, _mm_srli_epi64(_mm_set1_epi32(-1), 1)) + +#define OPENCV_HAL_IMPL_SSE_SHIFT_OP(_Tpuvec, _Tpsvec, suffix, srai) \ +inline _Tpuvec operator << (const _Tpuvec& a, int imm) \ +{ \ + return _Tpuvec(_mm_slli_##suffix(a.val, imm)); \ +} \ +inline _Tpsvec operator << (const _Tpsvec& a, int imm) \ +{ \ + return _Tpsvec(_mm_slli_##suffix(a.val, imm)); \ +} \ +inline _Tpuvec operator >> (const _Tpuvec& a, int imm) \ +{ \ + return _Tpuvec(_mm_srli_##suffix(a.val, imm)); \ +} \ +inline _Tpsvec operator >> (const _Tpsvec& a, int imm) \ +{ \ + return _Tpsvec(srai(a.val, imm)); \ +} \ +template \ +inline _Tpuvec v_shl(const _Tpuvec& a) \ +{ \ + return _Tpuvec(_mm_slli_##suffix(a.val, imm)); \ +} \ +template \ +inline _Tpsvec v_shl(const _Tpsvec& a) \ +{ \ + return _Tpsvec(_mm_slli_##suffix(a.val, imm)); \ +} \ +template \ +inline _Tpuvec v_shr(const _Tpuvec& a) \ +{ \ + return _Tpuvec(_mm_srli_##suffix(a.val, imm)); \ +} \ +template \ +inline _Tpsvec v_shr(const _Tpsvec& a) \ +{ \ + return _Tpsvec(srai(a.val, imm)); \ +} + +OPENCV_HAL_IMPL_SSE_SHIFT_OP(v_uint16x8, v_int16x8, epi16, _mm_srai_epi16) +OPENCV_HAL_IMPL_SSE_SHIFT_OP(v_uint32x4, v_int32x4, epi32, _mm_srai_epi32) +OPENCV_HAL_IMPL_SSE_SHIFT_OP(v_uint64x2, v_int64x2, epi64, v_srai_epi64) + +#define OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(_Tpvec, _Tp) \ +inline _Tpvec v_load(const _Tp* ptr) \ +{ return _Tpvec(_mm_loadu_si128((const __m128i*)ptr)); } \ +inline _Tpvec v_load_aligned(const _Tp* ptr) \ +{ return _Tpvec(_mm_load_si128((const __m128i*)ptr)); } \ +inline _Tpvec v_load_halves(const _Tp* ptr0, const _Tp* ptr1) \ +{ \ + return _Tpvec(_mm_unpacklo_epi64(_mm_loadl_epi64((const __m128i*)ptr0), \ + _mm_loadl_epi64((const __m128i*)ptr1))); \ +} \ +inline void v_store(_Tp* ptr, const _Tpvec& a) \ +{ _mm_storeu_si128((__m128i*)ptr, a.val); } \ +inline void v_store_aligned(_Tp* ptr, const _Tpvec& a) \ +{ _mm_store_si128((__m128i*)ptr, a.val); } \ +inline void v_store_low(_Tp* ptr, const _Tpvec& a) \ +{ _mm_storel_epi64((__m128i*)ptr, a.val); } \ +inline void v_store_high(_Tp* ptr, const _Tpvec& a) \ +{ _mm_storel_epi64((__m128i*)ptr, _mm_unpackhi_epi64(a.val, a.val)); } + +OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(v_uint8x16, uchar) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(v_int8x16, schar) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(v_uint16x8, ushort) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(v_int16x8, short) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(v_uint32x4, unsigned) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(v_int32x4, int) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(v_uint64x2, uint64) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INT_OP(v_int64x2, int64) + +#define OPENCV_HAL_IMPL_SSE_LOADSTORE_FLT_OP(_Tpvec, _Tp, suffix) \ +inline _Tpvec v_load(const _Tp* ptr) \ +{ return _Tpvec(_mm_loadu_##suffix(ptr)); } \ +inline _Tpvec v_load_aligned(const _Tp* ptr) \ +{ return _Tpvec(_mm_load_##suffix(ptr)); } \ +inline _Tpvec v_load_halves(const _Tp* ptr0, const _Tp* ptr1) \ +{ \ + return _Tpvec(_mm_castsi128_##suffix( \ + _mm_unpacklo_epi64(_mm_loadl_epi64((const __m128i*)ptr0), \ + _mm_loadl_epi64((const __m128i*)ptr1)))); \ +} \ +inline void v_store(_Tp* ptr, const _Tpvec& a) \ +{ _mm_storeu_##suffix(ptr, a.val); } \ +inline void v_store_aligned(_Tp* ptr, const _Tpvec& a) \ +{ _mm_store_##suffix(ptr, a.val); } \ +inline void v_store_low(_Tp* ptr, const _Tpvec& a) \ +{ _mm_storel_epi64((__m128i*)ptr, _mm_cast##suffix##_si128(a.val)); } \ +inline void v_store_high(_Tp* ptr, const _Tpvec& a) \ +{ \ + __m128i a1 = _mm_cast##suffix##_si128(a.val); \ + _mm_storel_epi64((__m128i*)ptr, _mm_unpackhi_epi64(a1, a1)); \ +} + +OPENCV_HAL_IMPL_SSE_LOADSTORE_FLT_OP(v_float32x4, float, ps) +OPENCV_HAL_IMPL_SSE_LOADSTORE_FLT_OP(v_float64x2, double, pd) + +#define OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(_Tpvec, scalartype, func, scalar_func) \ +inline scalartype v_reduce_##func(const _Tpvec& a) \ +{ \ + scalartype CV_DECL_ALIGNED(16) buf[4]; \ + v_store_aligned(buf, a); \ + scalartype s0 = scalar_func(buf[0], buf[1]); \ + scalartype s1 = scalar_func(buf[2], buf[3]); \ + return scalar_func(s0, s1); \ +} + +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_uint32x4, unsigned, sum, OPENCV_HAL_ADD) +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_uint32x4, unsigned, max, std::max) +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_uint32x4, unsigned, min, std::min) +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_int32x4, int, sum, OPENCV_HAL_ADD) +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_int32x4, int, max, std::max) +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_int32x4, int, min, std::min) +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_float32x4, float, sum, OPENCV_HAL_ADD) +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_float32x4, float, max, std::max) +OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_float32x4, float, min, std::min) + +#define OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(_Tpvec, suffix, pack_op, and_op, signmask, allmask) \ +inline int v_signmask(const _Tpvec& a) \ +{ \ + return and_op(_mm_movemask_##suffix(pack_op(a.val)), signmask); \ +} \ +inline bool v_check_all(const _Tpvec& a) \ +{ return and_op(_mm_movemask_##suffix(a.val), allmask) == allmask; } \ +inline bool v_check_any(const _Tpvec& a) \ +{ return and_op(_mm_movemask_##suffix(a.val), allmask) != 0; } + +#define OPENCV_HAL_PACKS(a) _mm_packs_epi16(a, a) +inline __m128i v_packq_epi32(__m128i a) +{ + __m128i b = _mm_packs_epi32(a, a); + return _mm_packs_epi16(b, b); +} + +OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint8x16, epi8, OPENCV_HAL_NOP, OPENCV_HAL_1ST, 65535, 65535) +OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int8x16, epi8, OPENCV_HAL_NOP, OPENCV_HAL_1ST, 65535, 65535) +OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint16x8, epi8, OPENCV_HAL_PACKS, OPENCV_HAL_AND, 255, (int)0xaaaa) +OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int16x8, epi8, OPENCV_HAL_PACKS, OPENCV_HAL_AND, 255, (int)0xaaaa) +OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_uint32x4, epi8, v_packq_epi32, OPENCV_HAL_AND, 15, (int)0x8888) +OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_int32x4, epi8, v_packq_epi32, OPENCV_HAL_AND, 15, (int)0x8888) +OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_float32x4, ps, OPENCV_HAL_NOP, OPENCV_HAL_1ST, 15, 15) +OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(v_float64x2, pd, OPENCV_HAL_NOP, OPENCV_HAL_1ST, 3, 3) + +#define OPENCV_HAL_IMPL_SSE_SELECT(_Tpvec, suffix) \ +inline _Tpvec v_select(const _Tpvec& mask, const _Tpvec& a, const _Tpvec& b) \ +{ \ + return _Tpvec(_mm_xor_##suffix(b.val, _mm_and_##suffix(_mm_xor_##suffix(b.val, a.val), mask.val))); \ +} + +OPENCV_HAL_IMPL_SSE_SELECT(v_uint8x16, si128) +OPENCV_HAL_IMPL_SSE_SELECT(v_int8x16, si128) +OPENCV_HAL_IMPL_SSE_SELECT(v_uint16x8, si128) +OPENCV_HAL_IMPL_SSE_SELECT(v_int16x8, si128) +OPENCV_HAL_IMPL_SSE_SELECT(v_uint32x4, si128) +OPENCV_HAL_IMPL_SSE_SELECT(v_int32x4, si128) +OPENCV_HAL_IMPL_SSE_SELECT(v_uint64x2, si128) +OPENCV_HAL_IMPL_SSE_SELECT(v_int64x2, si128) +OPENCV_HAL_IMPL_SSE_SELECT(v_float32x4, ps) +OPENCV_HAL_IMPL_SSE_SELECT(v_float64x2, pd) + +#define OPENCV_HAL_IMPL_SSE_EXPAND(_Tpuvec, _Tpwuvec, _Tpu, _Tpsvec, _Tpwsvec, _Tps, suffix, wsuffix, shift) \ +inline void v_expand(const _Tpuvec& a, _Tpwuvec& b0, _Tpwuvec& b1) \ +{ \ + __m128i z = _mm_setzero_si128(); \ + b0.val = _mm_unpacklo_##suffix(a.val, z); \ + b1.val = _mm_unpackhi_##suffix(a.val, z); \ +} \ +inline _Tpwuvec v_load_expand(const _Tpu* ptr) \ +{ \ + __m128i z = _mm_setzero_si128(); \ + return _Tpwuvec(_mm_unpacklo_##suffix(_mm_loadl_epi64((const __m128i*)ptr), z)); \ +} \ +inline void v_expand(const _Tpsvec& a, _Tpwsvec& b0, _Tpwsvec& b1) \ +{ \ + b0.val = _mm_srai_##wsuffix(_mm_unpacklo_##suffix(a.val, a.val), shift); \ + b1.val = _mm_srai_##wsuffix(_mm_unpackhi_##suffix(a.val, a.val), shift); \ +} \ +inline _Tpwsvec v_load_expand(const _Tps* ptr) \ +{ \ + __m128i a = _mm_loadl_epi64((const __m128i*)ptr); \ + return _Tpwsvec(_mm_srai_##wsuffix(_mm_unpacklo_##suffix(a, a), shift)); \ +} + +OPENCV_HAL_IMPL_SSE_EXPAND(v_uint8x16, v_uint16x8, uchar, v_int8x16, v_int16x8, schar, epi8, epi16, 8) +OPENCV_HAL_IMPL_SSE_EXPAND(v_uint16x8, v_uint32x4, ushort, v_int16x8, v_int32x4, short, epi16, epi32, 16) + +inline void v_expand(const v_uint32x4& a, v_uint64x2& b0, v_uint64x2& b1) +{ + __m128i z = _mm_setzero_si128(); + b0.val = _mm_unpacklo_epi32(a.val, z); + b1.val = _mm_unpackhi_epi32(a.val, z); +} +inline v_uint64x2 v_load_expand(const unsigned* ptr) +{ + __m128i z = _mm_setzero_si128(); + return v_uint64x2(_mm_unpacklo_epi32(_mm_loadl_epi64((const __m128i*)ptr), z)); +} +inline void v_expand(const v_int32x4& a, v_int64x2& b0, v_int64x2& b1) +{ + __m128i s = _mm_srai_epi32(a.val, 31); + b0.val = _mm_unpacklo_epi32(a.val, s); + b1.val = _mm_unpackhi_epi32(a.val, s); +} +inline v_int64x2 v_load_expand(const int* ptr) +{ + __m128i a = _mm_loadl_epi64((const __m128i*)ptr); + __m128i s = _mm_srai_epi32(a, 31); + return v_int64x2(_mm_unpacklo_epi32(a, s)); +} + +inline v_uint32x4 v_load_expand_q(const uchar* ptr) +{ + __m128i z = _mm_setzero_si128(); + __m128i a = _mm_cvtsi32_si128(*(const int*)ptr); + return v_uint32x4(_mm_unpacklo_epi16(_mm_unpacklo_epi8(a, z), z)); +} + +inline v_int32x4 v_load_expand_q(const schar* ptr) +{ + __m128i a = _mm_cvtsi32_si128(*(const int*)ptr); + a = _mm_unpacklo_epi8(a, a); + a = _mm_unpacklo_epi8(a, a); + return v_int32x4(_mm_srai_epi32(a, 24)); +} + +#define OPENCV_HAL_IMPL_SSE_UNPACKS(_Tpvec, suffix, cast_from, cast_to) \ +inline void v_zip(const _Tpvec& a0, const _Tpvec& a1, _Tpvec& b0, _Tpvec& b1) \ +{ \ + b0.val = _mm_unpacklo_##suffix(a0.val, a1.val); \ + b1.val = _mm_unpackhi_##suffix(a0.val, a1.val); \ +} \ +inline _Tpvec v_combine_low(const _Tpvec& a, const _Tpvec& b) \ +{ \ + __m128i a1 = cast_from(a.val), b1 = cast_from(b.val); \ + return _Tpvec(cast_to(_mm_unpacklo_epi64(a1, b1))); \ +} \ +inline _Tpvec v_combine_high(const _Tpvec& a, const _Tpvec& b) \ +{ \ + __m128i a1 = cast_from(a.val), b1 = cast_from(b.val); \ + return _Tpvec(cast_to(_mm_unpackhi_epi64(a1, b1))); \ +} \ +inline void v_recombine(const _Tpvec& a, const _Tpvec& b, _Tpvec& c, _Tpvec& d) \ +{ \ + __m128i a1 = cast_from(a.val), b1 = cast_from(b.val); \ + c.val = cast_to(_mm_unpacklo_epi64(a1, b1)); \ + d.val = cast_to(_mm_unpackhi_epi64(a1, b1)); \ +} + +OPENCV_HAL_IMPL_SSE_UNPACKS(v_uint8x16, epi8, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_UNPACKS(v_int8x16, epi8, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_UNPACKS(v_uint16x8, epi16, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_UNPACKS(v_int16x8, epi16, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_UNPACKS(v_uint32x4, epi32, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_UNPACKS(v_int32x4, epi32, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_UNPACKS(v_float32x4, ps, _mm_castps_si128, _mm_castsi128_ps) +OPENCV_HAL_IMPL_SSE_UNPACKS(v_float64x2, pd, _mm_castpd_si128, _mm_castsi128_pd) + +inline v_int32x4 v_round(const v_float32x4& a) +{ return v_int32x4(_mm_cvtps_epi32(a.val)); } + +inline v_int32x4 v_floor(const v_float32x4& a) +{ + __m128i a1 = _mm_cvtps_epi32(a.val); + __m128i mask = _mm_castps_si128(_mm_cmpgt_ps(_mm_cvtepi32_ps(a1), a.val)); + return v_int32x4(_mm_add_epi32(a1, mask)); +} + +inline v_int32x4 v_ceil(const v_float32x4& a) +{ + __m128i a1 = _mm_cvtps_epi32(a.val); + __m128i mask = _mm_castps_si128(_mm_cmpgt_ps(a.val, _mm_cvtepi32_ps(a1))); + return v_int32x4(_mm_sub_epi32(a1, mask)); +} + +inline v_int32x4 v_trunc(const v_float32x4& a) +{ return v_int32x4(_mm_cvttps_epi32(a.val)); } + +inline v_int32x4 v_round(const v_float64x2& a) +{ return v_int32x4(_mm_cvtpd_epi32(a.val)); } + +inline v_int32x4 v_floor(const v_float64x2& a) +{ + __m128i a1 = _mm_cvtpd_epi32(a.val); + __m128i mask = _mm_castpd_si128(_mm_cmpgt_pd(_mm_cvtepi32_pd(a1), a.val)); + mask = _mm_srli_si128(_mm_slli_si128(mask, 4), 8); // m0 m0 m1 m1 => m0 m1 0 0 + return v_int32x4(_mm_add_epi32(a1, mask)); +} + +inline v_int32x4 v_ceil(const v_float64x2& a) +{ + __m128i a1 = _mm_cvtpd_epi32(a.val); + __m128i mask = _mm_castpd_si128(_mm_cmpgt_pd(a.val, _mm_cvtepi32_pd(a1))); + mask = _mm_srli_si128(_mm_slli_si128(mask, 4), 8); // m0 m0 m1 m1 => m0 m1 0 0 + return v_int32x4(_mm_sub_epi32(a1, mask)); +} + +inline v_int32x4 v_trunc(const v_float64x2& a) +{ return v_int32x4(_mm_cvttpd_epi32(a.val)); } + +#define OPENCV_HAL_IMPL_SSE_TRANSPOSE4x4(_Tpvec, suffix, cast_from, cast_to) \ +inline void v_transpose4x4(const _Tpvec& a0, const _Tpvec& a1, \ + const _Tpvec& a2, const _Tpvec& a3, \ + _Tpvec& b0, _Tpvec& b1, \ + _Tpvec& b2, _Tpvec& b3) \ +{ \ + __m128i t0 = cast_from(_mm_unpacklo_##suffix(a0.val, a1.val)); \ + __m128i t1 = cast_from(_mm_unpacklo_##suffix(a2.val, a3.val)); \ + __m128i t2 = cast_from(_mm_unpackhi_##suffix(a0.val, a1.val)); \ + __m128i t3 = cast_from(_mm_unpackhi_##suffix(a2.val, a3.val)); \ +\ + b0.val = cast_to(_mm_unpacklo_epi64(t0, t1)); \ + b1.val = cast_to(_mm_unpackhi_epi64(t0, t1)); \ + b2.val = cast_to(_mm_unpacklo_epi64(t2, t3)); \ + b3.val = cast_to(_mm_unpackhi_epi64(t2, t3)); \ +} + +OPENCV_HAL_IMPL_SSE_TRANSPOSE4x4(v_uint32x4, epi32, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_TRANSPOSE4x4(v_int32x4, epi32, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_SSE_TRANSPOSE4x4(v_float32x4, ps, _mm_castps_si128, _mm_castsi128_ps) + +// adopted from sse_utils.hpp +inline void v_load_deinterleave(const uchar* ptr, v_uint8x16& a, v_uint8x16& b, v_uint8x16& c) +{ + __m128i t00 = _mm_loadu_si128((const __m128i*)ptr); + __m128i t01 = _mm_loadu_si128((const __m128i*)(ptr + 16)); + __m128i t02 = _mm_loadu_si128((const __m128i*)(ptr + 32)); + + __m128i t10 = _mm_unpacklo_epi8(t00, _mm_unpackhi_epi64(t01, t01)); + __m128i t11 = _mm_unpacklo_epi8(_mm_unpackhi_epi64(t00, t00), t02); + __m128i t12 = _mm_unpacklo_epi8(t01, _mm_unpackhi_epi64(t02, t02)); + + __m128i t20 = _mm_unpacklo_epi8(t10, _mm_unpackhi_epi64(t11, t11)); + __m128i t21 = _mm_unpacklo_epi8(_mm_unpackhi_epi64(t10, t10), t12); + __m128i t22 = _mm_unpacklo_epi8(t11, _mm_unpackhi_epi64(t12, t12)); + + __m128i t30 = _mm_unpacklo_epi8(t20, _mm_unpackhi_epi64(t21, t21)); + __m128i t31 = _mm_unpacklo_epi8(_mm_unpackhi_epi64(t20, t20), t22); + __m128i t32 = _mm_unpacklo_epi8(t21, _mm_unpackhi_epi64(t22, t22)); + + a.val = _mm_unpacklo_epi8(t30, _mm_unpackhi_epi64(t31, t31)); + b.val = _mm_unpacklo_epi8(_mm_unpackhi_epi64(t30, t30), t32); + c.val = _mm_unpacklo_epi8(t31, _mm_unpackhi_epi64(t32, t32)); +} + +inline void v_load_deinterleave(const uchar* ptr, v_uint8x16& a, v_uint8x16& b, v_uint8x16& c, v_uint8x16& d) +{ + __m128i u0 = _mm_loadu_si128((const __m128i*)ptr); // a0 b0 c0 d0 a1 b1 c1 d1 ... + __m128i u1 = _mm_loadu_si128((const __m128i*)(ptr + 16)); // a4 b4 c4 d4 ... + __m128i u2 = _mm_loadu_si128((const __m128i*)(ptr + 32)); // a8 b8 c8 d8 ... + __m128i u3 = _mm_loadu_si128((const __m128i*)(ptr + 48)); // a12 b12 c12 d12 ... + + __m128i v0 = _mm_unpacklo_epi8(u0, u2); // a0 a8 b0 b8 ... + __m128i v1 = _mm_unpackhi_epi8(u0, u2); // a2 a10 b2 b10 ... + __m128i v2 = _mm_unpacklo_epi8(u1, u3); // a4 a12 b4 b12 ... + __m128i v3 = _mm_unpackhi_epi8(u1, u3); // a6 a14 b4 b14 ... + + u0 = _mm_unpacklo_epi8(v0, v2); // a0 a4 a8 a12 ... + u1 = _mm_unpacklo_epi8(v1, v3); // a2 a6 a10 a14 ... + u2 = _mm_unpackhi_epi8(v0, v2); // a1 a5 a9 a13 ... + u3 = _mm_unpackhi_epi8(v1, v3); // a3 a7 a11 a15 ... + + v0 = _mm_unpacklo_epi8(u0, u1); // a0 a2 a4 a6 ... + v1 = _mm_unpacklo_epi8(u2, u3); // a1 a3 a5 a7 ... + v2 = _mm_unpackhi_epi8(u0, u1); // b0 b2 b4 b6 ... + v3 = _mm_unpackhi_epi8(u2, u3); // b1 b3 b5 b7 ... + + a.val = _mm_unpacklo_epi8(v0, v1); + b.val = _mm_unpacklo_epi8(v2, v3); + c.val = _mm_unpackhi_epi8(v0, v1); + d.val = _mm_unpacklo_epi8(v2, v3); +} + +inline void v_load_deinterleave(const ushort* ptr, v_uint16x8& a, v_uint16x8& b, v_uint16x8& c) +{ + __m128i t00 = _mm_loadu_si128((const __m128i*)ptr); + __m128i t01 = _mm_loadu_si128((const __m128i*)(ptr + 8)); + __m128i t02 = _mm_loadu_si128((const __m128i*)(ptr + 16)); + + __m128i t10 = _mm_unpacklo_epi16(t00, _mm_unpackhi_epi64(t01, t01)); + __m128i t11 = _mm_unpacklo_epi16(_mm_unpackhi_epi64(t00, t00), t02); + __m128i t12 = _mm_unpacklo_epi16(t01, _mm_unpackhi_epi64(t02, t02)); + + __m128i t20 = _mm_unpacklo_epi16(t10, _mm_unpackhi_epi64(t11, t11)); + __m128i t21 = _mm_unpacklo_epi16(_mm_unpackhi_epi64(t10, t10), t12); + __m128i t22 = _mm_unpacklo_epi16(t11, _mm_unpackhi_epi64(t12, t12)); + + a.val = _mm_unpacklo_epi16(t20, _mm_unpackhi_epi64(t21, t21)); + b.val = _mm_unpacklo_epi16(_mm_unpackhi_epi64(t20, t20), t22); + c.val = _mm_unpacklo_epi16(t21, _mm_unpackhi_epi64(t22, t22)); +} + +inline void v_load_deinterleave(const ushort* ptr, v_uint16x8& a, v_uint16x8& b, v_uint16x8& c, v_uint16x8& d) +{ + __m128i u0 = _mm_loadu_si128((const __m128i*)ptr); // a0 b0 c0 d0 a1 b1 c1 d1 + __m128i u1 = _mm_loadu_si128((const __m128i*)(ptr + 8)); // a2 b2 c2 d2 ... + __m128i u2 = _mm_loadu_si128((const __m128i*)(ptr + 16)); // a4 b4 c4 d4 ... + __m128i u3 = _mm_loadu_si128((const __m128i*)(ptr + 24)); // a6 b6 c6 d6 ... + + __m128i v0 = _mm_unpacklo_epi16(u0, u2); // a0 a4 b0 b4 ... + __m128i v1 = _mm_unpackhi_epi16(u0, u2); // a1 a5 b1 b5 ... + __m128i v2 = _mm_unpacklo_epi16(u1, u3); // a2 a6 b2 b6 ... + __m128i v3 = _mm_unpackhi_epi16(u1, u3); // a3 a7 b3 b7 ... + + u0 = _mm_unpacklo_epi16(v0, v2); // a0 a2 a4 a6 ... + u1 = _mm_unpacklo_epi16(v1, v3); // a1 a3 a5 a7 ... + u2 = _mm_unpackhi_epi16(v0, v2); // c0 c2 c4 c6 ... + u3 = _mm_unpackhi_epi16(v1, v3); // c1 c3 c5 c7 ... + + a.val = _mm_unpacklo_epi16(u0, u1); + b.val = _mm_unpackhi_epi16(u0, u1); + c.val = _mm_unpacklo_epi16(u2, u3); + d.val = _mm_unpackhi_epi16(u2, u3); +} + +inline void v_load_deinterleave(const unsigned* ptr, v_uint32x4& a, v_uint32x4& b, v_uint32x4& c) +{ + __m128i t00 = _mm_loadu_si128((const __m128i*)ptr); + __m128i t01 = _mm_loadu_si128((const __m128i*)(ptr + 4)); + __m128i t02 = _mm_loadu_si128((const __m128i*)(ptr + 8)); + + __m128i t10 = _mm_unpacklo_epi32(t00, _mm_unpackhi_epi64(t01, t01)); + __m128i t11 = _mm_unpacklo_epi32(_mm_unpackhi_epi64(t00, t00), t02); + __m128i t12 = _mm_unpacklo_epi32(t01, _mm_unpackhi_epi64(t02, t02)); + + a.val = _mm_unpacklo_epi32(t10, _mm_unpackhi_epi64(t11, t11)); + b.val = _mm_unpacklo_epi32(_mm_unpackhi_epi64(t10, t10), t12); + c.val = _mm_unpacklo_epi32(t11, _mm_unpackhi_epi64(t12, t12)); +} + +inline void v_load_deinterleave(const unsigned* ptr, v_uint32x4& a, v_uint32x4& b, v_uint32x4& c, v_uint32x4& d) +{ + v_uint32x4 u0(_mm_loadu_si128((const __m128i*)ptr)); // a0 b0 c0 d0 + v_uint32x4 u1(_mm_loadu_si128((const __m128i*)(ptr + 4))); // a1 b1 c1 d1 + v_uint32x4 u2(_mm_loadu_si128((const __m128i*)(ptr + 8))); // a2 b2 c2 d2 + v_uint32x4 u3(_mm_loadu_si128((const __m128i*)(ptr + 12))); // a3 b3 c3 d3 + + v_transpose4x4(u0, u1, u2, u3, a, b, c, d); +} + +inline void v_store_interleave( uchar* ptr, const v_uint8x16& a, const v_uint8x16& b, + const v_uint8x16& c ) +{ + __m128i z = _mm_setzero_si128(); + __m128i ab0 = _mm_unpacklo_epi8(a.val, b.val); + __m128i ab1 = _mm_unpackhi_epi8(a.val, b.val); + __m128i c0 = _mm_unpacklo_epi8(c.val, z); + __m128i c1 = _mm_unpackhi_epi8(c.val, z); + + __m128i p00 = _mm_unpacklo_epi16(ab0, c0); + __m128i p01 = _mm_unpackhi_epi16(ab0, c0); + __m128i p02 = _mm_unpacklo_epi16(ab1, c1); + __m128i p03 = _mm_unpackhi_epi16(ab1, c1); + + __m128i p10 = _mm_unpacklo_epi32(p00, p01); + __m128i p11 = _mm_unpackhi_epi32(p00, p01); + __m128i p12 = _mm_unpacklo_epi32(p02, p03); + __m128i p13 = _mm_unpackhi_epi32(p02, p03); + + __m128i p20 = _mm_unpacklo_epi64(p10, p11); + __m128i p21 = _mm_unpackhi_epi64(p10, p11); + __m128i p22 = _mm_unpacklo_epi64(p12, p13); + __m128i p23 = _mm_unpackhi_epi64(p12, p13); + + p20 = _mm_slli_si128(p20, 1); + p22 = _mm_slli_si128(p22, 1); + + __m128i p30 = _mm_slli_epi64(_mm_unpacklo_epi32(p20, p21), 8); + __m128i p31 = _mm_srli_epi64(_mm_unpackhi_epi32(p20, p21), 8); + __m128i p32 = _mm_slli_epi64(_mm_unpacklo_epi32(p22, p23), 8); + __m128i p33 = _mm_srli_epi64(_mm_unpackhi_epi32(p22, p23), 8); + + __m128i p40 = _mm_unpacklo_epi64(p30, p31); + __m128i p41 = _mm_unpackhi_epi64(p30, p31); + __m128i p42 = _mm_unpacklo_epi64(p32, p33); + __m128i p43 = _mm_unpackhi_epi64(p32, p33); + + __m128i v0 = _mm_or_si128(_mm_srli_si128(p40, 2), _mm_slli_si128(p41, 10)); + __m128i v1 = _mm_or_si128(_mm_srli_si128(p41, 6), _mm_slli_si128(p42, 6)); + __m128i v2 = _mm_or_si128(_mm_srli_si128(p42, 10), _mm_slli_si128(p43, 2)); + + _mm_storeu_si128((__m128i*)(ptr), v0); + _mm_storeu_si128((__m128i*)(ptr + 16), v1); + _mm_storeu_si128((__m128i*)(ptr + 32), v2); +} + +inline void v_store_interleave( uchar* ptr, const v_uint8x16& a, const v_uint8x16& b, + const v_uint8x16& c, const v_uint8x16& d) +{ + // a0 a1 a2 a3 .... + // b0 b1 b2 b3 .... + // c0 c1 c2 c3 .... + // d0 d1 d2 d3 .... + __m128i u0 = _mm_unpacklo_epi8(a.val, c.val); // a0 c0 a1 c1 ... + __m128i u1 = _mm_unpackhi_epi8(a.val, c.val); // a8 c8 a9 c9 ... + __m128i u2 = _mm_unpacklo_epi8(b.val, d.val); // b0 d0 b1 d1 ... + __m128i u3 = _mm_unpackhi_epi8(b.val, d.val); // b8 d8 b9 d9 ... + + __m128i v0 = _mm_unpacklo_epi8(u0, u2); // a0 b0 c0 d0 ... + __m128i v1 = _mm_unpacklo_epi8(u1, u3); // a8 b8 c8 d8 ... + __m128i v2 = _mm_unpackhi_epi8(u0, u2); // a4 b4 c4 d4 ... + __m128i v3 = _mm_unpackhi_epi8(u1, u3); // a12 b12 c12 d12 ... + + _mm_storeu_si128((__m128i*)ptr, v0); + _mm_storeu_si128((__m128i*)(ptr + 16), v2); + _mm_storeu_si128((__m128i*)(ptr + 32), v1); + _mm_storeu_si128((__m128i*)(ptr + 48), v3); +} + +inline void v_store_interleave( ushort* ptr, const v_uint16x8& a, + const v_uint16x8& b, + const v_uint16x8& c ) +{ + __m128i z = _mm_setzero_si128(); + __m128i ab0 = _mm_unpacklo_epi16(a.val, b.val); + __m128i ab1 = _mm_unpackhi_epi16(a.val, b.val); + __m128i c0 = _mm_unpacklo_epi16(c.val, z); + __m128i c1 = _mm_unpackhi_epi16(c.val, z); + + __m128i p10 = _mm_unpacklo_epi32(ab0, c0); + __m128i p11 = _mm_unpackhi_epi32(ab0, c0); + __m128i p12 = _mm_unpacklo_epi32(ab1, c1); + __m128i p13 = _mm_unpackhi_epi32(ab1, c1); + + __m128i p20 = _mm_unpacklo_epi64(p10, p11); + __m128i p21 = _mm_unpackhi_epi64(p10, p11); + __m128i p22 = _mm_unpacklo_epi64(p12, p13); + __m128i p23 = _mm_unpackhi_epi64(p12, p13); + + p20 = _mm_slli_si128(p20, 2); + p22 = _mm_slli_si128(p22, 2); + + __m128i p30 = _mm_unpacklo_epi64(p20, p21); + __m128i p31 = _mm_unpackhi_epi64(p20, p21); + __m128i p32 = _mm_unpacklo_epi64(p22, p23); + __m128i p33 = _mm_unpackhi_epi64(p22, p23); + + __m128i v0 = _mm_or_si128(_mm_srli_si128(p30, 2), _mm_slli_si128(p31, 10)); + __m128i v1 = _mm_or_si128(_mm_srli_si128(p31, 6), _mm_slli_si128(p32, 6)); + __m128i v2 = _mm_or_si128(_mm_srli_si128(p32, 10), _mm_slli_si128(p33, 2)); + + _mm_storeu_si128((__m128i*)(ptr), v0); + _mm_storeu_si128((__m128i*)(ptr + 8), v1); + _mm_storeu_si128((__m128i*)(ptr + 16), v2); +} + +inline void v_store_interleave( ushort* ptr, const v_uint16x8& a, const v_uint16x8& b, + const v_uint16x8& c, const v_uint16x8& d) +{ + // a0 a1 a2 a3 .... + // b0 b1 b2 b3 .... + // c0 c1 c2 c3 .... + // d0 d1 d2 d3 .... + __m128i u0 = _mm_unpacklo_epi16(a.val, c.val); // a0 c0 a1 c1 ... + __m128i u1 = _mm_unpackhi_epi16(a.val, c.val); // a4 c4 a5 c5 ... + __m128i u2 = _mm_unpacklo_epi16(b.val, d.val); // b0 d0 b1 d1 ... + __m128i u3 = _mm_unpackhi_epi16(b.val, d.val); // b4 d4 b5 d5 ... + + __m128i v0 = _mm_unpacklo_epi16(u0, u2); // a0 b0 c0 d0 ... + __m128i v1 = _mm_unpacklo_epi16(u1, u3); // a4 b4 c4 d4 ... + __m128i v2 = _mm_unpackhi_epi16(u0, u2); // a2 b2 c2 d2 ... + __m128i v3 = _mm_unpackhi_epi16(u1, u3); // a6 b6 c6 d6 ... + + _mm_storeu_si128((__m128i*)ptr, v0); + _mm_storeu_si128((__m128i*)(ptr + 8), v2); + _mm_storeu_si128((__m128i*)(ptr + 16), v1); + _mm_storeu_si128((__m128i*)(ptr + 24), v3); +} + +inline void v_store_interleave( unsigned* ptr, const v_uint32x4& a, const v_uint32x4& b, + const v_uint32x4& c ) +{ + v_uint32x4 z = v_setzero_u32(), u0, u1, u2, u3; + v_transpose4x4(a, b, c, z, u0, u1, u2, u3); + + __m128i v0 = _mm_or_si128(u0.val, _mm_slli_si128(u1.val, 12)); + __m128i v1 = _mm_or_si128(_mm_srli_si128(u1.val, 4), _mm_slli_si128(u2.val, 8)); + __m128i v2 = _mm_or_si128(_mm_srli_si128(u2.val, 8), _mm_slli_si128(u3.val, 4)); + + _mm_storeu_si128((__m128i*)ptr, v0); + _mm_storeu_si128((__m128i*)(ptr + 4), v1); + _mm_storeu_si128((__m128i*)(ptr + 8), v2); +} + +inline void v_store_interleave(unsigned* ptr, const v_uint32x4& a, const v_uint32x4& b, + const v_uint32x4& c, const v_uint32x4& d) +{ + v_uint32x4 t0, t1, t2, t3; + v_transpose4x4(a, b, c, d, t0, t1, t2, t3); + v_store(ptr, t0); + v_store(ptr + 4, t1); + v_store(ptr + 8, t2); + v_store(ptr + 12, t3); +} + +#define OPENCV_HAL_IMPL_SSE_LOADSTORE_INTERLEAVE(_Tpvec, _Tp, suffix, _Tpuvec, _Tpu, usuffix) \ +inline void v_load_deinterleave( const _Tp* ptr, _Tpvec& a0, \ + _Tpvec& b0, _Tpvec& c0 ) \ +{ \ + _Tpuvec a1, b1, c1; \ + v_load_deinterleave((const _Tpu*)ptr, a1, b1, c1); \ + a0 = v_reinterpret_as_##suffix(a1); \ + b0 = v_reinterpret_as_##suffix(b1); \ + c0 = v_reinterpret_as_##suffix(c1); \ +} \ +inline void v_load_deinterleave( const _Tp* ptr, _Tpvec& a0, \ + _Tpvec& b0, _Tpvec& c0, _Tpvec& d0 ) \ +{ \ + _Tpuvec a1, b1, c1, d1; \ + v_load_deinterleave((const _Tpu*)ptr, a1, b1, c1, d1); \ + a0 = v_reinterpret_as_##suffix(a1); \ + b0 = v_reinterpret_as_##suffix(b1); \ + c0 = v_reinterpret_as_##suffix(c1); \ + d0 = v_reinterpret_as_##suffix(d1); \ +} \ +inline void v_store_interleave( _Tp* ptr, const _Tpvec& a0, \ + const _Tpvec& b0, const _Tpvec& c0 ) \ +{ \ + _Tpuvec a1 = v_reinterpret_as_##usuffix(a0); \ + _Tpuvec b1 = v_reinterpret_as_##usuffix(b0); \ + _Tpuvec c1 = v_reinterpret_as_##usuffix(c0); \ + v_store_interleave((_Tpu*)ptr, a1, b1, c1); \ +} \ +inline void v_store_interleave( _Tp* ptr, const _Tpvec& a0, const _Tpvec& b0, \ + const _Tpvec& c0, const _Tpvec& d0 ) \ +{ \ + _Tpuvec a1 = v_reinterpret_as_##usuffix(a0); \ + _Tpuvec b1 = v_reinterpret_as_##usuffix(b0); \ + _Tpuvec c1 = v_reinterpret_as_##usuffix(c0); \ + _Tpuvec d1 = v_reinterpret_as_##usuffix(d0); \ + v_store_interleave((_Tpu*)ptr, a1, b1, c1, d1); \ +} + +OPENCV_HAL_IMPL_SSE_LOADSTORE_INTERLEAVE(v_int8x16, schar, s8, v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INTERLEAVE(v_int16x8, short, s16, v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INTERLEAVE(v_int32x4, int, s32, v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_SSE_LOADSTORE_INTERLEAVE(v_float32x4, float, f32, v_uint32x4, unsigned, u32) + +inline v_float32x4 v_cvt_f32(const v_int32x4& a) +{ + return v_float32x4(_mm_cvtepi32_ps(a.val)); +} + +inline v_float32x4 v_cvt_f32(const v_float64x2& a) +{ + return v_float32x4(_mm_cvtpd_ps(a.val)); +} + +inline v_float64x2 v_cvt_f64(const v_int32x4& a) +{ + return v_float64x2(_mm_cvtepi32_pd(a.val)); +} + +inline v_float64x2 v_cvt_f64(const v_float32x4& a) +{ + return v_float64x2(_mm_cvtps_pd(a.val)); +} + +} + +#endif diff --git a/include/opencv2/highgui.hpp b/include/opencv2/highgui.hpp new file mode 100644 index 0000000..9275ae7 --- /dev/null +++ b/include/opencv2/highgui.hpp @@ -0,0 +1,704 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HIGHGUI_HPP__ +#define __OPENCV_HIGHGUI_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" + +/** +@defgroup highgui High-level GUI + +While OpenCV was designed for use in full-scale applications and can be used within functionally +rich UI frameworks (such as Qt\*, WinForms\*, or Cocoa\*) or without any UI at all, sometimes there +it is required to try functionality quickly and visualize the results. This is what the HighGUI +module has been designed for. + +It provides easy interface to: + +- Create and manipulate windows that can display images and "remember" their content (no need to + handle repaint events from OS). +- Add trackbars to the windows, handle simple mouse events as well as keyboard commands. + +@{ + @defgroup highgui_opengl OpenGL support + @defgroup highgui_qt Qt New Functions + + ![image](pics/qtgui.png) + + This figure explains new functionality implemented with Qt\* GUI. The new GUI provides a statusbar, + a toolbar, and a control panel. The control panel can have trackbars and buttonbars attached to it. + If you cannot see the control panel, press Ctrl+P or right-click any Qt window and select **Display + properties window**. + + - To attach a trackbar, the window name parameter must be NULL. + + - To attach a buttonbar, a button must be created. If the last bar attached to the control panel + is a buttonbar, the new button is added to the right of the last button. If the last bar + attached to the control panel is a trackbar, or the control panel is empty, a new buttonbar is + created. Then, a new button is attached to it. + + See below the example used to generate the figure: : + @code + int main(int argc, char *argv[]) + int value = 50; + int value2 = 0; + + cvNamedWindow("main1",CV_WINDOW_NORMAL); + cvNamedWindow("main2",CV_WINDOW_AUTOSIZE | CV_GUI_NORMAL); + + cvCreateTrackbar( "track1", "main1", &value, 255, NULL);//OK tested + char* nameb1 = "button1"; + char* nameb2 = "button2"; + cvCreateButton(nameb1,callbackButton,nameb1,CV_CHECKBOX,1); + + cvCreateButton(nameb2,callbackButton,nameb2,CV_CHECKBOX,0); + cvCreateTrackbar( "track2", NULL, &value2, 255, NULL); + cvCreateButton("button5",callbackButton1,NULL,CV_RADIOBOX,0); + cvCreateButton("button6",callbackButton2,NULL,CV_RADIOBOX,1); + + cvSetMouseCallback( "main2",on_mouse,NULL ); + + IplImage* img1 = cvLoadImage("files/flower.jpg"); + IplImage* img2 = cvCreateImage(cvGetSize(img1),8,3); + CvCapture* video = cvCaptureFromFile("files/hockey.avi"); + IplImage* img3 = cvCreateImage(cvGetSize(cvQueryFrame(video)),8,3); + + while(cvWaitKey(33) != 27) + { + cvAddS(img1,cvScalarAll(value),img2); + cvAddS(cvQueryFrame(video),cvScalarAll(value2),img3); + cvShowImage("main1",img2); + cvShowImage("main2",img3); + } + + cvDestroyAllWindows(); + cvReleaseImage(&img1); + cvReleaseImage(&img2); + cvReleaseImage(&img3); + cvReleaseCapture(&video); + return 0; + } + @endcode + + @defgroup highgui_c C API +@} +*/ + +///////////////////////// graphical user interface ////////////////////////// +namespace cv +{ + +//! @addtogroup highgui +//! @{ + +// Flags for namedWindow +enum { WINDOW_NORMAL = 0x00000000, // the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size + WINDOW_AUTOSIZE = 0x00000001, // the user cannot resize the window, the size is constrainted by the image displayed + WINDOW_OPENGL = 0x00001000, // window with opengl support + + WINDOW_FULLSCREEN = 1, // change the window to fullscreen + WINDOW_FREERATIO = 0x00000100, // the image expends as much as it can (no ratio constraint) + WINDOW_KEEPRATIO = 0x00000000 // the ratio of the image is respected + }; + +// Flags for set / getWindowProperty +enum { WND_PROP_FULLSCREEN = 0, // fullscreen property (can be WINDOW_NORMAL or WINDOW_FULLSCREEN) + WND_PROP_AUTOSIZE = 1, // autosize property (can be WINDOW_NORMAL or WINDOW_AUTOSIZE) + WND_PROP_ASPECT_RATIO = 2, // window's aspect ration (can be set to WINDOW_FREERATIO or WINDOW_KEEPRATIO); + WND_PROP_OPENGL = 3 // opengl support + }; + +enum { EVENT_MOUSEMOVE = 0, + EVENT_LBUTTONDOWN = 1, + EVENT_RBUTTONDOWN = 2, + EVENT_MBUTTONDOWN = 3, + EVENT_LBUTTONUP = 4, + EVENT_RBUTTONUP = 5, + EVENT_MBUTTONUP = 6, + EVENT_LBUTTONDBLCLK = 7, + EVENT_RBUTTONDBLCLK = 8, + EVENT_MBUTTONDBLCLK = 9, + EVENT_MOUSEWHEEL = 10, + EVENT_MOUSEHWHEEL = 11 + }; + +enum { EVENT_FLAG_LBUTTON = 1, + EVENT_FLAG_RBUTTON = 2, + EVENT_FLAG_MBUTTON = 4, + EVENT_FLAG_CTRLKEY = 8, + EVENT_FLAG_SHIFTKEY = 16, + EVENT_FLAG_ALTKEY = 32 + }; + +// Qt font +enum { QT_FONT_LIGHT = 25, //QFont::Light, + QT_FONT_NORMAL = 50, //QFont::Normal, + QT_FONT_DEMIBOLD = 63, //QFont::DemiBold, + QT_FONT_BOLD = 75, //QFont::Bold, + QT_FONT_BLACK = 87 //QFont::Black + }; + +// Qt font style +enum { QT_STYLE_NORMAL = 0, //QFont::StyleNormal, + QT_STYLE_ITALIC = 1, //QFont::StyleItalic, + QT_STYLE_OBLIQUE = 2 //QFont::StyleOblique + }; + +// Qt "button" type +enum { QT_PUSH_BUTTON = 0, + QT_CHECKBOX = 1, + QT_RADIOBOX = 2 + }; + + +typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata); +typedef void (*TrackbarCallback)(int pos, void* userdata); +typedef void (*OpenGlDrawCallback)(void* userdata); +typedef void (*ButtonCallback)(int state, void* userdata); + +/** @brief Creates a window. + +@param winname Name of the window in the window caption that may be used as a window identifier. +@param flags Flags of the window. The supported flags are: +> - **WINDOW_NORMAL** If this is set, the user can resize the window (no constraint). +> - **WINDOW_AUTOSIZE** If this is set, the window size is automatically adjusted to fit the +> displayed image (see imshow ), and you cannot change the window size manually. +> - **WINDOW_OPENGL** If this is set, the window will be created with OpenGL support. + +The function namedWindow creates a window that can be used as a placeholder for images and +trackbars. Created windows are referred to by their names. + +If a window with the same name already exists, the function does nothing. + +You can call destroyWindow or destroyAllWindows to close the window and de-allocate any associated +memory usage. For a simple program, you do not really have to call these functions because all the +resources and windows of the application are closed automatically by the operating system upon exit. + +@note + +Qt backend supports additional flags: + - **CV_WINDOW_NORMAL or CV_WINDOW_AUTOSIZE:** CV_WINDOW_NORMAL enables you to resize the + window, whereas CV_WINDOW_AUTOSIZE adjusts automatically the window size to fit the + displayed image (see imshow ), and you cannot change the window size manually. + - **CV_WINDOW_FREERATIO or CV_WINDOW_KEEPRATIO:** CV_WINDOW_FREERATIO adjusts the image + with no respect to its ratio, whereas CV_WINDOW_KEEPRATIO keeps the image ratio. + - **CV_GUI_NORMAL or CV_GUI_EXPANDED:** CV_GUI_NORMAL is the old way to draw the window + without statusbar and toolbar, whereas CV_GUI_EXPANDED is a new enhanced GUI. +By default, flags == CV_WINDOW_AUTOSIZE | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED + */ +CV_EXPORTS_W void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE); + +/** @brief Destroys a window. + +@param winname Name of the window to be destroyed. + +The function destroyWindow destroys the window with the given name. + */ +CV_EXPORTS_W void destroyWindow(const String& winname); + +/** @brief Destroys all of the HighGUI windows. + +The function destroyAllWindows destroys all of the opened HighGUI windows. + */ +CV_EXPORTS_W void destroyAllWindows(); + +CV_EXPORTS_W int startWindowThread(); + +/** @brief Waits for a pressed key. + +@param delay Delay in milliseconds. 0 is the special value that means "forever". + +The function waitKey waits for a key event infinitely (when \f$\texttt{delay}\leq 0\f$ ) or for delay +milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the +function will not wait exactly delay ms, it will wait at least delay ms, depending on what else is +running on your computer at that time. It returns the code of the pressed key or -1 if no key was +pressed before the specified time had elapsed. + +@note + +This function is the only method in HighGUI that can fetch and handle events, so it needs to be +called periodically for normal event processing unless HighGUI is used within an environment that +takes care of event processing. + +@note + +The function only works if there is at least one HighGUI window created and the window is active. +If there are several HighGUI windows, any of them can be active. + */ +CV_EXPORTS_W int waitKey(int delay = 0); + +/** @brief Displays an image in the specified window. + +@param winname Name of the window. +@param mat Image to be shown. + +The function imshow displays an image in the specified window. If the window was created with the +CV_WINDOW_AUTOSIZE flag, the image is shown with its original size, however it is still limited by the screen resolution. +Otherwise, the image is scaled to fit the window. The function may scale the image, depending on its depth: + +- If the image is 8-bit unsigned, it is displayed as is. +- If the image is 16-bit unsigned or 32-bit integer, the pixels are divided by 256. That is, the + value range [0,255\*256] is mapped to [0,255]. +- If the image is 32-bit floating-point, the pixel values are multiplied by 255. That is, the + value range [0,1] is mapped to [0,255]. + +If window was created with OpenGL support, imshow also support ogl::Buffer , ogl::Texture2D and +cuda::GpuMat as input. + +If the window was not created before this function, it is assumed creating a window with CV_WINDOW_AUTOSIZE. + +If you need to show an image that is bigger than the screen resolution, you will need to call namedWindow("", WINDOW_NORMAL) before the imshow. + +@note This function should be followed by waitKey function which displays the image for specified +milliseconds. Otherwise, it won't display the image. For example, waitKey(0) will display the window +infinitely until any keypress (it is suitable for image display). waitKey(25) will display a frame +for 25 ms, after which display will be automatically closed. (If you put it in a loop to read +videos, it will display the video frame-by-frame) + +@note + +[Windows Backend Only] Pressing Ctrl+C will copy the image to the clipboard. + + */ +CV_EXPORTS_W void imshow(const String& winname, InputArray mat); + +/** @brief Resizes window to the specified size + +@param winname Window name +@param width The new window width +@param height The new window height + +@note + +- The specified window size is for the image area. Toolbars are not counted. +- Only windows created without CV_WINDOW_AUTOSIZE flag can be resized. + */ +CV_EXPORTS_W void resizeWindow(const String& winname, int width, int height); + +/** @brief Moves window to the specified position + +@param winname Window name +@param x The new x-coordinate of the window +@param y The new y-coordinate of the window + */ +CV_EXPORTS_W void moveWindow(const String& winname, int x, int y); + +/** @brief Changes parameters of a window dynamically. + +@param winname Name of the window. +@param prop_id Window property to edit. The following operation flags are available: + - **CV_WND_PROP_FULLSCREEN** Change if the window is fullscreen ( CV_WINDOW_NORMAL or + CV_WINDOW_FULLSCREEN ). + - **CV_WND_PROP_AUTOSIZE** Change if the window is resizable (CV_WINDOW_NORMAL or + CV_WINDOW_AUTOSIZE ). + - **CV_WND_PROP_ASPECTRATIO** Change if the aspect ratio of the image is preserved ( + CV_WINDOW_FREERATIO or CV_WINDOW_KEEPRATIO ). +@param prop_value New value of the window property. The following operation flags are available: + - **CV_WINDOW_NORMAL** Change the window to normal size or make the window resizable. + - **CV_WINDOW_AUTOSIZE** Constrain the size by the displayed image. The window is not + resizable. + - **CV_WINDOW_FULLSCREEN** Change the window to fullscreen. + - **CV_WINDOW_FREERATIO** Make the window resizable without any ratio constraints. + - **CV_WINDOW_KEEPRATIO** Make the window resizable, but preserve the proportions of the + displayed image. + +The function setWindowProperty enables changing properties of a window. + */ +CV_EXPORTS_W void setWindowProperty(const String& winname, int prop_id, double prop_value); + +/** @brief Updates window title +*/ +CV_EXPORTS_W void setWindowTitle(const String& winname, const String& title); + +/** @brief Provides parameters of a window. + +@param winname Name of the window. +@param prop_id Window property to retrieve. The following operation flags are available: + - **CV_WND_PROP_FULLSCREEN** Change if the window is fullscreen ( CV_WINDOW_NORMAL or + CV_WINDOW_FULLSCREEN ). + - **CV_WND_PROP_AUTOSIZE** Change if the window is resizable (CV_WINDOW_NORMAL or + CV_WINDOW_AUTOSIZE ). + - **CV_WND_PROP_ASPECTRATIO** Change if the aspect ratio of the image is preserved + (CV_WINDOW_FREERATIO or CV_WINDOW_KEEPRATIO ). + +See setWindowProperty to know the meaning of the returned values. + +The function getWindowProperty returns properties of a window. + */ +CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id); + +/** @brief Sets mouse handler for the specified window + +@param winname Window name +@param onMouse Mouse callback. See OpenCV samples, such as +, on how to specify and +use the callback. +@param userdata The optional parameter passed to the callback. + */ +CV_EXPORTS void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0); + +/** @brief Gets the mouse-wheel motion delta, when handling mouse-wheel events EVENT_MOUSEWHEEL and +EVENT_MOUSEHWHEEL. + +@param flags The mouse callback flags parameter. + +For regular mice with a scroll-wheel, delta will be a multiple of 120. The value 120 corresponds to +a one notch rotation of the wheel or the threshold for action to be taken and one such action should +occur for each delta. Some high-precision mice with higher-resolution freely-rotating wheels may +generate smaller values. + +For EVENT_MOUSEWHEEL positive and negative values mean forward and backward scrolling, +respectively. For EVENT_MOUSEHWHEEL, where available, positive and negative values mean right and +left scrolling, respectively. + +With the C API, the macro CV_GET_WHEEL_DELTA(flags) can be used alternatively. + +@note + +Mouse-wheel events are currently supported only on Windows. + */ +CV_EXPORTS int getMouseWheelDelta(int flags); + +/** @brief Creates a trackbar and attaches it to the specified window. + +@param trackbarname Name of the created trackbar. +@param winname Name of the window that will be used as a parent of the created trackbar. +@param value Optional pointer to an integer variable whose value reflects the position of the +slider. Upon creation, the slider position is defined by this variable. +@param count Maximal position of the slider. The minimal position is always 0. +@param onChange Pointer to the function to be called every time the slider changes position. This +function should be prototyped as void Foo(int,void\*); , where the first parameter is the trackbar +position and the second parameter is the user data (see the next parameter). If the callback is +the NULL pointer, no callbacks are called, but only value is updated. +@param userdata User data that is passed as is to the callback. It can be used to handle trackbar +events without using global variables. + +The function createTrackbar creates a trackbar (a slider or range control) with the specified name +and range, assigns a variable value to be a position synchronized with the trackbar and specifies +the callback function onChange to be called on the trackbar position change. The created trackbar is +displayed in the specified window winname. + +@note + +**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar should be attached to the +control panel. + +Clicking the label of each trackbar enables editing the trackbar values manually. + +@note + +- An example of using the trackbar functionality can be found at + opencv_source_code/samples/cpp/connected_components.cpp + */ +CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname, + int* value, int count, + TrackbarCallback onChange = 0, + void* userdata = 0); + +/** @brief Returns the trackbar position. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of the trackbar. + +The function returns the current position of the specified trackbar. + +@note + +**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +panel. + + */ +CV_EXPORTS_W int getTrackbarPos(const String& trackbarname, const String& winname); + +/** @brief Sets the trackbar position. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of trackbar. +@param pos New position. + +The function sets the position of the specified trackbar in the specified window. + +@note + +**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +panel. + */ +CV_EXPORTS_W void setTrackbarPos(const String& trackbarname, const String& winname, int pos); + +/** @brief Sets the trackbar maximum position. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of trackbar. +@param maxval New maximum position. + +The function sets the maximum position of the specified trackbar in the specified window. + +@note + +**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +panel. + */ +CV_EXPORTS_W void setTrackbarMax(const String& trackbarname, const String& winname, int maxval); + +//! @addtogroup highgui_opengl OpenGL support +//! @{ + +CV_EXPORTS void imshow(const String& winname, const ogl::Texture2D& tex); + +/** @brief Sets a callback function to be called to draw on top of displayed image. + +@param winname Name of the window. +@param onOpenGlDraw Pointer to the function to be called every frame. This function should be +prototyped as void Foo(void\*) . +@param userdata Pointer passed to the callback function. *(Optional)* + +The function setOpenGlDrawCallback can be used to draw 3D data on the window. See the example of +callback function below: : +@code + void on_opengl(void* param) + { + glLoadIdentity(); + + glTranslated(0.0, 0.0, -1.0); + + glRotatef( 55, 1, 0, 0 ); + glRotatef( 45, 0, 1, 0 ); + glRotatef( 0, 0, 0, 1 ); + + static const int coords[6][4][3] = { + { { +1, -1, -1 }, { -1, -1, -1 }, { -1, +1, -1 }, { +1, +1, -1 } }, + { { +1, +1, -1 }, { -1, +1, -1 }, { -1, +1, +1 }, { +1, +1, +1 } }, + { { +1, -1, +1 }, { +1, -1, -1 }, { +1, +1, -1 }, { +1, +1, +1 } }, + { { -1, -1, -1 }, { -1, -1, +1 }, { -1, +1, +1 }, { -1, +1, -1 } }, + { { +1, -1, +1 }, { -1, -1, +1 }, { -1, -1, -1 }, { +1, -1, -1 } }, + { { -1, -1, +1 }, { +1, -1, +1 }, { +1, +1, +1 }, { -1, +1, +1 } } + }; + + for (int i = 0; i < 6; ++i) { + glColor3ub( i*20, 100+i*10, i*42 ); + glBegin(GL_QUADS); + for (int j = 0; j < 4; ++j) { + glVertex3d(0.2 * coords[i][j][0], 0.2 * coords[i][j][1], 0.2 * coords[i][j][2]); + } + glEnd(); + } + } +@endcode + */ +CV_EXPORTS void setOpenGlDrawCallback(const String& winname, OpenGlDrawCallback onOpenGlDraw, void* userdata = 0); + +/** @brief Sets the specified window as current OpenGL context. + +@param winname Window name + */ +CV_EXPORTS void setOpenGlContext(const String& winname); + +/** @brief Force window to redraw its context and call draw callback ( setOpenGlDrawCallback ). + +@param winname Window name + */ +CV_EXPORTS void updateWindow(const String& winname); + +//! @} highgui_opengl + +//! @addtogroup highgui_qt +//! @{ +// Only for Qt + +struct QtFont +{ + const char* nameFont; // Qt: nameFont + Scalar color; // Qt: ColorFont -> cvScalar(blue_component, green_component, red_component[, alpha_component]) + int font_face; // Qt: bool italic + const int* ascii; // font data and metrics + const int* greek; + const int* cyrillic; + float hscale, vscale; + float shear; // slope coefficient: 0 - normal, >0 - italic + int thickness; // Qt: weight + float dx; // horizontal interval between letters + int line_type; // Qt: PointSize +}; + +/** @brief Creates the font to draw a text on an image. + +@param nameFont Name of the font. The name should match the name of a system font (such as +*Times*). If the font is not found, a default one is used. +@param pointSize Size of the font. If not specified, equal zero or negative, the point size of the +font is set to a system-dependent default value. Generally, this is 12 points. +@param color Color of the font in BGRA where A = 255 is fully transparent. Use the macro CV _ RGB +for simplicity. +@param weight Font weight. The following operation flags are available: + - **CV_FONT_LIGHT** Weight of 25 + - **CV_FONT_NORMAL** Weight of 50 + - **CV_FONT_DEMIBOLD** Weight of 63 + - **CV_FONT_BOLD** Weight of 75 + - **CV_FONT_BLACK** Weight of 87 + + You can also specify a positive integer for better control. +@param style Font style. The following operation flags are available: + - **CV_STYLE_NORMAL** Normal font + - **CV_STYLE_ITALIC** Italic font + - **CV_STYLE_OBLIQUE** Oblique font +@param spacing Spacing between characters. It can be negative or positive. + +The function fontQt creates a CvFont object. This CvFont is not compatible with putText . + +A basic usage of this function is the following: : +@code + CvFont font = fontQt(''Times''); + addText( img1, ``Hello World !'', Point(50,50), font); +@endcode + */ +CV_EXPORTS QtFont fontQt(const String& nameFont, int pointSize = -1, + Scalar color = Scalar::all(0), int weight = QT_FONT_NORMAL, + int style = QT_STYLE_NORMAL, int spacing = 0); + +/** @brief Creates the font to draw a text on an image. + +@param img 8-bit 3-channel image where the text should be drawn. +@param text Text to write on an image. +@param org Point(x,y) where the text should start on an image. +@param font Font to use to draw a text. + +The function addText draws *text* on an image *img* using a specific font *font* (see example fontQt +) + */ +CV_EXPORTS void addText( const Mat& img, const String& text, Point org, const QtFont& font); + +/** @brief Displays a text on a window image as an overlay for a specified duration. + +@param winname Name of the window. +@param text Overlay text to write on a window image. +@param delayms The period (in milliseconds), during which the overlay text is displayed. If this +function is called before the previous overlay text timed out, the timer is restarted and the text +is updated. If this value is zero, the text never disappears. + +The function displayOverlay displays useful information/tips on top of the window for a certain +amount of time *delayms*. The function does not modify the image, displayed in the window, that is, +after the specified delay the original content of the window is restored. + */ +CV_EXPORTS void displayOverlay(const String& winname, const String& text, int delayms = 0); + +/** @brief Displays a text on the window statusbar during the specified period of time. + +@param winname Name of the window. +@param text Text to write on the window statusbar. +@param delayms Duration (in milliseconds) to display the text. If this function is called before +the previous text timed out, the timer is restarted and the text is updated. If this value is +zero, the text never disappears. + +The function displayOverlay displays useful information/tips on top of the window for a certain +amount of time *delayms* . This information is displayed on the window statusbar (the window must be +created with the CV_GUI_EXPANDED flags). + */ +CV_EXPORTS void displayStatusBar(const String& winname, const String& text, int delayms = 0); + +/** @brief Saves parameters of the specified window. + +@param windowName Name of the window. + +The function saveWindowParameters saves size, location, flags, trackbars value, zoom and panning +location of the window window_name . + */ +CV_EXPORTS void saveWindowParameters(const String& windowName); + +/** @brief Loads parameters of the specified window. + +@param windowName Name of the window. + +The function loadWindowParameters loads size, location, flags, trackbars value, zoom and panning +location of the window window_name . + */ +CV_EXPORTS void loadWindowParameters(const String& windowName); + +CV_EXPORTS int startLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* argv[]); + +CV_EXPORTS void stopLoop(); + +/** @brief Attaches a button to the control panel. + +@param bar_name + Name of the button. +@param on_change Pointer to the function to be called every time the button changes its state. +This function should be prototyped as void Foo(int state,\*void); . *state* is the current state +of the button. It could be -1 for a push button, 0 or 1 for a check/radio box button. +@param userdata Pointer passed to the callback function. +@param type Optional type of the button. + - **CV_PUSH_BUTTON** Push button + - **CV_CHECKBOX** Checkbox button + - **CV_RADIOBOX** Radiobox button. The radiobox on the same buttonbar (same line) are + exclusive, that is only one can be selected at a time. +@param initial_button_state Default state of the button. Use for checkbox and radiobox. Its +value could be 0 or 1. *(Optional)* + +The function createButton attaches a button to the control panel. Each button is added to a +buttonbar to the right of the last button. A new buttonbar is created if nothing was attached to the +control panel before, or if the last element attached to the control panel was a trackbar. + +See below various examples of the createButton function call: : +@code + createButton(NULL,callbackButton);//create a push button "button 0", that will call callbackButton. + createButton("button2",callbackButton,NULL,CV_CHECKBOX,0); + createButton("button3",callbackButton,&value); + createButton("button5",callbackButton1,NULL,CV_RADIOBOX); + createButton("button6",callbackButton2,NULL,CV_PUSH_BUTTON,1); +@endcode +*/ +CV_EXPORTS int createButton( const String& bar_name, ButtonCallback on_change, + void* userdata = 0, int type = QT_PUSH_BUTTON, + bool initial_button_state = false); + +//! @} highgui_qt + +//! @} highgui + +} // cv + +#ifndef DISABLE_OPENCV_24_COMPATIBILITY +#include "opencv2/highgui/highgui_c.h" +#endif + +#endif diff --git a/include/opencv2/highgui/highgui.hpp b/include/opencv2/highgui/highgui.hpp new file mode 100644 index 0000000..160c9cf --- /dev/null +++ b/include/opencv2/highgui/highgui.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/highgui.hpp" diff --git a/include/opencv2/highgui/highgui_c.h b/include/opencv2/highgui/highgui_c.h new file mode 100644 index 0000000..46d4c95 --- /dev/null +++ b/include/opencv2/highgui/highgui_c.h @@ -0,0 +1,251 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HIGHGUI_H__ +#define __OPENCV_HIGHGUI_H__ + +#include "opencv2/core/core_c.h" +#include "opencv2/imgproc/imgproc_c.h" +#include "opencv2/imgcodecs/imgcodecs_c.h" +#include "opencv2/videoio/videoio_c.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup highgui_c + @{ + */ + +/****************************************************************************************\ +* Basic GUI functions * +\****************************************************************************************/ +//YV +//-----------New for Qt +/* For font */ +enum { CV_FONT_LIGHT = 25,//QFont::Light, + CV_FONT_NORMAL = 50,//QFont::Normal, + CV_FONT_DEMIBOLD = 63,//QFont::DemiBold, + CV_FONT_BOLD = 75,//QFont::Bold, + CV_FONT_BLACK = 87 //QFont::Black +}; + +enum { CV_STYLE_NORMAL = 0,//QFont::StyleNormal, + CV_STYLE_ITALIC = 1,//QFont::StyleItalic, + CV_STYLE_OBLIQUE = 2 //QFont::StyleOblique +}; +/* ---------*/ + +//for color cvScalar(blue_component, green_component, red_component[, alpha_component]) +//and alpha= 0 <-> 0xFF (not transparent <-> transparent) +CVAPI(CvFont) cvFontQt(const char* nameFont, int pointSize CV_DEFAULT(-1), CvScalar color CV_DEFAULT(cvScalarAll(0)), int weight CV_DEFAULT(CV_FONT_NORMAL), int style CV_DEFAULT(CV_STYLE_NORMAL), int spacing CV_DEFAULT(0)); + +CVAPI(void) cvAddText(const CvArr* img, const char* text, CvPoint org, CvFont *arg2); + +CVAPI(void) cvDisplayOverlay(const char* name, const char* text, int delayms CV_DEFAULT(0)); +CVAPI(void) cvDisplayStatusBar(const char* name, const char* text, int delayms CV_DEFAULT(0)); + +CVAPI(void) cvSaveWindowParameters(const char* name); +CVAPI(void) cvLoadWindowParameters(const char* name); +CVAPI(int) cvStartLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* argv[]); +CVAPI(void) cvStopLoop( void ); + +typedef void (CV_CDECL *CvButtonCallback)(int state, void* userdata); +enum {CV_PUSH_BUTTON = 0, CV_CHECKBOX = 1, CV_RADIOBOX = 2}; +CVAPI(int) cvCreateButton( const char* button_name CV_DEFAULT(NULL),CvButtonCallback on_change CV_DEFAULT(NULL), void* userdata CV_DEFAULT(NULL) , int button_type CV_DEFAULT(CV_PUSH_BUTTON), int initial_button_state CV_DEFAULT(0)); +//---------------------- + + +/* this function is used to set some external parameters in case of X Window */ +CVAPI(int) cvInitSystem( int argc, char** argv ); + +CVAPI(int) cvStartWindowThread( void ); + +// --------- YV --------- +enum +{ + //These 3 flags are used by cvSet/GetWindowProperty + CV_WND_PROP_FULLSCREEN = 0, //to change/get window's fullscreen property + CV_WND_PROP_AUTOSIZE = 1, //to change/get window's autosize property + CV_WND_PROP_ASPECTRATIO= 2, //to change/get window's aspectratio property + CV_WND_PROP_OPENGL = 3, //to change/get window's opengl support + + //These 2 flags are used by cvNamedWindow and cvSet/GetWindowProperty + CV_WINDOW_NORMAL = 0x00000000, //the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size + CV_WINDOW_AUTOSIZE = 0x00000001, //the user cannot resize the window, the size is constrainted by the image displayed + CV_WINDOW_OPENGL = 0x00001000, //window with opengl support + + //Those flags are only for Qt + CV_GUI_EXPANDED = 0x00000000, //status bar and tool bar + CV_GUI_NORMAL = 0x00000010, //old fashious way + + //These 3 flags are used by cvNamedWindow and cvSet/GetWindowProperty + CV_WINDOW_FULLSCREEN = 1,//change the window to fullscreen + CV_WINDOW_FREERATIO = 0x00000100,//the image expends as much as it can (no ratio constraint) + CV_WINDOW_KEEPRATIO = 0x00000000//the ration image is respected. +}; + +/* create window */ +CVAPI(int) cvNamedWindow( const char* name, int flags CV_DEFAULT(CV_WINDOW_AUTOSIZE) ); + +/* Set and Get Property of the window */ +CVAPI(void) cvSetWindowProperty(const char* name, int prop_id, double prop_value); +CVAPI(double) cvGetWindowProperty(const char* name, int prop_id); + +/* display image within window (highgui windows remember their content) */ +CVAPI(void) cvShowImage( const char* name, const CvArr* image ); + +/* resize/move window */ +CVAPI(void) cvResizeWindow( const char* name, int width, int height ); +CVAPI(void) cvMoveWindow( const char* name, int x, int y ); + + +/* destroy window and all the trackers associated with it */ +CVAPI(void) cvDestroyWindow( const char* name ); + +CVAPI(void) cvDestroyAllWindows(void); + +/* get native window handle (HWND in case of Win32 and Widget in case of X Window) */ +CVAPI(void*) cvGetWindowHandle( const char* name ); + +/* get name of highgui window given its native handle */ +CVAPI(const char*) cvGetWindowName( void* window_handle ); + + +typedef void (CV_CDECL *CvTrackbarCallback)(int pos); + +/* create trackbar and display it on top of given window, set callback */ +CVAPI(int) cvCreateTrackbar( const char* trackbar_name, const char* window_name, + int* value, int count, CvTrackbarCallback on_change CV_DEFAULT(NULL)); + +typedef void (CV_CDECL *CvTrackbarCallback2)(int pos, void* userdata); + +CVAPI(int) cvCreateTrackbar2( const char* trackbar_name, const char* window_name, + int* value, int count, CvTrackbarCallback2 on_change, + void* userdata CV_DEFAULT(0)); + +/* retrieve or set trackbar position */ +CVAPI(int) cvGetTrackbarPos( const char* trackbar_name, const char* window_name ); +CVAPI(void) cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos ); +CVAPI(void) cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval); + +enum +{ + CV_EVENT_MOUSEMOVE =0, + CV_EVENT_LBUTTONDOWN =1, + CV_EVENT_RBUTTONDOWN =2, + CV_EVENT_MBUTTONDOWN =3, + CV_EVENT_LBUTTONUP =4, + CV_EVENT_RBUTTONUP =5, + CV_EVENT_MBUTTONUP =6, + CV_EVENT_LBUTTONDBLCLK =7, + CV_EVENT_RBUTTONDBLCLK =8, + CV_EVENT_MBUTTONDBLCLK =9, + CV_EVENT_MOUSEWHEEL =10, + CV_EVENT_MOUSEHWHEEL =11 +}; + +enum +{ + CV_EVENT_FLAG_LBUTTON =1, + CV_EVENT_FLAG_RBUTTON =2, + CV_EVENT_FLAG_MBUTTON =4, + CV_EVENT_FLAG_CTRLKEY =8, + CV_EVENT_FLAG_SHIFTKEY =16, + CV_EVENT_FLAG_ALTKEY =32 +}; + + +#define CV_GET_WHEEL_DELTA(flags) ((short)((flags >> 16) & 0xffff)) // upper 16 bits + +typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param); + +/* assign callback for mouse events */ +CVAPI(void) cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, + void* param CV_DEFAULT(NULL)); + +/* wait for key event infinitely (delay<=0) or for "delay" milliseconds */ +CVAPI(int) cvWaitKey(int delay CV_DEFAULT(0)); + +// OpenGL support + +typedef void (CV_CDECL *CvOpenGlDrawCallback)(void* userdata); +CVAPI(void) cvSetOpenGlDrawCallback(const char* window_name, CvOpenGlDrawCallback callback, void* userdata CV_DEFAULT(NULL)); + +CVAPI(void) cvSetOpenGlContext(const char* window_name); +CVAPI(void) cvUpdateWindow(const char* window_name); + + +/****************************************************************************************\ + +* Obsolete functions/synonyms * +\****************************************************************************************/ + +#define cvAddSearchPath(path) +#define cvvInitSystem cvInitSystem +#define cvvNamedWindow cvNamedWindow +#define cvvShowImage cvShowImage +#define cvvResizeWindow cvResizeWindow +#define cvvDestroyWindow cvDestroyWindow +#define cvvCreateTrackbar cvCreateTrackbar +#define cvvAddSearchPath cvAddSearchPath +#define cvvWaitKey(name) cvWaitKey(0) +#define cvvWaitKeyEx(name,delay) cvWaitKey(delay) +#define HG_AUTOSIZE CV_WINDOW_AUTOSIZE +#define set_preprocess_func cvSetPreprocessFuncWin32 +#define set_postprocess_func cvSetPostprocessFuncWin32 + +#if defined WIN32 || defined _WIN32 + +CVAPI(void) cvSetPreprocessFuncWin32_(const void* callback); +CVAPI(void) cvSetPostprocessFuncWin32_(const void* callback); +#define cvSetPreprocessFuncWin32(callback) cvSetPreprocessFuncWin32_((const void*)(callback)) +#define cvSetPostprocessFuncWin32(callback) cvSetPostprocessFuncWin32_((const void*)(callback)) + +#endif + +/** @} highgui_c */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/opencv2/imgcodecs.hpp b/include/opencv2/imgcodecs.hpp new file mode 100644 index 0000000..91e44fb --- /dev/null +++ b/include/opencv2/imgcodecs.hpp @@ -0,0 +1,250 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_IMGCODECS_HPP__ +#define __OPENCV_IMGCODECS_HPP__ + +#include "opencv2/core.hpp" + +/** + @defgroup imgcodecs Image file reading and writing + @{ + @defgroup imgcodecs_c C API + @defgroup imgcodecs_ios iOS glue + @} +*/ + +//////////////////////////////// image codec //////////////////////////////// +namespace cv +{ + +//! @addtogroup imgcodecs +//! @{ + +//! Imread flags +enum ImreadModes { + IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). + IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image. + IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image. + IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. + IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format. + IMREAD_LOAD_GDAL = 8 //!< If set, use the gdal driver for loading the image. + }; + +//! Imwrite flags +enum ImwriteFlags { + IMWRITE_JPEG_QUALITY = 1, //!< For JPEG, it can be a quality from 0 to 100 (the higher is the better). Default value is 95. + IMWRITE_JPEG_PROGRESSIVE = 2, //!< Enable JPEG features, 0 or 1, default is False. + IMWRITE_JPEG_OPTIMIZE = 3, //!< Enable JPEG features, 0 or 1, default is False. + IMWRITE_JPEG_RST_INTERVAL = 4, //!< JPEG restart interval, 0 - 65535, default is 0 - no restart. + IMWRITE_JPEG_LUMA_QUALITY = 5, //!< Separate luma quality level, 0 - 100, default is 0 - don't use. + IMWRITE_JPEG_CHROMA_QUALITY = 6, //!< Separate chroma quality level, 0 - 100, default is 0 - don't use. + IMWRITE_PNG_COMPRESSION = 16, //!< For PNG, it can be the compression level from 0 to 9. A higher value means a smaller size and longer compression time. Default value is 3. + IMWRITE_PNG_STRATEGY = 17, //!< One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_DEFAULT. + IMWRITE_PNG_BILEVEL = 18, //!< Binary level PNG, 0 or 1, default is 0. + IMWRITE_PXM_BINARY = 32, //!< For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1. + IMWRITE_WEBP_QUALITY = 64 //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used. + }; + +//! Imwrite PNG specific flags +enum ImwritePNGFlags { + IMWRITE_PNG_STRATEGY_DEFAULT = 0, + IMWRITE_PNG_STRATEGY_FILTERED = 1, + IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, + IMWRITE_PNG_STRATEGY_RLE = 3, + IMWRITE_PNG_STRATEGY_FIXED = 4 + }; + +/** @brief Loads an image from a file. + +@anchor imread + +@param filename Name of file to be loaded. +@param flags Flag that can take values of @ref cv::ImreadModes + +The function imread loads an image from the specified file and returns it. If the image cannot be +read (because of missing file, improper permissions, unsupported or invalid format), the function +returns an empty matrix ( Mat::data==NULL ). Currently, the following file formats are supported: + +- Windows bitmaps - \*.bmp, \*.dib (always supported) +- JPEG files - \*.jpeg, \*.jpg, \*.jpe (see the *Notes* section) +- JPEG 2000 files - \*.jp2 (see the *Notes* section) +- Portable Network Graphics - \*.png (see the *Notes* section) +- WebP - \*.webp (see the *Notes* section) +- Portable image format - \*.pbm, \*.pgm, \*.ppm (always supported) +- Sun rasters - \*.sr, \*.ras (always supported) +- TIFF files - \*.tiff, \*.tif (see the *Notes* section) + +@note + +- The function determines the type of an image by the content, not by the file extension. +- On Microsoft Windows\* OS and MacOSX\*, the codecs shipped with an OpenCV image (libjpeg, + libpng, libtiff, and libjasper) are used by default. So, OpenCV can always read JPEGs, PNGs, + and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers. But beware + that currently these native image loaders give images with different pixel values because of + the color management embedded into MacOSX. +- On Linux\*, BSD flavors and other Unix-like open-source operating systems, OpenCV looks for + codecs supplied with an OS image. Install the relevant packages (do not forget the development + files, for example, "libjpeg-dev", in Debian\* and Ubuntu\*) to get the codec support or turn + on the OPENCV_BUILD_3RDPARTY_LIBS flag in CMake. + +@note In the case of color images, the decoded images will have the channels stored in B G R order. + */ +CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR ); + +/** @brief Loads a multi-page image from a file. (see imread for details.) + +@param filename Name of file to be loaded. +@param flags Flag that can take values of @ref cv::ImreadModes, default with IMREAD_ANYCOLOR. +@param mats A vector of Mat objects holding each page, if more than one. + +*/ +CV_EXPORTS_W bool imreadmulti(const String& filename, std::vector& mats, int flags = IMREAD_ANYCOLOR); + +/** @brief Saves an image to a specified file. + +@param filename Name of the file. +@param img Image to be saved. +@param params Format-specific save parameters encoded as pairs, see @ref cv::ImwriteFlags +paramId_1, paramValue_1, paramId_2, paramValue_2, ... . + +The function imwrite saves the image to the specified file. The image format is chosen based on the +filename extension (see imread for the list of extensions). Only 8-bit (or 16-bit unsigned (CV_16U) +in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with 'BGR' channel order) images +can be saved using this function. If the format, depth or channel order is different, use +Mat::convertTo , and cvtColor to convert it before saving. Or, use the universal FileStorage I/O +functions to save the image to XML or YAML format. + +It is possible to store PNG images with an alpha channel using this function. To do this, create +8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels +should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535. The sample below +shows how to create such a BGRA image and store to PNG file. It also demonstrates how to set custom +compression parameters : +@code + #include + #include + #include + + using namespace cv; + using namespace std; + + void createAlphaMat(Mat &mat) + { + CV_Assert(mat.channels() == 4); + for (int i = 0; i < mat.rows; ++i) { + for (int j = 0; j < mat.cols; ++j) { + Vec4b& bgra = mat.at(i, j); + bgra[0] = UCHAR_MAX; // Blue + bgra[1] = saturate_cast((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX); // Green + bgra[2] = saturate_cast((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX); // Red + bgra[3] = saturate_cast(0.5 * (bgra[1] + bgra[2])); // Alpha + } + } + } + + int main(int argv, char **argc) + { + // Create mat with alpha channel + Mat mat(480, 640, CV_8UC4); + createAlphaMat(mat); + + vector compression_params; + compression_params.push_back(IMWRITE_PNG_COMPRESSION); + compression_params.push_back(9); + + try { + imwrite("alpha.png", mat, compression_params); + } + catch (runtime_error& ex) { + fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); + return 1; + } + + fprintf(stdout, "Saved PNG file with alpha data.\n"); + return 0; + } +@endcode + */ +CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, + const std::vector& params = std::vector()); + +/** @overload */ +CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); + +/** @brief Reads an image from a buffer in memory. + +@param buf Input array or vector of bytes. +@param flags The same flags as in imread, see @ref cv::ImreadModes. +@param dst The optional output placeholder for the decoded matrix. It can save the image +reallocations when the function is called repeatedly for images of the same size. + +The function reads an image from the specified buffer in the memory. If the buffer is too short or +contains invalid data, the empty matrix/image is returned. + +See imread for the list of supported formats and flags description. + +@note In the case of color images, the decoded images will have the channels stored in B G R order. + */ +CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst); + +/** @brief Encodes an image into a memory buffer. + +@param ext File extension that defines the output format. +@param img Image to be written. +@param buf Output buffer resized to fit the compressed image. +@param params Format-specific parameters. See imwrite and @ref cv::ImwriteFlags. + +The function compresses the image and stores it in the memory buffer that is resized to fit the +result. See imwrite for the list of supported formats and flags description. + +@note cvEncodeImage returns single-row matrix of type CV_8UC1 that contains encoded image as array +of bytes. + */ +CV_EXPORTS_W bool imencode( const String& ext, InputArray img, + CV_OUT std::vector& buf, + const std::vector& params = std::vector()); + +//! @} imgcodecs + +} // cv + +#endif //__OPENCV_IMGCODECS_HPP__ diff --git a/include/opencv2/imgcodecs/imgcodecs.hpp b/include/opencv2/imgcodecs/imgcodecs.hpp new file mode 100644 index 0000000..a3cd232 --- /dev/null +++ b/include/opencv2/imgcodecs/imgcodecs.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/imgcodecs.hpp" diff --git a/include/opencv2/imgcodecs/imgcodecs_c.h b/include/opencv2/imgcodecs/imgcodecs_c.h new file mode 100644 index 0000000..ad793cc --- /dev/null +++ b/include/opencv2/imgcodecs/imgcodecs_c.h @@ -0,0 +1,137 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_IMGCODECS_H__ +#define __OPENCV_IMGCODECS_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup imgcodecs_c + @{ + */ + +enum +{ +/* 8bit, color or not */ + CV_LOAD_IMAGE_UNCHANGED =-1, +/* 8bit, gray */ + CV_LOAD_IMAGE_GRAYSCALE =0, +/* ?, color */ + CV_LOAD_IMAGE_COLOR =1, +/* any depth, ? */ + CV_LOAD_IMAGE_ANYDEPTH =2, +/* ?, any color */ + CV_LOAD_IMAGE_ANYCOLOR =4 +}; + +/* load image from file + iscolor can be a combination of above flags where CV_LOAD_IMAGE_UNCHANGED + overrides the other flags + using CV_LOAD_IMAGE_ANYCOLOR alone is equivalent to CV_LOAD_IMAGE_UNCHANGED + unless CV_LOAD_IMAGE_ANYDEPTH is specified images are converted to 8bit +*/ +CVAPI(IplImage*) cvLoadImage( const char* filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); +CVAPI(CvMat*) cvLoadImageM( const char* filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); + +enum +{ + CV_IMWRITE_JPEG_QUALITY =1, + CV_IMWRITE_JPEG_PROGRESSIVE =2, + CV_IMWRITE_JPEG_OPTIMIZE =3, + CV_IMWRITE_JPEG_RST_INTERVAL =4, + CV_IMWRITE_JPEG_LUMA_QUALITY =5, + CV_IMWRITE_JPEG_CHROMA_QUALITY =6, + CV_IMWRITE_PNG_COMPRESSION =16, + CV_IMWRITE_PNG_STRATEGY =17, + CV_IMWRITE_PNG_BILEVEL =18, + CV_IMWRITE_PNG_STRATEGY_DEFAULT =0, + CV_IMWRITE_PNG_STRATEGY_FILTERED =1, + CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY =2, + CV_IMWRITE_PNG_STRATEGY_RLE =3, + CV_IMWRITE_PNG_STRATEGY_FIXED =4, + CV_IMWRITE_PXM_BINARY =32, + CV_IMWRITE_WEBP_QUALITY =64 +}; + +/* save image to file */ +CVAPI(int) cvSaveImage( const char* filename, const CvArr* image, + const int* params CV_DEFAULT(0) ); + +/* decode image stored in the buffer */ +CVAPI(IplImage*) cvDecodeImage( const CvMat* buf, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); +CVAPI(CvMat*) cvDecodeImageM( const CvMat* buf, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); + +/* encode image and store the result as a byte vector (single-row 8uC1 matrix) */ +CVAPI(CvMat*) cvEncodeImage( const char* ext, const CvArr* image, + const int* params CV_DEFAULT(0) ); + +enum +{ + CV_CVTIMG_FLIP =1, + CV_CVTIMG_SWAP_RB =2 +}; + +/* utility function: convert one image to another with optional vertical flip */ +CVAPI(void) cvConvertImage( const CvArr* src, CvArr* dst, int flags CV_DEFAULT(0)); + +CVAPI(int) cvHaveImageReader(const char* filename); +CVAPI(int) cvHaveImageWriter(const char* filename); + + +/****************************************************************************************\ +* Obsolete functions/synonyms * +\****************************************************************************************/ + +#define cvvLoadImage(name) cvLoadImage((name),1) +#define cvvSaveImage cvSaveImage +#define cvvConvertImage cvConvertImage + +/** @} imgcodecs_c */ + +#ifdef __cplusplus +} +#endif + +#endif // __OPENCV_IMGCODECS_H__ diff --git a/include/opencv2/imgcodecs/ios.h b/include/opencv2/imgcodecs/ios.h new file mode 100644 index 0000000..fbd6371 --- /dev/null +++ b/include/opencv2/imgcodecs/ios.h @@ -0,0 +1,57 @@ + +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#import +#import +#import +#import +#include "opencv2/core/core.hpp" + +//! @addtogroup imgcodecs_ios +//! @{ + +UIImage* MatToUIImage(const cv::Mat& image); +void UIImageToMat(const UIImage* image, + cv::Mat& m, bool alphaExist = false); + +//! @} diff --git a/include/opencv2/imgproc.hpp b/include/opencv2/imgproc.hpp new file mode 100644 index 0000000..5c18545 --- /dev/null +++ b/include/opencv2/imgproc.hpp @@ -0,0 +1,4244 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_IMGPROC_HPP__ +#define __OPENCV_IMGPROC_HPP__ + +#include "opencv2/core.hpp" + +/** + @defgroup imgproc Image processing + @{ + @defgroup imgproc_filter Image Filtering + +Functions and classes described in this section are used to perform various linear or non-linear +filtering operations on 2D images (represented as Mat's). It means that for each pixel location +\f$(x,y)\f$ in the source image (normally, rectangular), its neighborhood is considered and used to +compute the response. In case of a linear filter, it is a weighted sum of pixel values. In case of +morphological operations, it is the minimum or maximum values, and so on. The computed response is +stored in the destination image at the same location \f$(x,y)\f$. It means that the output image +will be of the same size as the input image. Normally, the functions support multi-channel arrays, +in which case every channel is processed independently. Therefore, the output image will also have +the same number of channels as the input one. + +Another common feature of the functions and classes described in this section is that, unlike +simple arithmetic functions, they need to extrapolate values of some non-existing pixels. For +example, if you want to smooth an image using a Gaussian \f$3 \times 3\f$ filter, then, when +processing the left-most pixels in each row, you need pixels to the left of them, that is, outside +of the image. You can let these pixels be the same as the left-most image pixels ("replicated +border" extrapolation method), or assume that all the non-existing pixels are zeros ("constant +border" extrapolation method), and so on. OpenCV enables you to specify the extrapolation method. +For details, see cv::BorderTypes + +@anchor filter_depths +### Depth combinations +Input depth (src.depth()) | Output depth (ddepth) +--------------------------|---------------------- +CV_8U | -1/CV_16S/CV_32F/CV_64F +CV_16U/CV_16S | -1/CV_32F/CV_64F +CV_32F | -1/CV_32F/CV_64F +CV_64F | -1/CV_64F + +@note when ddepth=-1, the output image will have the same depth as the source. + + @defgroup imgproc_transform Geometric Image Transformations + +The functions in this section perform various geometrical transformations of 2D images. They do not +change the image content but deform the pixel grid and map this deformed grid to the destination +image. In fact, to avoid sampling artifacts, the mapping is done in the reverse order, from +destination to the source. That is, for each pixel \f$(x, y)\f$ of the destination image, the +functions compute coordinates of the corresponding "donor" pixel in the source image and copy the +pixel value: + +\f[\texttt{dst} (x,y)= \texttt{src} (f_x(x,y), f_y(x,y))\f] + +In case when you specify the forward mapping \f$\left: \texttt{src} \rightarrow +\texttt{dst}\f$, the OpenCV functions first compute the corresponding inverse mapping +\f$\left: \texttt{dst} \rightarrow \texttt{src}\f$ and then use the above formula. + +The actual implementations of the geometrical transformations, from the most generic remap and to +the simplest and the fastest resize, need to solve two main problems with the above formula: + +- Extrapolation of non-existing pixels. Similarly to the filtering functions described in the +previous section, for some \f$(x,y)\f$, either one of \f$f_x(x,y)\f$, or \f$f_y(x,y)\f$, or both +of them may fall outside of the image. In this case, an extrapolation method needs to be used. +OpenCV provides the same selection of extrapolation methods as in the filtering functions. In +addition, it provides the method BORDER_TRANSPARENT. This means that the corresponding pixels in +the destination image will not be modified at all. + +- Interpolation of pixel values. Usually \f$f_x(x,y)\f$ and \f$f_y(x,y)\f$ are floating-point +numbers. This means that \f$\left\f$ can be either an affine or perspective +transformation, or radial lens distortion correction, and so on. So, a pixel value at fractional +coordinates needs to be retrieved. In the simplest case, the coordinates can be just rounded to the +nearest integer coordinates and the corresponding pixel can be used. This is called a +nearest-neighbor interpolation. However, a better result can be achieved by using more +sophisticated [interpolation methods](http://en.wikipedia.org/wiki/Multivariate_interpolation) , +where a polynomial function is fit into some neighborhood of the computed pixel \f$(f_x(x,y), +f_y(x,y))\f$, and then the value of the polynomial at \f$(f_x(x,y), f_y(x,y))\f$ is taken as the +interpolated pixel value. In OpenCV, you can choose between several interpolation methods. See +resize for details. + + @defgroup imgproc_misc Miscellaneous Image Transformations + @defgroup imgproc_draw Drawing Functions + +Drawing functions work with matrices/images of arbitrary depth. The boundaries of the shapes can be +rendered with antialiasing (implemented only for 8-bit images for now). All the functions include +the parameter color that uses an RGB value (that may be constructed with the Scalar constructor ) +for color images and brightness for grayscale images. For color images, the channel ordering is +normally *Blue, Green, Red*. This is what imshow, imread, and imwrite expect. So, if you form a +color using the Scalar constructor, it should look like: + +\f[\texttt{Scalar} (blue \_ component, green \_ component, red \_ component[, alpha \_ component])\f] + +If you are using your own image rendering and I/O functions, you can use any channel ordering. The +drawing functions process each channel independently and do not depend on the channel order or even +on the used color space. The whole image can be converted from BGR to RGB or to a different color +space using cvtColor . + +If a drawn figure is partially or completely outside the image, the drawing functions clip it. Also, +many drawing functions can handle pixel coordinates specified with sub-pixel accuracy. This means +that the coordinates can be passed as fixed-point numbers encoded as integers. The number of +fractional bits is specified by the shift parameter and the real point coordinates are calculated as +\f$\texttt{Point}(x,y)\rightarrow\texttt{Point2f}(x*2^{-shift},y*2^{-shift})\f$ . This feature is +especially effective when rendering antialiased shapes. + +@note The functions do not support alpha-transparency when the target image is 4-channel. In this +case, the color[3] is simply copied to the repainted pixels. Thus, if you want to paint +semi-transparent shapes, you can paint them in a separate buffer and then blend it with the main +image. + + @defgroup imgproc_colormap ColorMaps in OpenCV + +The human perception isn't built for observing fine changes in grayscale images. Human eyes are more +sensitive to observing changes between colors, so you often need to recolor your grayscale images to +get a clue about them. OpenCV now comes with various colormaps to enhance the visualization in your +computer vision application. + +In OpenCV you only need applyColorMap to apply a colormap on a given image. The following sample +code reads the path to an image from command line, applies a Jet colormap on it and shows the +result: + +@code +#include +#include +#include +#include +using namespace cv; + +#include +using namespace std; + +int main(int argc, const char *argv[]) +{ + // We need an input image. (can be grayscale or color) + if (argc < 2) + { + cerr << "We need an image to process here. Please run: colorMap [path_to_image]" << endl; + return -1; + } + Mat img_in = imread(argv[1]); + if(img_in.empty()) + { + cerr << "Sample image (" << argv[1] << ") is empty. Please adjust your path, so it points to a valid input image!" << endl; + return -1; + } + // Holds the colormap version of the image: + Mat img_color; + // Apply the colormap: + applyColorMap(img_in, img_color, COLORMAP_JET); + // Show the result: + imshow("colorMap", img_color); + waitKey(0); + return 0; +} +@endcode + +@see cv::ColormapTypes + + @defgroup imgproc_hist Histograms + @defgroup imgproc_shape Structural Analysis and Shape Descriptors + @defgroup imgproc_motion Motion Analysis and Object Tracking + @defgroup imgproc_feature Feature Detection + @defgroup imgproc_object Object Detection + @defgroup imgproc_c C API + @} +*/ + +namespace cv +{ + +/** @addtogroup imgproc +@{ +*/ + +//! @addtogroup imgproc_filter +//! @{ + +//! type of morphological operation +enum MorphTypes{ + MORPH_ERODE = 0, //!< see cv::erode + MORPH_DILATE = 1, //!< see cv::dilate + MORPH_OPEN = 2, //!< an opening operation + //!< \f[\texttt{dst} = \mathrm{open} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \mathrm{erode} ( \texttt{src} , \texttt{element} ))\f] + MORPH_CLOSE = 3, //!< a closing operation + //!< \f[\texttt{dst} = \mathrm{close} ( \texttt{src} , \texttt{element} )= \mathrm{erode} ( \mathrm{dilate} ( \texttt{src} , \texttt{element} ))\f] + MORPH_GRADIENT = 4, //!< a morphological gradient + //!< \f[\texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} )\f] + MORPH_TOPHAT = 5, //!< "top hat" + //!< \f[\texttt{dst} = \mathrm{tophat} ( \texttt{src} , \texttt{element} )= \texttt{src} - \mathrm{open} ( \texttt{src} , \texttt{element} )\f] + MORPH_BLACKHAT = 6 //!< "black hat" + //!< \f[\texttt{dst} = \mathrm{blackhat} ( \texttt{src} , \texttt{element} )= \mathrm{close} ( \texttt{src} , \texttt{element} )- \texttt{src}\f] +}; + +//! shape of the structuring element +enum MorphShapes { + MORPH_RECT = 0, //!< a rectangular structuring element: \f[E_{ij}=1\f] + MORPH_CROSS = 1, //!< a cross-shaped structuring element: + //!< \f[E_{ij} = \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}\f] + MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed + //!< into the rectangle Rect(0, 0, esize.width, 0.esize.height) +}; + +//! @} imgproc_filter + +//! @addtogroup imgproc_transform +//! @{ + +//! interpolation algorithm +enum InterpolationFlags{ + /** nearest neighbor interpolation */ + INTER_NEAREST = 0, + /** bilinear interpolation */ + INTER_LINEAR = 1, + /** bicubic interpolation */ + INTER_CUBIC = 2, + /** resampling using pixel area relation. It may be a preferred method for image decimation, as + it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST + method. */ + INTER_AREA = 3, + /** Lanczos interpolation over 8x8 neighborhood */ + INTER_LANCZOS4 = 4, + /** mask for interpolation codes */ + INTER_MAX = 7, + /** flag, fills all of the destination image pixels. If some of them correspond to outliers in the + source image, they are set to zero */ + WARP_FILL_OUTLIERS = 8, + /** flag, inverse transformation + + For example, polar transforms: + - flag is __not__ set: \f$dst( \phi , \rho ) = src(x,y)\f$ + - flag is set: \f$dst(x,y) = src( \phi , \rho )\f$ + */ + WARP_INVERSE_MAP = 16 +}; + +enum InterpolationMasks { + INTER_BITS = 5, + INTER_BITS2 = INTER_BITS * 2, + INTER_TAB_SIZE = 1 << INTER_BITS, + INTER_TAB_SIZE2 = INTER_TAB_SIZE * INTER_TAB_SIZE + }; + +//! @} imgproc_transform + +//! @addtogroup imgproc_misc +//! @{ + +//! Distance types for Distance Transform and M-estimators +//! @see cv::distanceTransform, cv::fitLine +enum DistanceTypes { + DIST_USER = -1, //!< User defined distance + DIST_L1 = 1, //!< distance = |x1-x2| + |y1-y2| + DIST_L2 = 2, //!< the simple euclidean distance + DIST_C = 3, //!< distance = max(|x1-x2|,|y1-y2|) + DIST_L12 = 4, //!< L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1)) + DIST_FAIR = 5, //!< distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998 + DIST_WELSCH = 6, //!< distance = c^2/2(1-exp(-(x/c)^2)), c = 2.9846 + DIST_HUBER = 7 //!< distance = |x| \texttt{thresh}\)}{0}{otherwise}\f] + THRESH_BINARY_INV = 1, //!< \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{maxval}}{otherwise}\f] + THRESH_TRUNC = 2, //!< \f[\texttt{dst} (x,y) = \fork{\texttt{threshold}}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f] + THRESH_TOZERO = 3, //!< \f[\texttt{dst} (x,y) = \fork{\texttt{src}(x,y)}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{0}{otherwise}\f] + THRESH_TOZERO_INV = 4, //!< \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f] + THRESH_MASK = 7, + THRESH_OTSU = 8, //!< flag, use Otsu algorithm to choose the optimal threshold value + THRESH_TRIANGLE = 16 //!< flag, use Triangle algorithm to choose the optimal threshold value +}; + +//! adaptive threshold algorithm +//! see cv::adaptiveThreshold +enum AdaptiveThresholdTypes { + /** the threshold value \f$T(x,y)\f$ is a mean of the \f$\texttt{blockSize} \times + \texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$ minus C */ + ADAPTIVE_THRESH_MEAN_C = 0, + /** the threshold value \f$T(x, y)\f$ is a weighted sum (cross-correlation with a Gaussian + window) of the \f$\texttt{blockSize} \times \texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$ + minus C . The default sigma (standard deviation) is used for the specified blockSize . See + cv::getGaussianKernel*/ + ADAPTIVE_THRESH_GAUSSIAN_C = 1 +}; + +//! cv::undistort mode +enum UndistortTypes { + PROJ_SPHERICAL_ORTHO = 0, + PROJ_SPHERICAL_EQRECT = 1 + }; + +//! class of the pixel in GrabCut algorithm +enum GrabCutClasses { + GC_BGD = 0, //!< an obvious background pixels + GC_FGD = 1, //!< an obvious foreground (object) pixel + GC_PR_BGD = 2, //!< a possible background pixel + GC_PR_FGD = 3 //!< a possible foreground pixel +}; + +//! GrabCut algorithm flags +enum GrabCutModes { + /** The function initializes the state and the mask using the provided rectangle. After that it + runs iterCount iterations of the algorithm. */ + GC_INIT_WITH_RECT = 0, + /** The function initializes the state using the provided mask. Note that GC_INIT_WITH_RECT + and GC_INIT_WITH_MASK can be combined. Then, all the pixels outside of the ROI are + automatically initialized with GC_BGD .*/ + GC_INIT_WITH_MASK = 1, + /** The value means that the algorithm should just resume. */ + GC_EVAL = 2 +}; + +//! distanceTransform algorithm flags +enum DistanceTransformLabelTypes { + /** each connected component of zeros in src (as well as all the non-zero pixels closest to the + connected component) will be assigned the same label */ + DIST_LABEL_CCOMP = 0, + /** each zero pixel (and all the non-zero pixels closest to it) gets its own label. */ + DIST_LABEL_PIXEL = 1 +}; + +//! floodfill algorithm flags +enum FloodFillFlags { + /** If set, the difference between the current pixel and seed pixel is considered. Otherwise, + the difference between neighbor pixels is considered (that is, the range is floating). */ + FLOODFILL_FIXED_RANGE = 1 << 16, + /** If set, the function does not change the image ( newVal is ignored), and only fills the + mask with the value specified in bits 8-16 of flags as described above. This option only make + sense in function variants that have the mask parameter. */ + FLOODFILL_MASK_ONLY = 1 << 17 +}; + +//! @} imgproc_misc + +//! @addtogroup imgproc_shape +//! @{ + +//! connected components algorithm output formats +enum ConnectedComponentsTypes { + CC_STAT_LEFT = 0, //!< The leftmost (x) coordinate which is the inclusive start of the bounding + //!< box in the horizontal direction. + CC_STAT_TOP = 1, //!< The topmost (y) coordinate which is the inclusive start of the bounding + //!< box in the vertical direction. + CC_STAT_WIDTH = 2, //!< The horizontal size of the bounding box + CC_STAT_HEIGHT = 3, //!< The vertical size of the bounding box + CC_STAT_AREA = 4, //!< The total area (in pixels) of the connected component + CC_STAT_MAX = 5 +}; + +//! mode of the contour retrieval algorithm +enum RetrievalModes { + /** retrieves only the extreme outer contours. It sets `hierarchy[i][2]=hierarchy[i][3]=-1` for + all the contours. */ + RETR_EXTERNAL = 0, + /** retrieves all of the contours without establishing any hierarchical relationships. */ + RETR_LIST = 1, + /** retrieves all of the contours and organizes them into a two-level hierarchy. At the top + level, there are external boundaries of the components. At the second level, there are + boundaries of the holes. If there is another contour inside a hole of a connected component, it + is still put at the top level. */ + RETR_CCOMP = 2, + /** retrieves all of the contours and reconstructs a full hierarchy of nested contours.*/ + RETR_TREE = 3, + RETR_FLOODFILL = 4 //!< +}; + +//! the contour approximation algorithm +enum ContourApproximationModes { + /** stores absolutely all the contour points. That is, any 2 subsequent points (x1,y1) and + (x2,y2) of the contour will be either horizontal, vertical or diagonal neighbors, that is, + max(abs(x1-x2),abs(y2-y1))==1. */ + CHAIN_APPROX_NONE = 1, + /** compresses horizontal, vertical, and diagonal segments and leaves only their end points. + For example, an up-right rectangular contour is encoded with 4 points. */ + CHAIN_APPROX_SIMPLE = 2, + /** applies one of the flavors of the Teh-Chin chain approximation algorithm @cite TehChin89 */ + CHAIN_APPROX_TC89_L1 = 3, + /** applies one of the flavors of the Teh-Chin chain approximation algorithm @cite TehChin89 */ + CHAIN_APPROX_TC89_KCOS = 4 +}; + +//! @} imgproc_shape + +//! Variants of a Hough transform +enum HoughModes { + + /** classical or standard Hough transform. Every line is represented by two floating-point + numbers \f$(\rho, \theta)\f$ , where \f$\rho\f$ is a distance between (0,0) point and the line, + and \f$\theta\f$ is the angle between x-axis and the normal to the line. Thus, the matrix must + be (the created sequence will be) of CV_32FC2 type */ + HOUGH_STANDARD = 0, + /** probabilistic Hough transform (more efficient in case if the picture contains a few long + linear segments). It returns line segments rather than the whole line. Each segment is + represented by starting and ending points, and the matrix must be (the created sequence will + be) of the CV_32SC4 type. */ + HOUGH_PROBABILISTIC = 1, + /** multi-scale variant of the classical Hough transform. The lines are encoded the same way as + HOUGH_STANDARD. */ + HOUGH_MULTI_SCALE = 2, + HOUGH_GRADIENT = 3 //!< basically *21HT*, described in @cite Yuen90 +}; + +//! Variants of Line Segment %Detector +//! @ingroup imgproc_feature +enum LineSegmentDetectorModes { + LSD_REFINE_NONE = 0, //!< No refinement applied + LSD_REFINE_STD = 1, //!< Standard refinement is applied. E.g. breaking arches into smaller straighter line approximations. + LSD_REFINE_ADV = 2 //!< Advanced refinement. Number of false alarms is calculated, lines are + //!< refined through increase of precision, decrement in size, etc. +}; + +/** Histogram comparison methods + @ingroup imgproc_hist +*/ +enum HistCompMethods { + /** Correlation + \f[d(H_1,H_2) = \frac{\sum_I (H_1(I) - \bar{H_1}) (H_2(I) - \bar{H_2})}{\sqrt{\sum_I(H_1(I) - \bar{H_1})^2 \sum_I(H_2(I) - \bar{H_2})^2}}\f] + where + \f[\bar{H_k} = \frac{1}{N} \sum _J H_k(J)\f] + and \f$N\f$ is a total number of histogram bins. */ + HISTCMP_CORREL = 0, + /** Chi-Square + \f[d(H_1,H_2) = \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)}\f] */ + HISTCMP_CHISQR = 1, + /** Intersection + \f[d(H_1,H_2) = \sum _I \min (H_1(I), H_2(I))\f] */ + HISTCMP_INTERSECT = 2, + /** Bhattacharyya distance + (In fact, OpenCV computes Hellinger distance, which is related to Bhattacharyya coefficient.) + \f[d(H_1,H_2) = \sqrt{1 - \frac{1}{\sqrt{\bar{H_1} \bar{H_2} N^2}} \sum_I \sqrt{H_1(I) \cdot H_2(I)}}\f] */ + HISTCMP_BHATTACHARYYA = 3, + HISTCMP_HELLINGER = HISTCMP_BHATTACHARYYA, //!< Synonym for HISTCMP_BHATTACHARYYA + /** Alternative Chi-Square + \f[d(H_1,H_2) = 2 * \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)+H_2(I)}\f] + This alternative formula is regularly used for texture comparison. See e.g. @cite Puzicha1997 */ + HISTCMP_CHISQR_ALT = 4, + /** Kullback-Leibler divergence + \f[d(H_1,H_2) = \sum _I H_1(I) \log \left(\frac{H_1(I)}{H_2(I)}\right)\f] */ + HISTCMP_KL_DIV = 5 +}; + +/** the color conversion code +@see @ref imgproc_color_conversions +@ingroup imgproc_misc + */ +enum ColorConversionCodes { + COLOR_BGR2BGRA = 0, //!< add alpha channel to RGB or BGR image + COLOR_RGB2RGBA = COLOR_BGR2BGRA, + + COLOR_BGRA2BGR = 1, //!< remove alpha channel from RGB or BGR image + COLOR_RGBA2RGB = COLOR_BGRA2BGR, + + COLOR_BGR2RGBA = 2, //!< convert between RGB and BGR color spaces (with or without alpha channel) + COLOR_RGB2BGRA = COLOR_BGR2RGBA, + + COLOR_RGBA2BGR = 3, + COLOR_BGRA2RGB = COLOR_RGBA2BGR, + + COLOR_BGR2RGB = 4, + COLOR_RGB2BGR = COLOR_BGR2RGB, + + COLOR_BGRA2RGBA = 5, + COLOR_RGBA2BGRA = COLOR_BGRA2RGBA, + + COLOR_BGR2GRAY = 6, //!< convert between RGB/BGR and grayscale, @ref color_convert_rgb_gray "color conversions" + COLOR_RGB2GRAY = 7, + COLOR_GRAY2BGR = 8, + COLOR_GRAY2RGB = COLOR_GRAY2BGR, + COLOR_GRAY2BGRA = 9, + COLOR_GRAY2RGBA = COLOR_GRAY2BGRA, + COLOR_BGRA2GRAY = 10, + COLOR_RGBA2GRAY = 11, + + COLOR_BGR2BGR565 = 12, //!< convert between RGB/BGR and BGR565 (16-bit images) + COLOR_RGB2BGR565 = 13, + COLOR_BGR5652BGR = 14, + COLOR_BGR5652RGB = 15, + COLOR_BGRA2BGR565 = 16, + COLOR_RGBA2BGR565 = 17, + COLOR_BGR5652BGRA = 18, + COLOR_BGR5652RGBA = 19, + + COLOR_GRAY2BGR565 = 20, //!< convert between grayscale to BGR565 (16-bit images) + COLOR_BGR5652GRAY = 21, + + COLOR_BGR2BGR555 = 22, //!< convert between RGB/BGR and BGR555 (16-bit images) + COLOR_RGB2BGR555 = 23, + COLOR_BGR5552BGR = 24, + COLOR_BGR5552RGB = 25, + COLOR_BGRA2BGR555 = 26, + COLOR_RGBA2BGR555 = 27, + COLOR_BGR5552BGRA = 28, + COLOR_BGR5552RGBA = 29, + + COLOR_GRAY2BGR555 = 30, //!< convert between grayscale and BGR555 (16-bit images) + COLOR_BGR5552GRAY = 31, + + COLOR_BGR2XYZ = 32, //!< convert RGB/BGR to CIE XYZ, @ref color_convert_rgb_xyz "color conversions" + COLOR_RGB2XYZ = 33, + COLOR_XYZ2BGR = 34, + COLOR_XYZ2RGB = 35, + + COLOR_BGR2YCrCb = 36, //!< convert RGB/BGR to luma-chroma (aka YCC), @ref color_convert_rgb_ycrcb "color conversions" + COLOR_RGB2YCrCb = 37, + COLOR_YCrCb2BGR = 38, + COLOR_YCrCb2RGB = 39, + + COLOR_BGR2HSV = 40, //!< convert RGB/BGR to HSV (hue saturation value), @ref color_convert_rgb_hsv "color conversions" + COLOR_RGB2HSV = 41, + + COLOR_BGR2Lab = 44, //!< convert RGB/BGR to CIE Lab, @ref color_convert_rgb_lab "color conversions" + COLOR_RGB2Lab = 45, + + COLOR_BGR2Luv = 50, //!< convert RGB/BGR to CIE Luv, @ref color_convert_rgb_luv "color conversions" + COLOR_RGB2Luv = 51, + COLOR_BGR2HLS = 52, //!< convert RGB/BGR to HLS (hue lightness saturation), @ref color_convert_rgb_hls "color conversions" + COLOR_RGB2HLS = 53, + + COLOR_HSV2BGR = 54, //!< backward conversions to RGB/BGR + COLOR_HSV2RGB = 55, + + COLOR_Lab2BGR = 56, + COLOR_Lab2RGB = 57, + COLOR_Luv2BGR = 58, + COLOR_Luv2RGB = 59, + COLOR_HLS2BGR = 60, + COLOR_HLS2RGB = 61, + + COLOR_BGR2HSV_FULL = 66, //!< + COLOR_RGB2HSV_FULL = 67, + COLOR_BGR2HLS_FULL = 68, + COLOR_RGB2HLS_FULL = 69, + + COLOR_HSV2BGR_FULL = 70, + COLOR_HSV2RGB_FULL = 71, + COLOR_HLS2BGR_FULL = 72, + COLOR_HLS2RGB_FULL = 73, + + COLOR_LBGR2Lab = 74, + COLOR_LRGB2Lab = 75, + COLOR_LBGR2Luv = 76, + COLOR_LRGB2Luv = 77, + + COLOR_Lab2LBGR = 78, + COLOR_Lab2LRGB = 79, + COLOR_Luv2LBGR = 80, + COLOR_Luv2LRGB = 81, + + COLOR_BGR2YUV = 82, //!< convert between RGB/BGR and YUV + COLOR_RGB2YUV = 83, + COLOR_YUV2BGR = 84, + COLOR_YUV2RGB = 85, + + //! YUV 4:2:0 family to RGB + COLOR_YUV2RGB_NV12 = 90, + COLOR_YUV2BGR_NV12 = 91, + COLOR_YUV2RGB_NV21 = 92, + COLOR_YUV2BGR_NV21 = 93, + COLOR_YUV420sp2RGB = COLOR_YUV2RGB_NV21, + COLOR_YUV420sp2BGR = COLOR_YUV2BGR_NV21, + + COLOR_YUV2RGBA_NV12 = 94, + COLOR_YUV2BGRA_NV12 = 95, + COLOR_YUV2RGBA_NV21 = 96, + COLOR_YUV2BGRA_NV21 = 97, + COLOR_YUV420sp2RGBA = COLOR_YUV2RGBA_NV21, + COLOR_YUV420sp2BGRA = COLOR_YUV2BGRA_NV21, + + COLOR_YUV2RGB_YV12 = 98, + COLOR_YUV2BGR_YV12 = 99, + COLOR_YUV2RGB_IYUV = 100, + COLOR_YUV2BGR_IYUV = 101, + COLOR_YUV2RGB_I420 = COLOR_YUV2RGB_IYUV, + COLOR_YUV2BGR_I420 = COLOR_YUV2BGR_IYUV, + COLOR_YUV420p2RGB = COLOR_YUV2RGB_YV12, + COLOR_YUV420p2BGR = COLOR_YUV2BGR_YV12, + + COLOR_YUV2RGBA_YV12 = 102, + COLOR_YUV2BGRA_YV12 = 103, + COLOR_YUV2RGBA_IYUV = 104, + COLOR_YUV2BGRA_IYUV = 105, + COLOR_YUV2RGBA_I420 = COLOR_YUV2RGBA_IYUV, + COLOR_YUV2BGRA_I420 = COLOR_YUV2BGRA_IYUV, + COLOR_YUV420p2RGBA = COLOR_YUV2RGBA_YV12, + COLOR_YUV420p2BGRA = COLOR_YUV2BGRA_YV12, + + COLOR_YUV2GRAY_420 = 106, + COLOR_YUV2GRAY_NV21 = COLOR_YUV2GRAY_420, + COLOR_YUV2GRAY_NV12 = COLOR_YUV2GRAY_420, + COLOR_YUV2GRAY_YV12 = COLOR_YUV2GRAY_420, + COLOR_YUV2GRAY_IYUV = COLOR_YUV2GRAY_420, + COLOR_YUV2GRAY_I420 = COLOR_YUV2GRAY_420, + COLOR_YUV420sp2GRAY = COLOR_YUV2GRAY_420, + COLOR_YUV420p2GRAY = COLOR_YUV2GRAY_420, + + //! YUV 4:2:2 family to RGB + COLOR_YUV2RGB_UYVY = 107, + COLOR_YUV2BGR_UYVY = 108, + //COLOR_YUV2RGB_VYUY = 109, + //COLOR_YUV2BGR_VYUY = 110, + COLOR_YUV2RGB_Y422 = COLOR_YUV2RGB_UYVY, + COLOR_YUV2BGR_Y422 = COLOR_YUV2BGR_UYVY, + COLOR_YUV2RGB_UYNV = COLOR_YUV2RGB_UYVY, + COLOR_YUV2BGR_UYNV = COLOR_YUV2BGR_UYVY, + + COLOR_YUV2RGBA_UYVY = 111, + COLOR_YUV2BGRA_UYVY = 112, + //COLOR_YUV2RGBA_VYUY = 113, + //COLOR_YUV2BGRA_VYUY = 114, + COLOR_YUV2RGBA_Y422 = COLOR_YUV2RGBA_UYVY, + COLOR_YUV2BGRA_Y422 = COLOR_YUV2BGRA_UYVY, + COLOR_YUV2RGBA_UYNV = COLOR_YUV2RGBA_UYVY, + COLOR_YUV2BGRA_UYNV = COLOR_YUV2BGRA_UYVY, + + COLOR_YUV2RGB_YUY2 = 115, + COLOR_YUV2BGR_YUY2 = 116, + COLOR_YUV2RGB_YVYU = 117, + COLOR_YUV2BGR_YVYU = 118, + COLOR_YUV2RGB_YUYV = COLOR_YUV2RGB_YUY2, + COLOR_YUV2BGR_YUYV = COLOR_YUV2BGR_YUY2, + COLOR_YUV2RGB_YUNV = COLOR_YUV2RGB_YUY2, + COLOR_YUV2BGR_YUNV = COLOR_YUV2BGR_YUY2, + + COLOR_YUV2RGBA_YUY2 = 119, + COLOR_YUV2BGRA_YUY2 = 120, + COLOR_YUV2RGBA_YVYU = 121, + COLOR_YUV2BGRA_YVYU = 122, + COLOR_YUV2RGBA_YUYV = COLOR_YUV2RGBA_YUY2, + COLOR_YUV2BGRA_YUYV = COLOR_YUV2BGRA_YUY2, + COLOR_YUV2RGBA_YUNV = COLOR_YUV2RGBA_YUY2, + COLOR_YUV2BGRA_YUNV = COLOR_YUV2BGRA_YUY2, + + COLOR_YUV2GRAY_UYVY = 123, + COLOR_YUV2GRAY_YUY2 = 124, + //CV_YUV2GRAY_VYUY = CV_YUV2GRAY_UYVY, + COLOR_YUV2GRAY_Y422 = COLOR_YUV2GRAY_UYVY, + COLOR_YUV2GRAY_UYNV = COLOR_YUV2GRAY_UYVY, + COLOR_YUV2GRAY_YVYU = COLOR_YUV2GRAY_YUY2, + COLOR_YUV2GRAY_YUYV = COLOR_YUV2GRAY_YUY2, + COLOR_YUV2GRAY_YUNV = COLOR_YUV2GRAY_YUY2, + + //! alpha premultiplication + COLOR_RGBA2mRGBA = 125, + COLOR_mRGBA2RGBA = 126, + + //! RGB to YUV 4:2:0 family + COLOR_RGB2YUV_I420 = 127, + COLOR_BGR2YUV_I420 = 128, + COLOR_RGB2YUV_IYUV = COLOR_RGB2YUV_I420, + COLOR_BGR2YUV_IYUV = COLOR_BGR2YUV_I420, + + COLOR_RGBA2YUV_I420 = 129, + COLOR_BGRA2YUV_I420 = 130, + COLOR_RGBA2YUV_IYUV = COLOR_RGBA2YUV_I420, + COLOR_BGRA2YUV_IYUV = COLOR_BGRA2YUV_I420, + COLOR_RGB2YUV_YV12 = 131, + COLOR_BGR2YUV_YV12 = 132, + COLOR_RGBA2YUV_YV12 = 133, + COLOR_BGRA2YUV_YV12 = 134, + + //! Demosaicing + COLOR_BayerBG2BGR = 46, + COLOR_BayerGB2BGR = 47, + COLOR_BayerRG2BGR = 48, + COLOR_BayerGR2BGR = 49, + + COLOR_BayerBG2RGB = COLOR_BayerRG2BGR, + COLOR_BayerGB2RGB = COLOR_BayerGR2BGR, + COLOR_BayerRG2RGB = COLOR_BayerBG2BGR, + COLOR_BayerGR2RGB = COLOR_BayerGB2BGR, + + COLOR_BayerBG2GRAY = 86, + COLOR_BayerGB2GRAY = 87, + COLOR_BayerRG2GRAY = 88, + COLOR_BayerGR2GRAY = 89, + + //! Demosaicing using Variable Number of Gradients + COLOR_BayerBG2BGR_VNG = 62, + COLOR_BayerGB2BGR_VNG = 63, + COLOR_BayerRG2BGR_VNG = 64, + COLOR_BayerGR2BGR_VNG = 65, + + COLOR_BayerBG2RGB_VNG = COLOR_BayerRG2BGR_VNG, + COLOR_BayerGB2RGB_VNG = COLOR_BayerGR2BGR_VNG, + COLOR_BayerRG2RGB_VNG = COLOR_BayerBG2BGR_VNG, + COLOR_BayerGR2RGB_VNG = COLOR_BayerGB2BGR_VNG, + + //! Edge-Aware Demosaicing + COLOR_BayerBG2BGR_EA = 135, + COLOR_BayerGB2BGR_EA = 136, + COLOR_BayerRG2BGR_EA = 137, + COLOR_BayerGR2BGR_EA = 138, + + COLOR_BayerBG2RGB_EA = COLOR_BayerRG2BGR_EA, + COLOR_BayerGB2RGB_EA = COLOR_BayerGR2BGR_EA, + COLOR_BayerRG2RGB_EA = COLOR_BayerBG2BGR_EA, + COLOR_BayerGR2RGB_EA = COLOR_BayerGB2BGR_EA, + + + COLOR_COLORCVT_MAX = 139 +}; + +/** types of intersection between rectangles +@ingroup imgproc_shape +*/ +enum RectanglesIntersectTypes { + INTERSECT_NONE = 0, //!< No intersection + INTERSECT_PARTIAL = 1, //!< There is a partial intersection + INTERSECT_FULL = 2 //!< One of the rectangle is fully enclosed in the other +}; + +//! finds arbitrary template in the grayscale image using Generalized Hough Transform +class CV_EXPORTS GeneralizedHough : public Algorithm +{ +public: + //! set template to search + virtual void setTemplate(InputArray templ, Point templCenter = Point(-1, -1)) = 0; + virtual void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter = Point(-1, -1)) = 0; + + //! find template on image + virtual void detect(InputArray image, OutputArray positions, OutputArray votes = noArray()) = 0; + virtual void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions, OutputArray votes = noArray()) = 0; + + //! Canny low threshold. + virtual void setCannyLowThresh(int cannyLowThresh) = 0; + virtual int getCannyLowThresh() const = 0; + + //! Canny high threshold. + virtual void setCannyHighThresh(int cannyHighThresh) = 0; + virtual int getCannyHighThresh() const = 0; + + //! Minimum distance between the centers of the detected objects. + virtual void setMinDist(double minDist) = 0; + virtual double getMinDist() const = 0; + + //! Inverse ratio of the accumulator resolution to the image resolution. + virtual void setDp(double dp) = 0; + virtual double getDp() const = 0; + + //! Maximal size of inner buffers. + virtual void setMaxBufferSize(int maxBufferSize) = 0; + virtual int getMaxBufferSize() const = 0; +}; + +//! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122. +//! Detects position only without traslation and rotation +class CV_EXPORTS GeneralizedHoughBallard : public GeneralizedHough +{ +public: + //! R-Table levels. + virtual void setLevels(int levels) = 0; + virtual int getLevels() const = 0; + + //! The accumulator threshold for the template centers at the detection stage. The smaller it is, the more false positions may be detected. + virtual void setVotesThreshold(int votesThreshold) = 0; + virtual int getVotesThreshold() const = 0; +}; + +//! Guil, N., González-Linares, J.M. and Zapata, E.L. (1999). Bidimensional shape detection using an invariant approach. Pattern Recognition 32 (6): 1025-1038. +//! Detects position, traslation and rotation +class CV_EXPORTS GeneralizedHoughGuil : public GeneralizedHough +{ +public: + //! Angle difference in degrees between two points in feature. + virtual void setXi(double xi) = 0; + virtual double getXi() const = 0; + + //! Feature table levels. + virtual void setLevels(int levels) = 0; + virtual int getLevels() const = 0; + + //! Maximal difference between angles that treated as equal. + virtual void setAngleEpsilon(double angleEpsilon) = 0; + virtual double getAngleEpsilon() const = 0; + + //! Minimal rotation angle to detect in degrees. + virtual void setMinAngle(double minAngle) = 0; + virtual double getMinAngle() const = 0; + + //! Maximal rotation angle to detect in degrees. + virtual void setMaxAngle(double maxAngle) = 0; + virtual double getMaxAngle() const = 0; + + //! Angle step in degrees. + virtual void setAngleStep(double angleStep) = 0; + virtual double getAngleStep() const = 0; + + //! Angle votes threshold. + virtual void setAngleThresh(int angleThresh) = 0; + virtual int getAngleThresh() const = 0; + + //! Minimal scale to detect. + virtual void setMinScale(double minScale) = 0; + virtual double getMinScale() const = 0; + + //! Maximal scale to detect. + virtual void setMaxScale(double maxScale) = 0; + virtual double getMaxScale() const = 0; + + //! Scale step. + virtual void setScaleStep(double scaleStep) = 0; + virtual double getScaleStep() const = 0; + + //! Scale votes threshold. + virtual void setScaleThresh(int scaleThresh) = 0; + virtual int getScaleThresh() const = 0; + + //! Position votes threshold. + virtual void setPosThresh(int posThresh) = 0; + virtual int getPosThresh() const = 0; +}; + + +class CV_EXPORTS_W CLAHE : public Algorithm +{ +public: + CV_WRAP virtual void apply(InputArray src, OutputArray dst) = 0; + + CV_WRAP virtual void setClipLimit(double clipLimit) = 0; + CV_WRAP virtual double getClipLimit() const = 0; + + CV_WRAP virtual void setTilesGridSize(Size tileGridSize) = 0; + CV_WRAP virtual Size getTilesGridSize() const = 0; + + CV_WRAP virtual void collectGarbage() = 0; +}; + + +class CV_EXPORTS_W Subdiv2D +{ +public: + enum { PTLOC_ERROR = -2, + PTLOC_OUTSIDE_RECT = -1, + PTLOC_INSIDE = 0, + PTLOC_VERTEX = 1, + PTLOC_ON_EDGE = 2 + }; + + enum { NEXT_AROUND_ORG = 0x00, + NEXT_AROUND_DST = 0x22, + PREV_AROUND_ORG = 0x11, + PREV_AROUND_DST = 0x33, + NEXT_AROUND_LEFT = 0x13, + NEXT_AROUND_RIGHT = 0x31, + PREV_AROUND_LEFT = 0x20, + PREV_AROUND_RIGHT = 0x02 + }; + + CV_WRAP Subdiv2D(); + CV_WRAP Subdiv2D(Rect rect); + CV_WRAP void initDelaunay(Rect rect); + + CV_WRAP int insert(Point2f pt); + CV_WRAP void insert(const std::vector& ptvec); + CV_WRAP int locate(Point2f pt, CV_OUT int& edge, CV_OUT int& vertex); + + CV_WRAP int findNearest(Point2f pt, CV_OUT Point2f* nearestPt = 0); + CV_WRAP void getEdgeList(CV_OUT std::vector& edgeList) const; + CV_WRAP void getTriangleList(CV_OUT std::vector& triangleList) const; + CV_WRAP void getVoronoiFacetList(const std::vector& idx, CV_OUT std::vector >& facetList, + CV_OUT std::vector& facetCenters); + + CV_WRAP Point2f getVertex(int vertex, CV_OUT int* firstEdge = 0) const; + + CV_WRAP int getEdge( int edge, int nextEdgeType ) const; + CV_WRAP int nextEdge(int edge) const; + CV_WRAP int rotateEdge(int edge, int rotate) const; + CV_WRAP int symEdge(int edge) const; + CV_WRAP int edgeOrg(int edge, CV_OUT Point2f* orgpt = 0) const; + CV_WRAP int edgeDst(int edge, CV_OUT Point2f* dstpt = 0) const; + +protected: + int newEdge(); + void deleteEdge(int edge); + int newPoint(Point2f pt, bool isvirtual, int firstEdge = 0); + void deletePoint(int vtx); + void setEdgePoints( int edge, int orgPt, int dstPt ); + void splice( int edgeA, int edgeB ); + int connectEdges( int edgeA, int edgeB ); + void swapEdges( int edge ); + int isRightOf(Point2f pt, int edge) const; + void calcVoronoi(); + void clearVoronoi(); + void checkSubdiv() const; + + struct CV_EXPORTS Vertex + { + Vertex(); + Vertex(Point2f pt, bool _isvirtual, int _firstEdge=0); + bool isvirtual() const; + bool isfree() const; + + int firstEdge; + int type; + Point2f pt; + }; + + struct CV_EXPORTS QuadEdge + { + QuadEdge(); + QuadEdge(int edgeidx); + bool isfree() const; + + int next[4]; + int pt[4]; + }; + + std::vector vtx; + std::vector qedges; + int freeQEdge; + int freePoint; + bool validGeometry; + + int recentEdge; + Point2f topLeft; + Point2f bottomRight; +}; + +//! @addtogroup imgproc_feature +//! @{ + +/** @example lsd_lines.cpp +An example using the LineSegmentDetector +*/ + +/** @brief Line segment detector class + +following the algorithm described at @cite Rafael12 . +*/ +class CV_EXPORTS_W LineSegmentDetector : public Algorithm +{ +public: + + /** @brief Finds lines in the input image. + + This is the output of the default parameters of the algorithm on the above shown image. + + ![image](pics/building_lsd.png) + + @param _image A grayscale (CV_8UC1) input image. If only a roi needs to be selected, use: + `lsd_ptr-\>detect(image(roi), lines, ...); lines += Scalar(roi.x, roi.y, roi.x, roi.y);` + @param _lines A vector of Vec4i or Vec4f elements specifying the beginning and ending point of a line. Where + Vec4i/Vec4f is (x1, y1, x2, y2), point 1 is the start, point 2 - end. Returned lines are strictly + oriented depending on the gradient. + @param width Vector of widths of the regions, where the lines are found. E.g. Width of line. + @param prec Vector of precisions with which the lines are found. + @param nfa Vector containing number of false alarms in the line region, with precision of 10%. The + bigger the value, logarithmically better the detection. + - -1 corresponds to 10 mean false alarms + - 0 corresponds to 1 mean false alarm + - 1 corresponds to 0.1 mean false alarms + This vector will be calculated only when the objects type is LSD_REFINE_ADV. + */ + CV_WRAP virtual void detect(InputArray _image, OutputArray _lines, + OutputArray width = noArray(), OutputArray prec = noArray(), + OutputArray nfa = noArray()) = 0; + + /** @brief Draws the line segments on a given image. + @param _image The image, where the liens will be drawn. Should be bigger or equal to the image, + where the lines were found. + @param lines A vector of the lines that needed to be drawn. + */ + CV_WRAP virtual void drawSegments(InputOutputArray _image, InputArray lines) = 0; + + /** @brief Draws two groups of lines in blue and red, counting the non overlapping (mismatching) pixels. + + @param size The size of the image, where lines1 and lines2 were found. + @param lines1 The first group of lines that needs to be drawn. It is visualized in blue color. + @param lines2 The second group of lines. They visualized in red color. + @param _image Optional image, where the lines will be drawn. The image should be color(3-channel) + in order for lines1 and lines2 to be drawn in the above mentioned colors. + */ + CV_WRAP virtual int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image = noArray()) = 0; + + virtual ~LineSegmentDetector() { } +}; + +/** @brief Creates a smart pointer to a LineSegmentDetector object and initializes it. + +The LineSegmentDetector algorithm is defined using the standard values. Only advanced users may want +to edit those, as to tailor it for their own application. + +@param _refine The way found lines will be refined, see cv::LineSegmentDetectorModes +@param _scale The scale of the image that will be used to find the lines. Range (0..1]. +@param _sigma_scale Sigma for Gaussian filter. It is computed as sigma = _sigma_scale/_scale. +@param _quant Bound to the quantization error on the gradient norm. +@param _ang_th Gradient angle tolerance in degrees. +@param _log_eps Detection threshold: -log10(NFA) \> log_eps. Used only when advancent refinement +is chosen. +@param _density_th Minimal density of aligned region points in the enclosing rectangle. +@param _n_bins Number of bins in pseudo-ordering of gradient modulus. + */ +CV_EXPORTS_W Ptr createLineSegmentDetector( + int _refine = LSD_REFINE_STD, double _scale = 0.8, + double _sigma_scale = 0.6, double _quant = 2.0, double _ang_th = 22.5, + double _log_eps = 0, double _density_th = 0.7, int _n_bins = 1024); + +//! @} imgproc_feature + +//! @addtogroup imgproc_filter +//! @{ + +/** @brief Returns Gaussian filter coefficients. + +The function computes and returns the \f$\texttt{ksize} \times 1\f$ matrix of Gaussian filter +coefficients: + +\f[G_i= \alpha *e^{-(i-( \texttt{ksize} -1)/2)^2/(2* \texttt{sigma}^2)},\f] + +where \f$i=0..\texttt{ksize}-1\f$ and \f$\alpha\f$ is the scale factor chosen so that \f$\sum_i G_i=1\f$. + +Two of such generated kernels can be passed to sepFilter2D. Those functions automatically recognize +smoothing kernels (a symmetrical kernel with sum of weights equal to 1) and handle them accordingly. +You may also use the higher-level GaussianBlur. +@param ksize Aperture size. It should be odd ( \f$\texttt{ksize} \mod 2 = 1\f$ ) and positive. +@param sigma Gaussian standard deviation. If it is non-positive, it is computed from ksize as +`sigma = 0.3\*((ksize-1)\*0.5 - 1) + 0.8`. +@param ktype Type of filter coefficients. It can be CV_32F or CV_64F . +@sa sepFilter2D, getDerivKernels, getStructuringElement, GaussianBlur + */ +CV_EXPORTS_W Mat getGaussianKernel( int ksize, double sigma, int ktype = CV_64F ); + +/** @brief Returns filter coefficients for computing spatial image derivatives. + +The function computes and returns the filter coefficients for spatial image derivatives. When +`ksize=CV_SCHARR`, the Scharr \f$3 \times 3\f$ kernels are generated (see cv::Scharr). Otherwise, Sobel +kernels are generated (see cv::Sobel). The filters are normally passed to sepFilter2D or to + +@param kx Output matrix of row filter coefficients. It has the type ktype . +@param ky Output matrix of column filter coefficients. It has the type ktype . +@param dx Derivative order in respect of x. +@param dy Derivative order in respect of y. +@param ksize Aperture size. It can be CV_SCHARR, 1, 3, 5, or 7. +@param normalize Flag indicating whether to normalize (scale down) the filter coefficients or not. +Theoretically, the coefficients should have the denominator \f$=2^{ksize*2-dx-dy-2}\f$. If you are +going to filter floating-point images, you are likely to use the normalized kernels. But if you +compute derivatives of an 8-bit image, store the results in a 16-bit image, and wish to preserve +all the fractional bits, you may want to set normalize=false . +@param ktype Type of filter coefficients. It can be CV_32f or CV_64F . + */ +CV_EXPORTS_W void getDerivKernels( OutputArray kx, OutputArray ky, + int dx, int dy, int ksize, + bool normalize = false, int ktype = CV_32F ); + +/** @brief Returns Gabor filter coefficients. + +For more details about gabor filter equations and parameters, see: [Gabor +Filter](http://en.wikipedia.org/wiki/Gabor_filter). + +@param ksize Size of the filter returned. +@param sigma Standard deviation of the gaussian envelope. +@param theta Orientation of the normal to the parallel stripes of a Gabor function. +@param lambd Wavelength of the sinusoidal factor. +@param gamma Spatial aspect ratio. +@param psi Phase offset. +@param ktype Type of filter coefficients. It can be CV_32F or CV_64F . + */ +CV_EXPORTS_W Mat getGaborKernel( Size ksize, double sigma, double theta, double lambd, + double gamma, double psi = CV_PI*0.5, int ktype = CV_64F ); + +//! returns "magic" border value for erosion and dilation. It is automatically transformed to Scalar::all(-DBL_MAX) for dilation. +static inline Scalar morphologyDefaultBorderValue() { return Scalar::all(DBL_MAX); } + +/** @brief Returns a structuring element of the specified size and shape for morphological operations. + +The function constructs and returns the structuring element that can be further passed to cv::erode, +cv::dilate or cv::morphologyEx. But you can also construct an arbitrary binary mask yourself and use it as +the structuring element. + +@param shape Element shape that could be one of cv::MorphShapes +@param ksize Size of the structuring element. +@param anchor Anchor position within the element. The default value \f$(-1, -1)\f$ means that the +anchor is at the center. Note that only the shape of a cross-shaped element depends on the anchor +position. In other cases the anchor just regulates how much the result of the morphological +operation is shifted. + */ +CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1)); + +/** @brief Blurs an image using the median filter. + +The function smoothes an image using the median filter with the \f$\texttt{ksize} \times +\texttt{ksize}\f$ aperture. Each channel of a multi-channel image is processed independently. +In-place operation is supported. + +@param src input 1-, 3-, or 4-channel image; when ksize is 3 or 5, the image depth should be +CV_8U, CV_16U, or CV_32F, for larger aperture sizes, it can only be CV_8U. +@param dst destination array of the same size and type as src. +@param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ... +@sa bilateralFilter, blur, boxFilter, GaussianBlur + */ +CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize ); + +/** @brief Blurs an image using a Gaussian filter. + +The function convolves the source image with the specified Gaussian kernel. In-place filtering is +supported. + +@param src input image; the image can have any number of channels, which are processed +independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. +@param dst output image of the same size and type as src. +@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be +positive and odd. Or, they can be zero's and then they are computed from sigma. +@param sigmaX Gaussian kernel standard deviation in X direction. +@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be +equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height, +respectively (see cv::getGaussianKernel for details); to fully control the result regardless of +possible future modifications of all this semantics, it is recommended to specify all of ksize, +sigmaX, and sigmaY. +@param borderType pixel extrapolation method, see cv::BorderTypes + +@sa sepFilter2D, filter2D, blur, boxFilter, bilateralFilter, medianBlur + */ +CV_EXPORTS_W void GaussianBlur( InputArray src, OutputArray dst, Size ksize, + double sigmaX, double sigmaY = 0, + int borderType = BORDER_DEFAULT ); + +/** @brief Applies the bilateral filter to an image. + +The function applies bilateral filtering to the input image, as described in +http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html +bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. However, it is +very slow compared to most filters. + +_Sigma values_: For simplicity, you can set the 2 sigma values to be the same. If they are small (\< +10), the filter will not have much effect, whereas if they are large (\> 150), they will have a very +strong effect, making the image look "cartoonish". + +_Filter size_: Large filters (d \> 5) are very slow, so it is recommended to use d=5 for real-time +applications, and perhaps d=9 for offline applications that need heavy noise filtering. + +This filter does not work inplace. +@param src Source 8-bit or floating-point, 1-channel or 3-channel image. +@param dst Destination image of the same size and type as src . +@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive, +it is computed from sigmaSpace. +@param sigmaColor Filter sigma in the color space. A larger value of the parameter means that +farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting +in larger areas of semi-equal color. +@param sigmaSpace Filter sigma in the coordinate space. A larger value of the parameter means that +farther pixels will influence each other as long as their colors are close enough (see sigmaColor +). When d\>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is +proportional to sigmaSpace. +@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes + */ +CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d, + double sigmaColor, double sigmaSpace, + int borderType = BORDER_DEFAULT ); + +/** @brief Blurs an image using the box filter. + +The function smoothes an image using the kernel: + +\f[\texttt{K} = \alpha \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \end{bmatrix}\f] + +where + +\f[\alpha = \fork{\frac{1}{\texttt{ksize.width*ksize.height}}}{when \texttt{normalize=true}}{1}{otherwise}\f] + +Unnormalized box filter is useful for computing various integral characteristics over each pixel +neighborhood, such as covariance matrices of image derivatives (used in dense optical flow +algorithms, and so on). If you need to compute pixel sums over variable-size windows, use cv::integral. + +@param src input image. +@param dst output image of the same size and type as src. +@param ddepth the output image depth (-1 to use src.depth()). +@param ksize blurring kernel size. +@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel +center. +@param normalize flag, specifying whether the kernel is normalized by its area or not. +@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes +@sa blur, bilateralFilter, GaussianBlur, medianBlur, integral + */ +CV_EXPORTS_W void boxFilter( InputArray src, OutputArray dst, int ddepth, + Size ksize, Point anchor = Point(-1,-1), + bool normalize = true, + int borderType = BORDER_DEFAULT ); + +/** @brief Calculates the normalized sum of squares of the pixel values overlapping the filter. + +For every pixel \f$ (x, y) \f$ in the source image, the function calculates the sum of squares of those neighboring +pixel values which overlap the filter placed over the pixel \f$ (x, y) \f$. + +The unnormalized square box filter can be useful in computing local image statistics such as the the local +variance and standard deviation around the neighborhood of a pixel. + +@param _src input image +@param _dst output image of the same size and type as _src +@param ddepth the output image depth (-1 to use src.depth()) +@param ksize kernel size +@param anchor kernel anchor point. The default value of Point(-1, -1) denotes that the anchor is at the kernel +center. +@param normalize flag, specifying whether the kernel is to be normalized by it's area or not. +@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes +@sa boxFilter +*/ +CV_EXPORTS_W void sqrBoxFilter( InputArray _src, OutputArray _dst, int ddepth, + Size ksize, Point anchor = Point(-1, -1), + bool normalize = true, + int borderType = BORDER_DEFAULT ); + +/** @brief Blurs an image using the normalized box filter. + +The function smoothes an image using the kernel: + +\f[\texttt{K} = \frac{1}{\texttt{ksize.width*ksize.height}} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \end{bmatrix}\f] + +The call `blur(src, dst, ksize, anchor, borderType)` is equivalent to `boxFilter(src, dst, src.type(), +anchor, true, borderType)`. + +@param src input image; it can have any number of channels, which are processed independently, but +the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. +@param dst output image of the same size and type as src. +@param ksize blurring kernel size. +@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel +center. +@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes +@sa boxFilter, bilateralFilter, GaussianBlur, medianBlur + */ +CV_EXPORTS_W void blur( InputArray src, OutputArray dst, + Size ksize, Point anchor = Point(-1,-1), + int borderType = BORDER_DEFAULT ); + +/** @brief Convolves an image with the kernel. + +The function applies an arbitrary linear filter to an image. In-place operation is supported. When +the aperture is partially outside the image, the function interpolates outlier pixel values +according to the specified border mode. + +The function does actually compute correlation, not the convolution: + +\f[\texttt{dst} (x,y) = \sum _{ \stackrel{0\leq x' < \texttt{kernel.cols},}{0\leq y' < \texttt{kernel.rows}} } \texttt{kernel} (x',y')* \texttt{src} (x+x'- \texttt{anchor.x} ,y+y'- \texttt{anchor.y} )\f] + +That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip +the kernel using cv::flip and set the new anchor to `(kernel.cols - anchor.x - 1, kernel.rows - +anchor.y - 1)`. + +The function uses the DFT-based algorithm in case of sufficiently large kernels (~`11 x 11` or +larger) and the direct algorithm for small kernels. + +@param src input image. +@param dst output image of the same size and the same number of channels as src. +@param ddepth desired depth of the destination image, see @ref filter_depths "combinations" +@param kernel convolution kernel (or rather a correlation kernel), a single-channel floating point +matrix; if you want to apply different kernels to different channels, split the image into +separate color planes using split and process them individually. +@param anchor anchor of the kernel that indicates the relative position of a filtered point within +the kernel; the anchor should lie within the kernel; default value (-1,-1) means that the anchor +is at the kernel center. +@param delta optional value added to the filtered pixels before storing them in dst. +@param borderType pixel extrapolation method, see cv::BorderTypes +@sa sepFilter2D, dft, matchTemplate + */ +CV_EXPORTS_W void filter2D( InputArray src, OutputArray dst, int ddepth, + InputArray kernel, Point anchor = Point(-1,-1), + double delta = 0, int borderType = BORDER_DEFAULT ); + +/** @brief Applies a separable linear filter to an image. + +The function applies a separable linear filter to the image. That is, first, every row of src is +filtered with the 1D kernel kernelX. Then, every column of the result is filtered with the 1D +kernel kernelY. The final result shifted by delta is stored in dst . + +@param src Source image. +@param dst Destination image of the same size and the same number of channels as src . +@param ddepth Destination image depth, see @ref filter_depths "combinations" +@param kernelX Coefficients for filtering each row. +@param kernelY Coefficients for filtering each column. +@param anchor Anchor position within the kernel. The default value \f$(-1,-1)\f$ means that the anchor +is at the kernel center. +@param delta Value added to the filtered results before storing them. +@param borderType Pixel extrapolation method, see cv::BorderTypes +@sa filter2D, Sobel, GaussianBlur, boxFilter, blur + */ +CV_EXPORTS_W void sepFilter2D( InputArray src, OutputArray dst, int ddepth, + InputArray kernelX, InputArray kernelY, + Point anchor = Point(-1,-1), + double delta = 0, int borderType = BORDER_DEFAULT ); + +/** @brief Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator. + +In all cases except one, the \f$\texttt{ksize} \times \texttt{ksize}\f$ separable kernel is used to +calculate the derivative. When \f$\texttt{ksize = 1}\f$, the \f$3 \times 1\f$ or \f$1 \times 3\f$ +kernel is used (that is, no Gaussian smoothing is done). `ksize = 1` can only be used for the first +or the second x- or y- derivatives. + +There is also the special value `ksize = CV_SCHARR (-1)` that corresponds to the \f$3\times3\f$ Scharr +filter that may give more accurate results than the \f$3\times3\f$ Sobel. The Scharr aperture is + +\f[\vecthreethree{-3}{0}{3}{-10}{0}{10}{-3}{0}{3}\f] + +for the x-derivative, or transposed for the y-derivative. + +The function calculates an image derivative by convolving the image with the appropriate kernel: + +\f[\texttt{dst} = \frac{\partial^{xorder+yorder} \texttt{src}}{\partial x^{xorder} \partial y^{yorder}}\f] + +The Sobel operators combine Gaussian smoothing and differentiation, so the result is more or less +resistant to the noise. Most often, the function is called with ( xorder = 1, yorder = 0, ksize = 3) +or ( xorder = 0, yorder = 1, ksize = 3) to calculate the first x- or y- image derivative. The first +case corresponds to a kernel of: + +\f[\vecthreethree{-1}{0}{1}{-2}{0}{2}{-1}{0}{1}\f] + +The second case corresponds to a kernel of: + +\f[\vecthreethree{-1}{-2}{-1}{0}{0}{0}{1}{2}{1}\f] + +@param src input image. +@param dst output image of the same size and the same number of channels as src . +@param ddepth output image depth, see @ref filter_depths "combinations"; in the case of + 8-bit input images it will result in truncated derivatives. +@param dx order of the derivative x. +@param dy order of the derivative y. +@param ksize size of the extended Sobel kernel; it must be 1, 3, 5, or 7. +@param scale optional scale factor for the computed derivative values; by default, no scaling is +applied (see cv::getDerivKernels for details). +@param delta optional delta value that is added to the results prior to storing them in dst. +@param borderType pixel extrapolation method, see cv::BorderTypes +@sa Scharr, Laplacian, sepFilter2D, filter2D, GaussianBlur, cartToPolar + */ +CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth, + int dx, int dy, int ksize = 3, + double scale = 1, double delta = 0, + int borderType = BORDER_DEFAULT ); + +/** @brief Calculates the first x- or y- image derivative using Scharr operator. + +The function computes the first x- or y- spatial image derivative using the Scharr operator. The +call + +\f[\texttt{Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType)}\f] + +is equivalent to + +\f[\texttt{Sobel(src, dst, ddepth, dx, dy, CV\_SCHARR, scale, delta, borderType)} .\f] + +@param src input image. +@param dst output image of the same size and the same number of channels as src. +@param ddepth output image depth, see @ref filter_depths "combinations" +@param dx order of the derivative x. +@param dy order of the derivative y. +@param scale optional scale factor for the computed derivative values; by default, no scaling is +applied (see getDerivKernels for details). +@param delta optional delta value that is added to the results prior to storing them in dst. +@param borderType pixel extrapolation method, see cv::BorderTypes +@sa cartToPolar + */ +CV_EXPORTS_W void Scharr( InputArray src, OutputArray dst, int ddepth, + int dx, int dy, double scale = 1, double delta = 0, + int borderType = BORDER_DEFAULT ); + +/** @example laplace.cpp + An example using Laplace transformations for edge detection +*/ + +/** @brief Calculates the Laplacian of an image. + +The function calculates the Laplacian of the source image by adding up the second x and y +derivatives calculated using the Sobel operator: + +\f[\texttt{dst} = \Delta \texttt{src} = \frac{\partial^2 \texttt{src}}{\partial x^2} + \frac{\partial^2 \texttt{src}}{\partial y^2}\f] + +This is done when `ksize > 1`. When `ksize == 1`, the Laplacian is computed by filtering the image +with the following \f$3 \times 3\f$ aperture: + +\f[\vecthreethree {0}{1}{0}{1}{-4}{1}{0}{1}{0}\f] + +@param src Source image. +@param dst Destination image of the same size and the same number of channels as src . +@param ddepth Desired depth of the destination image. +@param ksize Aperture size used to compute the second-derivative filters. See getDerivKernels for +details. The size must be positive and odd. +@param scale Optional scale factor for the computed Laplacian values. By default, no scaling is +applied. See getDerivKernels for details. +@param delta Optional delta value that is added to the results prior to storing them in dst . +@param borderType Pixel extrapolation method, see cv::BorderTypes +@sa Sobel, Scharr + */ +CV_EXPORTS_W void Laplacian( InputArray src, OutputArray dst, int ddepth, + int ksize = 1, double scale = 1, double delta = 0, + int borderType = BORDER_DEFAULT ); + +//! @} imgproc_filter + +//! @addtogroup imgproc_feature +//! @{ + +/** @example edge.cpp + An example on using the canny edge detector +*/ + +/** @brief Finds edges in an image using the Canny algorithm @cite Canny86 . + +The function finds edges in the input image image and marks them in the output map edges using the +Canny algorithm. The smallest value between threshold1 and threshold2 is used for edge linking. The +largest value is used to find initial segments of strong edges. See + + +@param image 8-bit input image. +@param edges output edge map; single channels 8-bit image, which has the same size as image . +@param threshold1 first threshold for the hysteresis procedure. +@param threshold2 second threshold for the hysteresis procedure. +@param apertureSize aperture size for the Sobel operator. +@param L2gradient a flag, indicating whether a more accurate \f$L_2\f$ norm +\f$=\sqrt{(dI/dx)^2 + (dI/dy)^2}\f$ should be used to calculate the image gradient magnitude ( +L2gradient=true ), or whether the default \f$L_1\f$ norm \f$=|dI/dx|+|dI/dy|\f$ is enough ( +L2gradient=false ). + */ +CV_EXPORTS_W void Canny( InputArray image, OutputArray edges, + double threshold1, double threshold2, + int apertureSize = 3, bool L2gradient = false ); + +/** @brief Calculates the minimal eigenvalue of gradient matrices for corner detection. + +The function is similar to cornerEigenValsAndVecs but it calculates and stores only the minimal +eigenvalue of the covariance matrix of derivatives, that is, \f$\min(\lambda_1, \lambda_2)\f$ in terms +of the formulae in the cornerEigenValsAndVecs description. + +@param src Input single-channel 8-bit or floating-point image. +@param dst Image to store the minimal eigenvalues. It has the type CV_32FC1 and the same size as +src . +@param blockSize Neighborhood size (see the details on cornerEigenValsAndVecs ). +@param ksize Aperture parameter for the Sobel operator. +@param borderType Pixel extrapolation method. See cv::BorderTypes. + */ +CV_EXPORTS_W void cornerMinEigenVal( InputArray src, OutputArray dst, + int blockSize, int ksize = 3, + int borderType = BORDER_DEFAULT ); + +/** @brief Harris corner detector. + +The function runs the Harris corner detector on the image. Similarly to cornerMinEigenVal and +cornerEigenValsAndVecs , for each pixel \f$(x, y)\f$ it calculates a \f$2\times2\f$ gradient covariance +matrix \f$M^{(x,y)}\f$ over a \f$\texttt{blockSize} \times \texttt{blockSize}\f$ neighborhood. Then, it +computes the following characteristic: + +\f[\texttt{dst} (x,y) = \mathrm{det} M^{(x,y)} - k \cdot \left ( \mathrm{tr} M^{(x,y)} \right )^2\f] + +Corners in the image can be found as the local maxima of this response map. + +@param src Input single-channel 8-bit or floating-point image. +@param dst Image to store the Harris detector responses. It has the type CV_32FC1 and the same +size as src . +@param blockSize Neighborhood size (see the details on cornerEigenValsAndVecs ). +@param ksize Aperture parameter for the Sobel operator. +@param k Harris detector free parameter. See the formula below. +@param borderType Pixel extrapolation method. See cv::BorderTypes. + */ +CV_EXPORTS_W void cornerHarris( InputArray src, OutputArray dst, int blockSize, + int ksize, double k, + int borderType = BORDER_DEFAULT ); + +/** @brief Calculates eigenvalues and eigenvectors of image blocks for corner detection. + +For every pixel \f$p\f$ , the function cornerEigenValsAndVecs considers a blockSize \f$\times\f$ blockSize +neighborhood \f$S(p)\f$ . It calculates the covariation matrix of derivatives over the neighborhood as: + +\f[M = \begin{bmatrix} \sum _{S(p)}(dI/dx)^2 & \sum _{S(p)}dI/dx dI/dy \\ \sum _{S(p)}dI/dx dI/dy & \sum _{S(p)}(dI/dy)^2 \end{bmatrix}\f] + +where the derivatives are computed using the Sobel operator. + +After that, it finds eigenvectors and eigenvalues of \f$M\f$ and stores them in the destination image as +\f$(\lambda_1, \lambda_2, x_1, y_1, x_2, y_2)\f$ where + +- \f$\lambda_1, \lambda_2\f$ are the non-sorted eigenvalues of \f$M\f$ +- \f$x_1, y_1\f$ are the eigenvectors corresponding to \f$\lambda_1\f$ +- \f$x_2, y_2\f$ are the eigenvectors corresponding to \f$\lambda_2\f$ + +The output of the function can be used for robust edge or corner detection. + +@param src Input single-channel 8-bit or floating-point image. +@param dst Image to store the results. It has the same size as src and the type CV_32FC(6) . +@param blockSize Neighborhood size (see details below). +@param ksize Aperture parameter for the Sobel operator. +@param borderType Pixel extrapolation method. See cv::BorderTypes. + +@sa cornerMinEigenVal, cornerHarris, preCornerDetect + */ +CV_EXPORTS_W void cornerEigenValsAndVecs( InputArray src, OutputArray dst, + int blockSize, int ksize, + int borderType = BORDER_DEFAULT ); + +/** @brief Calculates a feature map for corner detection. + +The function calculates the complex spatial derivative-based function of the source image + +\f[\texttt{dst} = (D_x \texttt{src} )^2 \cdot D_{yy} \texttt{src} + (D_y \texttt{src} )^2 \cdot D_{xx} \texttt{src} - 2 D_x \texttt{src} \cdot D_y \texttt{src} \cdot D_{xy} \texttt{src}\f] + +where \f$D_x\f$,\f$D_y\f$ are the first image derivatives, \f$D_{xx}\f$,\f$D_{yy}\f$ are the second image +derivatives, and \f$D_{xy}\f$ is the mixed derivative. + +The corners can be found as local maximums of the functions, as shown below: +@code + Mat corners, dilated_corners; + preCornerDetect(image, corners, 3); + // dilation with 3x3 rectangular structuring element + dilate(corners, dilated_corners, Mat(), 1); + Mat corner_mask = corners == dilated_corners; +@endcode + +@param src Source single-channel 8-bit of floating-point image. +@param dst Output image that has the type CV_32F and the same size as src . +@param ksize %Aperture size of the Sobel . +@param borderType Pixel extrapolation method. See cv::BorderTypes. + */ +CV_EXPORTS_W void preCornerDetect( InputArray src, OutputArray dst, int ksize, + int borderType = BORDER_DEFAULT ); + +/** @brief Refines the corner locations. + +The function iterates to find the sub-pixel accurate location of corners or radial saddle points, as +shown on the figure below. + +![image](pics/cornersubpix.png) + +Sub-pixel accurate corner locator is based on the observation that every vector from the center \f$q\f$ +to a point \f$p\f$ located within a neighborhood of \f$q\f$ is orthogonal to the image gradient at \f$p\f$ +subject to image and measurement noise. Consider the expression: + +\f[\epsilon _i = {DI_{p_i}}^T \cdot (q - p_i)\f] + +where \f${DI_{p_i}}\f$ is an image gradient at one of the points \f$p_i\f$ in a neighborhood of \f$q\f$ . The +value of \f$q\f$ is to be found so that \f$\epsilon_i\f$ is minimized. A system of equations may be set up +with \f$\epsilon_i\f$ set to zero: + +\f[\sum _i(DI_{p_i} \cdot {DI_{p_i}}^T) - \sum _i(DI_{p_i} \cdot {DI_{p_i}}^T \cdot p_i)\f] + +where the gradients are summed within a neighborhood ("search window") of \f$q\f$ . Calling the first +gradient term \f$G\f$ and the second gradient term \f$b\f$ gives: + +\f[q = G^{-1} \cdot b\f] + +The algorithm sets the center of the neighborhood window at this new center \f$q\f$ and then iterates +until the center stays within a set threshold. + +@param image Input image. +@param corners Initial coordinates of the input corners and refined coordinates provided for +output. +@param winSize Half of the side length of the search window. For example, if winSize=Size(5,5) , +then a \f$5*2+1 \times 5*2+1 = 11 \times 11\f$ search window is used. +@param zeroZone Half of the size of the dead region in the middle of the search zone over which +the summation in the formula below is not done. It is used sometimes to avoid possible +singularities of the autocorrelation matrix. The value of (-1,-1) indicates that there is no such +a size. +@param criteria Criteria for termination of the iterative process of corner refinement. That is, +the process of corner position refinement stops either after criteria.maxCount iterations or when +the corner position moves by less than criteria.epsilon on some iteration. + */ +CV_EXPORTS_W void cornerSubPix( InputArray image, InputOutputArray corners, + Size winSize, Size zeroZone, + TermCriteria criteria ); + +/** @brief Determines strong corners on an image. + +The function finds the most prominent corners in the image or in the specified image region, as +described in @cite Shi94 + +- Function calculates the corner quality measure at every source image pixel using the + cornerMinEigenVal or cornerHarris . +- Function performs a non-maximum suppression (the local maximums in *3 x 3* neighborhood are + retained). +- The corners with the minimal eigenvalue less than + \f$\texttt{qualityLevel} \cdot \max_{x,y} qualityMeasureMap(x,y)\f$ are rejected. +- The remaining corners are sorted by the quality measure in the descending order. +- Function throws away each corner for which there is a stronger corner at a distance less than + maxDistance. + +The function can be used to initialize a point-based tracker of an object. + +@note If the function is called with different values A and B of the parameter qualityLevel , and +A \> B, the vector of returned corners with qualityLevel=A will be the prefix of the output vector +with qualityLevel=B . + +@param image Input 8-bit or floating-point 32-bit, single-channel image. +@param corners Output vector of detected corners. +@param maxCorners Maximum number of corners to return. If there are more corners than are found, +the strongest of them is returned. +@param qualityLevel Parameter characterizing the minimal accepted quality of image corners. The +parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue +(see cornerMinEigenVal ) or the Harris function response (see cornerHarris ). The corners with the +quality measure less than the product are rejected. For example, if the best corner has the +quality measure = 1500, and the qualityLevel=0.01 , then all the corners with the quality measure +less than 15 are rejected. +@param minDistance Minimum possible Euclidean distance between the returned corners. +@param mask Optional region of interest. If the image is not empty (it needs to have the type +CV_8UC1 and the same size as image ), it specifies the region in which the corners are detected. +@param blockSize Size of an average block for computing a derivative covariation matrix over each +pixel neighborhood. See cornerEigenValsAndVecs . +@param useHarrisDetector Parameter indicating whether to use a Harris detector (see cornerHarris) +or cornerMinEigenVal. +@param k Free parameter of the Harris detector. + +@sa cornerMinEigenVal, cornerHarris, calcOpticalFlowPyrLK, estimateRigidTransform, + */ +CV_EXPORTS_W void goodFeaturesToTrack( InputArray image, OutputArray corners, + int maxCorners, double qualityLevel, double minDistance, + InputArray mask = noArray(), int blockSize = 3, + bool useHarrisDetector = false, double k = 0.04 ); + +/** @example houghlines.cpp +An example using the Hough line detector +*/ + +/** @brief Finds lines in a binary image using the standard Hough transform. + +The function implements the standard or standard multi-scale Hough transform algorithm for line +detection. See for a good explanation of Hough +transform. + +@param image 8-bit, single-channel binary source image. The image may be modified by the function. +@param lines Output vector of lines. Each line is represented by a two-element vector +\f$(\rho, \theta)\f$ . \f$\rho\f$ is the distance from the coordinate origin \f$(0,0)\f$ (top-left corner of +the image). \f$\theta\f$ is the line rotation angle in radians ( +\f$0 \sim \textrm{vertical line}, \pi/2 \sim \textrm{horizontal line}\f$ ). +@param rho Distance resolution of the accumulator in pixels. +@param theta Angle resolution of the accumulator in radians. +@param threshold Accumulator threshold parameter. Only those lines are returned that get enough +votes ( \f$>\texttt{threshold}\f$ ). +@param srn For the multi-scale Hough transform, it is a divisor for the distance resolution rho . +The coarse accumulator distance resolution is rho and the accurate accumulator resolution is +rho/srn . If both srn=0 and stn=0 , the classical Hough transform is used. Otherwise, both these +parameters should be positive. +@param stn For the multi-scale Hough transform, it is a divisor for the distance resolution theta. +@param min_theta For standard and multi-scale Hough transform, minimum angle to check for lines. +Must fall between 0 and max_theta. +@param max_theta For standard and multi-scale Hough transform, maximum angle to check for lines. +Must fall between min_theta and CV_PI. + */ +CV_EXPORTS_W void HoughLines( InputArray image, OutputArray lines, + double rho, double theta, int threshold, + double srn = 0, double stn = 0, + double min_theta = 0, double max_theta = CV_PI ); + +/** @brief Finds line segments in a binary image using the probabilistic Hough transform. + +The function implements the probabilistic Hough transform algorithm for line detection, described +in @cite Matas00 + +See the line detection example below: + +@code + #include + #include + + using namespace cv; + + int main(int argc, char** argv) + { + Mat src, dst, color_dst; + if( argc != 2 || !(src=imread(argv[1], 0)).data) + return -1; + + Canny( src, dst, 50, 200, 3 ); + cvtColor( dst, color_dst, COLOR_GRAY2BGR ); + + #if 0 + vector lines; + HoughLines( dst, lines, 1, CV_PI/180, 100 ); + + for( size_t i = 0; i < lines.size(); i++ ) + { + float rho = lines[i][0]; + float theta = lines[i][1]; + double a = cos(theta), b = sin(theta); + double x0 = a*rho, y0 = b*rho; + Point pt1(cvRound(x0 + 1000*(-b)), + cvRound(y0 + 1000*(a))); + Point pt2(cvRound(x0 - 1000*(-b)), + cvRound(y0 - 1000*(a))); + line( color_dst, pt1, pt2, Scalar(0,0,255), 3, 8 ); + } + #else + vector lines; + HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 ); + for( size_t i = 0; i < lines.size(); i++ ) + { + line( color_dst, Point(lines[i][0], lines[i][1]), + Point(lines[i][2], lines[i][3]), Scalar(0,0,255), 3, 8 ); + } + #endif + namedWindow( "Source", 1 ); + imshow( "Source", src ); + + namedWindow( "Detected Lines", 1 ); + imshow( "Detected Lines", color_dst ); + + waitKey(0); + return 0; + } +@endcode +This is a sample picture the function parameters have been tuned for: + +![image](pics/building.jpg) + +And this is the output of the above program in case of the probabilistic Hough transform: + +![image](pics/houghp.png) + +@param image 8-bit, single-channel binary source image. The image may be modified by the function. +@param lines Output vector of lines. Each line is represented by a 4-element vector +\f$(x_1, y_1, x_2, y_2)\f$ , where \f$(x_1,y_1)\f$ and \f$(x_2, y_2)\f$ are the ending points of each detected +line segment. +@param rho Distance resolution of the accumulator in pixels. +@param theta Angle resolution of the accumulator in radians. +@param threshold Accumulator threshold parameter. Only those lines are returned that get enough +votes ( \f$>\texttt{threshold}\f$ ). +@param minLineLength Minimum line length. Line segments shorter than that are rejected. +@param maxLineGap Maximum allowed gap between points on the same line to link them. + +@sa LineSegmentDetector + */ +CV_EXPORTS_W void HoughLinesP( InputArray image, OutputArray lines, + double rho, double theta, int threshold, + double minLineLength = 0, double maxLineGap = 0 ); + +/** @example houghcircles.cpp +An example using the Hough circle detector +*/ + +/** @brief Finds circles in a grayscale image using the Hough transform. + +The function finds circles in a grayscale image using a modification of the Hough transform. + +Example: : +@code + #include + #include + #include + + using namespace cv; + + int main(int argc, char** argv) + { + Mat img, gray; + if( argc != 2 && !(img=imread(argv[1], 1)).data) + return -1; + cvtColor(img, gray, COLOR_BGR2GRAY); + // smooth it, otherwise a lot of false circles may be detected + GaussianBlur( gray, gray, Size(9, 9), 2, 2 ); + vector circles; + HoughCircles(gray, circles, HOUGH_GRADIENT, + 2, gray->rows/4, 200, 100 ); + for( size_t i = 0; i < circles.size(); i++ ) + { + Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); + int radius = cvRound(circles[i][2]); + // draw the circle center + circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 ); + // draw the circle outline + circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 ); + } + namedWindow( "circles", 1 ); + imshow( "circles", img ); + return 0; + } +@endcode + +@note Usually the function detects the centers of circles well. However, it may fail to find correct +radii. You can assist to the function by specifying the radius range ( minRadius and maxRadius ) if +you know it. Or, you may ignore the returned radius, use only the center, and find the correct +radius using an additional procedure. + +@param image 8-bit, single-channel, grayscale input image. +@param circles Output vector of found circles. Each vector is encoded as a 3-element +floating-point vector \f$(x, y, radius)\f$ . +@param method Detection method, see cv::HoughModes. Currently, the only implemented method is HOUGH_GRADIENT +@param dp Inverse ratio of the accumulator resolution to the image resolution. For example, if +dp=1 , the accumulator has the same resolution as the input image. If dp=2 , the accumulator has +half as big width and height. +@param minDist Minimum distance between the centers of the detected circles. If the parameter is +too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is +too large, some circles may be missed. +@param param1 First method-specific parameter. In case of CV_HOUGH_GRADIENT , it is the higher +threshold of the two passed to the Canny edge detector (the lower one is twice smaller). +@param param2 Second method-specific parameter. In case of CV_HOUGH_GRADIENT , it is the +accumulator threshold for the circle centers at the detection stage. The smaller it is, the more +false circles may be detected. Circles, corresponding to the larger accumulator values, will be +returned first. +@param minRadius Minimum circle radius. +@param maxRadius Maximum circle radius. + +@sa fitEllipse, minEnclosingCircle + */ +CV_EXPORTS_W void HoughCircles( InputArray image, OutputArray circles, + int method, double dp, double minDist, + double param1 = 100, double param2 = 100, + int minRadius = 0, int maxRadius = 0 ); + +//! @} imgproc_feature + +//! @addtogroup imgproc_filter +//! @{ + +/** @example morphology2.cpp + An example using the morphological operations +*/ + +/** @brief Erodes an image by using a specific structuring element. + +The function erodes the source image using the specified structuring element that determines the +shape of a pixel neighborhood over which the minimum is taken: + +\f[\texttt{dst} (x,y) = \min _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f] + +The function supports the in-place mode. Erosion can be applied several ( iterations ) times. In +case of multi-channel images, each channel is processed independently. + +@param src input image; the number of channels can be arbitrary, but the depth should be one of +CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. +@param dst output image of the same size and type as src. +@param kernel structuring element used for erosion; if `element=Mat()`, a `3 x 3` rectangular +structuring element is used. Kernel can be created using getStructuringElement. +@param anchor position of the anchor within the element; default value (-1, -1) means that the +anchor is at the element center. +@param iterations number of times erosion is applied. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of a constant border +@sa dilate, morphologyEx, getStructuringElement + */ +CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel, + Point anchor = Point(-1,-1), int iterations = 1, + int borderType = BORDER_CONSTANT, + const Scalar& borderValue = morphologyDefaultBorderValue() ); + +/** @brief Dilates an image by using a specific structuring element. + +The function dilates the source image using the specified structuring element that determines the +shape of a pixel neighborhood over which the maximum is taken: +\f[\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f] + +The function supports the in-place mode. Dilation can be applied several ( iterations ) times. In +case of multi-channel images, each channel is processed independently. + +@param src input image; the number of channels can be arbitrary, but the depth should be one of +CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. +@param dst output image of the same size and type as src\`. +@param kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular +structuring element is used. Kernel can be created using getStructuringElement +@param anchor position of the anchor within the element; default value (-1, -1) means that the +anchor is at the element center. +@param iterations number of times dilation is applied. +@param borderType pixel extrapolation method, see cv::BorderTypes +@param borderValue border value in case of a constant border +@sa erode, morphologyEx, getStructuringElement + */ +CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel, + Point anchor = Point(-1,-1), int iterations = 1, + int borderType = BORDER_CONSTANT, + const Scalar& borderValue = morphologyDefaultBorderValue() ); + +/** @brief Performs advanced morphological transformations. + +The function can perform advanced morphological transformations using an erosion and dilation as +basic operations. + +Any of the operations can be done in-place. In case of multi-channel images, each channel is +processed independently. + +@param src Source image. The number of channels can be arbitrary. The depth should be one of +CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. +@param dst Destination image of the same size and type as src\` . +@param kernel Structuring element. It can be created using getStructuringElement. +@param anchor Anchor position with the kernel. Negative values mean that the anchor is at the +kernel center. +@param op Type of a morphological operation, see cv::MorphTypes +@param iterations Number of times erosion and dilation are applied. +@param borderType Pixel extrapolation method, see cv::BorderTypes +@param borderValue Border value in case of a constant border. The default value has a special +meaning. +@sa dilate, erode, getStructuringElement + */ +CV_EXPORTS_W void morphologyEx( InputArray src, OutputArray dst, + int op, InputArray kernel, + Point anchor = Point(-1,-1), int iterations = 1, + int borderType = BORDER_CONSTANT, + const Scalar& borderValue = morphologyDefaultBorderValue() ); + +//! @} imgproc_filter + +//! @addtogroup imgproc_transform +//! @{ + +/** @brief Resizes an image. + +The function resize resizes the image src down to or up to the specified size. Note that the +initial dst type or size are not taken into account. Instead, the size and type are derived from +the `src`,`dsize`,`fx`, and `fy`. If you want to resize src so that it fits the pre-created dst, +you may call the function as follows: +@code + // explicitly specify dsize=dst.size(); fx and fy will be computed from that. + resize(src, dst, dst.size(), 0, 0, interpolation); +@endcode +If you want to decimate the image by factor of 2 in each direction, you can call the function this +way: +@code + // specify fx and fy and let the function compute the destination image size. + resize(src, dst, Size(), 0.5, 0.5, interpolation); +@endcode +To shrink an image, it will generally look best with CV_INTER_AREA interpolation, whereas to +enlarge an image, it will generally look best with CV_INTER_CUBIC (slow) or CV_INTER_LINEAR +(faster but still looks OK). + +@param src input image. +@param dst output image; it has the size dsize (when it is non-zero) or the size computed from +src.size(), fx, and fy; the type of dst is the same as of src. +@param dsize output image size; if it equals zero, it is computed as: + \f[\texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))}\f] + Either dsize or both fx and fy must be non-zero. +@param fx scale factor along the horizontal axis; when it equals 0, it is computed as +\f[\texttt{(double)dsize.width/src.cols}\f] +@param fy scale factor along the vertical axis; when it equals 0, it is computed as +\f[\texttt{(double)dsize.height/src.rows}\f] +@param interpolation interpolation method, see cv::InterpolationFlags + +@sa warpAffine, warpPerspective, remap + */ +CV_EXPORTS_W void resize( InputArray src, OutputArray dst, + Size dsize, double fx = 0, double fy = 0, + int interpolation = INTER_LINEAR ); + +/** @brief Applies an affine transformation to an image. + +The function warpAffine transforms the source image using the specified matrix: + +\f[\texttt{dst} (x,y) = \texttt{src} ( \texttt{M} _{11} x + \texttt{M} _{12} y + \texttt{M} _{13}, \texttt{M} _{21} x + \texttt{M} _{22} y + \texttt{M} _{23})\f] + +when the flag WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted +with cv::invertAffineTransform and then put in the formula above instead of M. The function cannot +operate in-place. + +@param src input image. +@param dst output image that has the size dsize and the same type as src . +@param M \f$2\times 3\f$ transformation matrix. +@param dsize size of the output image. +@param flags combination of interpolation methods (see cv::InterpolationFlags) and the optional +flag WARP_INVERSE_MAP that means that M is the inverse transformation ( +\f$\texttt{dst}\rightarrow\texttt{src}\f$ ). +@param borderMode pixel extrapolation method (see cv::BorderTypes); when +borderMode=BORDER_TRANSPARENT, it means that the pixels in the destination image corresponding to +the "outliers" in the source image are not modified by the function. +@param borderValue value used in case of a constant border; by default, it is 0. + +@sa warpPerspective, resize, remap, getRectSubPix, transform + */ +CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst, + InputArray M, Size dsize, + int flags = INTER_LINEAR, + int borderMode = BORDER_CONSTANT, + const Scalar& borderValue = Scalar()); + +/** @brief Applies a perspective transformation to an image. + +The function warpPerspective transforms the source image using the specified matrix: + +\f[\texttt{dst} (x,y) = \texttt{src} \left ( \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + M_{33}} , + \frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + M_{33}} \right )\f] + +when the flag WARP_INVERSE_MAP is set. Otherwise, the transformation is first inverted with invert +and then put in the formula above instead of M. The function cannot operate in-place. + +@param src input image. +@param dst output image that has the size dsize and the same type as src . +@param M \f$3\times 3\f$ transformation matrix. +@param dsize size of the output image. +@param flags combination of interpolation methods (INTER_LINEAR or INTER_NEAREST) and the +optional flag WARP_INVERSE_MAP, that sets M as the inverse transformation ( +\f$\texttt{dst}\rightarrow\texttt{src}\f$ ). +@param borderMode pixel extrapolation method (BORDER_CONSTANT or BORDER_REPLICATE). +@param borderValue value used in case of a constant border; by default, it equals 0. + +@sa warpAffine, resize, remap, getRectSubPix, perspectiveTransform + */ +CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst, + InputArray M, Size dsize, + int flags = INTER_LINEAR, + int borderMode = BORDER_CONSTANT, + const Scalar& borderValue = Scalar()); + +/** @brief Applies a generic geometrical transformation to an image. + +The function remap transforms the source image using the specified map: + +\f[\texttt{dst} (x,y) = \texttt{src} (map_x(x,y),map_y(x,y))\f] + +where values of pixels with non-integer coordinates are computed using one of available +interpolation methods. \f$map_x\f$ and \f$map_y\f$ can be encoded as separate floating-point maps +in \f$map_1\f$ and \f$map_2\f$ respectively, or interleaved floating-point maps of \f$(x,y)\f$ in +\f$map_1\f$, or fixed-point maps created by using convertMaps. The reason you might want to +convert from floating to fixed-point representations of a map is that they can yield much faster +(\~2x) remapping operations. In the converted case, \f$map_1\f$ contains pairs (cvFloor(x), +cvFloor(y)) and \f$map_2\f$ contains indices in a table of interpolation coefficients. + +This function cannot operate in-place. + +@param src Source image. +@param dst Destination image. It has the same size as map1 and the same type as src . +@param map1 The first map of either (x,y) points or just x values having the type CV_16SC2 , +CV_32FC1, or CV_32FC2. See convertMaps for details on converting a floating point +representation to fixed-point for speed. +@param map2 The second map of y values having the type CV_16UC1, CV_32FC1, or none (empty map +if map1 is (x,y) points), respectively. +@param interpolation Interpolation method (see cv::InterpolationFlags). The method INTER_AREA is +not supported by this function. +@param borderMode Pixel extrapolation method (see cv::BorderTypes). When +borderMode=BORDER_TRANSPARENT, it means that the pixels in the destination image that +corresponds to the "outliers" in the source image are not modified by the function. +@param borderValue Value used in case of a constant border. By default, it is 0. + */ +CV_EXPORTS_W void remap( InputArray src, OutputArray dst, + InputArray map1, InputArray map2, + int interpolation, int borderMode = BORDER_CONSTANT, + const Scalar& borderValue = Scalar()); + +/** @brief Converts image transformation maps from one representation to another. + +The function converts a pair of maps for remap from one representation to another. The following +options ( (map1.type(), map2.type()) \f$\rightarrow\f$ (dstmap1.type(), dstmap2.type()) ) are +supported: + +- \f$\texttt{(CV\_32FC1, CV\_32FC1)} \rightarrow \texttt{(CV\_16SC2, CV\_16UC1)}\f$. This is the +most frequently used conversion operation, in which the original floating-point maps (see remap ) +are converted to a more compact and much faster fixed-point representation. The first output array +contains the rounded coordinates and the second array (created only when nninterpolation=false ) +contains indices in the interpolation tables. + +- \f$\texttt{(CV\_32FC2)} \rightarrow \texttt{(CV\_16SC2, CV\_16UC1)}\f$. The same as above but +the original maps are stored in one 2-channel matrix. + +- Reverse conversion. Obviously, the reconstructed floating-point maps will not be exactly the same +as the originals. + +@param map1 The first input map of type CV_16SC2, CV_32FC1, or CV_32FC2 . +@param map2 The second input map of type CV_16UC1, CV_32FC1, or none (empty matrix), +respectively. +@param dstmap1 The first output map that has the type dstmap1type and the same size as src . +@param dstmap2 The second output map. +@param dstmap1type Type of the first output map that should be CV_16SC2, CV_32FC1, or +CV_32FC2 . +@param nninterpolation Flag indicating whether the fixed-point maps are used for the +nearest-neighbor or for a more complex interpolation. + +@sa remap, undistort, initUndistortRectifyMap + */ +CV_EXPORTS_W void convertMaps( InputArray map1, InputArray map2, + OutputArray dstmap1, OutputArray dstmap2, + int dstmap1type, bool nninterpolation = false ); + +/** @brief Calculates an affine matrix of 2D rotation. + +The function calculates the following matrix: + +\f[\begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot \texttt{center.x} - \beta \cdot \texttt{center.y} \\ - \beta & \alpha & \beta \cdot \texttt{center.x} + (1- \alpha ) \cdot \texttt{center.y} \end{bmatrix}\f] + +where + +\f[\begin{array}{l} \alpha = \texttt{scale} \cdot \cos \texttt{angle} , \\ \beta = \texttt{scale} \cdot \sin \texttt{angle} \end{array}\f] + +The transformation maps the rotation center to itself. If this is not the target, adjust the shift. + +@param center Center of the rotation in the source image. +@param angle Rotation angle in degrees. Positive values mean counter-clockwise rotation (the +coordinate origin is assumed to be the top-left corner). +@param scale Isotropic scale factor. + +@sa getAffineTransform, warpAffine, transform + */ +CV_EXPORTS_W Mat getRotationMatrix2D( Point2f center, double angle, double scale ); + +//! returns 3x3 perspective transformation for the corresponding 4 point pairs. +CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] ); + +/** @brief Calculates an affine transform from three pairs of the corresponding points. + +The function calculates the \f$2 \times 3\f$ matrix of an affine transform so that: + +\f[\begin{bmatrix} x'_i \\ y'_i \end{bmatrix} = \texttt{map\_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f] + +where + +\f[dst(i)=(x'_i,y'_i), src(i)=(x_i, y_i), i=0,1,2\f] + +@param src Coordinates of triangle vertices in the source image. +@param dst Coordinates of the corresponding triangle vertices in the destination image. + +@sa warpAffine, transform + */ +CV_EXPORTS Mat getAffineTransform( const Point2f src[], const Point2f dst[] ); + +/** @brief Inverts an affine transformation. + +The function computes an inverse affine transformation represented by \f$2 \times 3\f$ matrix M: + +\f[\begin{bmatrix} a_{11} & a_{12} & b_1 \\ a_{21} & a_{22} & b_2 \end{bmatrix}\f] + +The result is also a \f$2 \times 3\f$ matrix of the same type as M. + +@param M Original affine transformation. +@param iM Output reverse affine transformation. + */ +CV_EXPORTS_W void invertAffineTransform( InputArray M, OutputArray iM ); + +/** @brief Calculates a perspective transform from four pairs of the corresponding points. + +The function calculates the \f$3 \times 3\f$ matrix of a perspective transform so that: + +\f[\begin{bmatrix} t_i x'_i \\ t_i y'_i \\ t_i \end{bmatrix} = \texttt{map\_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f] + +where + +\f[dst(i)=(x'_i,y'_i), src(i)=(x_i, y_i), i=0,1,2,3\f] + +@param src Coordinates of quadrangle vertices in the source image. +@param dst Coordinates of the corresponding quadrangle vertices in the destination image. + +@sa findHomography, warpPerspective, perspectiveTransform + */ +CV_EXPORTS_W Mat getPerspectiveTransform( InputArray src, InputArray dst ); + +CV_EXPORTS_W Mat getAffineTransform( InputArray src, InputArray dst ); + +/** @brief Retrieves a pixel rectangle from an image with sub-pixel accuracy. + +The function getRectSubPix extracts pixels from src: + +\f[dst(x, y) = src(x + \texttt{center.x} - ( \texttt{dst.cols} -1)*0.5, y + \texttt{center.y} - ( \texttt{dst.rows} -1)*0.5)\f] + +where the values of the pixels at non-integer coordinates are retrieved using bilinear +interpolation. Every channel of multi-channel images is processed independently. While the center of +the rectangle must be inside the image, parts of the rectangle may be outside. In this case, the +replication border mode (see cv::BorderTypes) is used to extrapolate the pixel values outside of +the image. + +@param image Source image. +@param patchSize Size of the extracted patch. +@param center Floating point coordinates of the center of the extracted rectangle within the +source image. The center must be inside the image. +@param patch Extracted patch that has the size patchSize and the same number of channels as src . +@param patchType Depth of the extracted pixels. By default, they have the same depth as src . + +@sa warpAffine, warpPerspective + */ +CV_EXPORTS_W void getRectSubPix( InputArray image, Size patchSize, + Point2f center, OutputArray patch, int patchType = -1 ); + +/** @example polar_transforms.cpp +An example using the cv::linearPolar and cv::logPolar operations +*/ + +/** @brief Remaps an image to log-polar space. + +transforms the source image using the following transformation: +\f[dst( \phi , \rho ) = src(x,y)\f] +where +\f[\rho = M \cdot \log{\sqrt{x^2 + y^2}} , \phi =atan(y/x)\f] + +The function emulates the human "foveal" vision and can be used for fast scale and +rotation-invariant template matching, for object tracking and so forth. The function can not operate +in-place. + +@param src Source image +@param dst Destination image +@param center The transformation center; where the output precision is maximal +@param M Magnitude scale parameter. +@param flags A combination of interpolation methods, see cv::InterpolationFlags + */ +CV_EXPORTS_W void logPolar( InputArray src, OutputArray dst, + Point2f center, double M, int flags ); + +/** @brief Remaps an image to polar space. + +transforms the source image using the following transformation: +\f[dst( \phi , \rho ) = src(x,y)\f] +where +\f[\rho = (src.width/maxRadius) \cdot \sqrt{x^2 + y^2} , \phi =atan(y/x)\f] + +The function can not operate in-place. + +@param src Source image +@param dst Destination image +@param center The transformation center; +@param maxRadius Inverse magnitude scale parameter +@param flags A combination of interpolation methods, see cv::InterpolationFlags + */ +CV_EXPORTS_W void linearPolar( InputArray src, OutputArray dst, + Point2f center, double maxRadius, int flags ); + +//! @} imgproc_transform + +//! @addtogroup imgproc_misc +//! @{ + +/** @overload */ +CV_EXPORTS_W void integral( InputArray src, OutputArray sum, int sdepth = -1 ); + +/** @overload */ +CV_EXPORTS_AS(integral2) void integral( InputArray src, OutputArray sum, + OutputArray sqsum, int sdepth = -1, int sqdepth = -1 ); + +/** @brief Calculates the integral of an image. + +The functions calculate one or more integral images for the source image as follows: + +\f[\texttt{sum} (X,Y) = \sum _{x + +Calculates the cross-power spectrum of two supplied source arrays. The arrays are padded if needed +with getOptimalDFTSize. + +The function performs the following equations: +- First it applies a Hanning window (see ) to each +image to remove possible edge effects. This window is cached until the array size changes to speed +up processing time. +- Next it computes the forward DFTs of each source array: +\f[\mathbf{G}_a = \mathcal{F}\{src_1\}, \; \mathbf{G}_b = \mathcal{F}\{src_2\}\f] +where \f$\mathcal{F}\f$ is the forward DFT. +- It then computes the cross-power spectrum of each frequency domain array: +\f[R = \frac{ \mathbf{G}_a \mathbf{G}_b^*}{|\mathbf{G}_a \mathbf{G}_b^*|}\f] +- Next the cross-correlation is converted back into the time domain via the inverse DFT: +\f[r = \mathcal{F}^{-1}\{R\}\f] +- Finally, it computes the peak location and computes a 5x5 weighted centroid around the peak to +achieve sub-pixel accuracy. +\f[(\Delta x, \Delta y) = \texttt{weightedCentroid} \{\arg \max_{(x, y)}\{r\}\}\f] +- If non-zero, the response parameter is computed as the sum of the elements of r within the 5x5 +centroid around the peak location. It is normalized to a maximum of 1 (meaning there is a single +peak) and will be smaller when there are multiple peaks. + +@param src1 Source floating point array (CV_32FC1 or CV_64FC1) +@param src2 Source floating point array (CV_32FC1 or CV_64FC1) +@param window Floating point array with windowing coefficients to reduce edge effects (optional). +@param response Signal power within the 5x5 centroid around the peak, between 0 and 1 (optional). +@returns detected phase shift (sub-pixel) between the two arrays. + +@sa dft, getOptimalDFTSize, idft, mulSpectrums createHanningWindow + */ +CV_EXPORTS_W Point2d phaseCorrelate(InputArray src1, InputArray src2, + InputArray window = noArray(), CV_OUT double* response = 0); + +/** @brief This function computes a Hanning window coefficients in two dimensions. + +See (http://en.wikipedia.org/wiki/Hann_function) and (http://en.wikipedia.org/wiki/Window_function) +for more information. + +An example is shown below: +@code + // create hanning window of size 100x100 and type CV_32F + Mat hann; + createHanningWindow(hann, Size(100, 100), CV_32F); +@endcode +@param dst Destination array to place Hann coefficients in +@param winSize The window size specifications +@param type Created array type + */ +CV_EXPORTS_W void createHanningWindow(OutputArray dst, Size winSize, int type); + +//! @} imgproc_motion + +//! @addtogroup imgproc_misc +//! @{ + +/** @brief Applies a fixed-level threshold to each array element. + +The function applies fixed-level thresholding to a single-channel array. The function is typically +used to get a bi-level (binary) image out of a grayscale image ( cv::compare could be also used for +this purpose) or for removing a noise, that is, filtering out pixels with too small or too large +values. There are several types of thresholding supported by the function. They are determined by +type parameter. + +Also, the special values cv::THRESH_OTSU or cv::THRESH_TRIANGLE may be combined with one of the +above values. In these cases, the function determines the optimal threshold value using the Otsu's +or Triangle algorithm and uses it instead of the specified thresh . The function returns the +computed threshold value. Currently, the Otsu's and Triangle methods are implemented only for 8-bit +images. + +@param src input array (single-channel, 8-bit or 32-bit floating point). +@param dst output array of the same size and type as src. +@param thresh threshold value. +@param maxval maximum value to use with the THRESH_BINARY and THRESH_BINARY_INV thresholding +types. +@param type thresholding type (see the cv::ThresholdTypes). + +@sa adaptiveThreshold, findContours, compare, min, max + */ +CV_EXPORTS_W double threshold( InputArray src, OutputArray dst, + double thresh, double maxval, int type ); + + +/** @brief Applies an adaptive threshold to an array. + +The function transforms a grayscale image to a binary image according to the formulae: +- **THRESH_BINARY** + \f[dst(x,y) = \fork{\texttt{maxValue}}{if \(src(x,y) > T(x,y)\)}{0}{otherwise}\f] +- **THRESH_BINARY_INV** + \f[dst(x,y) = \fork{0}{if \(src(x,y) > T(x,y)\)}{\texttt{maxValue}}{otherwise}\f] +where \f$T(x,y)\f$ is a threshold calculated individually for each pixel (see adaptiveMethod parameter). + +The function can process the image in-place. + +@param src Source 8-bit single-channel image. +@param dst Destination image of the same size and the same type as src. +@param maxValue Non-zero value assigned to the pixels for which the condition is satisfied +@param adaptiveMethod Adaptive thresholding algorithm to use, see cv::AdaptiveThresholdTypes +@param thresholdType Thresholding type that must be either THRESH_BINARY or THRESH_BINARY_INV, +see cv::ThresholdTypes. +@param blockSize Size of a pixel neighborhood that is used to calculate a threshold value for the +pixel: 3, 5, 7, and so on. +@param C Constant subtracted from the mean or weighted mean (see the details below). Normally, it +is positive but may be zero or negative as well. + +@sa threshold, blur, GaussianBlur + */ +CV_EXPORTS_W void adaptiveThreshold( InputArray src, OutputArray dst, + double maxValue, int adaptiveMethod, + int thresholdType, int blockSize, double C ); + +//! @} imgproc_misc + +//! @addtogroup imgproc_filter +//! @{ + +/** @brief Blurs an image and downsamples it. + +By default, size of the output image is computed as `Size((src.cols+1)/2, (src.rows+1)/2)`, but in +any case, the following conditions should be satisfied: + +\f[\begin{array}{l} | \texttt{dstsize.width} *2-src.cols| \leq 2 \\ | \texttt{dstsize.height} *2-src.rows| \leq 2 \end{array}\f] + +The function performs the downsampling step of the Gaussian pyramid construction. First, it +convolves the source image with the kernel: + +\f[\frac{1}{256} \begin{bmatrix} 1 & 4 & 6 & 4 & 1 \\ 4 & 16 & 24 & 16 & 4 \\ 6 & 24 & 36 & 24 & 6 \\ 4 & 16 & 24 & 16 & 4 \\ 1 & 4 & 6 & 4 & 1 \end{bmatrix}\f] + +Then, it downsamples the image by rejecting even rows and columns. + +@param src input image. +@param dst output image; it has the specified size and the same type as src. +@param dstsize size of the output image. +@param borderType Pixel extrapolation method, see cv::BorderTypes (BORDER_CONSTANT isn't supported) + */ +CV_EXPORTS_W void pyrDown( InputArray src, OutputArray dst, + const Size& dstsize = Size(), int borderType = BORDER_DEFAULT ); + +/** @brief Upsamples an image and then blurs it. + +By default, size of the output image is computed as `Size(src.cols\*2, (src.rows\*2)`, but in any +case, the following conditions should be satisfied: + +\f[\begin{array}{l} | \texttt{dstsize.width} -src.cols*2| \leq ( \texttt{dstsize.width} \mod 2) \\ | \texttt{dstsize.height} -src.rows*2| \leq ( \texttt{dstsize.height} \mod 2) \end{array}\f] + +The function performs the upsampling step of the Gaussian pyramid construction, though it can +actually be used to construct the Laplacian pyramid. First, it upsamples the source image by +injecting even zero rows and columns and then convolves the result with the same kernel as in +pyrDown multiplied by 4. + +@param src input image. +@param dst output image. It has the specified size and the same type as src . +@param dstsize size of the output image. +@param borderType Pixel extrapolation method, see cv::BorderTypes (only BORDER_DEFAULT is supported) + */ +CV_EXPORTS_W void pyrUp( InputArray src, OutputArray dst, + const Size& dstsize = Size(), int borderType = BORDER_DEFAULT ); + +/** @brief Constructs the Gaussian pyramid for an image. + +The function constructs a vector of images and builds the Gaussian pyramid by recursively applying +pyrDown to the previously built pyramid layers, starting from `dst[0]==src`. + +@param src Source image. Check pyrDown for the list of supported types. +@param dst Destination vector of maxlevel+1 images of the same type as src. dst[0] will be the +same as src. dst[1] is the next pyramid layer, a smoothed and down-sized src, and so on. +@param maxlevel 0-based index of the last (the smallest) pyramid layer. It must be non-negative. +@param borderType Pixel extrapolation method, see cv::BorderTypes (BORDER_CONSTANT isn't supported) + */ +CV_EXPORTS void buildPyramid( InputArray src, OutputArrayOfArrays dst, + int maxlevel, int borderType = BORDER_DEFAULT ); + +//! @} imgproc_filter + +//! @addtogroup imgproc_transform +//! @{ + +/** @brief Transforms an image to compensate for lens distortion. + +The function transforms an image to compensate radial and tangential lens distortion. + +The function is simply a combination of cv::initUndistortRectifyMap (with unity R ) and cv::remap +(with bilinear interpolation). See the former function for details of the transformation being +performed. + +Those pixels in the destination image, for which there is no correspondent pixels in the source +image, are filled with zeros (black color). + +A particular subset of the source image that will be visible in the corrected image can be regulated +by newCameraMatrix. You can use cv::getOptimalNewCameraMatrix to compute the appropriate +newCameraMatrix depending on your requirements. + +The camera matrix and the distortion parameters can be determined using cv::calibrateCamera. If +the resolution of images is different from the resolution used at the calibration stage, \f$f_x, +f_y, c_x\f$ and \f$c_y\f$ need to be scaled accordingly, while the distortion coefficients remain +the same. + +@param src Input (distorted) image. +@param dst Output (corrected) image that has the same size and type as src . +@param cameraMatrix Input camera matrix \f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . +@param distCoeffs Input vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6]])\f$ of 4, 5, or 8 elements. If the vector is +NULL/empty, the zero distortion coefficients are assumed. +@param newCameraMatrix Camera matrix of the distorted image. By default, it is the same as +cameraMatrix but you may additionally scale and shift the result by using a different matrix. + */ +CV_EXPORTS_W void undistort( InputArray src, OutputArray dst, + InputArray cameraMatrix, + InputArray distCoeffs, + InputArray newCameraMatrix = noArray() ); + +/** @brief Computes the undistortion and rectification transformation map. + +The function computes the joint undistortion and rectification transformation and represents the +result in the form of maps for remap. The undistorted image looks like original, as if it is +captured with a camera using the camera matrix =newCameraMatrix and zero distortion. In case of a +monocular camera, newCameraMatrix is usually equal to cameraMatrix, or it can be computed by +cv::getOptimalNewCameraMatrix for a better control over scaling. In case of a stereo camera, +newCameraMatrix is normally set to P1 or P2 computed by cv::stereoRectify . + +Also, this new camera is oriented differently in the coordinate space, according to R. That, for +example, helps to align two heads of a stereo camera so that the epipolar lines on both images +become horizontal and have the same y- coordinate (in case of a horizontally aligned stereo camera). + +The function actually builds the maps for the inverse mapping algorithm that is used by remap. That +is, for each pixel \f$(u, v)\f$ in the destination (corrected and rectified) image, the function +computes the corresponding coordinates in the source image (that is, in the original image from +camera). The following process is applied: +\f[\begin{array}{l} x \leftarrow (u - {c'}_x)/{f'}_x \\ y \leftarrow (v - {c'}_y)/{f'}_y \\{[X\,Y\,W]} ^T \leftarrow R^{-1}*[x \, y \, 1]^T \\ x' \leftarrow X/W \\ y' \leftarrow Y/W \\ x" \leftarrow x' (1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + 2p_1 x' y' + p_2(r^2 + 2 x'^2) \\ y" \leftarrow y' (1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + p_1 (r^2 + 2 y'^2) + 2 p_2 x' y' \\ map_x(u,v) \leftarrow x" f_x + c_x \\ map_y(u,v) \leftarrow y" f_y + c_y \end{array}\f] +where \f$(k_1, k_2, p_1, p_2[, k_3])\f$ are the distortion coefficients. + +In case of a stereo camera, this function is called twice: once for each camera head, after +stereoRectify, which in its turn is called after cv::stereoCalibrate. But if the stereo camera +was not calibrated, it is still possible to compute the rectification transformations directly from +the fundamental matrix using cv::stereoRectifyUncalibrated. For each camera, the function computes +homography H as the rectification transformation in a pixel domain, not a rotation matrix R in 3D +space. R can be computed from H as +\f[\texttt{R} = \texttt{cameraMatrix} ^{-1} \cdot \texttt{H} \cdot \texttt{cameraMatrix}\f] +where cameraMatrix can be chosen arbitrarily. + +@param cameraMatrix Input camera matrix \f$A=\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . +@param distCoeffs Input vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6]])\f$ of 4, 5, or 8 elements. If the vector is +NULL/empty, the zero distortion coefficients are assumed. +@param R Optional rectification transformation in the object space (3x3 matrix). R1 or R2 , +computed by stereoRectify can be passed here. If the matrix is empty, the identity transformation +is assumed. In cvInitUndistortMap R assumed to be an identity matrix. +@param newCameraMatrix New camera matrix \f$A'=\vecthreethree{f_x'}{0}{c_x'}{0}{f_y'}{c_y'}{0}{0}{1}\f$. +@param size Undistorted image size. +@param m1type Type of the first output map that can be CV_32FC1 or CV_16SC2, see cv::convertMaps +@param map1 The first output map. +@param map2 The second output map. + */ +CV_EXPORTS_W void initUndistortRectifyMap( InputArray cameraMatrix, InputArray distCoeffs, + InputArray R, InputArray newCameraMatrix, + Size size, int m1type, OutputArray map1, OutputArray map2 ); + +//! initializes maps for cv::remap() for wide-angle +CV_EXPORTS_W float initWideAngleProjMap( InputArray cameraMatrix, InputArray distCoeffs, + Size imageSize, int destImageWidth, + int m1type, OutputArray map1, OutputArray map2, + int projType = PROJ_SPHERICAL_EQRECT, double alpha = 0); + +/** @brief Returns the default new camera matrix. + +The function returns the camera matrix that is either an exact copy of the input cameraMatrix (when +centerPrinicipalPoint=false ), or the modified one (when centerPrincipalPoint=true). + +In the latter case, the new camera matrix will be: + +\f[\begin{bmatrix} f_x && 0 && ( \texttt{imgSize.width} -1)*0.5 \\ 0 && f_y && ( \texttt{imgSize.height} -1)*0.5 \\ 0 && 0 && 1 \end{bmatrix} ,\f] + +where \f$f_x\f$ and \f$f_y\f$ are \f$(0,0)\f$ and \f$(1,1)\f$ elements of cameraMatrix, respectively. + +By default, the undistortion functions in OpenCV (see initUndistortRectifyMap, undistort) do not +move the principal point. However, when you work with stereo, it is important to move the principal +points in both views to the same y-coordinate (which is required by most of stereo correspondence +algorithms), and may be to the same x-coordinate too. So, you can form the new camera matrix for +each view where the principal points are located at the center. + +@param cameraMatrix Input camera matrix. +@param imgsize Camera view image size in pixels. +@param centerPrincipalPoint Location of the principal point in the new camera matrix. The +parameter indicates whether this location should be at the image center or not. + */ +CV_EXPORTS_W Mat getDefaultNewCameraMatrix( InputArray cameraMatrix, Size imgsize = Size(), + bool centerPrincipalPoint = false ); + +/** @brief Computes the ideal point coordinates from the observed point coordinates. + +The function is similar to cv::undistort and cv::initUndistortRectifyMap but it operates on a +sparse set of points instead of a raster image. Also the function performs a reverse transformation +to projectPoints. In case of a 3D object, it does not reconstruct its 3D coordinates, but for a +planar object, it does, up to a translation vector, if the proper R is specified. +@code + // (u,v) is the input point, (u', v') is the output point + // camera_matrix=[fx 0 cx; 0 fy cy; 0 0 1] + // P=[fx' 0 cx' tx; 0 fy' cy' ty; 0 0 1 tz] + x" = (u - cx)/fx + y" = (v - cy)/fy + (x',y') = undistort(x",y",dist_coeffs) + [X,Y,W]T = R*[x' y' 1]T + x = X/W, y = Y/W + // only performed if P=[fx' 0 cx' [tx]; 0 fy' cy' [ty]; 0 0 1 [tz]] is specified + u' = x*fx' + cx' + v' = y*fy' + cy', +@endcode +where cv::undistort is an approximate iterative algorithm that estimates the normalized original +point coordinates out of the normalized distorted point coordinates ("normalized" means that the +coordinates do not depend on the camera matrix). + +The function can be used for both a stereo camera head or a monocular camera (when R is empty). + +@param src Observed point coordinates, 1xN or Nx1 2-channel (CV_32FC2 or CV_64FC2). +@param dst Output ideal point coordinates after undistortion and reverse perspective +transformation. If matrix P is identity or omitted, dst will contain normalized point coordinates. +@param cameraMatrix Camera matrix \f$\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ . +@param distCoeffs Input vector of distortion coefficients +\f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6]])\f$ of 4, 5, or 8 elements. If the vector is +NULL/empty, the zero distortion coefficients are assumed. +@param R Rectification transformation in the object space (3x3 matrix). R1 or R2 computed by +cv::stereoRectify can be passed here. If the matrix is empty, the identity transformation is used. +@param P New camera matrix (3x3) or new projection matrix (3x4). P1 or P2 computed by +cv::stereoRectify can be passed here. If the matrix is empty, the identity new camera matrix is used. + */ +CV_EXPORTS_W void undistortPoints( InputArray src, OutputArray dst, + InputArray cameraMatrix, InputArray distCoeffs, + InputArray R = noArray(), InputArray P = noArray()); + +//! @} imgproc_transform + +//! @addtogroup imgproc_hist +//! @{ + +/** @example demhist.cpp +An example for creating histograms of an image +*/ + +/** @brief Calculates a histogram of a set of arrays. + +The functions calcHist calculate the histogram of one or more arrays. The elements of a tuple used +to increment a histogram bin are taken from the corresponding input arrays at the same location. The +sample below shows how to compute a 2D Hue-Saturation histogram for a color image. : +@code + #include + #include + + using namespace cv; + + int main( int argc, char** argv ) + { + Mat src, hsv; + if( argc != 2 || !(src=imread(argv[1], 1)).data ) + return -1; + + cvtColor(src, hsv, COLOR_BGR2HSV); + + // Quantize the hue to 30 levels + // and the saturation to 32 levels + int hbins = 30, sbins = 32; + int histSize[] = {hbins, sbins}; + // hue varies from 0 to 179, see cvtColor + float hranges[] = { 0, 180 }; + // saturation varies from 0 (black-gray-white) to + // 255 (pure spectrum color) + float sranges[] = { 0, 256 }; + const float* ranges[] = { hranges, sranges }; + MatND hist; + // we compute the histogram from the 0-th and 1-st channels + int channels[] = {0, 1}; + + calcHist( &hsv, 1, channels, Mat(), // do not use mask + hist, 2, histSize, ranges, + true, // the histogram is uniform + false ); + double maxVal=0; + minMaxLoc(hist, 0, &maxVal, 0, 0); + + int scale = 10; + Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3); + + for( int h = 0; h < hbins; h++ ) + for( int s = 0; s < sbins; s++ ) + { + float binVal = hist.at(h, s); + int intensity = cvRound(binVal*255/maxVal); + rectangle( histImg, Point(h*scale, s*scale), + Point( (h+1)*scale - 1, (s+1)*scale - 1), + Scalar::all(intensity), + CV_FILLED ); + } + + namedWindow( "Source", 1 ); + imshow( "Source", src ); + + namedWindow( "H-S Histogram", 1 ); + imshow( "H-S Histogram", histImg ); + waitKey(); + } +@endcode + +@param images Source arrays. They all should have the same depth, CV_8U or CV_32F , and the same +size. Each of them can have an arbitrary number of channels. +@param nimages Number of source images. +@param channels List of the dims channels used to compute the histogram. The first array channels +are numerated from 0 to images[0].channels()-1 , the second array channels are counted from +images[0].channels() to images[0].channels() + images[1].channels()-1, and so on. +@param mask Optional mask. If the matrix is not empty, it must be an 8-bit array of the same size +as images[i] . The non-zero mask elements mark the array elements counted in the histogram. +@param hist Output histogram, which is a dense or sparse dims -dimensional array. +@param dims Histogram dimensionality that must be positive and not greater than CV_MAX_DIMS +(equal to 32 in the current OpenCV version). +@param histSize Array of histogram sizes in each dimension. +@param ranges Array of the dims arrays of the histogram bin boundaries in each dimension. When the +histogram is uniform ( uniform =true), then for each dimension i it is enough to specify the lower +(inclusive) boundary \f$L_0\f$ of the 0-th histogram bin and the upper (exclusive) boundary +\f$U_{\texttt{histSize}[i]-1}\f$ for the last histogram bin histSize[i]-1 . That is, in case of a +uniform histogram each of ranges[i] is an array of 2 elements. When the histogram is not uniform ( +uniform=false ), then each of ranges[i] contains histSize[i]+1 elements: +\f$L_0, U_0=L_1, U_1=L_2, ..., U_{\texttt{histSize[i]}-2}=L_{\texttt{histSize[i]}-1}, U_{\texttt{histSize[i]}-1}\f$ +. The array elements, that are not between \f$L_0\f$ and \f$U_{\texttt{histSize[i]}-1}\f$ , are not +counted in the histogram. +@param uniform Flag indicating whether the histogram is uniform or not (see above). +@param accumulate Accumulation flag. If it is set, the histogram is not cleared in the beginning +when it is allocated. This feature enables you to compute a single histogram from several sets of +arrays, or to update the histogram in time. +*/ +CV_EXPORTS void calcHist( const Mat* images, int nimages, + const int* channels, InputArray mask, + OutputArray hist, int dims, const int* histSize, + const float** ranges, bool uniform = true, bool accumulate = false ); + +/** @overload + +this variant uses cv::SparseMat for output +*/ +CV_EXPORTS void calcHist( const Mat* images, int nimages, + const int* channels, InputArray mask, + SparseMat& hist, int dims, + const int* histSize, const float** ranges, + bool uniform = true, bool accumulate = false ); + +/** @overload */ +CV_EXPORTS_W void calcHist( InputArrayOfArrays images, + const std::vector& channels, + InputArray mask, OutputArray hist, + const std::vector& histSize, + const std::vector& ranges, + bool accumulate = false ); + +/** @brief Calculates the back projection of a histogram. + +The functions calcBackProject calculate the back project of the histogram. That is, similarly to +cv::calcHist , at each location (x, y) the function collects the values from the selected channels +in the input images and finds the corresponding histogram bin. But instead of incrementing it, the +function reads the bin value, scales it by scale , and stores in backProject(x,y) . In terms of +statistics, the function computes probability of each element value in respect with the empirical +probability distribution represented by the histogram. See how, for example, you can find and track +a bright-colored object in a scene: + +- Before tracking, show the object to the camera so that it covers almost the whole frame. +Calculate a hue histogram. The histogram may have strong maximums, corresponding to the dominant +colors in the object. + +- When tracking, calculate a back projection of a hue plane of each input video frame using that +pre-computed histogram. Threshold the back projection to suppress weak colors. It may also make +sense to suppress pixels with non-sufficient color saturation and too dark or too bright pixels. + +- Find connected components in the resulting picture and choose, for example, the largest +component. + +This is an approximate algorithm of the CamShift color object tracker. + +@param images Source arrays. They all should have the same depth, CV_8U or CV_32F , and the same +size. Each of them can have an arbitrary number of channels. +@param nimages Number of source images. +@param channels The list of channels used to compute the back projection. The number of channels +must match the histogram dimensionality. The first array channels are numerated from 0 to +images[0].channels()-1 , the second array channels are counted from images[0].channels() to +images[0].channels() + images[1].channels()-1, and so on. +@param hist Input histogram that can be dense or sparse. +@param backProject Destination back projection array that is a single-channel array of the same +size and depth as images[0] . +@param ranges Array of arrays of the histogram bin boundaries in each dimension. See calcHist . +@param scale Optional scale factor for the output back projection. +@param uniform Flag indicating whether the histogram is uniform or not (see above). + +@sa cv::calcHist, cv::compareHist + */ +CV_EXPORTS void calcBackProject( const Mat* images, int nimages, + const int* channels, InputArray hist, + OutputArray backProject, const float** ranges, + double scale = 1, bool uniform = true ); + +/** @overload */ +CV_EXPORTS void calcBackProject( const Mat* images, int nimages, + const int* channels, const SparseMat& hist, + OutputArray backProject, const float** ranges, + double scale = 1, bool uniform = true ); + +/** @overload */ +CV_EXPORTS_W void calcBackProject( InputArrayOfArrays images, const std::vector& channels, + InputArray hist, OutputArray dst, + const std::vector& ranges, + double scale ); + +/** @brief Compares two histograms. + +The function compare two dense or two sparse histograms using the specified method. + +The function returns \f$d(H_1, H_2)\f$ . + +While the function works well with 1-, 2-, 3-dimensional dense histograms, it may not be suitable +for high-dimensional sparse histograms. In such histograms, because of aliasing and sampling +problems, the coordinates of non-zero histogram bins can slightly shift. To compare such histograms +or more general sparse configurations of weighted points, consider using the cv::EMD function. + +@param H1 First compared histogram. +@param H2 Second compared histogram of the same size as H1 . +@param method Comparison method, see cv::HistCompMethods + */ +CV_EXPORTS_W double compareHist( InputArray H1, InputArray H2, int method ); + +/** @overload */ +CV_EXPORTS double compareHist( const SparseMat& H1, const SparseMat& H2, int method ); + +/** @brief Equalizes the histogram of a grayscale image. + +The function equalizes the histogram of the input image using the following algorithm: + +- Calculate the histogram \f$H\f$ for src . +- Normalize the histogram so that the sum of histogram bins is 255. +- Compute the integral of the histogram: +\f[H'_i = \sum _{0 \le j < i} H(j)\f] +- Transform the image using \f$H'\f$ as a look-up table: \f$\texttt{dst}(x,y) = H'(\texttt{src}(x,y))\f$ + +The algorithm normalizes the brightness and increases the contrast of the image. + +@param src Source 8-bit single channel image. +@param dst Destination image of the same size and type as src . + */ +CV_EXPORTS_W void equalizeHist( InputArray src, OutputArray dst ); + +/** @brief Computes the "minimal work" distance between two weighted point configurations. + +The function computes the earth mover distance and/or a lower boundary of the distance between the +two weighted point configurations. One of the applications described in @cite RubnerSept98, +@cite Rubner2000 is multi-dimensional histogram comparison for image retrieval. EMD is a transportation +problem that is solved using some modification of a simplex algorithm, thus the complexity is +exponential in the worst case, though, on average it is much faster. In the case of a real metric +the lower boundary can be calculated even faster (using linear-time algorithm) and it can be used +to determine roughly whether the two signatures are far enough so that they cannot relate to the +same object. + +@param signature1 First signature, a \f$\texttt{size1}\times \texttt{dims}+1\f$ floating-point matrix. +Each row stores the point weight followed by the point coordinates. The matrix is allowed to have +a single column (weights only) if the user-defined cost matrix is used. +@param signature2 Second signature of the same format as signature1 , though the number of rows +may be different. The total weights may be different. In this case an extra "dummy" point is added +to either signature1 or signature2 . +@param distType Used metric. See cv::DistanceTypes. +@param cost User-defined \f$\texttt{size1}\times \texttt{size2}\f$ cost matrix. Also, if a cost matrix +is used, lower boundary lowerBound cannot be calculated because it needs a metric function. +@param lowerBound Optional input/output parameter: lower boundary of a distance between the two +signatures that is a distance between mass centers. The lower boundary may not be calculated if +the user-defined cost matrix is used, the total weights of point configurations are not equal, or +if the signatures consist of weights only (the signature matrices have a single column). You +**must** initialize \*lowerBound . If the calculated distance between mass centers is greater or +equal to \*lowerBound (it means that the signatures are far enough), the function does not +calculate EMD. In any case \*lowerBound is set to the calculated distance between mass centers on +return. Thus, if you want to calculate both distance between mass centers and EMD, \*lowerBound +should be set to 0. +@param flow Resultant \f$\texttt{size1} \times \texttt{size2}\f$ flow matrix: \f$\texttt{flow}_{i,j}\f$ is +a flow from \f$i\f$ -th point of signature1 to \f$j\f$ -th point of signature2 . + */ +CV_EXPORTS float EMD( InputArray signature1, InputArray signature2, + int distType, InputArray cost=noArray(), + float* lowerBound = 0, OutputArray flow = noArray() ); + +//! @} imgproc_hist + +/** @example watershed.cpp +An example using the watershed algorithm + */ + +/** @brief Performs a marker-based image segmentation using the watershed algorithm. + +The function implements one of the variants of watershed, non-parametric marker-based segmentation +algorithm, described in @cite Meyer92 . + +Before passing the image to the function, you have to roughly outline the desired regions in the +image markers with positive (\>0) indices. So, every region is represented as one or more connected +components with the pixel values 1, 2, 3, and so on. Such markers can be retrieved from a binary +mask using findContours and drawContours (see the watershed.cpp demo). The markers are "seeds" of +the future image regions. All the other pixels in markers , whose relation to the outlined regions +is not known and should be defined by the algorithm, should be set to 0's. In the function output, +each pixel in markers is set to a value of the "seed" components or to -1 at boundaries between the +regions. + +@note Any two neighbor connected components are not necessarily separated by a watershed boundary +(-1's pixels); for example, they can touch each other in the initial marker image passed to the +function. + +@param image Input 8-bit 3-channel image. +@param markers Input/output 32-bit single-channel image (map) of markers. It should have the same +size as image . + +@sa findContours + +@ingroup imgproc_misc + */ +CV_EXPORTS_W void watershed( InputArray image, InputOutputArray markers ); + +//! @addtogroup imgproc_filter +//! @{ + +/** @brief Performs initial step of meanshift segmentation of an image. + +The function implements the filtering stage of meanshift segmentation, that is, the output of the +function is the filtered "posterized" image with color gradients and fine-grain texture flattened. +At every pixel (X,Y) of the input image (or down-sized input image, see below) the function executes +meanshift iterations, that is, the pixel (X,Y) neighborhood in the joint space-color hyperspace is +considered: + +\f[(x,y): X- \texttt{sp} \le x \le X+ \texttt{sp} , Y- \texttt{sp} \le y \le Y+ \texttt{sp} , ||(R,G,B)-(r,g,b)|| \le \texttt{sr}\f] + +where (R,G,B) and (r,g,b) are the vectors of color components at (X,Y) and (x,y), respectively +(though, the algorithm does not depend on the color space used, so any 3-component color space can +be used instead). Over the neighborhood the average spatial value (X',Y') and average color vector +(R',G',B') are found and they act as the neighborhood center on the next iteration: + +\f[(X,Y)~(X',Y'), (R,G,B)~(R',G',B').\f] + +After the iterations over, the color components of the initial pixel (that is, the pixel from where +the iterations started) are set to the final value (average color at the last iteration): + +\f[I(X,Y) <- (R*,G*,B*)\f] + +When maxLevel \> 0, the gaussian pyramid of maxLevel+1 levels is built, and the above procedure is +run on the smallest layer first. After that, the results are propagated to the larger layer and the +iterations are run again only on those pixels where the layer colors differ by more than sr from the +lower-resolution layer of the pyramid. That makes boundaries of color regions sharper. Note that the +results will be actually different from the ones obtained by running the meanshift procedure on the +whole original image (i.e. when maxLevel==0). + +@param src The source 8-bit, 3-channel image. +@param dst The destination image of the same format and the same size as the source. +@param sp The spatial window radius. +@param sr The color window radius. +@param maxLevel Maximum level of the pyramid for the segmentation. +@param termcrit Termination criteria: when to stop meanshift iterations. + */ +CV_EXPORTS_W void pyrMeanShiftFiltering( InputArray src, OutputArray dst, + double sp, double sr, int maxLevel = 1, + TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) ); + +//! @} + +//! @addtogroup imgproc_misc +//! @{ + +/** @example grabcut.cpp +An example using the GrabCut algorithm + */ + +/** @brief Runs the GrabCut algorithm. + +The function implements the [GrabCut image segmentation algorithm](http://en.wikipedia.org/wiki/GrabCut). + +@param img Input 8-bit 3-channel image. +@param mask Input/output 8-bit single-channel mask. The mask is initialized by the function when +mode is set to GC_INIT_WITH_RECT. Its elements may have one of the cv::GrabCutClasses. +@param rect ROI containing a segmented object. The pixels outside of the ROI are marked as +"obvious background". The parameter is only used when mode==GC_INIT_WITH_RECT . +@param bgdModel Temporary array for the background model. Do not modify it while you are +processing the same image. +@param fgdModel Temporary arrays for the foreground model. Do not modify it while you are +processing the same image. +@param iterCount Number of iterations the algorithm should make before returning the result. Note +that the result can be refined with further calls with mode==GC_INIT_WITH_MASK or +mode==GC_EVAL . +@param mode Operation mode that could be one of the cv::GrabCutModes + */ +CV_EXPORTS_W void grabCut( InputArray img, InputOutputArray mask, Rect rect, + InputOutputArray bgdModel, InputOutputArray fgdModel, + int iterCount, int mode = GC_EVAL ); + +/** @example distrans.cpp +An example on using the distance transform\ +*/ + + +/** @brief Calculates the distance to the closest zero pixel for each pixel of the source image. + +The functions distanceTransform calculate the approximate or precise distance from every binary +image pixel to the nearest zero pixel. For zero image pixels, the distance will obviously be zero. + +When maskSize == DIST_MASK_PRECISE and distanceType == DIST_L2 , the function runs the +algorithm described in @cite Felzenszwalb04 . This algorithm is parallelized with the TBB library. + +In other cases, the algorithm @cite Borgefors86 is used. This means that for a pixel the function +finds the shortest path to the nearest zero pixel consisting of basic shifts: horizontal, vertical, +diagonal, or knight's move (the latest is available for a \f$5\times 5\f$ mask). The overall +distance is calculated as a sum of these basic distances. Since the distance function should be +symmetric, all of the horizontal and vertical shifts must have the same cost (denoted as a ), all +the diagonal shifts must have the same cost (denoted as `b`), and all knight's moves must have the +same cost (denoted as `c`). For the cv::DIST_C and cv::DIST_L1 types, the distance is calculated +precisely, whereas for cv::DIST_L2 (Euclidean distance) the distance can be calculated only with a +relative error (a \f$5\times 5\f$ mask gives more accurate results). For `a`,`b`, and `c`, OpenCV +uses the values suggested in the original paper: +- DIST_L1: `a = 1, b = 2` +- DIST_L2: + - `3 x 3`: `a=0.955, b=1.3693` + - `5 x 5`: `a=1, b=1.4, c=2.1969` +- DIST_C: `a = 1, b = 1` + +Typically, for a fast, coarse distance estimation DIST_L2, a \f$3\times 3\f$ mask is used. For a +more accurate distance estimation DIST_L2, a \f$5\times 5\f$ mask or the precise algorithm is used. +Note that both the precise and the approximate algorithms are linear on the number of pixels. + +This variant of the function does not only compute the minimum distance for each pixel \f$(x, y)\f$ +but also identifies the nearest connected component consisting of zero pixels +(labelType==DIST_LABEL_CCOMP) or the nearest zero pixel (labelType==DIST_LABEL_PIXEL). Index of the +component/pixel is stored in `labels(x, y)`. When labelType==DIST_LABEL_CCOMP, the function +automatically finds connected components of zero pixels in the input image and marks them with +distinct labels. When labelType==DIST_LABEL_CCOMP, the function scans through the input image and +marks all the zero pixels with distinct labels. + +In this mode, the complexity is still linear. That is, the function provides a very fast way to +compute the Voronoi diagram for a binary image. Currently, the second variant can use only the +approximate distance transform algorithm, i.e. maskSize=DIST_MASK_PRECISE is not supported +yet. + +@param src 8-bit, single-channel (binary) source image. +@param dst Output image with calculated distances. It is a 8-bit or 32-bit floating-point, +single-channel image of the same size as src. +@param labels Output 2D array of labels (the discrete Voronoi diagram). It has the type +CV_32SC1 and the same size as src. +@param distanceType Type of distance, see cv::DistanceTypes +@param maskSize Size of the distance transform mask, see cv::DistanceTransformMasks. +DIST_MASK_PRECISE is not supported by this variant. In case of the DIST_L1 or DIST_C distance type, +the parameter is forced to 3 because a \f$3\times 3\f$ mask gives the same result as \f$5\times +5\f$ or any larger aperture. +@param labelType Type of the label array to build, see cv::DistanceTransformLabelTypes. + */ +CV_EXPORTS_AS(distanceTransformWithLabels) void distanceTransform( InputArray src, OutputArray dst, + OutputArray labels, int distanceType, int maskSize, + int labelType = DIST_LABEL_CCOMP ); + +/** @overload +@param src 8-bit, single-channel (binary) source image. +@param dst Output image with calculated distances. It is a 8-bit or 32-bit floating-point, +single-channel image of the same size as src . +@param distanceType Type of distance, see cv::DistanceTypes +@param maskSize Size of the distance transform mask, see cv::DistanceTransformMasks. In case of the +DIST_L1 or DIST_C distance type, the parameter is forced to 3 because a \f$3\times 3\f$ mask gives +the same result as \f$5\times 5\f$ or any larger aperture. +@param dstType Type of output image. It can be CV_8U or CV_32F. Type CV_8U can be used only for +the first variant of the function and distanceType == DIST_L1. +*/ +CV_EXPORTS_W void distanceTransform( InputArray src, OutputArray dst, + int distanceType, int maskSize, int dstType=CV_32F); + +/** @example ffilldemo.cpp + An example using the FloodFill technique +*/ + +/** @overload + +variant without `mask` parameter +*/ +CV_EXPORTS int floodFill( InputOutputArray image, + Point seedPoint, Scalar newVal, CV_OUT Rect* rect = 0, + Scalar loDiff = Scalar(), Scalar upDiff = Scalar(), + int flags = 4 ); + +/** @brief Fills a connected component with the given color. + +The functions floodFill fill a connected component starting from the seed point with the specified +color. The connectivity is determined by the color/brightness closeness of the neighbor pixels. The +pixel at \f$(x,y)\f$ is considered to belong to the repainted domain if: + +- in case of a grayscale image and floating range +\f[\texttt{src} (x',y')- \texttt{loDiff} \leq \texttt{src} (x,y) \leq \texttt{src} (x',y')+ \texttt{upDiff}\f] + + +- in case of a grayscale image and fixed range +\f[\texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)- \texttt{loDiff} \leq \texttt{src} (x,y) \leq \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)+ \texttt{upDiff}\f] + + +- in case of a color image and floating range +\f[\texttt{src} (x',y')_r- \texttt{loDiff} _r \leq \texttt{src} (x,y)_r \leq \texttt{src} (x',y')_r+ \texttt{upDiff} _r,\f] +\f[\texttt{src} (x',y')_g- \texttt{loDiff} _g \leq \texttt{src} (x,y)_g \leq \texttt{src} (x',y')_g+ \texttt{upDiff} _g\f] +and +\f[\texttt{src} (x',y')_b- \texttt{loDiff} _b \leq \texttt{src} (x,y)_b \leq \texttt{src} (x',y')_b+ \texttt{upDiff} _b\f] + + +- in case of a color image and fixed range +\f[\texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_r- \texttt{loDiff} _r \leq \texttt{src} (x,y)_r \leq \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_r+ \texttt{upDiff} _r,\f] +\f[\texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_g- \texttt{loDiff} _g \leq \texttt{src} (x,y)_g \leq \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_g+ \texttt{upDiff} _g\f] +and +\f[\texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_b- \texttt{loDiff} _b \leq \texttt{src} (x,y)_b \leq \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_b+ \texttt{upDiff} _b\f] + + +where \f$src(x',y')\f$ is the value of one of pixel neighbors that is already known to belong to the +component. That is, to be added to the connected component, a color/brightness of the pixel should +be close enough to: +- Color/brightness of one of its neighbors that already belong to the connected component in case +of a floating range. +- Color/brightness of the seed point in case of a fixed range. + +Use these functions to either mark a connected component with the specified color in-place, or build +a mask and then extract the contour, or copy the region to another image, and so on. + +@param image Input/output 1- or 3-channel, 8-bit, or floating-point image. It is modified by the +function unless the FLOODFILL_MASK_ONLY flag is set in the second variant of the function. See +the details below. +@param mask Operation mask that should be a single-channel 8-bit image, 2 pixels wider and 2 pixels +taller than image. Since this is both an input and output parameter, you must take responsibility +of initializing it. Flood-filling cannot go across non-zero pixels in the input mask. For example, +an edge detector output can be used as a mask to stop filling at edges. On output, pixels in the +mask corresponding to filled pixels in the image are set to 1 or to the a value specified in flags +as described below. It is therefore possible to use the same mask in multiple calls to the function +to make sure the filled areas do not overlap. +@param seedPoint Starting point. +@param newVal New value of the repainted domain pixels. +@param loDiff Maximal lower brightness/color difference between the currently observed pixel and +one of its neighbors belonging to the component, or a seed pixel being added to the component. +@param upDiff Maximal upper brightness/color difference between the currently observed pixel and +one of its neighbors belonging to the component, or a seed pixel being added to the component. +@param rect Optional output parameter set by the function to the minimum bounding rectangle of the +repainted domain. +@param flags Operation flags. The first 8 bits contain a connectivity value. The default value of +4 means that only the four nearest neighbor pixels (those that share an edge) are considered. A +connectivity value of 8 means that the eight nearest neighbor pixels (those that share a corner) +will be considered. The next 8 bits (8-16) contain a value between 1 and 255 with which to fill +the mask (the default value is 1). For example, 4 | ( 255 \<\< 8 ) will consider 4 nearest +neighbours and fill the mask with a value of 255. The following additional options occupy higher +bits and therefore may be further combined with the connectivity and mask fill values using +bit-wise or (|), see cv::FloodFillFlags. + +@note Since the mask is larger than the filled image, a pixel \f$(x, y)\f$ in image corresponds to the +pixel \f$(x+1, y+1)\f$ in the mask . + +@sa findContours + */ +CV_EXPORTS_W int floodFill( InputOutputArray image, InputOutputArray mask, + Point seedPoint, Scalar newVal, CV_OUT Rect* rect=0, + Scalar loDiff = Scalar(), Scalar upDiff = Scalar(), + int flags = 4 ); + +/** @brief Converts an image from one color space to another. + +The function converts an input image from one color space to another. In case of a transformation +to-from RGB color space, the order of the channels should be specified explicitly (RGB or BGR). Note +that the default color format in OpenCV is often referred to as RGB but it is actually BGR (the +bytes are reversed). So the first byte in a standard (24-bit) color image will be an 8-bit Blue +component, the second byte will be Green, and the third byte will be Red. The fourth, fifth, and +sixth bytes would then be the second pixel (Blue, then Green, then Red), and so on. + +The conventional ranges for R, G, and B channel values are: +- 0 to 255 for CV_8U images +- 0 to 65535 for CV_16U images +- 0 to 1 for CV_32F images + +In case of linear transformations, the range does not matter. But in case of a non-linear +transformation, an input RGB image should be normalized to the proper value range to get the correct +results, for example, for RGB \f$\rightarrow\f$ L\*u\*v\* transformation. For example, if you have a +32-bit floating-point image directly converted from an 8-bit image without any scaling, then it will +have the 0..255 value range instead of 0..1 assumed by the function. So, before calling cvtColor , +you need first to scale the image down: +@code + img *= 1./255; + cvtColor(img, img, COLOR_BGR2Luv); +@endcode +If you use cvtColor with 8-bit images, the conversion will have some information lost. For many +applications, this will not be noticeable but it is recommended to use 32-bit images in applications +that need the full range of colors or that convert an image before an operation and then convert +back. + +If conversion adds the alpha channel, its value will set to the maximum of corresponding channel +range: 255 for CV_8U, 65535 for CV_16U, 1 for CV_32F. + +@param src input image: 8-bit unsigned, 16-bit unsigned ( CV_16UC... ), or single-precision +floating-point. +@param dst output image of the same size and depth as src. +@param code color space conversion code (see cv::ColorConversionCodes). +@param dstCn number of channels in the destination image; if the parameter is 0, the number of the +channels is derived automatically from src and code. + +@see @ref imgproc_color_conversions + */ +CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 ); + +//! @} imgproc_misc + +// main function for all demosaicing procceses +CV_EXPORTS_W void demosaicing(InputArray _src, OutputArray _dst, int code, int dcn = 0); + +//! @addtogroup imgproc_shape +//! @{ + +/** @brief Calculates all of the moments up to the third order of a polygon or rasterized shape. + +The function computes moments, up to the 3rd order, of a vector shape or a rasterized shape. The +results are returned in the structure cv::Moments. + +@param array Raster image (single-channel, 8-bit or floating-point 2D array) or an array ( +\f$1 \times N\f$ or \f$N \times 1\f$ ) of 2D points (Point or Point2f ). +@param binaryImage If it is true, all non-zero image pixels are treated as 1's. The parameter is +used for images only. +@returns moments. + +@sa contourArea, arcLength + */ +CV_EXPORTS_W Moments moments( InputArray array, bool binaryImage = false ); + +/** @brief Calculates seven Hu invariants. + +The function calculates seven Hu invariants (introduced in @cite Hu62; see also +) defined as: + +\f[\begin{array}{l} hu[0]= \eta _{20}+ \eta _{02} \\ hu[1]=( \eta _{20}- \eta _{02})^{2}+4 \eta _{11}^{2} \\ hu[2]=( \eta _{30}-3 \eta _{12})^{2}+ (3 \eta _{21}- \eta _{03})^{2} \\ hu[3]=( \eta _{30}+ \eta _{12})^{2}+ ( \eta _{21}+ \eta _{03})^{2} \\ hu[4]=( \eta _{30}-3 \eta _{12})( \eta _{30}+ \eta _{12})[( \eta _{30}+ \eta _{12})^{2}-3( \eta _{21}+ \eta _{03})^{2}]+(3 \eta _{21}- \eta _{03})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}] \\ hu[5]=( \eta _{20}- \eta _{02})[( \eta _{30}+ \eta _{12})^{2}- ( \eta _{21}+ \eta _{03})^{2}]+4 \eta _{11}( \eta _{30}+ \eta _{12})( \eta _{21}+ \eta _{03}) \\ hu[6]=(3 \eta _{21}- \eta _{03})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}]-( \eta _{30}-3 \eta _{12})( \eta _{21}+ \eta _{03})[3( \eta _{30}+ \eta _{12})^{2}-( \eta _{21}+ \eta _{03})^{2}] \\ \end{array}\f] + +where \f$\eta_{ji}\f$ stands for \f$\texttt{Moments::nu}_{ji}\f$ . + +These values are proved to be invariants to the image scale, rotation, and reflection except the +seventh one, whose sign is changed by reflection. This invariance is proved with the assumption of +infinite image resolution. In case of raster images, the computed Hu invariants for the original and +transformed images are a bit different. + +@param moments Input moments computed with moments . +@param hu Output Hu invariants. + +@sa matchShapes + */ +CV_EXPORTS void HuMoments( const Moments& moments, double hu[7] ); + +/** @overload */ +CV_EXPORTS_W void HuMoments( const Moments& m, OutputArray hu ); + +//! @} imgproc_shape + +//! @addtogroup imgproc_object +//! @{ + +//! type of the template matching operation +enum TemplateMatchModes { + TM_SQDIFF = 0, //!< \f[R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2\f] + TM_SQDIFF_NORMED = 1, //!< \f[R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f] + TM_CCORR = 2, //!< \f[R(x,y)= \sum _{x',y'} (T(x',y') \cdot I(x+x',y+y'))\f] + TM_CCORR_NORMED = 3, //!< \f[R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f] + TM_CCOEFF = 4, //!< \f[R(x,y)= \sum _{x',y'} (T'(x',y') \cdot I'(x+x',y+y'))\f] + //!< where + //!< \f[\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}\f] + TM_CCOEFF_NORMED = 5 //!< \f[R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }\f] +}; + +/** @brief Compares a template against overlapped image regions. + +The function slides through image , compares the overlapped patches of size \f$w \times h\f$ against +templ using the specified method and stores the comparison results in result . Here are the formulae +for the available comparison methods ( \f$I\f$ denotes image, \f$T\f$ template, \f$R\f$ result ). The summation +is done over template and/or the image patch: \f$x' = 0...w-1, y' = 0...h-1\f$ + +After the function finishes the comparison, the best matches can be found as global minimums (when +TM_SQDIFF was used) or maximums (when TM_CCORR or TM_CCOEFF was used) using the +minMaxLoc function. In case of a color image, template summation in the numerator and each sum in +the denominator is done over all of the channels and separate mean values are used for each channel. +That is, the function can take a color template and a color image. The result will still be a +single-channel image, which is easier to analyze. + +@param image Image where the search is running. It must be 8-bit or 32-bit floating-point. +@param templ Searched template. It must be not greater than the source image and have the same +data type. +@param result Map of comparison results. It must be single-channel 32-bit floating-point. If image +is \f$W \times H\f$ and templ is \f$w \times h\f$ , then result is \f$(W-w+1) \times (H-h+1)\f$ . +@param method Parameter specifying the comparison method, see cv::TemplateMatchModes +@param mask Mask of searched template. It must have the same datatype and size with templ. It is +not set by default. + */ +CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ, + OutputArray result, int method, InputArray mask = noArray() ); + +//! @} + +//! @addtogroup imgproc_shape +//! @{ + +/** @brief computes the connected components labeled image of boolean image + +image with 4 or 8 way connectivity - returns N, the total number of labels [0, N-1] where 0 +represents the background label. ltype specifies the output label image type, an important +consideration based on the total number of labels or alternatively the total number of pixels in +the source image. + +@param image the image to be labeled +@param labels destination labeled image +@param connectivity 8 or 4 for 8-way or 4-way connectivity respectively +@param ltype output image label type. Currently CV_32S and CV_16U are supported. + */ +CV_EXPORTS_W int connectedComponents(InputArray image, OutputArray labels, + int connectivity = 8, int ltype = CV_32S); + +/** @overload +@param image the image to be labeled +@param labels destination labeled image +@param stats statistics output for each label, including the background label, see below for +available statistics. Statistics are accessed via stats(label, COLUMN) where COLUMN is one of +cv::ConnectedComponentsTypes +@param centroids floating point centroid (x,y) output for each label, including the background label +@param connectivity 8 or 4 for 8-way or 4-way connectivity respectively +@param ltype output image label type. Currently CV_32S and CV_16U are supported. +*/ +CV_EXPORTS_W int connectedComponentsWithStats(InputArray image, OutputArray labels, + OutputArray stats, OutputArray centroids, + int connectivity = 8, int ltype = CV_32S); + + +/** @brief Finds contours in a binary image. + +The function retrieves contours from the binary image using the algorithm @cite Suzuki85 . The contours +are a useful tool for shape analysis and object detection and recognition. See squares.c in the +OpenCV sample directory. + +@note Source image is modified by this function. Also, the function does not take into account +1-pixel border of the image (it's filled with 0's and used for neighbor analysis in the algorithm), +therefore the contours touching the image border will be clipped. + +@param image Source, an 8-bit single-channel image. Non-zero pixels are treated as 1's. Zero +pixels remain 0's, so the image is treated as binary . You can use compare , inRange , threshold , +adaptiveThreshold , Canny , and others to create a binary image out of a grayscale or color one. +The function modifies the image while extracting the contours. If mode equals to RETR_CCOMP +or RETR_FLOODFILL, the input can also be a 32-bit integer image of labels (CV_32SC1). +@param contours Detected contours. Each contour is stored as a vector of points. +@param hierarchy Optional output vector, containing information about the image topology. It has +as many elements as the number of contours. For each i-th contour contours[i] , the elements +hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to 0-based indices +in contours of the next and previous contours at the same hierarchical level, the first child +contour and the parent contour, respectively. If for the contour i there are no next, previous, +parent, or nested contours, the corresponding elements of hierarchy[i] will be negative. +@param mode Contour retrieval mode, see cv::RetrievalModes +@param method Contour approximation method, see cv::ContourApproximationModes +@param offset Optional offset by which every contour point is shifted. This is useful if the +contours are extracted from the image ROI and then they should be analyzed in the whole image +context. + */ +CV_EXPORTS_W void findContours( InputOutputArray image, OutputArrayOfArrays contours, + OutputArray hierarchy, int mode, + int method, Point offset = Point()); + +/** @overload */ +CV_EXPORTS void findContours( InputOutputArray image, OutputArrayOfArrays contours, + int mode, int method, Point offset = Point()); + +/** @brief Approximates a polygonal curve(s) with the specified precision. + +The functions approxPolyDP approximate a curve or a polygon with another curve/polygon with less +vertices so that the distance between them is less or equal to the specified precision. It uses the +Douglas-Peucker algorithm + +@param curve Input vector of a 2D point stored in std::vector or Mat +@param approxCurve Result of the approximation. The type should match the type of the input curve. +@param epsilon Parameter specifying the approximation accuracy. This is the maximum distance +between the original curve and its approximation. +@param closed If true, the approximated curve is closed (its first and last vertices are +connected). Otherwise, it is not closed. + */ +CV_EXPORTS_W void approxPolyDP( InputArray curve, + OutputArray approxCurve, + double epsilon, bool closed ); + +/** @brief Calculates a contour perimeter or a curve length. + +The function computes a curve length or a closed contour perimeter. + +@param curve Input vector of 2D points, stored in std::vector or Mat. +@param closed Flag indicating whether the curve is closed or not. + */ +CV_EXPORTS_W double arcLength( InputArray curve, bool closed ); + +/** @brief Calculates the up-right bounding rectangle of a point set. + +The function calculates and returns the minimal up-right bounding rectangle for the specified point set. + +@param points Input 2D point set, stored in std::vector or Mat. + */ +CV_EXPORTS_W Rect boundingRect( InputArray points ); + +/** @brief Calculates a contour area. + +The function computes a contour area. Similarly to moments , the area is computed using the Green +formula. Thus, the returned area and the number of non-zero pixels, if you draw the contour using +drawContours or fillPoly , can be different. Also, the function will most certainly give a wrong +results for contours with self-intersections. + +Example: +@code + vector contour; + contour.push_back(Point2f(0, 0)); + contour.push_back(Point2f(10, 0)); + contour.push_back(Point2f(10, 10)); + contour.push_back(Point2f(5, 4)); + + double area0 = contourArea(contour); + vector approx; + approxPolyDP(contour, approx, 5, true); + double area1 = contourArea(approx); + + cout << "area0 =" << area0 << endl << + "area1 =" << area1 << endl << + "approx poly vertices" << approx.size() << endl; +@endcode +@param contour Input vector of 2D points (contour vertices), stored in std::vector or Mat. +@param oriented Oriented area flag. If it is true, the function returns a signed area value, +depending on the contour orientation (clockwise or counter-clockwise). Using this feature you can +determine orientation of a contour by taking the sign of an area. By default, the parameter is +false, which means that the absolute value is returned. + */ +CV_EXPORTS_W double contourArea( InputArray contour, bool oriented = false ); + +/** @brief Finds a rotated rectangle of the minimum area enclosing the input 2D point set. + +The function calculates and returns the minimum-area bounding rectangle (possibly rotated) for a +specified point set. See the OpenCV sample minarea.cpp . Developer should keep in mind that the +returned rotatedRect can contain negative indices when data is close to the containing Mat element +boundary. + +@param points Input vector of 2D points, stored in std::vector\<\> or Mat + */ +CV_EXPORTS_W RotatedRect minAreaRect( InputArray points ); + +/** @brief Finds the four vertices of a rotated rect. Useful to draw the rotated rectangle. + +The function finds the four vertices of a rotated rectangle. This function is useful to draw the +rectangle. In C++, instead of using this function, you can directly use box.points() method. Please +visit the [tutorial on bounding +rectangle](http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.html#bounding-rects-circles) +for more information. + +@param box The input rotated rectangle. It may be the output of +@param points The output array of four vertices of rectangles. + */ +CV_EXPORTS_W void boxPoints(RotatedRect box, OutputArray points); + +/** @brief Finds a circle of the minimum area enclosing a 2D point set. + +The function finds the minimal enclosing circle of a 2D point set using an iterative algorithm. See +the OpenCV sample minarea.cpp . + +@param points Input vector of 2D points, stored in std::vector\<\> or Mat +@param center Output center of the circle. +@param radius Output radius of the circle. + */ +CV_EXPORTS_W void minEnclosingCircle( InputArray points, + CV_OUT Point2f& center, CV_OUT float& radius ); + +/** @example minarea.cpp + */ + +/** @brief Finds a triangle of minimum area enclosing a 2D point set and returns its area. + +The function finds a triangle of minimum area enclosing the given set of 2D points and returns its +area. The output for a given 2D point set is shown in the image below. 2D points are depicted in +*red* and the enclosing triangle in *yellow*. + +![Sample output of the minimum enclosing triangle function](pics/minenclosingtriangle.png) + +The implementation of the algorithm is based on O'Rourke's @cite ORourke86 and Klee and Laskowski's +@cite KleeLaskowski85 papers. O'Rourke provides a \f$\theta(n)\f$ algorithm for finding the minimal +enclosing triangle of a 2D convex polygon with n vertices. Since the minEnclosingTriangle function +takes a 2D point set as input an additional preprocessing step of computing the convex hull of the +2D point set is required. The complexity of the convexHull function is \f$O(n log(n))\f$ which is higher +than \f$\theta(n)\f$. Thus the overall complexity of the function is \f$O(n log(n))\f$. + +@param points Input vector of 2D points with depth CV_32S or CV_32F, stored in std::vector\<\> or Mat +@param triangle Output vector of three 2D points defining the vertices of the triangle. The depth +of the OutputArray must be CV_32F. + */ +CV_EXPORTS_W double minEnclosingTriangle( InputArray points, CV_OUT OutputArray triangle ); + +/** @brief Compares two shapes. + +The function compares two shapes. All three implemented methods use the Hu invariants (see cv::HuMoments) + +@param contour1 First contour or grayscale image. +@param contour2 Second contour or grayscale image. +@param method Comparison method, see ::ShapeMatchModes +@param parameter Method-specific parameter (not supported now). + */ +CV_EXPORTS_W double matchShapes( InputArray contour1, InputArray contour2, + int method, double parameter ); + +/** @example convexhull.cpp +An example using the convexHull functionality +*/ + +/** @brief Finds the convex hull of a point set. + +The functions find the convex hull of a 2D point set using the Sklansky's algorithm @cite Sklansky82 +that has *O(N logN)* complexity in the current implementation. See the OpenCV sample convexhull.cpp +that demonstrates the usage of different function variants. + +@param points Input 2D point set, stored in std::vector or Mat. +@param hull Output convex hull. It is either an integer vector of indices or vector of points. In +the first case, the hull elements are 0-based indices of the convex hull points in the original +array (since the set of convex hull points is a subset of the original point set). In the second +case, hull elements are the convex hull points themselves. +@param clockwise Orientation flag. If it is true, the output convex hull is oriented clockwise. +Otherwise, it is oriented counter-clockwise. The assumed coordinate system has its X axis pointing +to the right, and its Y axis pointing upwards. +@param returnPoints Operation flag. In case of a matrix, when the flag is true, the function +returns convex hull points. Otherwise, it returns indices of the convex hull points. When the +output array is std::vector, the flag is ignored, and the output depends on the type of the +vector: std::vector\ implies returnPoints=true, std::vector\ implies +returnPoints=false. + */ +CV_EXPORTS_W void convexHull( InputArray points, OutputArray hull, + bool clockwise = false, bool returnPoints = true ); + +/** @brief Finds the convexity defects of a contour. + +The figure below displays convexity defects of a hand contour: + +![image](pics/defects.png) + +@param contour Input contour. +@param convexhull Convex hull obtained using convexHull that should contain indices of the contour +points that make the hull. +@param convexityDefects The output vector of convexity defects. In C++ and the new Python/Java +interface each convexity defect is represented as 4-element integer vector (a.k.a. cv::Vec4i): +(start_index, end_index, farthest_pt_index, fixpt_depth), where indices are 0-based indices +in the original contour of the convexity defect beginning, end and the farthest point, and +fixpt_depth is fixed-point approximation (with 8 fractional bits) of the distance between the +farthest contour point and the hull. That is, to get the floating-point value of the depth will be +fixpt_depth/256.0. + */ +CV_EXPORTS_W void convexityDefects( InputArray contour, InputArray convexhull, OutputArray convexityDefects ); + +/** @brief Tests a contour convexity. + +The function tests whether the input contour is convex or not. The contour must be simple, that is, +without self-intersections. Otherwise, the function output is undefined. + +@param contour Input vector of 2D points, stored in std::vector\<\> or Mat + */ +CV_EXPORTS_W bool isContourConvex( InputArray contour ); + +//! finds intersection of two convex polygons +CV_EXPORTS_W float intersectConvexConvex( InputArray _p1, InputArray _p2, + OutputArray _p12, bool handleNested = true ); + +/** @example fitellipse.cpp + An example using the fitEllipse technique +*/ + +/** @brief Fits an ellipse around a set of 2D points. + +The function calculates the ellipse that fits (in a least-squares sense) a set of 2D points best of +all. It returns the rotated rectangle in which the ellipse is inscribed. The first algorithm described by @cite Fitzgibbon95 +is used. Developer should keep in mind that it is possible that the returned +ellipse/rotatedRect data contains negative indices, due to the data points being close to the +border of the containing Mat element. + +@param points Input 2D point set, stored in std::vector\<\> or Mat + */ +CV_EXPORTS_W RotatedRect fitEllipse( InputArray points ); + +/** @brief Fits a line to a 2D or 3D point set. + +The function fitLine fits a line to a 2D or 3D point set by minimizing \f$\sum_i \rho(r_i)\f$ where +\f$r_i\f$ is a distance between the \f$i^{th}\f$ point, the line and \f$\rho(r)\f$ is a distance function, one +of the following: +- DIST_L2 +\f[\rho (r) = r^2/2 \quad \text{(the simplest and the fastest least-squares method)}\f] +- DIST_L1 +\f[\rho (r) = r\f] +- DIST_L12 +\f[\rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1)\f] +- DIST_FAIR +\f[\rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{where} \quad C=1.3998\f] +- DIST_WELSCH +\f[\rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{where} \quad C=2.9846\f] +- DIST_HUBER +\f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f] + +The algorithm is based on the M-estimator ( ) technique +that iteratively fits the line using the weighted least-squares algorithm. After each iteration the +weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ . + +@param points Input vector of 2D or 3D points, stored in std::vector\<\> or Mat. +@param line Output line parameters. In case of 2D fitting, it should be a vector of 4 elements +(like Vec4f) - (vx, vy, x0, y0), where (vx, vy) is a normalized vector collinear to the line and +(x0, y0) is a point on the line. In case of 3D fitting, it should be a vector of 6 elements (like +Vec6f) - (vx, vy, vz, x0, y0, z0), where (vx, vy, vz) is a normalized vector collinear to the line +and (x0, y0, z0) is a point on the line. +@param distType Distance used by the M-estimator, see cv::DistanceTypes +@param param Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value +is chosen. +@param reps Sufficient accuracy for the radius (distance between the coordinate origin and the line). +@param aeps Sufficient accuracy for the angle. 0.01 would be a good default value for reps and aeps. + */ +CV_EXPORTS_W void fitLine( InputArray points, OutputArray line, int distType, + double param, double reps, double aeps ); + +/** @brief Performs a point-in-contour test. + +The function determines whether the point is inside a contour, outside, or lies on an edge (or +coincides with a vertex). It returns positive (inside), negative (outside), or zero (on an edge) +value, correspondingly. When measureDist=false , the return value is +1, -1, and 0, respectively. +Otherwise, the return value is a signed distance between the point and the nearest contour edge. + +See below a sample output of the function where each image pixel is tested against the contour: + +![sample output](pics/pointpolygon.png) + +@param contour Input contour. +@param pt Point tested against the contour. +@param measureDist If true, the function estimates the signed distance from the point to the +nearest contour edge. Otherwise, the function only checks if the point is inside a contour or not. + */ +CV_EXPORTS_W double pointPolygonTest( InputArray contour, Point2f pt, bool measureDist ); + +/** @brief Finds out if there is any intersection between two rotated rectangles. + +If there is then the vertices of the interesecting region are returned as well. + +Below are some examples of intersection configurations. The hatched pattern indicates the +intersecting region and the red vertices are returned by the function. + +![intersection examples](pics/intersection.png) + +@param rect1 First rectangle +@param rect2 Second rectangle +@param intersectingRegion The output array of the verticies of the intersecting region. It returns +at most 8 vertices. Stored as std::vector\ or cv::Mat as Mx1 of type CV_32FC2. +@returns One of cv::RectanglesIntersectTypes + */ +CV_EXPORTS_W int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion ); + +//! @} imgproc_shape + +CV_EXPORTS_W Ptr createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8)); + +//! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122. +//! Detects position only without traslation and rotation +CV_EXPORTS Ptr createGeneralizedHoughBallard(); + +//! Guil, N., González-Linares, J.M. and Zapata, E.L. (1999). Bidimensional shape detection using an invariant approach. Pattern Recognition 32 (6): 1025-1038. +//! Detects position, traslation and rotation +CV_EXPORTS Ptr createGeneralizedHoughGuil(); + +//! Performs linear blending of two images +CV_EXPORTS void blendLinear(InputArray src1, InputArray src2, InputArray weights1, InputArray weights2, OutputArray dst); + +//! @addtogroup imgproc_colormap +//! @{ + +//! GNU Octave/MATLAB equivalent colormaps +enum ColormapTypes +{ + COLORMAP_AUTUMN = 0, //!< ![autumn](pics/colormaps/colorscale_autumn.jpg) + COLORMAP_BONE = 1, //!< ![bone](pics/colormaps/colorscale_bone.jpg) + COLORMAP_JET = 2, //!< ![jet](pics/colormaps/colorscale_jet.jpg) + COLORMAP_WINTER = 3, //!< ![winter](pics/colormaps/colorscale_winter.jpg) + COLORMAP_RAINBOW = 4, //!< ![rainbow](pics/colormaps/colorscale_rainbow.jpg) + COLORMAP_OCEAN = 5, //!< ![ocean](pics/colormaps/colorscale_ocean.jpg) + COLORMAP_SUMMER = 6, //!< ![summer](pics/colormaps/colorscale_summer.jpg) + COLORMAP_SPRING = 7, //!< ![spring](pics/colormaps/colorscale_spring.jpg) + COLORMAP_COOL = 8, //!< ![cool](pics/colormaps/colorscale_cool.jpg) + COLORMAP_HSV = 9, //!< ![HSV](pics/colormaps/colorscale_hsv.jpg) + COLORMAP_PINK = 10, //!< ![pink](pics/colormaps/colorscale_pink.jpg) + COLORMAP_HOT = 11, //!< ![hot](pics/colormaps/colorscale_hot.jpg) + COLORMAP_PARULA = 12 //!< ![hot](pics/colormaps/colorscale_parula.jpg) +}; + +/** @brief Applies a GNU Octave/MATLAB equivalent colormap on a given image. + +@param src The source image, grayscale or colored does not matter. +@param dst The result is the colormapped source image. Note: Mat::create is called on dst. +@param colormap The colormap to apply, see cv::ColormapTypes + */ +CV_EXPORTS_W void applyColorMap(InputArray src, OutputArray dst, int colormap); + +//! @} imgproc_colormap + +//! @addtogroup imgproc_draw +//! @{ + +/** @brief Draws a line segment connecting two points. + +The function line draws the line segment between pt1 and pt2 points in the image. The line is +clipped by the image boundaries. For non-antialiased lines with integer coordinates, the 8-connected +or 4-connected Bresenham algorithm is used. Thick lines are drawn with rounding endings. Antialiased +lines are drawn using Gaussian filtering. + +@param img Image. +@param pt1 First point of the line segment. +@param pt2 Second point of the line segment. +@param color Line color. +@param thickness Line thickness. +@param lineType Type of the line, see cv::LineTypes. +@param shift Number of fractional bits in the point coordinates. + */ +CV_EXPORTS_W void line(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, + int thickness = 1, int lineType = LINE_8, int shift = 0); + +/** @brief Draws a arrow segment pointing from the first point to the second one. + +The function arrowedLine draws an arrow between pt1 and pt2 points in the image. See also cv::line. + +@param img Image. +@param pt1 The point the arrow starts from. +@param pt2 The point the arrow points to. +@param color Line color. +@param thickness Line thickness. +@param line_type Type of the line, see cv::LineTypes +@param shift Number of fractional bits in the point coordinates. +@param tipLength The length of the arrow tip in relation to the arrow length + */ +CV_EXPORTS_W void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, + int thickness=1, int line_type=8, int shift=0, double tipLength=0.1); + +/** @brief Draws a simple, thick, or filled up-right rectangle. + +The function rectangle draws a rectangle outline or a filled rectangle whose two opposite corners +are pt1 and pt2. + +@param img Image. +@param pt1 Vertex of the rectangle. +@param pt2 Vertex of the rectangle opposite to pt1 . +@param color Rectangle color or brightness (grayscale image). +@param thickness Thickness of lines that make up the rectangle. Negative values, like CV_FILLED , +mean that the function has to draw a filled rectangle. +@param lineType Type of the line. See the line description. +@param shift Number of fractional bits in the point coordinates. + */ +CV_EXPORTS_W void rectangle(InputOutputArray img, Point pt1, Point pt2, + const Scalar& color, int thickness = 1, + int lineType = LINE_8, int shift = 0); + +/** @overload + +use `rec` parameter as alternative specification of the drawn rectangle: `r.tl() and +r.br()-Point(1,1)` are opposite corners +*/ +CV_EXPORTS void rectangle(CV_IN_OUT Mat& img, Rect rec, + const Scalar& color, int thickness = 1, + int lineType = LINE_8, int shift = 0); + +/** @brief Draws a circle. + +The function circle draws a simple or filled circle with a given center and radius. +@param img Image where the circle is drawn. +@param center Center of the circle. +@param radius Radius of the circle. +@param color Circle color. +@param thickness Thickness of the circle outline, if positive. Negative thickness means that a +filled circle is to be drawn. +@param lineType Type of the circle boundary. See the line description. +@param shift Number of fractional bits in the coordinates of the center and in the radius value. + */ +CV_EXPORTS_W void circle(InputOutputArray img, Point center, int radius, + const Scalar& color, int thickness = 1, + int lineType = LINE_8, int shift = 0); + +/** @brief Draws a simple or thick elliptic arc or fills an ellipse sector. + +The functions ellipse with less parameters draw an ellipse outline, a filled ellipse, an elliptic +arc, or a filled ellipse sector. A piecewise-linear curve is used to approximate the elliptic arc +boundary. If you need more control of the ellipse rendering, you can retrieve the curve using +ellipse2Poly and then render it with polylines or fill it with fillPoly . If you use the first +variant of the function and want to draw the whole ellipse, not an arc, pass startAngle=0 and +endAngle=360 . The figure below explains the meaning of the parameters. + +![Parameters of Elliptic Arc](pics/ellipse.png) + +@param img Image. +@param center Center of the ellipse. +@param axes Half of the size of the ellipse main axes. +@param angle Ellipse rotation angle in degrees. +@param startAngle Starting angle of the elliptic arc in degrees. +@param endAngle Ending angle of the elliptic arc in degrees. +@param color Ellipse color. +@param thickness Thickness of the ellipse arc outline, if positive. Otherwise, this indicates that +a filled ellipse sector is to be drawn. +@param lineType Type of the ellipse boundary. See the line description. +@param shift Number of fractional bits in the coordinates of the center and values of axes. + */ +CV_EXPORTS_W void ellipse(InputOutputArray img, Point center, Size axes, + double angle, double startAngle, double endAngle, + const Scalar& color, int thickness = 1, + int lineType = LINE_8, int shift = 0); + +/** @overload +@param img Image. +@param box Alternative ellipse representation via RotatedRect. This means that the function draws +an ellipse inscribed in the rotated rectangle. +@param color Ellipse color. +@param thickness Thickness of the ellipse arc outline, if positive. Otherwise, this indicates that +a filled ellipse sector is to be drawn. +@param lineType Type of the ellipse boundary. See the line description. +*/ +CV_EXPORTS_W void ellipse(InputOutputArray img, const RotatedRect& box, const Scalar& color, + int thickness = 1, int lineType = LINE_8); + +/** @overload */ +CV_EXPORTS void fillConvexPoly(Mat& img, const Point* pts, int npts, + const Scalar& color, int lineType = LINE_8, + int shift = 0); + +/** @brief Fills a convex polygon. + +The function fillConvexPoly draws a filled convex polygon. This function is much faster than the +function cv::fillPoly . It can fill not only convex polygons but any monotonic polygon without +self-intersections, that is, a polygon whose contour intersects every horizontal line (scan line) +twice at the most (though, its top-most and/or the bottom edge could be horizontal). + +@param img Image. +@param points Polygon vertices. +@param color Polygon color. +@param lineType Type of the polygon boundaries. See the line description. +@param shift Number of fractional bits in the vertex coordinates. + */ +CV_EXPORTS_W void fillConvexPoly(InputOutputArray img, InputArray points, + const Scalar& color, int lineType = LINE_8, + int shift = 0); + +/** @overload */ +CV_EXPORTS void fillPoly(Mat& img, const Point** pts, + const int* npts, int ncontours, + const Scalar& color, int lineType = LINE_8, int shift = 0, + Point offset = Point() ); + +/** @brief Fills the area bounded by one or more polygons. + +The function fillPoly fills an area bounded by several polygonal contours. The function can fill +complex areas, for example, areas with holes, contours with self-intersections (some of their +parts), and so forth. + +@param img Image. +@param pts Array of polygons where each polygon is represented as an array of points. +@param color Polygon color. +@param lineType Type of the polygon boundaries. See the line description. +@param shift Number of fractional bits in the vertex coordinates. +@param offset Optional offset of all points of the contours. + */ +CV_EXPORTS_W void fillPoly(InputOutputArray img, InputArrayOfArrays pts, + const Scalar& color, int lineType = LINE_8, int shift = 0, + Point offset = Point() ); + +/** @overload */ +CV_EXPORTS void polylines(Mat& img, const Point* const* pts, const int* npts, + int ncontours, bool isClosed, const Scalar& color, + int thickness = 1, int lineType = LINE_8, int shift = 0 ); + +/** @brief Draws several polygonal curves. + +@param img Image. +@param pts Array of polygonal curves. +@param isClosed Flag indicating whether the drawn polylines are closed or not. If they are closed, +the function draws a line from the last vertex of each curve to its first vertex. +@param color Polyline color. +@param thickness Thickness of the polyline edges. +@param lineType Type of the line segments. See the line description. +@param shift Number of fractional bits in the vertex coordinates. + +The function polylines draws one or more polygonal curves. + */ +CV_EXPORTS_W void polylines(InputOutputArray img, InputArrayOfArrays pts, + bool isClosed, const Scalar& color, + int thickness = 1, int lineType = LINE_8, int shift = 0 ); + +/** @example contours2.cpp + An example using the drawContour functionality +*/ + +/** @example segment_objects.cpp +An example using drawContours to clean up a background segmentation result + */ + +/** @brief Draws contours outlines or filled contours. + +The function draws contour outlines in the image if \f$\texttt{thickness} \ge 0\f$ or fills the area +bounded by the contours if \f$\texttt{thickness}<0\f$ . The example below shows how to retrieve +connected components from the binary image and label them: : +@code + #include "opencv2/imgproc.hpp" + #include "opencv2/highgui.hpp" + + using namespace cv; + using namespace std; + + int main( int argc, char** argv ) + { + Mat src; + // the first command-line parameter must be a filename of the binary + // (black-n-white) image + if( argc != 2 || !(src=imread(argv[1], 0)).data) + return -1; + + Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3); + + src = src > 1; + namedWindow( "Source", 1 ); + imshow( "Source", src ); + + vector > contours; + vector hierarchy; + + findContours( src, contours, hierarchy, + RETR_CCOMP, CHAIN_APPROX_SIMPLE ); + + // iterate through all the top-level contours, + // draw each connected component with its own random color + int idx = 0; + for( ; idx >= 0; idx = hierarchy[idx][0] ) + { + Scalar color( rand()&255, rand()&255, rand()&255 ); + drawContours( dst, contours, idx, color, FILLED, 8, hierarchy ); + } + + namedWindow( "Components", 1 ); + imshow( "Components", dst ); + waitKey(0); + } +@endcode + +@param image Destination image. +@param contours All the input contours. Each contour is stored as a point vector. +@param contourIdx Parameter indicating a contour to draw. If it is negative, all the contours are drawn. +@param color Color of the contours. +@param thickness Thickness of lines the contours are drawn with. If it is negative (for example, +thickness=CV_FILLED ), the contour interiors are drawn. +@param lineType Line connectivity. See cv::LineTypes. +@param hierarchy Optional information about hierarchy. It is only needed if you want to draw only +some of the contours (see maxLevel ). +@param maxLevel Maximal level for drawn contours. If it is 0, only the specified contour is drawn. +If it is 1, the function draws the contour(s) and all the nested contours. If it is 2, the function +draws the contours, all the nested contours, all the nested-to-nested contours, and so on. This +parameter is only taken into account when there is hierarchy available. +@param offset Optional contour shift parameter. Shift all the drawn contours by the specified +\f$\texttt{offset}=(dx,dy)\f$ . + */ +CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours, + int contourIdx, const Scalar& color, + int thickness = 1, int lineType = LINE_8, + InputArray hierarchy = noArray(), + int maxLevel = INT_MAX, Point offset = Point() ); + +/** @brief Clips the line against the image rectangle. + +The functions clipLine calculate a part of the line segment that is entirely within the specified +rectangle. They return false if the line segment is completely outside the rectangle. Otherwise, +they return true . +@param imgSize Image size. The image rectangle is Rect(0, 0, imgSize.width, imgSize.height) . +@param pt1 First line point. +@param pt2 Second line point. + */ +CV_EXPORTS bool clipLine(Size imgSize, CV_IN_OUT Point& pt1, CV_IN_OUT Point& pt2); + +/** @overload +@param imgRect Image rectangle. +@param pt1 First line point. +@param pt2 Second line point. +*/ +CV_EXPORTS_W bool clipLine(Rect imgRect, CV_OUT CV_IN_OUT Point& pt1, CV_OUT CV_IN_OUT Point& pt2); + +/** @brief Approximates an elliptic arc with a polyline. + +The function ellipse2Poly computes the vertices of a polyline that approximates the specified +elliptic arc. It is used by cv::ellipse. + +@param center Center of the arc. +@param axes Half of the size of the ellipse main axes. See the ellipse for details. +@param angle Rotation angle of the ellipse in degrees. See the ellipse for details. +@param arcStart Starting angle of the elliptic arc in degrees. +@param arcEnd Ending angle of the elliptic arc in degrees. +@param delta Angle between the subsequent polyline vertices. It defines the approximation +accuracy. +@param pts Output vector of polyline vertices. + */ +CV_EXPORTS_W void ellipse2Poly( Point center, Size axes, int angle, + int arcStart, int arcEnd, int delta, + CV_OUT std::vector& pts ); + +/** @brief Draws a text string. + +The function putText renders the specified text string in the image. Symbols that cannot be rendered +using the specified font are replaced by question marks. See getTextSize for a text rendering code +example. + +@param img Image. +@param text Text string to be drawn. +@param org Bottom-left corner of the text string in the image. +@param fontFace Font type, see cv::HersheyFonts. +@param fontScale Font scale factor that is multiplied by the font-specific base size. +@param color Text color. +@param thickness Thickness of the lines used to draw a text. +@param lineType Line type. See the line for details. +@param bottomLeftOrigin When true, the image data origin is at the bottom-left corner. Otherwise, +it is at the top-left corner. + */ +CV_EXPORTS_W void putText( InputOutputArray img, const String& text, Point org, + int fontFace, double fontScale, Scalar color, + int thickness = 1, int lineType = LINE_8, + bool bottomLeftOrigin = false ); + +/** @brief Calculates the width and height of a text string. + +The function getTextSize calculates and returns the size of a box that contains the specified text. +That is, the following code renders some text, the tight box surrounding it, and the baseline: : +@code + String text = "Funny text inside the box"; + int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX; + double fontScale = 2; + int thickness = 3; + + Mat img(600, 800, CV_8UC3, Scalar::all(0)); + + int baseline=0; + Size textSize = getTextSize(text, fontFace, + fontScale, thickness, &baseline); + baseline += thickness; + + // center the text + Point textOrg((img.cols - textSize.width)/2, + (img.rows + textSize.height)/2); + + // draw the box + rectangle(img, textOrg + Point(0, baseline), + textOrg + Point(textSize.width, -textSize.height), + Scalar(0,0,255)); + // ... and the baseline first + line(img, textOrg + Point(0, thickness), + textOrg + Point(textSize.width, thickness), + Scalar(0, 0, 255)); + + // then put the text itself + putText(img, text, textOrg, fontFace, fontScale, + Scalar::all(255), thickness, 8); +@endcode + +@param text Input text string. +@param fontFace Font to use, see cv::HersheyFonts. +@param fontScale Font scale factor that is multiplied by the font-specific base size. +@param thickness Thickness of lines used to render the text. See putText for details. +@param[out] baseLine y-coordinate of the baseline relative to the bottom-most text +point. +@return The size of a box that contains the specified text. + +@see cv::putText + */ +CV_EXPORTS_W Size getTextSize(const String& text, int fontFace, + double fontScale, int thickness, + CV_OUT int* baseLine); + +/** @brief Line iterator + +The class is used to iterate over all the pixels on the raster line +segment connecting two specified points. + +The class LineIterator is used to get each pixel of a raster line. It +can be treated as versatile implementation of the Bresenham algorithm +where you can stop at each pixel and do some extra processing, for +example, grab pixel values along the line or draw a line with an effect +(for example, with XOR operation). + +The number of pixels along the line is stored in LineIterator::count. +The method LineIterator::pos returns the current position in the image: + +@code{.cpp} +// grabs pixels along the line (pt1, pt2) +// from 8-bit 3-channel image to the buffer +LineIterator it(img, pt1, pt2, 8); +LineIterator it2 = it; +vector buf(it.count); + +for(int i = 0; i < it.count; i++, ++it) + buf[i] = *(const Vec3b)*it; + +// alternative way of iterating through the line +for(int i = 0; i < it2.count; i++, ++it2) +{ + Vec3b val = img.at(it2.pos()); + CV_Assert(buf[i] == val); +} +@endcode +*/ +class CV_EXPORTS LineIterator +{ +public: + /** @brief intializes the iterator + + creates iterators for the line connecting pt1 and pt2 + the line will be clipped on the image boundaries + the line is 8-connected or 4-connected + If leftToRight=true, then the iteration is always done + from the left-most point to the right most, + not to depend on the ordering of pt1 and pt2 parameters + */ + LineIterator( const Mat& img, Point pt1, Point pt2, + int connectivity = 8, bool leftToRight = false ); + /** @brief returns pointer to the current pixel + */ + uchar* operator *(); + /** @brief prefix increment operator (++it). shifts iterator to the next pixel + */ + LineIterator& operator ++(); + /** @brief postfix increment operator (it++). shifts iterator to the next pixel + */ + LineIterator operator ++(int); + /** @brief returns coordinates of the current pixel + */ + Point pos() const; + + uchar* ptr; + const uchar* ptr0; + int step, elemSize; + int err, count; + int minusDelta, plusDelta; + int minusStep, plusStep; +}; + +//! @cond IGNORED + +// === LineIterator implementation === + +inline +uchar* LineIterator::operator *() +{ + return ptr; +} + +inline +LineIterator& LineIterator::operator ++() +{ + int mask = err < 0 ? -1 : 0; + err += minusDelta + (plusDelta & mask); + ptr += minusStep + (plusStep & mask); + return *this; +} + +inline +LineIterator LineIterator::operator ++(int) +{ + LineIterator it = *this; + ++(*this); + return it; +} + +inline +Point LineIterator::pos() const +{ + Point p; + p.y = (int)((ptr - ptr0)/step); + p.x = (int)(((ptr - ptr0) - p.y*step)/elemSize); + return p; +} + +//! @endcond + +//! @} imgproc_draw + +//! @} imgproc + +} // cv + +#ifndef DISABLE_OPENCV_24_COMPATIBILITY +#include "opencv2/imgproc/imgproc_c.h" +#endif + +#endif diff --git a/include/opencv2/imgproc/imgproc.hpp b/include/opencv2/imgproc/imgproc.hpp new file mode 100644 index 0000000..4175bd0 --- /dev/null +++ b/include/opencv2/imgproc/imgproc.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/imgproc.hpp" diff --git a/include/opencv2/imgproc/imgproc_c.h b/include/opencv2/imgproc/imgproc_c.h new file mode 100644 index 0000000..87518d7 --- /dev/null +++ b/include/opencv2/imgproc/imgproc_c.h @@ -0,0 +1,1210 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_IMGPROC_IMGPROC_C_H__ +#define __OPENCV_IMGPROC_IMGPROC_C_H__ + +#include "opencv2/imgproc/types_c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup imgproc_c +@{ +*/ + +/*********************** Background statistics accumulation *****************************/ + +/** @brief Adds image to accumulator +@see cv::accumulate +*/ +CVAPI(void) cvAcc( const CvArr* image, CvArr* sum, + const CvArr* mask CV_DEFAULT(NULL) ); + +/** @brief Adds squared image to accumulator +@see cv::accumulateSquare +*/ +CVAPI(void) cvSquareAcc( const CvArr* image, CvArr* sqsum, + const CvArr* mask CV_DEFAULT(NULL) ); + +/** @brief Adds a product of two images to accumulator +@see cv::accumulateProduct +*/ +CVAPI(void) cvMultiplyAcc( const CvArr* image1, const CvArr* image2, CvArr* acc, + const CvArr* mask CV_DEFAULT(NULL) ); + +/** @brief Adds image to accumulator with weights: acc = acc*(1-alpha) + image*alpha +@see cv::accumulateWeighted +*/ +CVAPI(void) cvRunningAvg( const CvArr* image, CvArr* acc, double alpha, + const CvArr* mask CV_DEFAULT(NULL) ); + +/****************************************************************************************\ +* Image Processing * +\****************************************************************************************/ + +/** Copies source 2D array inside of the larger destination array and + makes a border of the specified type (IPL_BORDER_*) around the copied area. */ +CVAPI(void) cvCopyMakeBorder( const CvArr* src, CvArr* dst, CvPoint offset, + int bordertype, CvScalar value CV_DEFAULT(cvScalarAll(0))); + +/** @brief Smooths the image in one of several ways. + +@param src The source image +@param dst The destination image +@param smoothtype Type of the smoothing, see SmoothMethod_c +@param size1 The first parameter of the smoothing operation, the aperture width. Must be a +positive odd number (1, 3, 5, ...) +@param size2 The second parameter of the smoothing operation, the aperture height. Ignored by +CV_MEDIAN and CV_BILATERAL methods. In the case of simple scaled/non-scaled and Gaussian blur if +size2 is zero, it is set to size1. Otherwise it must be a positive odd number. +@param sigma1 In the case of a Gaussian parameter this parameter may specify Gaussian \f$\sigma\f$ +(standard deviation). If it is zero, it is calculated from the kernel size: +\f[\sigma = 0.3 (n/2 - 1) + 0.8 \quad \text{where} \quad n= \begin{array}{l l} \mbox{\texttt{size1} for horizontal kernel} \\ \mbox{\texttt{size2} for vertical kernel} \end{array}\f] +Using standard sigma for small kernels ( \f$3\times 3\f$ to \f$7\times 7\f$ ) gives better speed. If +sigma1 is not zero, while size1 and size2 are zeros, the kernel size is calculated from the +sigma (to provide accurate enough operation). +@param sigma2 additional parameter for bilateral filtering + +@see cv::GaussianBlur, cv::blur, cv::medianBlur, cv::bilateralFilter. + */ +CVAPI(void) cvSmooth( const CvArr* src, CvArr* dst, + int smoothtype CV_DEFAULT(CV_GAUSSIAN), + int size1 CV_DEFAULT(3), + int size2 CV_DEFAULT(0), + double sigma1 CV_DEFAULT(0), + double sigma2 CV_DEFAULT(0)); + +/** @brief Convolves an image with the kernel. + +@param src input image. +@param dst output image of the same size and the same number of channels as src. +@param kernel convolution kernel (or rather a correlation kernel), a single-channel floating point +matrix; if you want to apply different kernels to different channels, split the image into +separate color planes using split and process them individually. +@param anchor anchor of the kernel that indicates the relative position of a filtered point within +the kernel; the anchor should lie within the kernel; default value (-1,-1) means that the anchor +is at the kernel center. + +@see cv::filter2D + */ +CVAPI(void) cvFilter2D( const CvArr* src, CvArr* dst, const CvMat* kernel, + CvPoint anchor CV_DEFAULT(cvPoint(-1,-1))); + +/** @brief Finds integral image: SUM(X,Y) = sum(x \texttt{hist1}(I)\)}{\frac{\texttt{hist2}(I) \cdot \texttt{scale}}{\texttt{hist1}(I)}}{if \(\texttt{hist1}(I) \ne 0\) and \(\texttt{hist2}(I) \le \texttt{hist1}(I)\)}\f] + +@param hist1 First histogram (the divisor). +@param hist2 Second histogram. +@param dst_hist Destination histogram. +@param scale Scale factor for the destination histogram. + */ +CVAPI(void) cvCalcProbDensity( const CvHistogram* hist1, const CvHistogram* hist2, + CvHistogram* dst_hist, double scale CV_DEFAULT(255) ); + +/** @brief equalizes histogram of 8-bit single-channel image +@see cv::equalizeHist +*/ +CVAPI(void) cvEqualizeHist( const CvArr* src, CvArr* dst ); + + +/** @brief Applies distance transform to binary image +@see cv::distanceTransform +*/ +CVAPI(void) cvDistTransform( const CvArr* src, CvArr* dst, + int distance_type CV_DEFAULT(CV_DIST_L2), + int mask_size CV_DEFAULT(3), + const float* mask CV_DEFAULT(NULL), + CvArr* labels CV_DEFAULT(NULL), + int labelType CV_DEFAULT(CV_DIST_LABEL_CCOMP)); + + +/** @brief Applies fixed-level threshold to grayscale image. + + This is a basic operation applied before retrieving contours +@see cv::threshold +*/ +CVAPI(double) cvThreshold( const CvArr* src, CvArr* dst, + double threshold, double max_value, + int threshold_type ); + +/** @brief Applies adaptive threshold to grayscale image. + + The two parameters for methods CV_ADAPTIVE_THRESH_MEAN_C and + CV_ADAPTIVE_THRESH_GAUSSIAN_C are: + neighborhood size (3, 5, 7 etc.), + and a constant subtracted from mean (...,-3,-2,-1,0,1,2,3,...) +@see cv::adaptiveThreshold +*/ +CVAPI(void) cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value, + int adaptive_method CV_DEFAULT(CV_ADAPTIVE_THRESH_MEAN_C), + int threshold_type CV_DEFAULT(CV_THRESH_BINARY), + int block_size CV_DEFAULT(3), + double param1 CV_DEFAULT(5)); + +/** @brief Fills the connected component until the color difference gets large enough +@see cv::floodFill +*/ +CVAPI(void) cvFloodFill( CvArr* image, CvPoint seed_point, + CvScalar new_val, CvScalar lo_diff CV_DEFAULT(cvScalarAll(0)), + CvScalar up_diff CV_DEFAULT(cvScalarAll(0)), + CvConnectedComp* comp CV_DEFAULT(NULL), + int flags CV_DEFAULT(4), + CvArr* mask CV_DEFAULT(NULL)); + +/****************************************************************************************\ +* Feature detection * +\****************************************************************************************/ + +/** @brief Runs canny edge detector +@see cv::Canny +*/ +CVAPI(void) cvCanny( const CvArr* image, CvArr* edges, double threshold1, + double threshold2, int aperture_size CV_DEFAULT(3) ); + +/** @brief Calculates constraint image for corner detection + + Dx^2 * Dyy + Dxx * Dy^2 - 2 * Dx * Dy * Dxy. + Applying threshold to the result gives coordinates of corners +@see cv::preCornerDetect +*/ +CVAPI(void) cvPreCornerDetect( const CvArr* image, CvArr* corners, + int aperture_size CV_DEFAULT(3) ); + +/** @brief Calculates eigen values and vectors of 2x2 + gradient covariation matrix at every image pixel +@see cv::cornerEigenValsAndVecs +*/ +CVAPI(void) cvCornerEigenValsAndVecs( const CvArr* image, CvArr* eigenvv, + int block_size, int aperture_size CV_DEFAULT(3) ); + +/** @brief Calculates minimal eigenvalue for 2x2 gradient covariation matrix at + every image pixel +@see cv::cornerMinEigenVal +*/ +CVAPI(void) cvCornerMinEigenVal( const CvArr* image, CvArr* eigenval, + int block_size, int aperture_size CV_DEFAULT(3) ); + +/** @brief Harris corner detector: + + Calculates det(M) - k*(trace(M)^2), where M is 2x2 gradient covariation matrix for each pixel +@see cv::cornerHarris +*/ +CVAPI(void) cvCornerHarris( const CvArr* image, CvArr* harris_response, + int block_size, int aperture_size CV_DEFAULT(3), + double k CV_DEFAULT(0.04) ); + +/** @brief Adjust corner position using some sort of gradient search +@see cv::cornerSubPix +*/ +CVAPI(void) cvFindCornerSubPix( const CvArr* image, CvPoint2D32f* corners, + int count, CvSize win, CvSize zero_zone, + CvTermCriteria criteria ); + +/** @brief Finds a sparse set of points within the selected region + that seem to be easy to track +@see cv::goodFeaturesToTrack +*/ +CVAPI(void) cvGoodFeaturesToTrack( const CvArr* image, CvArr* eig_image, + CvArr* temp_image, CvPoint2D32f* corners, + int* corner_count, double quality_level, + double min_distance, + const CvArr* mask CV_DEFAULT(NULL), + int block_size CV_DEFAULT(3), + int use_harris CV_DEFAULT(0), + double k CV_DEFAULT(0.04) ); + +/** @brief Finds lines on binary image using one of several methods. + + line_storage is either memory storage or 1 x _max number of lines_ CvMat, its + number of columns is changed by the function. + method is one of CV_HOUGH_*; + rho, theta and threshold are used for each of those methods; + param1 ~ line length, param2 ~ line gap - for probabilistic, + param1 ~ srn, param2 ~ stn - for multi-scale +@see cv::HoughLines +*/ +CVAPI(CvSeq*) cvHoughLines2( CvArr* image, void* line_storage, int method, + double rho, double theta, int threshold, + double param1 CV_DEFAULT(0), double param2 CV_DEFAULT(0), + double min_theta CV_DEFAULT(0), double max_theta CV_DEFAULT(CV_PI)); + +/** @brief Finds circles in the image +@see cv::HoughCircles +*/ +CVAPI(CvSeq*) cvHoughCircles( CvArr* image, void* circle_storage, + int method, double dp, double min_dist, + double param1 CV_DEFAULT(100), + double param2 CV_DEFAULT(100), + int min_radius CV_DEFAULT(0), + int max_radius CV_DEFAULT(0)); + +/** @brief Fits a line into set of 2d or 3d points in a robust way (M-estimator technique) +@see cv::fitLine +*/ +CVAPI(void) cvFitLine( const CvArr* points, int dist_type, double param, + double reps, double aeps, float* line ); + +/****************************************************************************************\ +* Drawing * +\****************************************************************************************/ + +/****************************************************************************************\ +* Drawing functions work with images/matrices of arbitrary type. * +* For color images the channel order is BGR[A] * +* Antialiasing is supported only for 8-bit image now. * +* All the functions include parameter color that means rgb value (that may be * +* constructed with CV_RGB macro) for color images and brightness * +* for grayscale images. * +* If a drawn figure is partially or completely outside of the image, it is clipped.* +\****************************************************************************************/ + +#define CV_RGB( r, g, b ) cvScalar( (b), (g), (r), 0 ) +#define CV_FILLED -1 + +#define CV_AA 16 + +/** @brief Draws 4-connected, 8-connected or antialiased line segment connecting two points +@see cv::line +*/ +CVAPI(void) cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, + CvScalar color, int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0) ); + +/** @brief Draws a rectangle given two opposite corners of the rectangle (pt1 & pt2) + + if thickness<0 (e.g. thickness == CV_FILLED), the filled box is drawn +@see cv::rectangle +*/ +CVAPI(void) cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, + CvScalar color, int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8), + int shift CV_DEFAULT(0)); + +/** @brief Draws a rectangle specified by a CvRect structure +@see cv::rectangle +*/ +CVAPI(void) cvRectangleR( CvArr* img, CvRect r, + CvScalar color, int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8), + int shift CV_DEFAULT(0)); + + +/** @brief Draws a circle with specified center and radius. + + Thickness works in the same way as with cvRectangle +@see cv::circle +*/ +CVAPI(void) cvCircle( CvArr* img, CvPoint center, int radius, + CvScalar color, int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0)); + +/** @brief Draws ellipse outline, filled ellipse, elliptic arc or filled elliptic sector + + depending on _thickness_, _start_angle_ and _end_angle_ parameters. The resultant figure + is rotated by _angle_. All the angles are in degrees +@see cv::ellipse +*/ +CVAPI(void) cvEllipse( CvArr* img, CvPoint center, CvSize axes, + double angle, double start_angle, double end_angle, + CvScalar color, int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0)); + +CV_INLINE void cvEllipseBox( CvArr* img, CvBox2D box, CvScalar color, + int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0) ) +{ + CvSize axes; + axes.width = cvRound(box.size.width*0.5); + axes.height = cvRound(box.size.height*0.5); + + cvEllipse( img, cvPointFrom32f( box.center ), axes, box.angle, + 0, 360, color, thickness, line_type, shift ); +} + +/** @brief Fills convex or monotonous polygon. +@see cv::fillConvexPoly +*/ +CVAPI(void) cvFillConvexPoly( CvArr* img, const CvPoint* pts, int npts, CvScalar color, + int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0)); + +/** @brief Fills an area bounded by one or more arbitrary polygons +@see cv::fillPoly +*/ +CVAPI(void) cvFillPoly( CvArr* img, CvPoint** pts, const int* npts, + int contours, CvScalar color, + int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0) ); + +/** @brief Draws one or more polygonal curves +@see cv::polylines +*/ +CVAPI(void) cvPolyLine( CvArr* img, CvPoint** pts, const int* npts, int contours, + int is_closed, CvScalar color, int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8), int shift CV_DEFAULT(0) ); + +#define cvDrawRect cvRectangle +#define cvDrawLine cvLine +#define cvDrawCircle cvCircle +#define cvDrawEllipse cvEllipse +#define cvDrawPolyLine cvPolyLine + +/** @brief Clips the line segment connecting *pt1 and *pt2 + by the rectangular window + + (0<=xptr will point to pt1 (or pt2, see left_to_right description) location in +the image. Returns the number of pixels on the line between the ending points. +@see cv::LineIterator +*/ +CVAPI(int) cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2, + CvLineIterator* line_iterator, + int connectivity CV_DEFAULT(8), + int left_to_right CV_DEFAULT(0)); + +#define CV_NEXT_LINE_POINT( line_iterator ) \ +{ \ + int _line_iterator_mask = (line_iterator).err < 0 ? -1 : 0; \ + (line_iterator).err += (line_iterator).minus_delta + \ + ((line_iterator).plus_delta & _line_iterator_mask); \ + (line_iterator).ptr += (line_iterator).minus_step + \ + ((line_iterator).plus_step & _line_iterator_mask); \ +} + + +#define CV_FONT_HERSHEY_SIMPLEX 0 +#define CV_FONT_HERSHEY_PLAIN 1 +#define CV_FONT_HERSHEY_DUPLEX 2 +#define CV_FONT_HERSHEY_COMPLEX 3 +#define CV_FONT_HERSHEY_TRIPLEX 4 +#define CV_FONT_HERSHEY_COMPLEX_SMALL 5 +#define CV_FONT_HERSHEY_SCRIPT_SIMPLEX 6 +#define CV_FONT_HERSHEY_SCRIPT_COMPLEX 7 + +#define CV_FONT_ITALIC 16 + +#define CV_FONT_VECTOR0 CV_FONT_HERSHEY_SIMPLEX + + +/** Font structure */ +typedef struct CvFont +{ + const char* nameFont; //Qt:nameFont + CvScalar color; //Qt:ColorFont -> cvScalar(blue_component, green_component, red_component[, alpha_component]) + int font_face; //Qt: bool italic /** =CV_FONT_* */ + const int* ascii; //!< font data and metrics + const int* greek; + const int* cyrillic; + float hscale, vscale; + float shear; //!< slope coefficient: 0 - normal, >0 - italic + int thickness; //!< Qt: weight /** letters thickness */ + float dx; //!< horizontal interval between letters + int line_type; //!< Qt: PointSize +} +CvFont; + +/** @brief Initializes font structure (OpenCV 1.x API). + +The function initializes the font structure that can be passed to text rendering functions. + +@param font Pointer to the font structure initialized by the function +@param font_face Font name identifier. See cv::HersheyFonts and corresponding old CV_* identifiers. +@param hscale Horizontal scale. If equal to 1.0f , the characters have the original width +depending on the font type. If equal to 0.5f , the characters are of half the original width. +@param vscale Vertical scale. If equal to 1.0f , the characters have the original height depending +on the font type. If equal to 0.5f , the characters are of half the original height. +@param shear Approximate tangent of the character slope relative to the vertical line. A zero +value means a non-italic font, 1.0f means about a 45 degree slope, etc. +@param thickness Thickness of the text strokes +@param line_type Type of the strokes, see line description + +@sa cvPutText + */ +CVAPI(void) cvInitFont( CvFont* font, int font_face, + double hscale, double vscale, + double shear CV_DEFAULT(0), + int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8)); + +CV_INLINE CvFont cvFont( double scale, int thickness CV_DEFAULT(1) ) +{ + CvFont font; + cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, scale, scale, 0, thickness, CV_AA ); + return font; +} + +/** @brief Renders text stroke with specified font and color at specified location. + CvFont should be initialized with cvInitFont +@see cvInitFont, cvGetTextSize, cvFont, cv::putText +*/ +CVAPI(void) cvPutText( CvArr* img, const char* text, CvPoint org, + const CvFont* font, CvScalar color ); + +/** @brief Calculates bounding box of text stroke (useful for alignment) +@see cv::getTextSize +*/ +CVAPI(void) cvGetTextSize( const char* text_string, const CvFont* font, + CvSize* text_size, int* baseline ); + +/** @brief Unpacks color value + +if arrtype is CV_8UC?, _color_ is treated as packed color value, otherwise the first channels +(depending on arrtype) of destination scalar are set to the same value = _color_ +*/ +CVAPI(CvScalar) cvColorToScalar( double packed_color, int arrtype ); + +/** @brief Returns the polygon points which make up the given ellipse. + +The ellipse is define by the box of size 'axes' rotated 'angle' around the 'center'. A partial +sweep of the ellipse arc can be done by spcifying arc_start and arc_end to be something other than +0 and 360, respectively. The input array 'pts' must be large enough to hold the result. The total +number of points stored into 'pts' is returned by this function. +@see cv::ellipse2Poly +*/ +CVAPI(int) cvEllipse2Poly( CvPoint center, CvSize axes, + int angle, int arc_start, int arc_end, CvPoint * pts, int delta ); + +/** @brief Draws contour outlines or filled interiors on the image +@see cv::drawContours +*/ +CVAPI(void) cvDrawContours( CvArr *img, CvSeq* contour, + CvScalar external_color, CvScalar hole_color, + int max_level, int thickness CV_DEFAULT(1), + int line_type CV_DEFAULT(8), + CvPoint offset CV_DEFAULT(cvPoint(0,0))); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/opencv2/imgproc/types_c.h b/include/opencv2/imgproc/types_c.h new file mode 100644 index 0000000..5ecb460 --- /dev/null +++ b/include/opencv2/imgproc/types_c.h @@ -0,0 +1,626 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_IMGPROC_TYPES_C_H__ +#define __OPENCV_IMGPROC_TYPES_C_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup imgproc_c + @{ +*/ + +/** Connected component structure */ +typedef struct CvConnectedComp +{ + double area; /** DBL_EPSILON ? 1./std::sqrt(am00) : 0; + } + operator cv::Moments() const + { + return cv::Moments(m00, m10, m01, m20, m11, m02, m30, m21, m12, m03); + } +#endif +} +CvMoments; + +/** Hu invariants */ +typedef struct CvHuMoments +{ + double hu1, hu2, hu3, hu4, hu5, hu6, hu7; /**< Hu invariants */ +} +CvHuMoments; + +/** Template matching methods */ +enum +{ + CV_TM_SQDIFF =0, + CV_TM_SQDIFF_NORMED =1, + CV_TM_CCORR =2, + CV_TM_CCORR_NORMED =3, + CV_TM_CCOEFF =4, + CV_TM_CCOEFF_NORMED =5 +}; + +typedef float (CV_CDECL * CvDistanceFunction)( const float* a, const float* b, void* user_param ); + +/** Contour retrieval modes */ +enum +{ + CV_RETR_EXTERNAL=0, + CV_RETR_LIST=1, + CV_RETR_CCOMP=2, + CV_RETR_TREE=3, + CV_RETR_FLOODFILL=4 +}; + +/** Contour approximation methods */ +enum +{ + CV_CHAIN_CODE=0, + CV_CHAIN_APPROX_NONE=1, + CV_CHAIN_APPROX_SIMPLE=2, + CV_CHAIN_APPROX_TC89_L1=3, + CV_CHAIN_APPROX_TC89_KCOS=4, + CV_LINK_RUNS=5 +}; + +/* +Internal structure that is used for sequential retrieving contours from the image. +It supports both hierarchical and plane variants of Suzuki algorithm. +*/ +typedef struct _CvContourScanner* CvContourScanner; + +/** Freeman chain reader state */ +typedef struct CvChainPtReader +{ + CV_SEQ_READER_FIELDS() + char code; + CvPoint pt; + schar deltas[8][2]; +} +CvChainPtReader; + +/** initializes 8-element array for fast access to 3x3 neighborhood of a pixel */ +#define CV_INIT_3X3_DELTAS( deltas, step, nch ) \ + ((deltas)[0] = (nch), (deltas)[1] = -(step) + (nch), \ + (deltas)[2] = -(step), (deltas)[3] = -(step) - (nch), \ + (deltas)[4] = -(nch), (deltas)[5] = (step) - (nch), \ + (deltas)[6] = (step), (deltas)[7] = (step) + (nch)) + + +/** Contour approximation algorithms */ +enum +{ + CV_POLY_APPROX_DP = 0 +}; + +/** @brief Shape matching methods + +\f$A\f$ denotes object1,\f$B\f$ denotes object2 + +\f$\begin{array}{l} m^A_i = \mathrm{sign} (h^A_i) \cdot \log{h^A_i} \\ m^B_i = \mathrm{sign} (h^B_i) \cdot \log{h^B_i} \end{array}\f$ + +and \f$h^A_i, h^B_i\f$ are the Hu moments of \f$A\f$ and \f$B\f$ , respectively. +*/ +enum ShapeMatchModes +{ + CV_CONTOURS_MATCH_I1 =1, //!< \f[I_1(A,B) = \sum _{i=1...7} \left | \frac{1}{m^A_i} - \frac{1}{m^B_i} \right |\f] + CV_CONTOURS_MATCH_I2 =2, //!< \f[I_2(A,B) = \sum _{i=1...7} \left | m^A_i - m^B_i \right |\f] + CV_CONTOURS_MATCH_I3 =3 //!< \f[I_3(A,B) = \max _{i=1...7} \frac{ \left| m^A_i - m^B_i \right| }{ \left| m^A_i \right| }\f] +}; + +/** Shape orientation */ +enum +{ + CV_CLOCKWISE =1, + CV_COUNTER_CLOCKWISE =2 +}; + + +/** Convexity defect */ +typedef struct CvConvexityDefect +{ + CvPoint* start; /**< point of the contour where the defect begins */ + CvPoint* end; /**< point of the contour where the defect ends */ + CvPoint* depth_point; /**< the farthest from the convex hull point within the defect */ + float depth; /**< distance between the farthest point and the convex hull */ +} CvConvexityDefect; + + +/** Histogram comparison methods */ +enum +{ + CV_COMP_CORREL =0, + CV_COMP_CHISQR =1, + CV_COMP_INTERSECT =2, + CV_COMP_BHATTACHARYYA =3, + CV_COMP_HELLINGER =CV_COMP_BHATTACHARYYA, + CV_COMP_CHISQR_ALT =4, + CV_COMP_KL_DIV =5 +}; + +/** Mask size for distance transform */ +enum +{ + CV_DIST_MASK_3 =3, + CV_DIST_MASK_5 =5, + CV_DIST_MASK_PRECISE =0 +}; + +/** Content of output label array: connected components or pixels */ +enum +{ + CV_DIST_LABEL_CCOMP = 0, + CV_DIST_LABEL_PIXEL = 1 +}; + +/** Distance types for Distance Transform and M-estimators */ +enum +{ + CV_DIST_USER =-1, /**< User defined distance */ + CV_DIST_L1 =1, /**< distance = |x1-x2| + |y1-y2| */ + CV_DIST_L2 =2, /**< the simple euclidean distance */ + CV_DIST_C =3, /**< distance = max(|x1-x2|,|y1-y2|) */ + CV_DIST_L12 =4, /**< L1-L2 metric: distance = 2(sqrt(1+x*x/2) - 1)) */ + CV_DIST_FAIR =5, /**< distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998 */ + CV_DIST_WELSCH =6, /**< distance = c^2/2(1-exp(-(x/c)^2)), c = 2.9846 */ + CV_DIST_HUBER =7 /**< distance = |x| threshold ? max_value : 0 */ + CV_THRESH_BINARY_INV =1, /**< value = value > threshold ? 0 : max_value */ + CV_THRESH_TRUNC =2, /**< value = value > threshold ? threshold : value */ + CV_THRESH_TOZERO =3, /**< value = value > threshold ? value : 0 */ + CV_THRESH_TOZERO_INV =4, /**< value = value > threshold ? 0 : value */ + CV_THRESH_MASK =7, + CV_THRESH_OTSU =8, /**< use Otsu algorithm to choose the optimal threshold value; + combine the flag with one of the above CV_THRESH_* values */ + CV_THRESH_TRIANGLE =16 /**< use Triangle algorithm to choose the optimal threshold value; + combine the flag with one of the above CV_THRESH_* values, but not + with CV_THRESH_OTSU */ +}; + +/** Adaptive threshold methods */ +enum +{ + CV_ADAPTIVE_THRESH_MEAN_C =0, + CV_ADAPTIVE_THRESH_GAUSSIAN_C =1 +}; + +/** FloodFill flags */ +enum +{ + CV_FLOODFILL_FIXED_RANGE =(1 << 16), + CV_FLOODFILL_MASK_ONLY =(1 << 17) +}; + + +/** Canny edge detector flags */ +enum +{ + CV_CANNY_L2_GRADIENT =(1 << 31) +}; + +/** Variants of a Hough transform */ +enum +{ + CV_HOUGH_STANDARD =0, + CV_HOUGH_PROBABILISTIC =1, + CV_HOUGH_MULTI_SCALE =2, + CV_HOUGH_GRADIENT =3 +}; + + +/* Fast search data structures */ +struct CvFeatureTree; +struct CvLSH; +struct CvLSHOperations; + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/opencv2/ml.hpp b/include/opencv2/ml.hpp new file mode 100644 index 0000000..d0d2c33 --- /dev/null +++ b/include/opencv2/ml.hpp @@ -0,0 +1,1499 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Copyright (C) 2014, Itseez Inc, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_ML_HPP__ +#define __OPENCV_ML_HPP__ + +#ifdef __cplusplus +# include "opencv2/core.hpp" +#endif + +#ifdef __cplusplus + +#include +#include +#include + +/** + @defgroup ml Machine Learning + + The Machine Learning Library (MLL) is a set of classes and functions for statistical + classification, regression, and clustering of data. + + Most of the classification and regression algorithms are implemented as C++ classes. As the + algorithms have different sets of features (like an ability to handle missing measurements or + categorical input variables), there is a little common ground between the classes. This common + ground is defined by the class cv::ml::StatModel that all the other ML classes are derived from. + + See detailed overview here: @ref ml_intro. + */ + +namespace cv +{ + +namespace ml +{ + +//! @addtogroup ml +//! @{ + +/** @brief Variable types */ +enum VariableTypes +{ + VAR_NUMERICAL =0, //!< same as VAR_ORDERED + VAR_ORDERED =0, //!< ordered variables + VAR_CATEGORICAL =1 //!< categorical variables +}; + +/** @brief %Error types */ +enum ErrorTypes +{ + TEST_ERROR = 0, + TRAIN_ERROR = 1 +}; + +/** @brief Sample types */ +enum SampleTypes +{ + ROW_SAMPLE = 0, //!< each training sample is a row of samples + COL_SAMPLE = 1 //!< each training sample occupies a column of samples +}; + +/** @brief The structure represents the logarithmic grid range of statmodel parameters. + +It is used for optimizing statmodel accuracy by varying model parameters, the accuracy estimate +being computed by cross-validation. + */ +class CV_EXPORTS ParamGrid +{ +public: + /** @brief Default constructor */ + ParamGrid(); + /** @brief Constructor with parameters */ + ParamGrid(double _minVal, double _maxVal, double _logStep); + + double minVal; //!< Minimum value of the statmodel parameter. Default value is 0. + double maxVal; //!< Maximum value of the statmodel parameter. Default value is 0. + /** @brief Logarithmic step for iterating the statmodel parameter. + + The grid determines the following iteration sequence of the statmodel parameter values: + \f[(minVal, minVal*step, minVal*{step}^2, \dots, minVal*{logStep}^n),\f] + where \f$n\f$ is the maximal index satisfying + \f[\texttt{minVal} * \texttt{logStep} ^n < \texttt{maxVal}\f] + The grid is logarithmic, so logStep must always be greater then 1. Default value is 1. + */ + double logStep; +}; + +/** @brief Class encapsulating training data. + +Please note that the class only specifies the interface of training data, but not implementation. +All the statistical model classes in _ml_ module accepts Ptr\ as parameter. In other +words, you can create your own class derived from TrainData and pass smart pointer to the instance +of this class into StatModel::train. + +@sa @ref ml_intro_data + */ +class CV_EXPORTS_W TrainData +{ +public: + static inline float missingValue() { return FLT_MAX; } + virtual ~TrainData(); + + CV_WRAP virtual int getLayout() const = 0; + CV_WRAP virtual int getNTrainSamples() const = 0; + CV_WRAP virtual int getNTestSamples() const = 0; + CV_WRAP virtual int getNSamples() const = 0; + CV_WRAP virtual int getNVars() const = 0; + CV_WRAP virtual int getNAllVars() const = 0; + + CV_WRAP virtual void getSample(InputArray varIdx, int sidx, float* buf) const = 0; + CV_WRAP virtual Mat getSamples() const = 0; + CV_WRAP virtual Mat getMissing() const = 0; + + /** @brief Returns matrix of train samples + + @param layout The requested layout. If it's different from the initial one, the matrix is + transposed. See ml::SampleTypes. + @param compressSamples if true, the function returns only the training samples (specified by + sampleIdx) + @param compressVars if true, the function returns the shorter training samples, containing only + the active variables. + + In current implementation the function tries to avoid physical data copying and returns the + matrix stored inside TrainData (unless the transposition or compression is needed). + */ + CV_WRAP virtual Mat getTrainSamples(int layout=ROW_SAMPLE, + bool compressSamples=true, + bool compressVars=true) const = 0; + + /** @brief Returns the vector of responses + + The function returns ordered or the original categorical responses. Usually it's used in + regression algorithms. + */ + CV_WRAP virtual Mat getTrainResponses() const = 0; + + /** @brief Returns the vector of normalized categorical responses + + The function returns vector of responses. Each response is integer from `0` to `-1`. The actual label value can be retrieved then from the class label vector, see + TrainData::getClassLabels. + */ + CV_WRAP virtual Mat getTrainNormCatResponses() const = 0; + CV_WRAP virtual Mat getTestResponses() const = 0; + CV_WRAP virtual Mat getTestNormCatResponses() const = 0; + CV_WRAP virtual Mat getResponses() const = 0; + CV_WRAP virtual Mat getNormCatResponses() const = 0; + CV_WRAP virtual Mat getSampleWeights() const = 0; + CV_WRAP virtual Mat getTrainSampleWeights() const = 0; + CV_WRAP virtual Mat getTestSampleWeights() const = 0; + CV_WRAP virtual Mat getVarIdx() const = 0; + CV_WRAP virtual Mat getVarType() const = 0; + CV_WRAP virtual int getResponseType() const = 0; + CV_WRAP virtual Mat getTrainSampleIdx() const = 0; + CV_WRAP virtual Mat getTestSampleIdx() const = 0; + CV_WRAP virtual void getValues(int vi, InputArray sidx, float* values) const = 0; + virtual void getNormCatValues(int vi, InputArray sidx, int* values) const = 0; + CV_WRAP virtual Mat getDefaultSubstValues() const = 0; + + CV_WRAP virtual int getCatCount(int vi) const = 0; + + /** @brief Returns the vector of class labels + + The function returns vector of unique labels occurred in the responses. + */ + CV_WRAP virtual Mat getClassLabels() const = 0; + + CV_WRAP virtual Mat getCatOfs() const = 0; + CV_WRAP virtual Mat getCatMap() const = 0; + + /** @brief Splits the training data into the training and test parts + @sa TrainData::setTrainTestSplitRatio + */ + CV_WRAP virtual void setTrainTestSplit(int count, bool shuffle=true) = 0; + + /** @brief Splits the training data into the training and test parts + + The function selects a subset of specified relative size and then returns it as the training + set. If the function is not called, all the data is used for training. Please, note that for + each of TrainData::getTrain\* there is corresponding TrainData::getTest\*, so that the test + subset can be retrieved and processed as well. + @sa TrainData::setTrainTestSplit + */ + CV_WRAP virtual void setTrainTestSplitRatio(double ratio, bool shuffle=true) = 0; + CV_WRAP virtual void shuffleTrainTest() = 0; + + CV_WRAP static Mat getSubVector(const Mat& vec, const Mat& idx); + + /** @brief Reads the dataset from a .csv file and returns the ready-to-use training data. + + @param filename The input file name + @param headerLineCount The number of lines in the beginning to skip; besides the header, the + function also skips empty lines and lines staring with `#` + @param responseStartIdx Index of the first output variable. If -1, the function considers the + last variable as the response + @param responseEndIdx Index of the last output variable + 1. If -1, then there is single + response variable at responseStartIdx. + @param varTypeSpec The optional text string that specifies the variables' types. It has the + format `ord[n1-n2,n3,n4-n5,...]cat[n6,n7-n8,...]`. That is, variables from `n1 to n2` + (inclusive range), `n3`, `n4 to n5` ... are considered ordered and `n6`, `n7 to n8` ... are + considered as categorical. The range `[n1..n2] + [n3] + [n4..n5] + ... + [n6] + [n7..n8]` + should cover all the variables. If varTypeSpec is not specified, then algorithm uses the + following rules: + - all input variables are considered ordered by default. If some column contains has non- + numerical values, e.g. 'apple', 'pear', 'apple', 'apple', 'mango', the corresponding + variable is considered categorical. + - if there are several output variables, they are all considered as ordered. Error is + reported when non-numerical values are used. + - if there is a single output variable, then if its values are non-numerical or are all + integers, then it's considered categorical. Otherwise, it's considered ordered. + @param delimiter The character used to separate values in each line. + @param missch The character used to specify missing measurements. It should not be a digit. + Although it's a non-numerical value, it surely does not affect the decision of whether the + variable ordered or categorical. + */ + static Ptr loadFromCSV(const String& filename, + int headerLineCount, + int responseStartIdx=-1, + int responseEndIdx=-1, + const String& varTypeSpec=String(), + char delimiter=',', + char missch='?'); + + /** @brief Creates training data from in-memory arrays. + + @param samples matrix of samples. It should have CV_32F type. + @param layout see ml::SampleTypes. + @param responses matrix of responses. If the responses are scalar, they should be stored as a + single row or as a single column. The matrix should have type CV_32F or CV_32S (in the + former case the responses are considered as ordered by default; in the latter case - as + categorical) + @param varIdx vector specifying which variables to use for training. It can be an integer vector + (CV_32S) containing 0-based variable indices or byte vector (CV_8U) containing a mask of + active variables. + @param sampleIdx vector specifying which samples to use for training. It can be an integer + vector (CV_32S) containing 0-based sample indices or byte vector (CV_8U) containing a mask + of training samples. + @param sampleWeights optional vector with weights for each sample. It should have CV_32F type. + @param varType optional vector of type CV_8U and size ` + + `, containing types of each input and output variable. See + ml::VariableTypes. + */ + CV_WRAP static Ptr create(InputArray samples, int layout, InputArray responses, + InputArray varIdx=noArray(), InputArray sampleIdx=noArray(), + InputArray sampleWeights=noArray(), InputArray varType=noArray()); +}; + +/** @brief Base class for statistical models in OpenCV ML. + */ +class CV_EXPORTS_W StatModel : public Algorithm +{ +public: + /** Predict options */ + enum Flags { + UPDATE_MODEL = 1, + RAW_OUTPUT=1, //!< makes the method return the raw results (the sum), not the class label + COMPRESSED_INPUT=2, + PREPROCESSED_INPUT=4 + }; + + /** @brief Returns the number of variables in training samples */ + CV_WRAP virtual int getVarCount() const = 0; + + CV_WRAP virtual bool empty() const; + + /** @brief Returns true if the model is trained */ + CV_WRAP virtual bool isTrained() const = 0; + /** @brief Returns true if the model is classifier */ + CV_WRAP virtual bool isClassifier() const = 0; + + /** @brief Trains the statistical model + + @param trainData training data that can be loaded from file using TrainData::loadFromCSV or + created with TrainData::create. + @param flags optional flags, depending on the model. Some of the models can be updated with the + new training samples, not completely overwritten (such as NormalBayesClassifier or ANN_MLP). + */ + CV_WRAP virtual bool train( const Ptr& trainData, int flags=0 ); + + /** @brief Trains the statistical model + + @param samples training samples + @param layout See ml::SampleTypes. + @param responses vector of responses associated with the training samples. + */ + CV_WRAP virtual bool train( InputArray samples, int layout, InputArray responses ); + + /** @brief Computes error on the training or test dataset + + @param data the training data + @param test if true, the error is computed over the test subset of the data, otherwise it's + computed over the training subset of the data. Please note that if you loaded a completely + different dataset to evaluate already trained classifier, you will probably want not to set + the test subset at all with TrainData::setTrainTestSplitRatio and specify test=false, so + that the error is computed for the whole new set. Yes, this sounds a bit confusing. + @param resp the optional output responses. + + The method uses StatModel::predict to compute the error. For regression models the error is + computed as RMS, for classifiers - as a percent of missclassified samples (0%-100%). + */ + CV_WRAP virtual float calcError( const Ptr& data, bool test, OutputArray resp ) const; + + /** @brief Predicts response(s) for the provided sample(s) + + @param samples The input samples, floating-point matrix + @param results The optional output matrix of results. + @param flags The optional flags, model-dependent. See cv::ml::StatModel::Flags. + */ + CV_WRAP virtual float predict( InputArray samples, OutputArray results=noArray(), int flags=0 ) const = 0; + + /** @brief Create and train model with default parameters + + The class must implement static `create()` method with no parameters or with all default parameter values + */ + template static Ptr<_Tp> train(const Ptr& data, int flags=0) + { + Ptr<_Tp> model = _Tp::create(); + return !model.empty() && model->train(data, flags) ? model : Ptr<_Tp>(); + } +}; + +/****************************************************************************************\ +* Normal Bayes Classifier * +\****************************************************************************************/ + +/** @brief Bayes classifier for normally distributed data. + +@sa @ref ml_intro_bayes + */ +class CV_EXPORTS_W NormalBayesClassifier : public StatModel +{ +public: + /** @brief Predicts the response for sample(s). + + The method estimates the most probable classes for input vectors. Input vectors (one or more) + are stored as rows of the matrix inputs. In case of multiple input vectors, there should be one + output vector outputs. The predicted class for a single input vector is returned by the method. + The vector outputProbs contains the output probabilities corresponding to each element of + result. + */ + CV_WRAP virtual float predictProb( InputArray inputs, OutputArray outputs, + OutputArray outputProbs, int flags=0 ) const = 0; + + /** Creates empty model + Use StatModel::train to train the model after creation. */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* K-Nearest Neighbour Classifier * +\****************************************************************************************/ + +/** @brief The class implements K-Nearest Neighbors model + +@sa @ref ml_intro_knn + */ +class CV_EXPORTS_W KNearest : public StatModel +{ +public: + + /** Default number of neighbors to use in predict method. */ + /** @see setDefaultK */ + CV_WRAP virtual int getDefaultK() const = 0; + /** @copybrief getDefaultK @see getDefaultK */ + CV_WRAP virtual void setDefaultK(int val) = 0; + + /** Whether classification or regression model should be trained. */ + /** @see setIsClassifier */ + CV_WRAP virtual bool getIsClassifier() const = 0; + /** @copybrief getIsClassifier @see getIsClassifier */ + CV_WRAP virtual void setIsClassifier(bool val) = 0; + + /** Parameter for KDTree implementation. */ + /** @see setEmax */ + CV_WRAP virtual int getEmax() const = 0; + /** @copybrief getEmax @see getEmax */ + CV_WRAP virtual void setEmax(int val) = 0; + + /** %Algorithm type, one of KNearest::Types. */ + /** @see setAlgorithmType */ + CV_WRAP virtual int getAlgorithmType() const = 0; + /** @copybrief getAlgorithmType @see getAlgorithmType */ + CV_WRAP virtual void setAlgorithmType(int val) = 0; + + /** @brief Finds the neighbors and predicts responses for input vectors. + + @param samples Input samples stored by rows. It is a single-precision floating-point matrix of + ` * k` size. + @param k Number of used nearest neighbors. Should be greater than 1. + @param results Vector with results of prediction (regression or classification) for each input + sample. It is a single-precision floating-point vector with `` elements. + @param neighborResponses Optional output values for corresponding neighbors. It is a single- + precision floating-point matrix of ` * k` size. + @param dist Optional output distances from the input vectors to the corresponding neighbors. It + is a single-precision floating-point matrix of ` * k` size. + + For each input vector (a row of the matrix samples), the method finds the k nearest neighbors. + In case of regression, the predicted result is a mean value of the particular vector's neighbor + responses. In case of classification, the class is determined by voting. + + For each input vector, the neighbors are sorted by their distances to the vector. + + In case of C++ interface you can use output pointers to empty matrices and the function will + allocate memory itself. + + If only a single input vector is passed, all output matrices are optional and the predicted + value is returned by the method. + + The function is parallelized with the TBB library. + */ + CV_WRAP virtual float findNearest( InputArray samples, int k, + OutputArray results, + OutputArray neighborResponses=noArray(), + OutputArray dist=noArray() ) const = 0; + + /** @brief Implementations of KNearest algorithm + */ + enum Types + { + BRUTE_FORCE=1, + KDTREE=2 + }; + + /** @brief Creates the empty model + + The static method creates empty %KNearest classifier. It should be then trained using StatModel::train method. + */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* Support Vector Machines * +\****************************************************************************************/ + +/** @brief Support Vector Machines. + +@sa @ref ml_intro_svm + */ +class CV_EXPORTS_W SVM : public StatModel +{ +public: + + class CV_EXPORTS Kernel : public Algorithm + { + public: + virtual int getType() const = 0; + virtual void calc( int vcount, int n, const float* vecs, const float* another, float* results ) = 0; + }; + + /** Type of a %SVM formulation. + See SVM::Types. Default value is SVM::C_SVC. */ + /** @see setType */ + CV_WRAP virtual int getType() const = 0; + /** @copybrief getType @see getType */ + CV_WRAP virtual void setType(int val) = 0; + + /** Parameter \f$\gamma\f$ of a kernel function. + For SVM::POLY, SVM::RBF, SVM::SIGMOID or SVM::CHI2. Default value is 1. */ + /** @see setGamma */ + CV_WRAP virtual double getGamma() const = 0; + /** @copybrief getGamma @see getGamma */ + CV_WRAP virtual void setGamma(double val) = 0; + + /** Parameter _coef0_ of a kernel function. + For SVM::POLY or SVM::SIGMOID. Default value is 0.*/ + /** @see setCoef0 */ + CV_WRAP virtual double getCoef0() const = 0; + /** @copybrief getCoef0 @see getCoef0 */ + CV_WRAP virtual void setCoef0(double val) = 0; + + /** Parameter _degree_ of a kernel function. + For SVM::POLY. Default value is 0. */ + /** @see setDegree */ + CV_WRAP virtual double getDegree() const = 0; + /** @copybrief getDegree @see getDegree */ + CV_WRAP virtual void setDegree(double val) = 0; + + /** Parameter _C_ of a %SVM optimization problem. + For SVM::C_SVC, SVM::EPS_SVR or SVM::NU_SVR. Default value is 0. */ + /** @see setC */ + CV_WRAP virtual double getC() const = 0; + /** @copybrief getC @see getC */ + CV_WRAP virtual void setC(double val) = 0; + + /** Parameter \f$\nu\f$ of a %SVM optimization problem. + For SVM::NU_SVC, SVM::ONE_CLASS or SVM::NU_SVR. Default value is 0. */ + /** @see setNu */ + CV_WRAP virtual double getNu() const = 0; + /** @copybrief getNu @see getNu */ + CV_WRAP virtual void setNu(double val) = 0; + + /** Parameter \f$\epsilon\f$ of a %SVM optimization problem. + For SVM::EPS_SVR. Default value is 0. */ + /** @see setP */ + CV_WRAP virtual double getP() const = 0; + /** @copybrief getP @see getP */ + CV_WRAP virtual void setP(double val) = 0; + + /** Optional weights in the SVM::C_SVC problem, assigned to particular classes. + They are multiplied by _C_ so the parameter _C_ of class _i_ becomes `classWeights(i) * C`. Thus + these weights affect the misclassification penalty for different classes. The larger weight, + the larger penalty on misclassification of data from the corresponding class. Default value is + empty Mat. */ + /** @see setClassWeights */ + CV_WRAP virtual cv::Mat getClassWeights() const = 0; + /** @copybrief getClassWeights @see getClassWeights */ + CV_WRAP virtual void setClassWeights(const cv::Mat &val) = 0; + + /** Termination criteria of the iterative %SVM training procedure which solves a partial + case of constrained quadratic optimization problem. + You can specify tolerance and/or the maximum number of iterations. Default value is + `TermCriteria( TermCriteria::MAX_ITER + TermCriteria::EPS, 1000, FLT_EPSILON )`; */ + /** @see setTermCriteria */ + CV_WRAP virtual cv::TermCriteria getTermCriteria() const = 0; + /** @copybrief getTermCriteria @see getTermCriteria */ + CV_WRAP virtual void setTermCriteria(const cv::TermCriteria &val) = 0; + + /** Type of a %SVM kernel. + See SVM::KernelTypes. Default value is SVM::RBF. */ + CV_WRAP virtual int getKernelType() const = 0; + + /** Initialize with one of predefined kernels. + See SVM::KernelTypes. */ + CV_WRAP virtual void setKernel(int kernelType) = 0; + + /** Initialize with custom kernel. + See SVM::Kernel class for implementation details */ + virtual void setCustomKernel(const Ptr &_kernel) = 0; + + //! %SVM type + enum Types { + /** C-Support Vector Classification. n-class classification (n \f$\geq\f$ 2), allows + imperfect separation of classes with penalty multiplier C for outliers. */ + C_SVC=100, + /** \f$\nu\f$-Support Vector Classification. n-class classification with possible + imperfect separation. Parameter \f$\nu\f$ (in the range 0..1, the larger the value, the smoother + the decision boundary) is used instead of C. */ + NU_SVC=101, + /** Distribution Estimation (One-class %SVM). All the training data are from + the same class, %SVM builds a boundary that separates the class from the rest of the feature + space. */ + ONE_CLASS=102, + /** \f$\epsilon\f$-Support Vector Regression. The distance between feature vectors + from the training set and the fitting hyper-plane must be less than p. For outliers the + penalty multiplier C is used. */ + EPS_SVR=103, + /** \f$\nu\f$-Support Vector Regression. \f$\nu\f$ is used instead of p. + See @cite LibSVM for details. */ + NU_SVR=104 + }; + + /** @brief %SVM kernel type + + A comparison of different kernels on the following 2D test case with four classes. Four + SVM::C_SVC SVMs have been trained (one against rest) with auto_train. Evaluation on three + different kernels (SVM::CHI2, SVM::INTER, SVM::RBF). The color depicts the class with max score. + Bright means max-score \> 0, dark means max-score \< 0. + ![image](pics/SVM_Comparison.png) + */ + enum KernelTypes { + /** Returned by SVM::getKernelType in case when custom kernel has been set */ + CUSTOM=-1, + /** Linear kernel. No mapping is done, linear discrimination (or regression) is + done in the original feature space. It is the fastest option. \f$K(x_i, x_j) = x_i^T x_j\f$. */ + LINEAR=0, + /** Polynomial kernel: + \f$K(x_i, x_j) = (\gamma x_i^T x_j + coef0)^{degree}, \gamma > 0\f$. */ + POLY=1, + /** Radial basis function (RBF), a good choice in most cases. + \f$K(x_i, x_j) = e^{-\gamma ||x_i - x_j||^2}, \gamma > 0\f$. */ + RBF=2, + /** Sigmoid kernel: \f$K(x_i, x_j) = \tanh(\gamma x_i^T x_j + coef0)\f$. */ + SIGMOID=3, + /** Exponential Chi2 kernel, similar to the RBF kernel: + \f$K(x_i, x_j) = e^{-\gamma \chi^2(x_i,x_j)}, \chi^2(x_i,x_j) = (x_i-x_j)^2/(x_i+x_j), \gamma > 0\f$. */ + CHI2=4, + /** Histogram intersection kernel. A fast kernel. \f$K(x_i, x_j) = min(x_i,x_j)\f$. */ + INTER=5 + }; + + //! %SVM params type + enum ParamTypes { + C=0, + GAMMA=1, + P=2, + NU=3, + COEF=4, + DEGREE=5 + }; + + /** @brief Trains an %SVM with optimal parameters. + + @param data the training data that can be constructed using TrainData::create or + TrainData::loadFromCSV. + @param kFold Cross-validation parameter. The training set is divided into kFold subsets. One + subset is used to test the model, the others form the train set. So, the %SVM algorithm is + executed kFold times. + @param Cgrid grid for C + @param gammaGrid grid for gamma + @param pGrid grid for p + @param nuGrid grid for nu + @param coeffGrid grid for coeff + @param degreeGrid grid for degree + @param balanced If true and the problem is 2-class classification then the method creates more + balanced cross-validation subsets that is proportions between classes in subsets are close + to such proportion in the whole train dataset. + + The method trains the %SVM model automatically by choosing the optimal parameters C, gamma, p, + nu, coef0, degree. Parameters are considered optimal when the cross-validation + estimate of the test set error is minimal. + + If there is no need to optimize a parameter, the corresponding grid step should be set to any + value less than or equal to 1. For example, to avoid optimization in gamma, set `gammaGrid.step + = 0`, `gammaGrid.minVal`, `gamma_grid.maxVal` as arbitrary numbers. In this case, the value + `Gamma` is taken for gamma. + + And, finally, if the optimization in a parameter is required but the corresponding grid is + unknown, you may call the function SVM::getDefaultGrid. To generate a grid, for example, for + gamma, call `SVM::getDefaultGrid(SVM::GAMMA)`. + + This function works for the classification (SVM::C_SVC or SVM::NU_SVC) as well as for the + regression (SVM::EPS_SVR or SVM::NU_SVR). If it is SVM::ONE_CLASS, no optimization is made and + the usual %SVM with parameters specified in params is executed. + */ + virtual bool trainAuto( const Ptr& data, int kFold = 10, + ParamGrid Cgrid = SVM::getDefaultGrid(SVM::C), + ParamGrid gammaGrid = SVM::getDefaultGrid(SVM::GAMMA), + ParamGrid pGrid = SVM::getDefaultGrid(SVM::P), + ParamGrid nuGrid = SVM::getDefaultGrid(SVM::NU), + ParamGrid coeffGrid = SVM::getDefaultGrid(SVM::COEF), + ParamGrid degreeGrid = SVM::getDefaultGrid(SVM::DEGREE), + bool balanced=false) = 0; + + /** @brief Retrieves all the support vectors + + The method returns all the support vector as floating-point matrix, where support vectors are + stored as matrix rows. + */ + CV_WRAP virtual Mat getSupportVectors() const = 0; + + /** @brief Retrieves the decision function + + @param i the index of the decision function. If the problem solved is regression, 1-class or + 2-class classification, then there will be just one decision function and the index should + always be 0. Otherwise, in the case of N-class classification, there will be \f$N(N-1)/2\f$ + decision functions. + @param alpha the optional output vector for weights, corresponding to different support vectors. + In the case of linear %SVM all the alpha's will be 1's. + @param svidx the optional output vector of indices of support vectors within the matrix of + support vectors (which can be retrieved by SVM::getSupportVectors). In the case of linear + %SVM each decision function consists of a single "compressed" support vector. + + The method returns rho parameter of the decision function, a scalar subtracted from the weighted + sum of kernel responses. + */ + CV_WRAP virtual double getDecisionFunction(int i, OutputArray alpha, OutputArray svidx) const = 0; + + /** @brief Generates a grid for %SVM parameters. + + @param param_id %SVM parameters IDs that must be one of the SVM::ParamTypes. The grid is + generated for the parameter with this ID. + + The function generates a grid for the specified parameter of the %SVM algorithm. The grid may be + passed to the function SVM::trainAuto. + */ + static ParamGrid getDefaultGrid( int param_id ); + + /** Creates empty model. + Use StatModel::train to train the model. Since %SVM has several parameters, you may want to + find the best parameters for your problem, it can be done with SVM::trainAuto. */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* Expectation - Maximization * +\****************************************************************************************/ + +/** @brief The class implements the Expectation Maximization algorithm. + +@sa @ref ml_intro_em + */ +class CV_EXPORTS_W EM : public StatModel +{ +public: + //! Type of covariation matrices + enum Types { + /** A scaled identity matrix \f$\mu_k * I\f$. There is the only + parameter \f$\mu_k\f$ to be estimated for each matrix. The option may be used in special cases, + when the constraint is relevant, or as a first step in the optimization (for example in case + when the data is preprocessed with PCA). The results of such preliminary estimation may be + passed again to the optimization procedure, this time with + covMatType=EM::COV_MAT_DIAGONAL. */ + COV_MAT_SPHERICAL=0, + /** A diagonal matrix with positive diagonal elements. The number of + free parameters is d for each matrix. This is most commonly used option yielding good + estimation results. */ + COV_MAT_DIAGONAL=1, + /** A symmetric positively defined matrix. The number of free + parameters in each matrix is about \f$d^2/2\f$. It is not recommended to use this option, unless + there is pretty accurate initial estimation of the parameters and/or a huge number of + training samples. */ + COV_MAT_GENERIC=2, + COV_MAT_DEFAULT=COV_MAT_DIAGONAL + }; + + //! Default parameters + enum {DEFAULT_NCLUSTERS=5, DEFAULT_MAX_ITERS=100}; + + //! The initial step + enum {START_E_STEP=1, START_M_STEP=2, START_AUTO_STEP=0}; + + /** The number of mixture components in the Gaussian mixture model. + Default value of the parameter is EM::DEFAULT_NCLUSTERS=5. Some of %EM implementation could + determine the optimal number of mixtures within a specified value range, but that is not the + case in ML yet. */ + /** @see setClustersNumber */ + CV_WRAP virtual int getClustersNumber() const = 0; + /** @copybrief getClustersNumber @see getClustersNumber */ + CV_WRAP virtual void setClustersNumber(int val) = 0; + + /** Constraint on covariance matrices which defines type of matrices. + See EM::Types. */ + /** @see setCovarianceMatrixType */ + CV_WRAP virtual int getCovarianceMatrixType() const = 0; + /** @copybrief getCovarianceMatrixType @see getCovarianceMatrixType */ + CV_WRAP virtual void setCovarianceMatrixType(int val) = 0; + + /** The termination criteria of the %EM algorithm. + The %EM algorithm can be terminated by the number of iterations termCrit.maxCount (number of + M-steps) or when relative change of likelihood logarithm is less than termCrit.epsilon. Default + maximum number of iterations is EM::DEFAULT_MAX_ITERS=100. */ + /** @see setTermCriteria */ + CV_WRAP virtual TermCriteria getTermCriteria() const = 0; + /** @copybrief getTermCriteria @see getTermCriteria */ + CV_WRAP virtual void setTermCriteria(const TermCriteria &val) = 0; + + /** @brief Returns weights of the mixtures + + Returns vector with the number of elements equal to the number of mixtures. + */ + CV_WRAP virtual Mat getWeights() const = 0; + /** @brief Returns the cluster centers (means of the Gaussian mixture) + + Returns matrix with the number of rows equal to the number of mixtures and number of columns + equal to the space dimensionality. + */ + CV_WRAP virtual Mat getMeans() const = 0; + /** @brief Returns covariation matrices + + Returns vector of covariation matrices. Number of matrices is the number of gaussian mixtures, + each matrix is a square floating-point matrix NxN, where N is the space dimensionality. + */ + virtual void getCovs(std::vector& covs) const = 0; + + /** @brief Returns a likelihood logarithm value and an index of the most probable mixture component + for the given sample. + + @param sample A sample for classification. It should be a one-channel matrix of + \f$1 \times dims\f$ or \f$dims \times 1\f$ size. + @param probs Optional output matrix that contains posterior probabilities of each component + given the sample. It has \f$1 \times nclusters\f$ size and CV_64FC1 type. + + The method returns a two-element double vector. Zero element is a likelihood logarithm value for + the sample. First element is an index of the most probable mixture component for the given + sample. + */ + CV_WRAP CV_WRAP virtual Vec2d predict2(InputArray sample, OutputArray probs) const = 0; + + /** @brief Estimate the Gaussian mixture parameters from a samples set. + + This variation starts with Expectation step. Initial values of the model parameters will be + estimated by the k-means algorithm. + + Unlike many of the ML models, %EM is an unsupervised learning algorithm and it does not take + responses (class labels or function values) as input. Instead, it computes the *Maximum + Likelihood Estimate* of the Gaussian mixture parameters from an input sample set, stores all the + parameters inside the structure: \f$p_{i,k}\f$ in probs, \f$a_k\f$ in means , \f$S_k\f$ in + covs[k], \f$\pi_k\f$ in weights , and optionally computes the output "class label" for each + sample: \f$\texttt{labels}_i=\texttt{arg max}_k(p_{i,k}), i=1..N\f$ (indices of the most + probable mixture component for each sample). + + The trained model can be used further for prediction, just like any other classifier. The + trained model is similar to the NormalBayesClassifier. + + @param samples Samples from which the Gaussian mixture model will be estimated. It should be a + one-channel matrix, each row of which is a sample. If the matrix does not have CV_64F type + it will be converted to the inner matrix of such type for the further computing. + @param logLikelihoods The optional output matrix that contains a likelihood logarithm value for + each sample. It has \f$nsamples \times 1\f$ size and CV_64FC1 type. + @param labels The optional output "class label" for each sample: + \f$\texttt{labels}_i=\texttt{arg max}_k(p_{i,k}), i=1..N\f$ (indices of the most probable + mixture component for each sample). It has \f$nsamples \times 1\f$ size and CV_32SC1 type. + @param probs The optional output matrix that contains posterior probabilities of each Gaussian + mixture component given the each sample. It has \f$nsamples \times nclusters\f$ size and + CV_64FC1 type. + */ + CV_WRAP virtual bool trainEM(InputArray samples, + OutputArray logLikelihoods=noArray(), + OutputArray labels=noArray(), + OutputArray probs=noArray()) = 0; + + /** @brief Estimate the Gaussian mixture parameters from a samples set. + + This variation starts with Expectation step. You need to provide initial means \f$a_k\f$ of + mixture components. Optionally you can pass initial weights \f$\pi_k\f$ and covariance matrices + \f$S_k\f$ of mixture components. + + @param samples Samples from which the Gaussian mixture model will be estimated. It should be a + one-channel matrix, each row of which is a sample. If the matrix does not have CV_64F type + it will be converted to the inner matrix of such type for the further computing. + @param means0 Initial means \f$a_k\f$ of mixture components. It is a one-channel matrix of + \f$nclusters \times dims\f$ size. If the matrix does not have CV_64F type it will be + converted to the inner matrix of such type for the further computing. + @param covs0 The vector of initial covariance matrices \f$S_k\f$ of mixture components. Each of + covariance matrices is a one-channel matrix of \f$dims \times dims\f$ size. If the matrices + do not have CV_64F type they will be converted to the inner matrices of such type for the + further computing. + @param weights0 Initial weights \f$\pi_k\f$ of mixture components. It should be a one-channel + floating-point matrix with \f$1 \times nclusters\f$ or \f$nclusters \times 1\f$ size. + @param logLikelihoods The optional output matrix that contains a likelihood logarithm value for + each sample. It has \f$nsamples \times 1\f$ size and CV_64FC1 type. + @param labels The optional output "class label" for each sample: + \f$\texttt{labels}_i=\texttt{arg max}_k(p_{i,k}), i=1..N\f$ (indices of the most probable + mixture component for each sample). It has \f$nsamples \times 1\f$ size and CV_32SC1 type. + @param probs The optional output matrix that contains posterior probabilities of each Gaussian + mixture component given the each sample. It has \f$nsamples \times nclusters\f$ size and + CV_64FC1 type. + */ + CV_WRAP virtual bool trainE(InputArray samples, InputArray means0, + InputArray covs0=noArray(), + InputArray weights0=noArray(), + OutputArray logLikelihoods=noArray(), + OutputArray labels=noArray(), + OutputArray probs=noArray()) = 0; + + /** @brief Estimate the Gaussian mixture parameters from a samples set. + + This variation starts with Maximization step. You need to provide initial probabilities + \f$p_{i,k}\f$ to use this option. + + @param samples Samples from which the Gaussian mixture model will be estimated. It should be a + one-channel matrix, each row of which is a sample. If the matrix does not have CV_64F type + it will be converted to the inner matrix of such type for the further computing. + @param probs0 + @param logLikelihoods The optional output matrix that contains a likelihood logarithm value for + each sample. It has \f$nsamples \times 1\f$ size and CV_64FC1 type. + @param labels The optional output "class label" for each sample: + \f$\texttt{labels}_i=\texttt{arg max}_k(p_{i,k}), i=1..N\f$ (indices of the most probable + mixture component for each sample). It has \f$nsamples \times 1\f$ size and CV_32SC1 type. + @param probs The optional output matrix that contains posterior probabilities of each Gaussian + mixture component given the each sample. It has \f$nsamples \times nclusters\f$ size and + CV_64FC1 type. + */ + CV_WRAP virtual bool trainM(InputArray samples, InputArray probs0, + OutputArray logLikelihoods=noArray(), + OutputArray labels=noArray(), + OutputArray probs=noArray()) = 0; + + /** Creates empty %EM model. + The model should be trained then using StatModel::train(traindata, flags) method. Alternatively, you + can use one of the EM::train\* methods or load it from file using Algorithm::load\(filename). + */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* Decision Tree * +\****************************************************************************************/ + +/** @brief The class represents a single decision tree or a collection of decision trees. + +The current public interface of the class allows user to train only a single decision tree, however +the class is capable of storing multiple decision trees and using them for prediction (by summing +responses or using a voting schemes), and the derived from DTrees classes (such as RTrees and Boost) +use this capability to implement decision tree ensembles. + +@sa @ref ml_intro_trees +*/ +class CV_EXPORTS_W DTrees : public StatModel +{ +public: + /** Predict options */ + enum Flags { PREDICT_AUTO=0, PREDICT_SUM=(1<<8), PREDICT_MAX_VOTE=(2<<8), PREDICT_MASK=(3<<8) }; + + /** Cluster possible values of a categorical variable into K\<=maxCategories clusters to + find a suboptimal split. + If a discrete variable, on which the training procedure tries to make a split, takes more than + maxCategories values, the precise best subset estimation may take a very long time because the + algorithm is exponential. Instead, many decision trees engines (including our implementation) + try to find sub-optimal split in this case by clustering all the samples into maxCategories + clusters that is some categories are merged together. The clustering is applied only in n \> + 2-class classification problems for categorical variables with N \> max_categories possible + values. In case of regression and 2-class classification the optimal split can be found + efficiently without employing clustering, thus the parameter is not used in these cases. + Default value is 10.*/ + /** @see setMaxCategories */ + CV_WRAP virtual int getMaxCategories() const = 0; + /** @copybrief getMaxCategories @see getMaxCategories */ + CV_WRAP virtual void setMaxCategories(int val) = 0; + + /** The maximum possible depth of the tree. + That is the training algorithms attempts to split a node while its depth is less than maxDepth. + The root node has zero depth. The actual depth may be smaller if the other termination criteria + are met (see the outline of the training procedure @ref ml_intro_trees "here"), and/or if the + tree is pruned. Default value is INT_MAX.*/ + /** @see setMaxDepth */ + CV_WRAP virtual int getMaxDepth() const = 0; + /** @copybrief getMaxDepth @see getMaxDepth */ + CV_WRAP virtual void setMaxDepth(int val) = 0; + + /** If the number of samples in a node is less than this parameter then the node will not be split. + + Default value is 10.*/ + /** @see setMinSampleCount */ + CV_WRAP virtual int getMinSampleCount() const = 0; + /** @copybrief getMinSampleCount @see getMinSampleCount */ + CV_WRAP virtual void setMinSampleCount(int val) = 0; + + /** If CVFolds \> 1 then algorithms prunes the built decision tree using K-fold + cross-validation procedure where K is equal to CVFolds. + Default value is 10.*/ + /** @see setCVFolds */ + CV_WRAP virtual int getCVFolds() const = 0; + /** @copybrief getCVFolds @see getCVFolds */ + CV_WRAP virtual void setCVFolds(int val) = 0; + + /** If true then surrogate splits will be built. + These splits allow to work with missing data and compute variable importance correctly. + Default value is false. + @note currently it's not implemented.*/ + /** @see setUseSurrogates */ + CV_WRAP virtual bool getUseSurrogates() const = 0; + /** @copybrief getUseSurrogates @see getUseSurrogates */ + CV_WRAP virtual void setUseSurrogates(bool val) = 0; + + /** If true then a pruning will be harsher. + This will make a tree more compact and more resistant to the training data noise but a bit less + accurate. Default value is true.*/ + /** @see setUse1SERule */ + CV_WRAP virtual bool getUse1SERule() const = 0; + /** @copybrief getUse1SERule @see getUse1SERule */ + CV_WRAP virtual void setUse1SERule(bool val) = 0; + + /** If true then pruned branches are physically removed from the tree. + Otherwise they are retained and it is possible to get results from the original unpruned (or + pruned less aggressively) tree. Default value is true.*/ + /** @see setTruncatePrunedTree */ + CV_WRAP virtual bool getTruncatePrunedTree() const = 0; + /** @copybrief getTruncatePrunedTree @see getTruncatePrunedTree */ + CV_WRAP virtual void setTruncatePrunedTree(bool val) = 0; + + /** Termination criteria for regression trees. + If all absolute differences between an estimated value in a node and values of train samples + in this node are less than this parameter then the node will not be split further. Default + value is 0.01f*/ + /** @see setRegressionAccuracy */ + CV_WRAP virtual float getRegressionAccuracy() const = 0; + /** @copybrief getRegressionAccuracy @see getRegressionAccuracy */ + CV_WRAP virtual void setRegressionAccuracy(float val) = 0; + + /** @brief The array of a priori class probabilities, sorted by the class label value. + + The parameter can be used to tune the decision tree preferences toward a certain class. For + example, if you want to detect some rare anomaly occurrence, the training base will likely + contain much more normal cases than anomalies, so a very good classification performance + will be achieved just by considering every case as normal. To avoid this, the priors can be + specified, where the anomaly probability is artificially increased (up to 0.5 or even + greater), so the weight of the misclassified anomalies becomes much bigger, and the tree is + adjusted properly. + + You can also think about this parameter as weights of prediction categories which determine + relative weights that you give to misclassification. That is, if the weight of the first + category is 1 and the weight of the second category is 10, then each mistake in predicting + the second category is equivalent to making 10 mistakes in predicting the first category. + Default value is empty Mat.*/ + /** @see setPriors */ + CV_WRAP virtual cv::Mat getPriors() const = 0; + /** @copybrief getPriors @see getPriors */ + CV_WRAP virtual void setPriors(const cv::Mat &val) = 0; + + /** @brief The class represents a decision tree node. + */ + class CV_EXPORTS Node + { + public: + Node(); + double value; //!< Value at the node: a class label in case of classification or estimated + //!< function value in case of regression. + int classIdx; //!< Class index normalized to 0..class_count-1 range and assigned to the + //!< node. It is used internally in classification trees and tree ensembles. + int parent; //!< Index of the parent node + int left; //!< Index of the left child node + int right; //!< Index of right child node + int defaultDir; //!< Default direction where to go (-1: left or +1: right). It helps in the + //!< case of missing values. + int split; //!< Index of the first split + }; + + /** @brief The class represents split in a decision tree. + */ + class CV_EXPORTS Split + { + public: + Split(); + int varIdx; //!< Index of variable on which the split is created. + bool inversed; //!< If true, then the inverse split rule is used (i.e. left and right + //!< branches are exchanged in the rule expressions below). + float quality; //!< The split quality, a positive number. It is used to choose the best split. + int next; //!< Index of the next split in the list of splits for the node + float c; /**< The threshold value in case of split on an ordered variable. + The rule is: + @code{.none} + if var_value < c + then next_node <- left + else next_node <- right + @endcode */ + int subsetOfs; /**< Offset of the bitset used by the split on a categorical variable. + The rule is: + @code{.none} + if bitset[var_value] == 1 + then next_node <- left + else next_node <- right + @endcode */ + }; + + /** @brief Returns indices of root nodes + */ + virtual const std::vector& getRoots() const = 0; + /** @brief Returns all the nodes + + all the node indices are indices in the returned vector + */ + virtual const std::vector& getNodes() const = 0; + /** @brief Returns all the splits + + all the split indices are indices in the returned vector + */ + virtual const std::vector& getSplits() const = 0; + /** @brief Returns all the bitsets for categorical splits + + Split::subsetOfs is an offset in the returned vector + */ + virtual const std::vector& getSubsets() const = 0; + + /** @brief Creates the empty model + + The static method creates empty decision tree with the specified parameters. It should be then + trained using train method (see StatModel::train). Alternatively, you can load the model from + file using Algorithm::load\(filename). + */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* Random Trees Classifier * +\****************************************************************************************/ + +/** @brief The class implements the random forest predictor. + +@sa @ref ml_intro_rtrees + */ +class CV_EXPORTS_W RTrees : public DTrees +{ +public: + + /** If true then variable importance will be calculated and then it can be retrieved by RTrees::getVarImportance. + Default value is false.*/ + /** @see setCalculateVarImportance */ + CV_WRAP virtual bool getCalculateVarImportance() const = 0; + /** @copybrief getCalculateVarImportance @see getCalculateVarImportance */ + CV_WRAP virtual void setCalculateVarImportance(bool val) = 0; + + /** The size of the randomly selected subset of features at each tree node and that are used + to find the best split(s). + If you set it to 0 then the size will be set to the square root of the total number of + features. Default value is 0.*/ + /** @see setActiveVarCount */ + CV_WRAP virtual int getActiveVarCount() const = 0; + /** @copybrief getActiveVarCount @see getActiveVarCount */ + CV_WRAP virtual void setActiveVarCount(int val) = 0; + + /** The termination criteria that specifies when the training algorithm stops. + Either when the specified number of trees is trained and added to the ensemble or when + sufficient accuracy (measured as OOB error) is achieved. Typically the more trees you have the + better the accuracy. However, the improvement in accuracy generally diminishes and asymptotes + pass a certain number of trees. Also to keep in mind, the number of tree increases the + prediction time linearly. Default value is TermCriteria(TermCriteria::MAX_ITERS + + TermCriteria::EPS, 50, 0.1)*/ + /** @see setTermCriteria */ + CV_WRAP virtual TermCriteria getTermCriteria() const = 0; + /** @copybrief getTermCriteria @see getTermCriteria */ + CV_WRAP virtual void setTermCriteria(const TermCriteria &val) = 0; + + /** Returns the variable importance array. + The method returns the variable importance vector, computed at the training stage when + CalculateVarImportance is set to true. If this flag was set to false, the empty matrix is + returned. + */ + CV_WRAP virtual Mat getVarImportance() const = 0; + + /** Creates the empty model. + Use StatModel::train to train the model, StatModel::train to create and train the model, + Algorithm::load to load the pre-trained model. + */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* Boosted tree classifier * +\****************************************************************************************/ + +/** @brief Boosted tree classifier derived from DTrees + +@sa @ref ml_intro_boost + */ +class CV_EXPORTS_W Boost : public DTrees +{ +public: + /** Type of the boosting algorithm. + See Boost::Types. Default value is Boost::REAL. */ + /** @see setBoostType */ + CV_WRAP virtual int getBoostType() const = 0; + /** @copybrief getBoostType @see getBoostType */ + CV_WRAP virtual void setBoostType(int val) = 0; + + /** The number of weak classifiers. + Default value is 100. */ + /** @see setWeakCount */ + CV_WRAP virtual int getWeakCount() const = 0; + /** @copybrief getWeakCount @see getWeakCount */ + CV_WRAP virtual void setWeakCount(int val) = 0; + + /** A threshold between 0 and 1 used to save computational time. + Samples with summary weight \f$\leq 1 - weight_trim_rate\f$ do not participate in the *next* + iteration of training. Set this parameter to 0 to turn off this functionality. Default value is 0.95.*/ + /** @see setWeightTrimRate */ + CV_WRAP virtual double getWeightTrimRate() const = 0; + /** @copybrief getWeightTrimRate @see getWeightTrimRate */ + CV_WRAP virtual void setWeightTrimRate(double val) = 0; + + /** Boosting type. + Gentle AdaBoost and Real AdaBoost are often the preferable choices. */ + enum Types { + DISCRETE=0, //!< Discrete AdaBoost. + REAL=1, //!< Real AdaBoost. It is a technique that utilizes confidence-rated predictions + //!< and works well with categorical data. + LOGIT=2, //!< LogitBoost. It can produce good regression fits. + GENTLE=3 //!< Gentle AdaBoost. It puts less weight on outlier data points and for that + //!(filename) to load the pre-trained model. */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* Gradient Boosted Trees * +\****************************************************************************************/ + +/*class CV_EXPORTS_W GBTrees : public DTrees +{ +public: + struct CV_EXPORTS_W_MAP Params : public DTrees::Params + { + CV_PROP_RW int weakCount; + CV_PROP_RW int lossFunctionType; + CV_PROP_RW float subsamplePortion; + CV_PROP_RW float shrinkage; + + Params(); + Params( int lossFunctionType, int weakCount, float shrinkage, + float subsamplePortion, int maxDepth, bool useSurrogates ); + }; + + enum {SQUARED_LOSS=0, ABSOLUTE_LOSS, HUBER_LOSS=3, DEVIANCE_LOSS}; + + virtual void setK(int k) = 0; + + virtual float predictSerial( InputArray samples, + OutputArray weakResponses, int flags) const = 0; + + static Ptr create(const Params& p); +};*/ + +/****************************************************************************************\ +* Artificial Neural Networks (ANN) * +\****************************************************************************************/ + +/////////////////////////////////// Multi-Layer Perceptrons ////////////////////////////// + +/** @brief Artificial Neural Networks - Multi-Layer Perceptrons. + +Unlike many other models in ML that are constructed and trained at once, in the MLP model these +steps are separated. First, a network with the specified topology is created using the non-default +constructor or the method ANN_MLP::create. All the weights are set to zeros. Then, the network is +trained using a set of input and output vectors. The training procedure can be repeated more than +once, that is, the weights can be adjusted based on the new training data. + +Additional flags for StatModel::train are available: ANN_MLP::TrainFlags. + +@sa @ref ml_intro_ann + */ +class CV_EXPORTS_W ANN_MLP : public StatModel +{ +public: + /** Available training methods */ + enum TrainingMethods { + BACKPROP=0, //!< The back-propagation algorithm. + RPROP=1 //!< The RPROP algorithm. See @cite RPROP93 for details. + }; + + /** Sets training method and common parameters. + @param method Default value is ANN_MLP::RPROP. See ANN_MLP::TrainingMethods. + @param param1 passed to setRpropDW0 for ANN_MLP::RPROP and to setBackpropWeightScale for ANN_MLP::BACKPROP + @param param2 passed to setRpropDWMin for ANN_MLP::RPROP and to setBackpropMomentumScale for ANN_MLP::BACKPROP. + */ + CV_WRAP virtual void setTrainMethod(int method, double param1 = 0, double param2 = 0) = 0; + + /** Returns current training method */ + CV_WRAP virtual int getTrainMethod() const = 0; + + /** Initialize the activation function for each neuron. + Currently the default and the only fully supported activation function is ANN_MLP::SIGMOID_SYM. + @param type The type of activation function. See ANN_MLP::ActivationFunctions. + @param param1 The first parameter of the activation function, \f$\alpha\f$. Default value is 0. + @param param2 The second parameter of the activation function, \f$\beta\f$. Default value is 0. + */ + CV_WRAP virtual void setActivationFunction(int type, double param1 = 0, double param2 = 0) = 0; + + /** Integer vector specifying the number of neurons in each layer including the input and output layers. + The very first element specifies the number of elements in the input layer. + The last element - number of elements in the output layer. Default value is empty Mat. + @sa getLayerSizes */ + CV_WRAP virtual void setLayerSizes(InputArray _layer_sizes) = 0; + + /** Integer vector specifying the number of neurons in each layer including the input and output layers. + The very first element specifies the number of elements in the input layer. + The last element - number of elements in the output layer. + @sa setLayerSizes */ + CV_WRAP virtual cv::Mat getLayerSizes() const = 0; + + /** Termination criteria of the training algorithm. + You can specify the maximum number of iterations (maxCount) and/or how much the error could + change between the iterations to make the algorithm continue (epsilon). Default value is + TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 1000, 0.01).*/ + /** @see setTermCriteria */ + CV_WRAP virtual TermCriteria getTermCriteria() const = 0; + /** @copybrief getTermCriteria @see getTermCriteria */ + CV_WRAP virtual void setTermCriteria(TermCriteria val) = 0; + + /** BPROP: Strength of the weight gradient term. + The recommended value is about 0.1. Default value is 0.1.*/ + /** @see setBackpropWeightScale */ + CV_WRAP virtual double getBackpropWeightScale() const = 0; + /** @copybrief getBackpropWeightScale @see getBackpropWeightScale */ + CV_WRAP virtual void setBackpropWeightScale(double val) = 0; + + /** BPROP: Strength of the momentum term (the difference between weights on the 2 previous iterations). + This parameter provides some inertia to smooth the random fluctuations of the weights. It can + vary from 0 (the feature is disabled) to 1 and beyond. The value 0.1 or so is good enough. + Default value is 0.1.*/ + /** @see setBackpropMomentumScale */ + CV_WRAP virtual double getBackpropMomentumScale() const = 0; + /** @copybrief getBackpropMomentumScale @see getBackpropMomentumScale */ + CV_WRAP virtual void setBackpropMomentumScale(double val) = 0; + + /** RPROP: Initial value \f$\Delta_0\f$ of update-values \f$\Delta_{ij}\f$. + Default value is 0.1.*/ + /** @see setRpropDW0 */ + CV_WRAP virtual double getRpropDW0() const = 0; + /** @copybrief getRpropDW0 @see getRpropDW0 */ + CV_WRAP virtual void setRpropDW0(double val) = 0; + + /** RPROP: Increase factor \f$\eta^+\f$. + It must be \>1. Default value is 1.2.*/ + /** @see setRpropDWPlus */ + CV_WRAP virtual double getRpropDWPlus() const = 0; + /** @copybrief getRpropDWPlus @see getRpropDWPlus */ + CV_WRAP virtual void setRpropDWPlus(double val) = 0; + + /** RPROP: Decrease factor \f$\eta^-\f$. + It must be \<1. Default value is 0.5.*/ + /** @see setRpropDWMinus */ + CV_WRAP virtual double getRpropDWMinus() const = 0; + /** @copybrief getRpropDWMinus @see getRpropDWMinus */ + CV_WRAP virtual void setRpropDWMinus(double val) = 0; + + /** RPROP: Update-values lower limit \f$\Delta_{min}\f$. + It must be positive. Default value is FLT_EPSILON.*/ + /** @see setRpropDWMin */ + CV_WRAP virtual double getRpropDWMin() const = 0; + /** @copybrief getRpropDWMin @see getRpropDWMin */ + CV_WRAP virtual void setRpropDWMin(double val) = 0; + + /** RPROP: Update-values upper limit \f$\Delta_{max}\f$. + It must be \>1. Default value is 50.*/ + /** @see setRpropDWMax */ + CV_WRAP virtual double getRpropDWMax() const = 0; + /** @copybrief getRpropDWMax @see getRpropDWMax */ + CV_WRAP virtual void setRpropDWMax(double val) = 0; + + /** possible activation functions */ + enum ActivationFunctions { + /** Identity function: \f$f(x)=x\f$ */ + IDENTITY = 0, + /** Symmetrical sigmoid: \f$f(x)=\beta*(1-e^{-\alpha x})/(1+e^{-\alpha x}\f$ + @note + If you are using the default sigmoid activation function with the default parameter values + fparam1=0 and fparam2=0 then the function used is y = 1.7159\*tanh(2/3 \* x), so the output + will range from [-1.7159, 1.7159], instead of [0,1].*/ + SIGMOID_SYM = 1, + /** Gaussian function: \f$f(x)=\beta e^{-\alpha x*x}\f$ */ + GAUSSIAN = 2 + }; + + /** Train options */ + enum TrainFlags { + /** Update the network weights, rather than compute them from scratch. In the latter case + the weights are initialized using the Nguyen-Widrow algorithm. */ + UPDATE_WEIGHTS = 1, + /** Do not normalize the input vectors. If this flag is not set, the training algorithm + normalizes each input feature independently, shifting its mean value to 0 and making the + standard deviation equal to 1. If the network is assumed to be updated frequently, the new + training data could be much different from original one. In this case, you should take care + of proper normalization. */ + NO_INPUT_SCALE = 2, + /** Do not normalize the output vectors. If the flag is not set, the training algorithm + normalizes each output feature independently, by transforming it to the certain range + depending on the used activation function. */ + NO_OUTPUT_SCALE = 4 + }; + + CV_WRAP virtual Mat getWeights(int layerIdx) const = 0; + + /** @brief Creates empty model + + Use StatModel::train to train the model, Algorithm::load\(filename) to load the pre-trained model. + Note that the train method has optional flags: ANN_MLP::TrainFlags. + */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* Logistic Regression * +\****************************************************************************************/ + +/** @brief Implements Logistic Regression classifier. + +@sa @ref ml_intro_lr + */ +class CV_EXPORTS_W LogisticRegression : public StatModel +{ +public: + + /** Learning rate. */ + /** @see setLearningRate */ + CV_WRAP virtual double getLearningRate() const = 0; + /** @copybrief getLearningRate @see getLearningRate */ + CV_WRAP virtual void setLearningRate(double val) = 0; + + /** Number of iterations. */ + /** @see setIterations */ + CV_WRAP virtual int getIterations() const = 0; + /** @copybrief getIterations @see getIterations */ + CV_WRAP virtual void setIterations(int val) = 0; + + /** Kind of regularization to be applied. See LogisticRegression::RegKinds. */ + /** @see setRegularization */ + CV_WRAP virtual int getRegularization() const = 0; + /** @copybrief getRegularization @see getRegularization */ + CV_WRAP virtual void setRegularization(int val) = 0; + + /** Kind of training method used. See LogisticRegression::Methods. */ + /** @see setTrainMethod */ + CV_WRAP virtual int getTrainMethod() const = 0; + /** @copybrief getTrainMethod @see getTrainMethod */ + CV_WRAP virtual void setTrainMethod(int val) = 0; + + /** Specifies the number of training samples taken in each step of Mini-Batch Gradient + Descent. Will only be used if using LogisticRegression::MINI_BATCH training algorithm. It + has to take values less than the total number of training samples. */ + /** @see setMiniBatchSize */ + CV_WRAP virtual int getMiniBatchSize() const = 0; + /** @copybrief getMiniBatchSize @see getMiniBatchSize */ + CV_WRAP virtual void setMiniBatchSize(int val) = 0; + + /** Termination criteria of the algorithm. */ + /** @see setTermCriteria */ + CV_WRAP virtual TermCriteria getTermCriteria() const = 0; + /** @copybrief getTermCriteria @see getTermCriteria */ + CV_WRAP virtual void setTermCriteria(TermCriteria val) = 0; + + //! Regularization kinds + enum RegKinds { + REG_DISABLE = -1, //!< Regularization disabled + REG_L1 = 0, //!< %L1 norm + REG_L2 = 1 //!< %L2 norm + }; + + //! Training methods + enum Methods { + BATCH = 0, + MINI_BATCH = 1 //!< Set MiniBatchSize to a positive integer when using this method. + }; + + /** @brief Predicts responses for input samples and returns a float type. + + @param samples The input data for the prediction algorithm. Matrix [m x n], where each row + contains variables (features) of one object being classified. Should have data type CV_32F. + @param results Predicted labels as a column matrix of type CV_32S. + @param flags Not used. + */ + CV_WRAP virtual float predict( InputArray samples, OutputArray results=noArray(), int flags=0 ) const = 0; + + /** @brief This function returns the trained paramters arranged across rows. + + For a two class classifcation problem, it returns a row matrix. It returns learnt paramters of + the Logistic Regression as a matrix of type CV_32F. + */ + CV_WRAP virtual Mat get_learnt_thetas() const = 0; + + /** @brief Creates empty model. + + Creates Logistic Regression model with parameters given. + */ + CV_WRAP static Ptr create(); +}; + +/****************************************************************************************\ +* Auxilary functions declarations * +\****************************************************************************************/ + +/** @brief Generates _sample_ from multivariate normal distribution + +@param mean an average row vector +@param cov symmetric covariation matrix +@param nsamples returned samples count +@param samples returned samples array +*/ +CV_EXPORTS void randMVNormal( InputArray mean, InputArray cov, int nsamples, OutputArray samples); + +/** @brief Generates sample from gaussian mixture distribution */ +CV_EXPORTS void randGaussMixture( InputArray means, InputArray covs, InputArray weights, + int nsamples, OutputArray samples, OutputArray sampClasses ); + +/** @brief Creates test set */ +CV_EXPORTS void createConcentricSpheresTestSet( int nsamples, int nfeatures, int nclasses, + OutputArray samples, OutputArray responses); + +//! @} ml + +} +} + +#endif // __cplusplus +#endif // __OPENCV_ML_HPP__ + +/* End of file. */ diff --git a/include/opencv2/ml/ml.hpp b/include/opencv2/ml/ml.hpp new file mode 100644 index 0000000..f6f9cd8 --- /dev/null +++ b/include/opencv2/ml/ml.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/ml.hpp" diff --git a/include/opencv2/objdetect.hpp b/include/opencv2/objdetect.hpp new file mode 100644 index 0000000..bd932e6 --- /dev/null +++ b/include/opencv2/objdetect.hpp @@ -0,0 +1,466 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_OBJDETECT_HPP__ +#define __OPENCV_OBJDETECT_HPP__ + +#include "opencv2/core.hpp" + +/** +@defgroup objdetect Object Detection + +Haar Feature-based Cascade Classifier for Object Detection +---------------------------------------------------------- + +The object detector described below has been initially proposed by Paul Viola @cite Viola01 and +improved by Rainer Lienhart @cite Lienhart02 . + +First, a classifier (namely a *cascade of boosted classifiers working with haar-like features*) is +trained with a few hundred sample views of a particular object (i.e., a face or a car), called +positive examples, that are scaled to the same size (say, 20x20), and negative examples - arbitrary +images of the same size. + +After a classifier is trained, it can be applied to a region of interest (of the same size as used +during the training) in an input image. The classifier outputs a "1" if the region is likely to show +the object (i.e., face/car), and "0" otherwise. To search for the object in the whole image one can +move the search window across the image and check every location using the classifier. The +classifier is designed so that it can be easily "resized" in order to be able to find the objects of +interest at different sizes, which is more efficient than resizing the image itself. So, to find an +object of an unknown size in the image the scan procedure should be done several times at different +scales. + +The word "cascade" in the classifier name means that the resultant classifier consists of several +simpler classifiers (*stages*) that are applied subsequently to a region of interest until at some +stage the candidate is rejected or all the stages are passed. The word "boosted" means that the +classifiers at every stage of the cascade are complex themselves and they are built out of basic +classifiers using one of four different boosting techniques (weighted voting). Currently Discrete +Adaboost, Real Adaboost, Gentle Adaboost and Logitboost are supported. The basic classifiers are +decision-tree classifiers with at least 2 leaves. Haar-like features are the input to the basic +classifiers, and are calculated as described below. The current algorithm uses the following +Haar-like features: + +![image](pics/haarfeatures.png) + +The feature used in a particular classifier is specified by its shape (1a, 2b etc.), position within +the region of interest and the scale (this scale is not the same as the scale used at the detection +stage, though these two scales are multiplied). For example, in the case of the third line feature +(2c) the response is calculated as the difference between the sum of image pixels under the +rectangle covering the whole feature (including the two white stripes and the black stripe in the +middle) and the sum of the image pixels under the black stripe multiplied by 3 in order to +compensate for the differences in the size of areas. The sums of pixel values over a rectangular +regions are calculated rapidly using integral images (see below and the integral description). + +To see the object detector at work, have a look at the facedetect demo: + + +The following reference is for the detection part only. There is a separate application called +opencv_traincascade that can train a cascade of boosted classifiers from a set of samples. + +@note In the new C++ interface it is also possible to use LBP (local binary pattern) features in +addition to Haar-like features. .. [Viola01] Paul Viola and Michael J. Jones. Rapid Object Detection +using a Boosted Cascade of Simple Features. IEEE CVPR, 2001. The paper is available online at + + +@{ + @defgroup objdetect_c C API +@} + */ + +typedef struct CvHaarClassifierCascade CvHaarClassifierCascade; + +namespace cv +{ + +//! @addtogroup objdetect +//! @{ + +///////////////////////////// Object Detection //////////////////////////// + +//! class for grouping object candidates, detected by Cascade Classifier, HOG etc. +//! instance of the class is to be passed to cv::partition (see cxoperations.hpp) +class CV_EXPORTS SimilarRects +{ +public: + SimilarRects(double _eps) : eps(_eps) {} + inline bool operator()(const Rect& r1, const Rect& r2) const + { + double delta = eps*(std::min(r1.width, r2.width) + std::min(r1.height, r2.height))*0.5; + return std::abs(r1.x - r2.x) <= delta && + std::abs(r1.y - r2.y) <= delta && + std::abs(r1.x + r1.width - r2.x - r2.width) <= delta && + std::abs(r1.y + r1.height - r2.y - r2.height) <= delta; + } + double eps; +}; + +/** @brief Groups the object candidate rectangles. + +@param rectList Input/output vector of rectangles. Output vector includes retained and grouped +rectangles. (The Python list is not modified in place.) +@param groupThreshold Minimum possible number of rectangles minus 1. The threshold is used in a +group of rectangles to retain it. +@param eps Relative difference between sides of the rectangles to merge them into a group. + +The function is a wrapper for the generic function partition . It clusters all the input rectangles +using the rectangle equivalence criteria that combines rectangles with similar sizes and similar +locations. The similarity is defined by eps. When eps=0 , no clustering is done at all. If +\f$\texttt{eps}\rightarrow +\inf\f$ , all the rectangles are put in one cluster. Then, the small +clusters containing less than or equal to groupThreshold rectangles are rejected. In each other +cluster, the average rectangle is computed and put into the output rectangle list. + */ +CV_EXPORTS void groupRectangles(std::vector& rectList, int groupThreshold, double eps = 0.2); +/** @overload */ +CV_EXPORTS_W void groupRectangles(CV_IN_OUT std::vector& rectList, CV_OUT std::vector& weights, + int groupThreshold, double eps = 0.2); +/** @overload */ +CV_EXPORTS void groupRectangles(std::vector& rectList, int groupThreshold, + double eps, std::vector* weights, std::vector* levelWeights ); +/** @overload */ +CV_EXPORTS void groupRectangles(std::vector& rectList, std::vector& rejectLevels, + std::vector& levelWeights, int groupThreshold, double eps = 0.2); +/** @overload */ +CV_EXPORTS void groupRectangles_meanshift(std::vector& rectList, std::vector& foundWeights, + std::vector& foundScales, + double detectThreshold = 0.0, Size winDetSize = Size(64, 128)); + +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvHaarClassifierCascade* obj) const; + +enum { CASCADE_DO_CANNY_PRUNING = 1, + CASCADE_SCALE_IMAGE = 2, + CASCADE_FIND_BIGGEST_OBJECT = 4, + CASCADE_DO_ROUGH_SEARCH = 8 + }; + +class CV_EXPORTS_W BaseCascadeClassifier : public Algorithm +{ +public: + virtual ~BaseCascadeClassifier(); + virtual bool empty() const = 0; + virtual bool load( const String& filename ) = 0; + virtual void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + double scaleFactor, + int minNeighbors, int flags, + Size minSize, Size maxSize ) = 0; + + virtual void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& numDetections, + double scaleFactor, + int minNeighbors, int flags, + Size minSize, Size maxSize ) = 0; + + virtual void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& rejectLevels, + CV_OUT std::vector& levelWeights, + double scaleFactor, + int minNeighbors, int flags, + Size minSize, Size maxSize, + bool outputRejectLevels ) = 0; + + virtual bool isOldFormatCascade() const = 0; + virtual Size getOriginalWindowSize() const = 0; + virtual int getFeatureType() const = 0; + virtual void* getOldCascade() = 0; + + class CV_EXPORTS MaskGenerator + { + public: + virtual ~MaskGenerator() {} + virtual Mat generateMask(const Mat& src)=0; + virtual void initializeMask(const Mat& /*src*/) { } + }; + virtual void setMaskGenerator(const Ptr& maskGenerator) = 0; + virtual Ptr getMaskGenerator() = 0; +}; + +/** @brief Cascade classifier class for object detection. + */ +class CV_EXPORTS_W CascadeClassifier +{ +public: + CV_WRAP CascadeClassifier(); + /** @brief Loads a classifier from a file. + + @param filename Name of the file from which the classifier is loaded. + */ + CV_WRAP CascadeClassifier(const String& filename); + ~CascadeClassifier(); + /** @brief Checks whether the classifier has been loaded. + */ + CV_WRAP bool empty() const; + /** @brief Loads a classifier from a file. + + @param filename Name of the file from which the classifier is loaded. The file may contain an old + HAAR classifier trained by the haartraining application or a new cascade classifier trained by the + traincascade application. + */ + CV_WRAP bool load( const String& filename ); + /** @brief Reads a classifier from a FileStorage node. + + @note The file may contain a new cascade classifier (trained traincascade application) only. + */ + CV_WRAP bool read( const FileNode& node ); + + /** @brief Detects objects of different sizes in the input image. The detected objects are returned as a list + of rectangles. + + @param image Matrix of the type CV_8U containing an image where objects are detected. + @param objects Vector of rectangles where each rectangle contains the detected object, the + rectangles may be partially outside the original image. + @param scaleFactor Parameter specifying how much the image size is reduced at each image scale. + @param minNeighbors Parameter specifying how many neighbors each candidate rectangle should have + to retain it. + @param flags Parameter with the same meaning for an old cascade as in the function + cvHaarDetectObjects. It is not used for a new cascade. + @param minSize Minimum possible object size. Objects smaller than that are ignored. + @param maxSize Maximum possible object size. Objects larger than that are ignored. + + The function is parallelized with the TBB library. + + @note + - (Python) A face detection example using cascade classifiers can be found at + opencv_source_code/samples/python2/facedetect.py + */ + CV_WRAP void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + double scaleFactor = 1.1, + int minNeighbors = 3, int flags = 0, + Size minSize = Size(), + Size maxSize = Size() ); + + /** @overload + @param image Matrix of the type CV_8U containing an image where objects are detected. + @param objects Vector of rectangles where each rectangle contains the detected object, the + rectangles may be partially outside the original image. + @param numDetections Vector of detection numbers for the corresponding objects. An object's number + of detections is the number of neighboring positively classified rectangles that were joined + together to form the object. + @param scaleFactor Parameter specifying how much the image size is reduced at each image scale. + @param minNeighbors Parameter specifying how many neighbors each candidate rectangle should have + to retain it. + @param flags Parameter with the same meaning for an old cascade as in the function + cvHaarDetectObjects. It is not used for a new cascade. + @param minSize Minimum possible object size. Objects smaller than that are ignored. + @param maxSize Maximum possible object size. Objects larger than that are ignored. + */ + CV_WRAP_AS(detectMultiScale2) void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& numDetections, + double scaleFactor=1.1, + int minNeighbors=3, int flags=0, + Size minSize=Size(), + Size maxSize=Size() ); + + /** @overload + if `outputRejectLevels` is `true` returns `rejectLevels` and `levelWeights` + */ + CV_WRAP_AS(detectMultiScale3) void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& rejectLevels, + CV_OUT std::vector& levelWeights, + double scaleFactor = 1.1, + int minNeighbors = 3, int flags = 0, + Size minSize = Size(), + Size maxSize = Size(), + bool outputRejectLevels = false ); + + CV_WRAP bool isOldFormatCascade() const; + CV_WRAP Size getOriginalWindowSize() const; + CV_WRAP int getFeatureType() const; + void* getOldCascade(); + + CV_WRAP static bool convert(const String& oldcascade, const String& newcascade); + + void setMaskGenerator(const Ptr& maskGenerator); + Ptr getMaskGenerator(); + + Ptr cc; +}; + +CV_EXPORTS Ptr createFaceDetectionMaskGenerator(); + +//////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector ////////////// + +//! struct for detection region of interest (ROI) +struct DetectionROI +{ + //! scale(size) of the bounding box + double scale; + //! set of requrested locations to be evaluated + std::vector locations; + //! vector that will contain confidence values for each location + std::vector confidences; +}; + +struct CV_EXPORTS_W HOGDescriptor +{ +public: + enum { L2Hys = 0 + }; + enum { DEFAULT_NLEVELS = 64 + }; + + CV_WRAP HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8), + cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1), + histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true), + free_coef(-1.f), nlevels(HOGDescriptor::DEFAULT_NLEVELS), signedGradient(false) + {} + + CV_WRAP HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, + Size _cellSize, int _nbins, int _derivAperture=1, double _winSigma=-1, + int _histogramNormType=HOGDescriptor::L2Hys, + double _L2HysThreshold=0.2, bool _gammaCorrection=false, + int _nlevels=HOGDescriptor::DEFAULT_NLEVELS, bool _signedGradient=false) + : winSize(_winSize), blockSize(_blockSize), blockStride(_blockStride), cellSize(_cellSize), + nbins(_nbins), derivAperture(_derivAperture), winSigma(_winSigma), + histogramNormType(_histogramNormType), L2HysThreshold(_L2HysThreshold), + gammaCorrection(_gammaCorrection), free_coef(-1.f), nlevels(_nlevels), signedGradient(_signedGradient) + {} + + CV_WRAP HOGDescriptor(const String& filename) + { + load(filename); + } + + HOGDescriptor(const HOGDescriptor& d) + { + d.copyTo(*this); + } + + virtual ~HOGDescriptor() {} + + CV_WRAP size_t getDescriptorSize() const; + CV_WRAP bool checkDetectorSize() const; + CV_WRAP double getWinSigma() const; + + CV_WRAP virtual void setSVMDetector(InputArray _svmdetector); + + virtual bool read(FileNode& fn); + virtual void write(FileStorage& fs, const String& objname) const; + + CV_WRAP virtual bool load(const String& filename, const String& objname = String()); + CV_WRAP virtual void save(const String& filename, const String& objname = String()) const; + virtual void copyTo(HOGDescriptor& c) const; + + CV_WRAP virtual void compute(InputArray img, + CV_OUT std::vector& descriptors, + Size winStride = Size(), Size padding = Size(), + const std::vector& locations = std::vector()) const; + + //! with found weights output + CV_WRAP virtual void detect(const Mat& img, CV_OUT std::vector& foundLocations, + CV_OUT std::vector& weights, + double hitThreshold = 0, Size winStride = Size(), + Size padding = Size(), + const std::vector& searchLocations = std::vector()) const; + //! without found weights output + virtual void detect(const Mat& img, CV_OUT std::vector& foundLocations, + double hitThreshold = 0, Size winStride = Size(), + Size padding = Size(), + const std::vector& searchLocations=std::vector()) const; + + //! with result weights output + CV_WRAP virtual void detectMultiScale(InputArray img, CV_OUT std::vector& foundLocations, + CV_OUT std::vector& foundWeights, double hitThreshold = 0, + Size winStride = Size(), Size padding = Size(), double scale = 1.05, + double finalThreshold = 2.0,bool useMeanshiftGrouping = false) const; + //! without found weights output + virtual void detectMultiScale(InputArray img, CV_OUT std::vector& foundLocations, + double hitThreshold = 0, Size winStride = Size(), + Size padding = Size(), double scale = 1.05, + double finalThreshold = 2.0, bool useMeanshiftGrouping = false) const; + + CV_WRAP virtual void computeGradient(const Mat& img, CV_OUT Mat& grad, CV_OUT Mat& angleOfs, + Size paddingTL = Size(), Size paddingBR = Size()) const; + + CV_WRAP static std::vector getDefaultPeopleDetector(); + CV_WRAP static std::vector getDaimlerPeopleDetector(); + + CV_PROP Size winSize; + CV_PROP Size blockSize; + CV_PROP Size blockStride; + CV_PROP Size cellSize; + CV_PROP int nbins; + CV_PROP int derivAperture; + CV_PROP double winSigma; + CV_PROP int histogramNormType; + CV_PROP double L2HysThreshold; + CV_PROP bool gammaCorrection; + CV_PROP std::vector svmDetector; + UMat oclSvmDetector; + float free_coef; + CV_PROP int nlevels; + CV_PROP bool signedGradient; + + + //! evaluate specified ROI and return confidence value for each location + virtual void detectROI(const cv::Mat& img, const std::vector &locations, + CV_OUT std::vector& foundLocations, CV_OUT std::vector& confidences, + double hitThreshold = 0, cv::Size winStride = Size(), + cv::Size padding = Size()) const; + + //! evaluate specified ROI and return confidence value for each location in multiple scales + virtual void detectMultiScaleROI(const cv::Mat& img, + CV_OUT std::vector& foundLocations, + std::vector& locations, + double hitThreshold = 0, + int groupThreshold = 0) const; + + //! read/parse Dalal's alt model file + void readALTModel(String modelfile); + void groupRectangles(std::vector& rectList, std::vector& weights, int groupThreshold, double eps) const; +}; + +//! @} objdetect + +} + +#include "opencv2/objdetect/detection_based_tracker.hpp" + +#ifndef DISABLE_OPENCV_24_COMPATIBILITY +#include "opencv2/objdetect/objdetect_c.h" +#endif + +#endif diff --git a/include/opencv2/objdetect/detection_based_tracker.hpp b/include/opencv2/objdetect/detection_based_tracker.hpp new file mode 100644 index 0000000..54117fd --- /dev/null +++ b/include/opencv2/objdetect/detection_based_tracker.hpp @@ -0,0 +1,224 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_OBJDETECT_DBT_HPP__ +#define __OPENCV_OBJDETECT_DBT_HPP__ + +#if defined(__linux__) || defined(LINUX) || defined(__APPLE__) || defined(__ANDROID__) || \ + (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1700) + +#include + +namespace cv +{ + +//! @addtogroup objdetect +//! @{ + +class CV_EXPORTS DetectionBasedTracker +{ + public: + struct Parameters + { + int maxTrackLifetime; + int minDetectionPeriod; //the minimal time between run of the big object detector (on the whole frame) in ms (1000 mean 1 sec), default=0 + + Parameters(); + }; + + class IDetector + { + public: + IDetector(): + minObjSize(96, 96), + maxObjSize(INT_MAX, INT_MAX), + minNeighbours(2), + scaleFactor(1.1f) + {} + + virtual void detect(const cv::Mat& image, std::vector& objects) = 0; + + void setMinObjectSize(const cv::Size& min) + { + minObjSize = min; + } + void setMaxObjectSize(const cv::Size& max) + { + maxObjSize = max; + } + cv::Size getMinObjectSize() const + { + return minObjSize; + } + cv::Size getMaxObjectSize() const + { + return maxObjSize; + } + float getScaleFactor() + { + return scaleFactor; + } + void setScaleFactor(float value) + { + scaleFactor = value; + } + int getMinNeighbours() + { + return minNeighbours; + } + void setMinNeighbours(int value) + { + minNeighbours = value; + } + virtual ~IDetector() {} + + protected: + cv::Size minObjSize; + cv::Size maxObjSize; + int minNeighbours; + float scaleFactor; + }; + + DetectionBasedTracker(cv::Ptr mainDetector, cv::Ptr trackingDetector, const Parameters& params); + virtual ~DetectionBasedTracker(); + + virtual bool run(); + virtual void stop(); + virtual void resetTracking(); + + virtual void process(const cv::Mat& imageGray); + + bool setParameters(const Parameters& params); + const Parameters& getParameters() const; + + + typedef std::pair Object; + virtual void getObjects(std::vector& result) const; + virtual void getObjects(std::vector& result) const; + + enum ObjectStatus + { + DETECTED_NOT_SHOWN_YET, + DETECTED, + DETECTED_TEMPORARY_LOST, + WRONG_OBJECT + }; + struct ExtObject + { + int id; + cv::Rect location; + ObjectStatus status; + ExtObject(int _id, cv::Rect _location, ObjectStatus _status) + :id(_id), location(_location), status(_status) + { + } + }; + virtual void getObjects(std::vector& result) const; + + + virtual int addObject(const cv::Rect& location); //returns id of the new object + + protected: + class SeparateDetectionWork; + cv::Ptr separateDetectionWork; + friend void* workcycleObjectDetectorFunction(void* p); + + struct InnerParameters + { + int numLastPositionsToTrack; + int numStepsToWaitBeforeFirstShow; + int numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown; + int numStepsToShowWithoutDetecting; + + float coeffTrackingWindowSize; + float coeffObjectSizeToTrack; + float coeffObjectSpeedUsingInPrediction; + + InnerParameters(); + }; + Parameters parameters; + InnerParameters innerParameters; + + struct TrackedObject + { + typedef std::vector PositionsVector; + + PositionsVector lastPositions; + + int numDetectedFrames; + int numFramesNotDetected; + int id; + + TrackedObject(const cv::Rect& rect):numDetectedFrames(1), numFramesNotDetected(0) + { + lastPositions.push_back(rect); + id=getNextId(); + }; + + static int getNextId() + { + static int _id=0; + return _id++; + } + }; + + int numTrackedSteps; + std::vector trackedObjects; + + std::vector weightsPositionsSmoothing; + std::vector weightsSizesSmoothing; + + cv::Ptr cascadeForTracking; + + void updateTrackedObjects(const std::vector& detectedObjects); + cv::Rect calcTrackedObjectPositionToShow(int i) const; + cv::Rect calcTrackedObjectPositionToShow(int i, ObjectStatus& status) const; + void detectInRegion(const cv::Mat& img, const cv::Rect& r, std::vector& detectedObjectsInRegions); +}; + +//! @} objdetect + +} //end of cv namespace +#endif + +#endif diff --git a/include/opencv2/objdetect/objdetect.hpp b/include/opencv2/objdetect/objdetect.hpp new file mode 100644 index 0000000..3ee284f --- /dev/null +++ b/include/opencv2/objdetect/objdetect.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/objdetect.hpp" diff --git a/include/opencv2/objdetect/objdetect_c.h b/include/opencv2/objdetect/objdetect_c.h new file mode 100644 index 0000000..632a438 --- /dev/null +++ b/include/opencv2/objdetect/objdetect_c.h @@ -0,0 +1,165 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_OBJDETECT_C_H__ +#define __OPENCV_OBJDETECT_C_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +#include +#include + +extern "C" { +#endif + +/** @addtogroup objdetect_c + @{ + */ + +/****************************************************************************************\ +* Haar-like Object Detection functions * +\****************************************************************************************/ + +#define CV_HAAR_MAGIC_VAL 0x42500000 +#define CV_TYPE_NAME_HAAR "opencv-haar-classifier" + +#define CV_IS_HAAR_CLASSIFIER( haar ) \ + ((haar) != NULL && \ + (((const CvHaarClassifierCascade*)(haar))->flags & CV_MAGIC_MASK)==CV_HAAR_MAGIC_VAL) + +#define CV_HAAR_FEATURE_MAX 3 + +typedef struct CvHaarFeature +{ + int tilted; + struct + { + CvRect r; + float weight; + } rect[CV_HAAR_FEATURE_MAX]; +} CvHaarFeature; + +typedef struct CvHaarClassifier +{ + int count; + CvHaarFeature* haar_feature; + float* threshold; + int* left; + int* right; + float* alpha; +} CvHaarClassifier; + +typedef struct CvHaarStageClassifier +{ + int count; + float threshold; + CvHaarClassifier* classifier; + + int next; + int child; + int parent; +} CvHaarStageClassifier; + +typedef struct CvHidHaarClassifierCascade CvHidHaarClassifierCascade; + +typedef struct CvHaarClassifierCascade +{ + int flags; + int count; + CvSize orig_window_size; + CvSize real_window_size; + double scale; + CvHaarStageClassifier* stage_classifier; + CvHidHaarClassifierCascade* hid_cascade; +} CvHaarClassifierCascade; + +typedef struct CvAvgComp +{ + CvRect rect; + int neighbors; +} CvAvgComp; + +/* Loads haar classifier cascade from a directory. + It is obsolete: convert your cascade to xml and use cvLoad instead */ +CVAPI(CvHaarClassifierCascade*) cvLoadHaarClassifierCascade( + const char* directory, CvSize orig_window_size); + +CVAPI(void) cvReleaseHaarClassifierCascade( CvHaarClassifierCascade** cascade ); + +#define CV_HAAR_DO_CANNY_PRUNING 1 +#define CV_HAAR_SCALE_IMAGE 2 +#define CV_HAAR_FIND_BIGGEST_OBJECT 4 +#define CV_HAAR_DO_ROUGH_SEARCH 8 + +CVAPI(CvSeq*) cvHaarDetectObjects( const CvArr* image, + CvHaarClassifierCascade* cascade, CvMemStorage* storage, + double scale_factor CV_DEFAULT(1.1), + int min_neighbors CV_DEFAULT(3), int flags CV_DEFAULT(0), + CvSize min_size CV_DEFAULT(cvSize(0,0)), CvSize max_size CV_DEFAULT(cvSize(0,0))); + +/* sets images for haar classifier cascade */ +CVAPI(void) cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* cascade, + const CvArr* sum, const CvArr* sqsum, + const CvArr* tilted_sum, double scale ); + +/* runs the cascade on the specified window */ +CVAPI(int) cvRunHaarClassifierCascade( const CvHaarClassifierCascade* cascade, + CvPoint pt, int start_stage CV_DEFAULT(0)); + +/** @} objdetect_c */ + +#ifdef __cplusplus +} + +CV_EXPORTS CvSeq* cvHaarDetectObjectsForROC( const CvArr* image, + CvHaarClassifierCascade* cascade, CvMemStorage* storage, + std::vector& rejectLevels, std::vector& levelWeightds, + double scale_factor = 1.1, + int min_neighbors = 3, int flags = 0, + CvSize min_size = cvSize(0, 0), CvSize max_size = cvSize(0, 0), + bool outputRejectLevels = false ); + +#endif + +#endif /* __OPENCV_OBJDETECT_C_H__ */ diff --git a/include/opencv2/opencv.hpp b/include/opencv2/opencv.hpp new file mode 100644 index 0000000..fd9ca58 --- /dev/null +++ b/include/opencv2/opencv.hpp @@ -0,0 +1,58 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_ALL_HPP__ +#define __OPENCV_ALL_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/video.hpp" +#include "opencv2/features2d.hpp" +#include "opencv2/objdetect.hpp" +#include "opencv2/calib3d.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/videoio.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/ml.hpp" + +#endif diff --git a/include/opencv2/opencv_modules.hpp b/include/opencv2/opencv_modules.hpp new file mode 100644 index 0000000..ebca30a --- /dev/null +++ b/include/opencv2/opencv_modules.hpp @@ -0,0 +1,27 @@ +/* + * ** File generated automatically, do not modify ** + * + * This file defines the list of modules available in current build configuration + * + * +*/ + +#define HAVE_OPENCV_CALIB3D +#define HAVE_OPENCV_CORE +#define HAVE_OPENCV_FEATURES2D +#define HAVE_OPENCV_FLANN +#define HAVE_OPENCV_HAL +#define HAVE_OPENCV_HIGHGUI +#define HAVE_OPENCV_IMGCODECS +#define HAVE_OPENCV_IMGPROC +#define HAVE_OPENCV_ML +#define HAVE_OPENCV_OBJDETECT +#define HAVE_OPENCV_PHOTO +#define HAVE_OPENCV_SHAPE +#define HAVE_OPENCV_STITCHING +#define HAVE_OPENCV_SUPERRES +#define HAVE_OPENCV_VIDEO +#define HAVE_OPENCV_VIDEOIO +#define HAVE_OPENCV_VIDEOSTAB + + diff --git a/include/opencv2/photo.hpp b/include/opencv2/photo.hpp new file mode 100644 index 0000000..3d96912 --- /dev/null +++ b/include/opencv2/photo.hpp @@ -0,0 +1,870 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_PHOTO_HPP__ +#define __OPENCV_PHOTO_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" + +/** +@defgroup photo Computational Photography +@{ + @defgroup photo_denoise Denoising + @defgroup photo_hdr HDR imaging + +This section describes high dynamic range imaging algorithms namely tonemapping, exposure alignment, +camera calibration with multiple exposures and exposure fusion. + + @defgroup photo_clone Seamless Cloning + @defgroup photo_render Non-Photorealistic Rendering + @defgroup photo_c C API +@} + */ + +namespace cv +{ + +//! @addtogroup photo +//! @{ + +//! the inpainting algorithm +enum +{ + INPAINT_NS = 0, // Navier-Stokes algorithm + INPAINT_TELEA = 1 // A. Telea algorithm +}; + +enum +{ + NORMAL_CLONE = 1, + MIXED_CLONE = 2, + MONOCHROME_TRANSFER = 3 +}; + +enum +{ + RECURS_FILTER = 1, + NORMCONV_FILTER = 2 +}; + +/** @brief Restores the selected region in an image using the region neighborhood. + +@param src Input 8-bit 1-channel or 3-channel image. +@param inpaintMask Inpainting mask, 8-bit 1-channel image. Non-zero pixels indicate the area that +needs to be inpainted. +@param dst Output image with the same size and type as src . +@param inpaintRadius Radius of a circular neighborhood of each point inpainted that is considered +by the algorithm. +@param flags Inpainting method that could be one of the following: +- **INPAINT_NS** Navier-Stokes based method [Navier01] +- **INPAINT_TELEA** Method by Alexandru Telea @cite Telea04 . + +The function reconstructs the selected image area from the pixel near the area boundary. The +function may be used to remove dust and scratches from a scanned photo, or to remove undesirable +objects from still images or video. See for more details. + +@note + - An example using the inpainting technique can be found at + opencv_source_code/samples/cpp/inpaint.cpp + - (Python) An example using the inpainting technique can be found at + opencv_source_code/samples/python2/inpaint.py + */ +CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, + OutputArray dst, double inpaintRadius, int flags ); + +//! @addtogroup photo_denoise +//! @{ + +/** @brief Perform image denoising using Non-local Means Denoising algorithm + with several computational +optimizations. Noise expected to be a gaussian white noise + +@param src Input 8-bit 1-channel, 2-channel, 3-channel or 4-channel image. +@param dst Output image with the same size and type as src . +@param templateWindowSize Size in pixels of the template patch that is used to compute weights. +Should be odd. Recommended value 7 pixels +@param searchWindowSize Size in pixels of the window that is used to compute weighted average for +given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater +denoising time. Recommended value 21 pixels +@param h Parameter regulating filter strength. Big h value perfectly removes noise but also +removes image details, smaller h value preserves details but also preserves some noise + +This function expected to be applied to grayscale images. For colored images look at +fastNlMeansDenoisingColored. Advanced usage of this functions can be manual denoising of colored +image in different colorspaces. Such approach is used in fastNlMeansDenoisingColored by converting +image to CIELAB colorspace and then separately denoise L and AB components with different h +parameter. + */ +CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, + int templateWindowSize = 7, int searchWindowSize = 21); + +/** @brief Perform image denoising using Non-local Means Denoising algorithm + with several computational +optimizations. Noise expected to be a gaussian white noise + +@param src Input 8-bit or 16-bit (only with NORM_L1) 1-channel, +2-channel, 3-channel or 4-channel image. +@param dst Output image with the same size and type as src . +@param templateWindowSize Size in pixels of the template patch that is used to compute weights. +Should be odd. Recommended value 7 pixels +@param searchWindowSize Size in pixels of the window that is used to compute weighted average for +given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater +denoising time. Recommended value 21 pixels +@param h Array of parameters regulating filter strength, either one +parameter applied to all channels or one per channel in dst. Big h value +perfectly removes noise but also removes image details, smaller h +value preserves details but also preserves some noise +@param normType Type of norm used for weight calculation. Can be either NORM_L2 or NORM_L1 + +This function expected to be applied to grayscale images. For colored images look at +fastNlMeansDenoisingColored. Advanced usage of this functions can be manual denoising of colored +image in different colorspaces. Such approach is used in fastNlMeansDenoisingColored by converting +image to CIELAB colorspace and then separately denoise L and AB components with different h +parameter. + */ +CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, + const std::vector& h, + int templateWindowSize = 7, int searchWindowSize = 21, + int normType = NORM_L2); + +/** @brief Modification of fastNlMeansDenoising function for colored images + +@param src Input 8-bit 3-channel image. +@param dst Output image with the same size and type as src . +@param templateWindowSize Size in pixels of the template patch that is used to compute weights. +Should be odd. Recommended value 7 pixels +@param searchWindowSize Size in pixels of the window that is used to compute weighted average for +given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater +denoising time. Recommended value 21 pixels +@param h Parameter regulating filter strength for luminance component. Bigger h value perfectly +removes noise but also removes image details, smaller h value preserves details but also preserves +some noise +@param hColor The same as h but for color components. For most images value equals 10 +will be enough to remove colored noise and do not distort colors + +The function converts image to CIELAB colorspace and then separately denoise L and AB components +with given h parameters using fastNlMeansDenoising function. + */ +CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); + +/** @brief Modification of fastNlMeansDenoising function for images sequence where consequtive images have been +captured in small period of time. For example video. This version of the function is for grayscale +images or for manual manipulation with colorspaces. For more details see + + +@param srcImgs Input 8-bit 1-channel, 2-channel, 3-channel or +4-channel images sequence. All images should have the same type and +size. +@param imgToDenoiseIndex Target image to denoise index in srcImgs sequence +@param temporalWindowSize Number of surrounding images to use for target image denoising. Should +be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to +imgToDenoiseIndex - temporalWindowSize / 2 from srcImgs will be used to denoise +srcImgs[imgToDenoiseIndex] image. +@param dst Output image with the same size and type as srcImgs images. +@param templateWindowSize Size in pixels of the template patch that is used to compute weights. +Should be odd. Recommended value 7 pixels +@param searchWindowSize Size in pixels of the window that is used to compute weighted average for +given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater +denoising time. Recommended value 21 pixels +@param h Parameter regulating filter strength. Bigger h value +perfectly removes noise but also removes image details, smaller h +value preserves details but also preserves some noise + */ +CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); + +/** @brief Modification of fastNlMeansDenoising function for images sequence where consequtive images have been +captured in small period of time. For example video. This version of the function is for grayscale +images or for manual manipulation with colorspaces. For more details see + + +@param srcImgs Input 8-bit or 16-bit (only with NORM_L1) 1-channel, +2-channel, 3-channel or 4-channel images sequence. All images should +have the same type and size. +@param imgToDenoiseIndex Target image to denoise index in srcImgs sequence +@param temporalWindowSize Number of surrounding images to use for target image denoising. Should +be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to +imgToDenoiseIndex - temporalWindowSize / 2 from srcImgs will be used to denoise +srcImgs[imgToDenoiseIndex] image. +@param dst Output image with the same size and type as srcImgs images. +@param templateWindowSize Size in pixels of the template patch that is used to compute weights. +Should be odd. Recommended value 7 pixels +@param searchWindowSize Size in pixels of the window that is used to compute weighted average for +given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater +denoising time. Recommended value 21 pixels +@param h Array of parameters regulating filter strength, either one +parameter applied to all channels or one per channel in dst. Big h value +perfectly removes noise but also removes image details, smaller h +value preserves details but also preserves some noise +@param normType Type of norm used for weight calculation. Can be either NORM_L2 or NORM_L1 + */ +CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + const std::vector& h, + int templateWindowSize = 7, int searchWindowSize = 21, + int normType = NORM_L2); + +/** @brief Modification of fastNlMeansDenoisingMulti function for colored images sequences + +@param srcImgs Input 8-bit 3-channel images sequence. All images should have the same type and +size. +@param imgToDenoiseIndex Target image to denoise index in srcImgs sequence +@param temporalWindowSize Number of surrounding images to use for target image denoising. Should +be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to +imgToDenoiseIndex - temporalWindowSize / 2 from srcImgs will be used to denoise +srcImgs[imgToDenoiseIndex] image. +@param dst Output image with the same size and type as srcImgs images. +@param templateWindowSize Size in pixels of the template patch that is used to compute weights. +Should be odd. Recommended value 7 pixels +@param searchWindowSize Size in pixels of the window that is used to compute weighted average for +given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater +denoising time. Recommended value 21 pixels +@param h Parameter regulating filter strength for luminance component. Bigger h value perfectly +removes noise but also removes image details, smaller h value preserves details but also preserves +some noise. +@param hColor The same as h but for color components. + +The function converts images to CIELAB colorspace and then separately denoise L and AB components +with given h parameters using fastNlMeansDenoisingMulti function. + */ +CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); + +/** @brief Primal-dual algorithm is an algorithm for solving special types of variational problems (that is, +finding a function to minimize some functional). As the image denoising, in particular, may be seen +as the variational problem, primal-dual algorithm then can be used to perform denoising and this is +exactly what is implemented. + +It should be noted, that this implementation was taken from the July 2013 blog entry +@cite MA13 , which also contained (slightly more general) ready-to-use source code on Python. +Subsequently, that code was rewritten on C++ with the usage of openCV by Vadim Pisarevsky at the end +of July 2013 and finally it was slightly adapted by later authors. + +Although the thorough discussion and justification of the algorithm involved may be found in +@cite ChambolleEtAl, it might make sense to skim over it here, following @cite MA13 . To begin +with, we consider the 1-byte gray-level images as the functions from the rectangular domain of +pixels (it may be seen as set +\f$\left\{(x,y)\in\mathbb{N}\times\mathbb{N}\mid 1\leq x\leq n,\;1\leq y\leq m\right\}\f$ for some +\f$m,\;n\in\mathbb{N}\f$) into \f$\{0,1,\dots,255\}\f$. We shall denote the noised images as \f$f_i\f$ and with +this view, given some image \f$x\f$ of the same size, we may measure how bad it is by the formula + +\f[\left\|\left\|\nabla x\right\|\right\| + \lambda\sum_i\left\|\left\|x-f_i\right\|\right\|\f] + +\f$\|\|\cdot\|\|\f$ here denotes \f$L_2\f$-norm and as you see, the first addend states that we want our +image to be smooth (ideally, having zero gradient, thus being constant) and the second states that +we want our result to be close to the observations we've got. If we treat \f$x\f$ as a function, this is +exactly the functional what we seek to minimize and here the Primal-Dual algorithm comes into play. + +@param observations This array should contain one or more noised versions of the image that is to +be restored. +@param result Here the denoised image will be stored. There is no need to do pre-allocation of +storage space, as it will be automatically allocated, if necessary. +@param lambda Corresponds to \f$\lambda\f$ in the formulas above. As it is enlarged, the smooth +(blurred) images are treated more favorably than detailed (but maybe more noised) ones. Roughly +speaking, as it becomes smaller, the result will be more blur but more sever outliers will be +removed. +@param niters Number of iterations that the algorithm will run. Of course, as more iterations as +better, but it is hard to quantitatively refine this statement, so just use the default and +increase it if the results are poor. + */ +CV_EXPORTS_W void denoise_TVL1(const std::vector& observations,Mat& result, double lambda=1.0, int niters=30); + +//! @} photo_denoise + +//! @addtogroup photo_hdr +//! @{ + +enum { LDR_SIZE = 256 }; + +/** @brief Base class for tonemapping algorithms - tools that are used to map HDR image to 8-bit range. + */ +class CV_EXPORTS_W Tonemap : public Algorithm +{ +public: + /** @brief Tonemaps image + + @param src source image - 32-bit 3-channel Mat + @param dst destination image - 32-bit 3-channel Mat with values in [0, 1] range + */ + CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; + + CV_WRAP virtual float getGamma() const = 0; + CV_WRAP virtual void setGamma(float gamma) = 0; +}; + +/** @brief Creates simple linear mapper with gamma correction + +@param gamma positive value for gamma correction. Gamma value of 1.0 implies no correction, gamma +equal to 2.2f is suitable for most displays. +Generally gamma \> 1 brightens the image and gamma \< 1 darkens it. + */ +CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); + +/** @brief Adaptive logarithmic mapping is a fast global tonemapping algorithm that scales the image in +logarithmic domain. + +Since it's a global operator the same function is applied to all the pixels, it is controlled by the +bias parameter. + +Optional saturation enhancement is possible as described in @cite FL02 . + +For more information see @cite DM03 . + */ +class CV_EXPORTS_W TonemapDrago : public Tonemap +{ +public: + + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; + + CV_WRAP virtual float getBias() const = 0; + CV_WRAP virtual void setBias(float bias) = 0; +}; + +/** @brief Creates TonemapDrago object + +@param gamma gamma value for gamma correction. See createTonemap +@param saturation positive saturation enhancement value. 1.0 preserves saturation, values greater +than 1 increase saturation and values less than 1 decrease it. +@param bias value for bias function in [0, 1] range. Values from 0.7 to 0.9 usually give best +results, default value is 0.85. + */ +CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); + +/** @brief This algorithm decomposes image into two layers: base layer and detail layer using bilateral filter +and compresses contrast of the base layer thus preserving all the details. + +This implementation uses regular bilateral filter from opencv. + +Saturation enhancement is possible as in ocvTonemapDrago. + +For more information see @cite DD02 . + */ +class CV_EXPORTS_W TonemapDurand : public Tonemap +{ +public: + + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; + + CV_WRAP virtual float getContrast() const = 0; + CV_WRAP virtual void setContrast(float contrast) = 0; + + CV_WRAP virtual float getSigmaSpace() const = 0; + CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; + + CV_WRAP virtual float getSigmaColor() const = 0; + CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; +}; + +/** @brief Creates TonemapDurand object + +@param gamma gamma value for gamma correction. See createTonemap +@param contrast resulting contrast on logarithmic scale, i. e. log(max / min), where max and min +are maximum and minimum luminance values of the resulting image. +@param saturation saturation enhancement value. See createTonemapDrago +@param sigma_space bilateral filter sigma in color space +@param sigma_color bilateral filter sigma in coordinate space + */ +CV_EXPORTS_W Ptr +createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); + +/** @brief This is a global tonemapping operator that models human visual system. + +Mapping function is controlled by adaptation parameter, that is computed using light adaptation and +color adaptation. + +For more information see @cite RD05 . + */ +class CV_EXPORTS_W TonemapReinhard : public Tonemap +{ +public: + CV_WRAP virtual float getIntensity() const = 0; + CV_WRAP virtual void setIntensity(float intensity) = 0; + + CV_WRAP virtual float getLightAdaptation() const = 0; + CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; + + CV_WRAP virtual float getColorAdaptation() const = 0; + CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; +}; + +/** @brief Creates TonemapReinhard object + +@param gamma gamma value for gamma correction. See createTonemap +@param intensity result intensity in [-8, 8] range. Greater intensity produces brighter results. +@param light_adapt light adaptation in [0, 1] range. If 1 adaptation is based only on pixel +value, if 0 it's global, otherwise it's a weighted mean of this two cases. +@param color_adapt chromatic adaptation in [0, 1] range. If 1 channels are treated independently, +if 0 adaptation level is the same for each channel. + */ +CV_EXPORTS_W Ptr +createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); + +/** @brief This algorithm transforms image to contrast using gradients on all levels of gaussian pyramid, +transforms contrast values to HVS response and scales the response. After this the image is +reconstructed from new contrast values. + +For more information see @cite MM06 . + */ +class CV_EXPORTS_W TonemapMantiuk : public Tonemap +{ +public: + CV_WRAP virtual float getScale() const = 0; + CV_WRAP virtual void setScale(float scale) = 0; + + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; +}; + +/** @brief Creates TonemapMantiuk object + +@param gamma gamma value for gamma correction. See createTonemap +@param scale contrast scale factor. HVS response is multiplied by this parameter, thus compressing +dynamic range. Values from 0.6 to 0.9 produce best results. +@param saturation saturation enhancement value. See createTonemapDrago + */ +CV_EXPORTS_W Ptr +createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); + +/** @brief The base class for algorithms that align images of the same scene with different exposures + */ +class CV_EXPORTS_W AlignExposures : public Algorithm +{ +public: + /** @brief Aligns images + + @param src vector of input images + @param dst vector of aligned images + @param times vector of exposure time values for each image + @param response 256x1 matrix with inverse camera response function for each pixel value, it should + have the same number of channels as images. + */ + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; +}; + +/** @brief This algorithm converts images to median threshold bitmaps (1 for pixels brighter than median +luminance and 0 otherwise) and than aligns the resulting bitmaps using bit operations. + +It is invariant to exposure, so exposure values and camera response are not necessary. + +In this implementation new image regions are filled with zeros. + +For more information see @cite GW03 . + */ +class CV_EXPORTS_W AlignMTB : public AlignExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; + + /** @brief Short version of process, that doesn't take extra arguments. + + @param src vector of input images + @param dst vector of aligned images + */ + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; + + /** @brief Calculates shift between two images, i. e. how to shift the second image to correspond it with the + first. + + @param img0 first image + @param img1 second image + */ + CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; + /** @brief Helper function, that shift Mat filling new regions with zeros. + + @param src input image + @param dst result image + @param shift shift value + */ + CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; + /** @brief Computes median threshold and exclude bitmaps of given image. + + @param img input image + @param tb median threshold bitmap + @param eb exclude bitmap + */ + CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; + + CV_WRAP virtual int getMaxBits() const = 0; + CV_WRAP virtual void setMaxBits(int max_bits) = 0; + + CV_WRAP virtual int getExcludeRange() const = 0; + CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; + + CV_WRAP virtual bool getCut() const = 0; + CV_WRAP virtual void setCut(bool value) = 0; +}; + +/** @brief Creates AlignMTB object + +@param max_bits logarithm to the base 2 of maximal shift in each dimension. Values of 5 and 6 are +usually good enough (31 and 63 pixels shift respectively). +@param exclude_range range for exclusion bitmap that is constructed to suppress noise around the +median value. +@param cut if true cuts images, otherwise fills the new regions with zeros. + */ +CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); + +/** @brief The base class for camera response calibration algorithms. + */ +class CV_EXPORTS_W CalibrateCRF : public Algorithm +{ +public: + /** @brief Recovers inverse camera response. + + @param src vector of input images + @param dst 256x1 matrix with inverse camera response function + @param times vector of exposure time values for each image + */ + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; + +/** @brief Inverse camera response function is extracted for each brightness value by minimizing an objective +function as linear system. Objective function is constructed using pixel values on the same position +in all images, extra term is added to make the result smoother. + +For more information see @cite DM97 . + */ +class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF +{ +public: + CV_WRAP virtual float getLambda() const = 0; + CV_WRAP virtual void setLambda(float lambda) = 0; + + CV_WRAP virtual int getSamples() const = 0; + CV_WRAP virtual void setSamples(int samples) = 0; + + CV_WRAP virtual bool getRandom() const = 0; + CV_WRAP virtual void setRandom(bool random) = 0; +}; + +/** @brief Creates CalibrateDebevec object + +@param samples number of pixel locations to use +@param lambda smoothness term weight. Greater values produce smoother results, but can alter the +response. +@param random if true sample pixel locations are chosen at random, otherwise the form a +rectangular grid. + */ +CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); + +/** @brief Inverse camera response function is extracted for each brightness value by minimizing an objective +function as linear system. This algorithm uses all image pixels. + +For more information see @cite RB99 . + */ +class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF +{ +public: + CV_WRAP virtual int getMaxIter() const = 0; + CV_WRAP virtual void setMaxIter(int max_iter) = 0; + + CV_WRAP virtual float getThreshold() const = 0; + CV_WRAP virtual void setThreshold(float threshold) = 0; + + CV_WRAP virtual Mat getRadiance() const = 0; +}; + +/** @brief Creates CalibrateRobertson object + +@param max_iter maximal number of Gauss-Seidel solver iterations. +@param threshold target difference between results of two successive steps of the minimization. + */ +CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); + +/** @brief The base class algorithms that can merge exposure sequence to a single image. + */ +class CV_EXPORTS_W MergeExposures : public Algorithm +{ +public: + /** @brief Merges images. + + @param src vector of input images + @param dst result image + @param times vector of exposure time values for each image + @param response 256x1 matrix with inverse camera response function for each pixel value, it should + have the same number of channels as images. + */ + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; +}; + +/** @brief The resulting HDR image is calculated as weighted average of the exposures considering exposure +values and camera response. + +For more information see @cite DM97 . + */ +class CV_EXPORTS_W MergeDebevec : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; + +/** @brief Creates MergeDebevec object + */ +CV_EXPORTS_W Ptr createMergeDebevec(); + +/** @brief Pixels are weighted using contrast, saturation and well-exposedness measures, than images are +combined using laplacian pyramids. + +The resulting image weight is constructed as weighted average of contrast, saturation and +well-exposedness measures. + +The resulting image doesn't require tonemapping and can be converted to 8-bit image by multiplying +by 255, but it's recommended to apply gamma correction and/or linear tonemapping. + +For more information see @cite MK07 . + */ +class CV_EXPORTS_W MergeMertens : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + /** @brief Short version of process, that doesn't take extra arguments. + + @param src vector of input images + @param dst result image + */ + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; + + CV_WRAP virtual float getContrastWeight() const = 0; + CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; + + CV_WRAP virtual float getSaturationWeight() const = 0; + CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; + + CV_WRAP virtual float getExposureWeight() const = 0; + CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; +}; + +/** @brief Creates MergeMertens object + +@param contrast_weight contrast measure weight. See MergeMertens. +@param saturation_weight saturation measure weight +@param exposure_weight well-exposedness measure weight + */ +CV_EXPORTS_W Ptr +createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); + +/** @brief The resulting HDR image is calculated as weighted average of the exposures considering exposure +values and camera response. + +For more information see @cite RB99 . + */ +class CV_EXPORTS_W MergeRobertson : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; + +/** @brief Creates MergeRobertson object + */ +CV_EXPORTS_W Ptr createMergeRobertson(); + +//! @} photo_hdr + +/** @brief Transforms a color image to a grayscale image. It is a basic tool in digital printing, stylized +black-and-white photograph rendering, and in many single channel image processing applications +@cite CL12 . + +@param src Input 8-bit 3-channel image. +@param grayscale Output 8-bit 1-channel image. +@param color_boost Output 8-bit 3-channel image. + +This function is to be applied on color images. + */ +CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); + +//! @addtogroup photo_clone +//! @{ + +/** @brief Image editing tasks concern either global changes (color/intensity corrections, filters, +deformations) or local changes concerned to a selection. Here we are interested in achieving local +changes, ones that are restricted to a region manually selected (ROI), in a seamless and effortless +manner. The extent of the changes ranges from slight distortions to complete replacement by novel +content @cite PM03 . + +@param src Input 8-bit 3-channel image. +@param dst Input 8-bit 3-channel image. +@param mask Input 8-bit 1 or 3-channel image. +@param p Point in dst image where object is placed. +@param blend Output image with the same size and type as dst. +@param flags Cloning method that could be one of the following: +- **NORMAL_CLONE** The power of the method is fully expressed when inserting objects with +complex outlines into a new background +- **MIXED_CLONE** The classic method, color-based selection and alpha masking might be time +consuming and often leaves an undesirable halo. Seamless cloning, even averaged with the +original image, is not effective. Mixed seamless cloning based on a loose selection proves +effective. +- **FEATURE_EXCHANGE** Feature exchange allows the user to easily replace certain features of +one object by alternative features. + */ +CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, + OutputArray blend, int flags); + +/** @brief Given an original color image, two differently colored versions of this image can be mixed +seamlessly. + +@param src Input 8-bit 3-channel image. +@param mask Input 8-bit 1 or 3-channel image. +@param dst Output image with the same size and type as src . +@param red_mul R-channel multiply factor. +@param green_mul G-channel multiply factor. +@param blue_mul B-channel multiply factor. + +Multiplication factor is between .5 to 2.5. + */ +CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0f, + float green_mul = 1.0f, float blue_mul = 1.0f); + +/** @brief Applying an appropriate non-linear transformation to the gradient field inside the selection and +then integrating back with a Poisson solver, modifies locally the apparent illumination of an image. + +@param src Input 8-bit 3-channel image. +@param mask Input 8-bit 1 or 3-channel image. +@param dst Output image with the same size and type as src. +@param alpha Value ranges between 0-2. +@param beta Value ranges between 0-2. + +This is useful to highlight under-exposed foreground objects or to reduce specular reflections. + */ +CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, + float alpha = 0.2f, float beta = 0.4f); + +/** @brief By retaining only the gradients at edge locations, before integrating with the Poisson solver, one +washes out the texture of the selected region, giving its contents a flat aspect. Here Canny Edge +Detector is used. + +@param src Input 8-bit 3-channel image. +@param mask Input 8-bit 1 or 3-channel image. +@param dst Output image with the same size and type as src. +@param low_threshold Range from 0 to 100. +@param high_threshold Value \> 100. +@param kernel_size The size of the Sobel kernel to be used. + +**NOTE:** + +The algorithm assumes that the color of the source image is close to that of the destination. This +assumption means that when the colors don't match, the source image color gets tinted toward the +color of the destination image. + */ +CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, + float low_threshold = 30, float high_threshold = 45, + int kernel_size = 3); + +//! @} photo_clone + +//! @addtogroup photo_render +//! @{ + +/** @brief Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing +filters are used in many different applications @cite EM11 . + +@param src Input 8-bit 3-channel image. +@param dst Output 8-bit 3-channel image. +@param flags Edge preserving filters: +- **RECURS_FILTER** = 1 +- **NORMCONV_FILTER** = 2 +@param sigma_s Range between 0 to 200. +@param sigma_r Range between 0 to 1. + */ +CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, + float sigma_s = 60, float sigma_r = 0.4f); + +/** @brief This filter enhances the details of a particular image. + +@param src Input 8-bit 3-channel image. +@param dst Output image with the same size and type as src. +@param sigma_s Range between 0 to 200. +@param sigma_r Range between 0 to 1. + */ +CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, + float sigma_r = 0.15f); + +/** @brief Pencil-like non-photorealistic line drawing + +@param src Input 8-bit 3-channel image. +@param dst1 Output 8-bit 1-channel image. +@param dst2 Output image with the same size and type as src. +@param sigma_s Range between 0 to 200. +@param sigma_r Range between 0 to 1. +@param shade_factor Range between 0 to 0.1. + */ +CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, + float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f); + +/** @brief Stylization aims to produce digital imagery with a wide variety of effects not focused on +photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low +contrast while preserving, or enhancing, high-contrast features. + +@param src Input 8-bit 3-channel image. +@param dst Output image with the same size and type as src. +@param sigma_s Range between 0 to 200. +@param sigma_r Range between 0 to 1. + */ +CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45f); + +//! @} photo_render + +//! @} photo + +} // cv + +#ifndef DISABLE_OPENCV_24_COMPATIBILITY +#include "opencv2/photo/photo_c.h" +#endif + +#endif diff --git a/include/opencv2/photo/cuda.hpp b/include/opencv2/photo/cuda.hpp new file mode 100644 index 0000000..aeac1fa --- /dev/null +++ b/include/opencv2/photo/cuda.hpp @@ -0,0 +1,132 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_PHOTO_CUDA_HPP__ +#define __OPENCV_PHOTO_CUDA_HPP__ + +#include "opencv2/core/cuda.hpp" + +namespace cv { namespace cuda { + +//! @addtogroup photo_denoise +//! @{ + +/** @brief Performs pure non local means denoising without any simplification, and thus it is not fast. + +@param src Source image. Supports only CV_8UC1, CV_8UC2 and CV_8UC3. +@param dst Destination image. +@param h Filter sigma regulating filter strength for color. +@param search_window Size of search window. +@param block_size Size of block used for computing weights. +@param borderMode Border type. See borderInterpolate for details. BORDER_REFLECT101 , +BORDER_REPLICATE , BORDER_CONSTANT , BORDER_REFLECT and BORDER_WRAP are supported for now. +@param stream Stream for the asynchronous version. + +@sa + fastNlMeansDenoising + */ +CV_EXPORTS void nonLocalMeans(InputArray src, OutputArray dst, + float h, + int search_window = 21, + int block_size = 7, + int borderMode = BORDER_DEFAULT, + Stream& stream = Stream::Null()); + +/** @brief Perform image denoising using Non-local Means Denoising algorithm + with several computational +optimizations. Noise expected to be a gaussian white noise + +@param src Input 8-bit 1-channel, 2-channel or 3-channel image. +@param dst Output image with the same size and type as src . +@param h Parameter regulating filter strength. Big h value perfectly removes noise but also +removes image details, smaller h value preserves details but also preserves some noise +@param search_window Size in pixels of the window that is used to compute weighted average for +given pixel. Should be odd. Affect performance linearly: greater search_window - greater +denoising time. Recommended value 21 pixels +@param block_size Size in pixels of the template patch that is used to compute weights. Should be +odd. Recommended value 7 pixels +@param stream Stream for the asynchronous invocations. + +This function expected to be applied to grayscale images. For colored images look at +FastNonLocalMeansDenoising::labMethod. + +@sa + fastNlMeansDenoising + */ +CV_EXPORTS void fastNlMeansDenoising(InputArray src, OutputArray dst, + float h, + int search_window = 21, + int block_size = 7, + Stream& stream = Stream::Null()); + +/** @brief Modification of fastNlMeansDenoising function for colored images + +@param src Input 8-bit 3-channel image. +@param dst Output image with the same size and type as src . +@param h_luminance Parameter regulating filter strength. Big h value perfectly removes noise but +also removes image details, smaller h value preserves details but also preserves some noise +@param photo_render float The same as h but for color components. For most images value equals 10 will be +enough to remove colored noise and do not distort colors +@param search_window Size in pixels of the window that is used to compute weighted average for +given pixel. Should be odd. Affect performance linearly: greater search_window - greater +denoising time. Recommended value 21 pixels +@param block_size Size in pixels of the template patch that is used to compute weights. Should be +odd. Recommended value 7 pixels +@param stream Stream for the asynchronous invocations. + +The function converts image to CIELAB colorspace and then separately denoise L and AB components +with given h parameters using FastNonLocalMeansDenoising::simpleMethod function. + +@sa + fastNlMeansDenoisingColored + */ +CV_EXPORTS void fastNlMeansDenoisingColored(InputArray src, OutputArray dst, + float h_luminance, float photo_render, + int search_window = 21, + int block_size = 7, + Stream& stream = Stream::Null()); + +//! @} photo + +}} // namespace cv { namespace cuda { + +#endif /* __OPENCV_PHOTO_CUDA_HPP__ */ diff --git a/include/opencv2/photo/photo.hpp b/include/opencv2/photo/photo.hpp new file mode 100644 index 0000000..8af5e9f --- /dev/null +++ b/include/opencv2/photo/photo.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/photo.hpp" diff --git a/include/opencv2/photo/photo_c.h b/include/opencv2/photo/photo_c.h new file mode 100644 index 0000000..07ca9b3 --- /dev/null +++ b/include/opencv2/photo/photo_c.h @@ -0,0 +1,74 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_PHOTO_C_H__ +#define __OPENCV_PHOTO_C_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup photo_c + @{ + */ + +/* Inpainting algorithms */ +enum InpaintingModes +{ + CV_INPAINT_NS =0, + CV_INPAINT_TELEA =1 +}; + + +/* Inpaints the selected region in the image */ +CVAPI(void) cvInpaint( const CvArr* src, const CvArr* inpaint_mask, + CvArr* dst, double inpaintRange, int flags ); + +/** @} */ + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //__OPENCV_PHOTO_C_H__ diff --git a/include/opencv2/shape.hpp b/include/opencv2/shape.hpp new file mode 100644 index 0000000..6999476 --- /dev/null +++ b/include/opencv2/shape.hpp @@ -0,0 +1,57 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2012, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_SHAPE_HPP__ +#define __OPENCV_SHAPE_HPP__ + +#include "opencv2/shape/emdL1.hpp" +#include "opencv2/shape/shape_transformer.hpp" +#include "opencv2/shape/hist_cost.hpp" +#include "opencv2/shape/shape_distance.hpp" + +/** + @defgroup shape Shape Distance and Matching + */ + +#endif + +/* End of file. */ diff --git a/include/opencv2/shape/emdL1.hpp b/include/opencv2/shape/emdL1.hpp new file mode 100644 index 0000000..1dfa758 --- /dev/null +++ b/include/opencv2/shape/emdL1.hpp @@ -0,0 +1,72 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2012, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_EMD_L1_HPP__ +#define __OPENCV_EMD_L1_HPP__ + +#include "opencv2/core.hpp" + +namespace cv +{ +/****************************************************************************************\ +* EMDL1 Function * +\****************************************************************************************/ + +//! @addtogroup shape +//! @{ + +/** @brief Computes the "minimal work" distance between two weighted point configurations base on the papers +"EMD-L1: An efficient and Robust Algorithm for comparing histogram-based descriptors", by Haibin +Ling and Kazunori Okuda; and "The Earth Mover's Distance is the Mallows Distance: Some Insights from +Statistics", by Elizaveta Levina and Peter Bickel. + +@param signature1 First signature, a single column floating-point matrix. Each row is the value of +the histogram in each bin. +@param signature2 Second signature of the same format and size as signature1. + */ +CV_EXPORTS float EMDL1(InputArray signature1, InputArray signature2); + +//! @} + +}//namespace cv + +#endif diff --git a/include/opencv2/shape/hist_cost.hpp b/include/opencv2/shape/hist_cost.hpp new file mode 100644 index 0000000..15c0a87 --- /dev/null +++ b/include/opencv2/shape/hist_cost.hpp @@ -0,0 +1,111 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HIST_COST_HPP__ +#define __OPENCV_HIST_COST_HPP__ + +#include "opencv2/imgproc.hpp" + +namespace cv +{ + +//! @addtogroup shape +//! @{ + +/** @brief Abstract base class for histogram cost algorithms. + */ +class CV_EXPORTS_W HistogramCostExtractor : public Algorithm +{ +public: + CV_WRAP virtual void buildCostMatrix(InputArray descriptors1, InputArray descriptors2, OutputArray costMatrix) = 0; + + CV_WRAP virtual void setNDummies(int nDummies) = 0; + CV_WRAP virtual int getNDummies() const = 0; + + CV_WRAP virtual void setDefaultCost(float defaultCost) = 0; + CV_WRAP virtual float getDefaultCost() const = 0; +}; + +/** @brief A norm based cost extraction. : + */ +class CV_EXPORTS_W NormHistogramCostExtractor : public HistogramCostExtractor +{ +public: + CV_WRAP virtual void setNormFlag(int flag) = 0; + CV_WRAP virtual int getNormFlag() const = 0; +}; + +CV_EXPORTS_W Ptr + createNormHistogramCostExtractor(int flag=DIST_L2, int nDummies=25, float defaultCost=0.2f); + +/** @brief An EMD based cost extraction. : + */ +class CV_EXPORTS_W EMDHistogramCostExtractor : public HistogramCostExtractor +{ +public: + CV_WRAP virtual void setNormFlag(int flag) = 0; + CV_WRAP virtual int getNormFlag() const = 0; +}; + +CV_EXPORTS_W Ptr + createEMDHistogramCostExtractor(int flag=DIST_L2, int nDummies=25, float defaultCost=0.2f); + +/** @brief An Chi based cost extraction. : + */ +class CV_EXPORTS_W ChiHistogramCostExtractor : public HistogramCostExtractor +{}; + +CV_EXPORTS_W Ptr createChiHistogramCostExtractor(int nDummies=25, float defaultCost=0.2f); + +/** @brief An EMD-L1 based cost extraction. : + */ +class CV_EXPORTS_W EMDL1HistogramCostExtractor : public HistogramCostExtractor +{}; + +CV_EXPORTS_W Ptr + createEMDL1HistogramCostExtractor(int nDummies=25, float defaultCost=0.2f); + +//! @} + +} // cv +#endif diff --git a/include/opencv2/shape/shape.hpp b/include/opencv2/shape/shape.hpp new file mode 100644 index 0000000..5c4da3c --- /dev/null +++ b/include/opencv2/shape/shape.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/shape.hpp" diff --git a/include/opencv2/shape/shape_distance.hpp b/include/opencv2/shape/shape_distance.hpp new file mode 100644 index 0000000..4b0c3b5 --- /dev/null +++ b/include/opencv2/shape/shape_distance.hpp @@ -0,0 +1,224 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_SHAPE_SHAPE_DISTANCE_HPP__ +#define __OPENCV_SHAPE_SHAPE_DISTANCE_HPP__ +#include "opencv2/core.hpp" +#include "opencv2/shape/hist_cost.hpp" +#include "opencv2/shape/shape_transformer.hpp" + +namespace cv +{ + +//! @addtogroup shape +//! @{ + +/** @brief Abstract base class for shape distance algorithms. + */ +class CV_EXPORTS_W ShapeDistanceExtractor : public Algorithm +{ +public: + /** @brief Compute the shape distance between two shapes defined by its contours. + + @param contour1 Contour defining first shape. + @param contour2 Contour defining second shape. + */ + CV_WRAP virtual float computeDistance(InputArray contour1, InputArray contour2) = 0; +}; + +/***********************************************************************************/ +/***********************************************************************************/ +/***********************************************************************************/ +/** @brief Implementation of the Shape Context descriptor and matching algorithm + +proposed by Belongie et al. in "Shape Matching and Object Recognition Using Shape Contexts" (PAMI +2002). This implementation is packaged in a generic scheme, in order to allow you the +implementation of the common variations of the original pipeline. +*/ +class CV_EXPORTS_W ShapeContextDistanceExtractor : public ShapeDistanceExtractor +{ +public: + /** @brief Establish the number of angular bins for the Shape Context Descriptor used in the shape matching + pipeline. + + @param nAngularBins The number of angular bins in the shape context descriptor. + */ + CV_WRAP virtual void setAngularBins(int nAngularBins) = 0; + CV_WRAP virtual int getAngularBins() const = 0; + + /** @brief Establish the number of radial bins for the Shape Context Descriptor used in the shape matching + pipeline. + + @param nRadialBins The number of radial bins in the shape context descriptor. + */ + CV_WRAP virtual void setRadialBins(int nRadialBins) = 0; + CV_WRAP virtual int getRadialBins() const = 0; + + /** @brief Set the inner radius of the shape context descriptor. + + @param innerRadius The value of the inner radius. + */ + CV_WRAP virtual void setInnerRadius(float innerRadius) = 0; + CV_WRAP virtual float getInnerRadius() const = 0; + + /** @brief Set the outer radius of the shape context descriptor. + + @param outerRadius The value of the outer radius. + */ + CV_WRAP virtual void setOuterRadius(float outerRadius) = 0; + CV_WRAP virtual float getOuterRadius() const = 0; + + CV_WRAP virtual void setRotationInvariant(bool rotationInvariant) = 0; + CV_WRAP virtual bool getRotationInvariant() const = 0; + + /** @brief Set the weight of the shape context distance in the final value of the shape distance. The shape + context distance between two shapes is defined as the symmetric sum of shape context matching costs + over best matching points. The final value of the shape distance is a user-defined linear + combination of the shape context distance, an image appearance distance, and a bending energy. + + @param shapeContextWeight The weight of the shape context distance in the final distance value. + */ + CV_WRAP virtual void setShapeContextWeight(float shapeContextWeight) = 0; + CV_WRAP virtual float getShapeContextWeight() const = 0; + + /** @brief Set the weight of the Image Appearance cost in the final value of the shape distance. The image + appearance cost is defined as the sum of squared brightness differences in Gaussian windows around + corresponding image points. The final value of the shape distance is a user-defined linear + combination of the shape context distance, an image appearance distance, and a bending energy. If + this value is set to a number different from 0, is mandatory to set the images that correspond to + each shape. + + @param imageAppearanceWeight The weight of the appearance cost in the final distance value. + */ + CV_WRAP virtual void setImageAppearanceWeight(float imageAppearanceWeight) = 0; + CV_WRAP virtual float getImageAppearanceWeight() const = 0; + + /** @brief Set the weight of the Bending Energy in the final value of the shape distance. The bending energy + definition depends on what transformation is being used to align the shapes. The final value of the + shape distance is a user-defined linear combination of the shape context distance, an image + appearance distance, and a bending energy. + + @param bendingEnergyWeight The weight of the Bending Energy in the final distance value. + */ + CV_WRAP virtual void setBendingEnergyWeight(float bendingEnergyWeight) = 0; + CV_WRAP virtual float getBendingEnergyWeight() const = 0; + + /** @brief Set the images that correspond to each shape. This images are used in the calculation of the Image + Appearance cost. + + @param image1 Image corresponding to the shape defined by contours1. + @param image2 Image corresponding to the shape defined by contours2. + */ + CV_WRAP virtual void setImages(InputArray image1, InputArray image2) = 0; + CV_WRAP virtual void getImages(OutputArray image1, OutputArray image2) const = 0; + + CV_WRAP virtual void setIterations(int iterations) = 0; + CV_WRAP virtual int getIterations() const = 0; + + /** @brief Set the algorithm used for building the shape context descriptor cost matrix. + + @param comparer Smart pointer to a HistogramCostExtractor, an algorithm that defines the cost + matrix between descriptors. + */ + CV_WRAP virtual void setCostExtractor(Ptr comparer) = 0; + CV_WRAP virtual Ptr getCostExtractor() const = 0; + + /** @brief Set the value of the standard deviation for the Gaussian window for the image appearance cost. + + @param sigma Standard Deviation. + */ + CV_WRAP virtual void setStdDev(float sigma) = 0; + CV_WRAP virtual float getStdDev() const = 0; + + /** @brief Set the algorithm used for aligning the shapes. + + @param transformer Smart pointer to a ShapeTransformer, an algorithm that defines the aligning + transformation. + */ + CV_WRAP virtual void setTransformAlgorithm(Ptr transformer) = 0; + CV_WRAP virtual Ptr getTransformAlgorithm() const = 0; +}; + +/* Complete constructor */ +CV_EXPORTS_W Ptr + createShapeContextDistanceExtractor(int nAngularBins=12, int nRadialBins=4, + float innerRadius=0.2f, float outerRadius=2, int iterations=3, + const Ptr &comparer = createChiHistogramCostExtractor(), + const Ptr &transformer = createThinPlateSplineShapeTransformer()); + +/***********************************************************************************/ +/***********************************************************************************/ +/***********************************************************************************/ +/** @brief A simple Hausdorff distance measure between shapes defined by contours + +according to the paper "Comparing Images using the Hausdorff distance." by D.P. Huttenlocher, G.A. +Klanderman, and W.J. Rucklidge. (PAMI 1993). : + */ +class CV_EXPORTS_W HausdorffDistanceExtractor : public ShapeDistanceExtractor +{ +public: + /** @brief Set the norm used to compute the Hausdorff value between two shapes. It can be L1 or L2 norm. + + @param distanceFlag Flag indicating which norm is used to compute the Hausdorff distance + (NORM_L1, NORM_L2). + */ + CV_WRAP virtual void setDistanceFlag(int distanceFlag) = 0; + CV_WRAP virtual int getDistanceFlag() const = 0; + + /** @brief This method sets the rank proportion (or fractional value) that establish the Kth ranked value of + the partial Hausdorff distance. Experimentally had been shown that 0.6 is a good value to compare + shapes. + + @param rankProportion fractional value (between 0 and 1). + */ + CV_WRAP virtual void setRankProportion(float rankProportion) = 0; + CV_WRAP virtual float getRankProportion() const = 0; +}; + +/* Constructor */ +CV_EXPORTS_W Ptr createHausdorffDistanceExtractor(int distanceFlag=cv::NORM_L2, float rankProp=0.6f); + +//! @} + +} // cv +#endif diff --git a/include/opencv2/shape/shape_transformer.hpp b/include/opencv2/shape/shape_transformer.hpp new file mode 100644 index 0000000..2180613 --- /dev/null +++ b/include/opencv2/shape/shape_transformer.hpp @@ -0,0 +1,132 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_SHAPE_SHAPE_TRANSFORM_HPP__ +#define __OPENCV_SHAPE_SHAPE_TRANSFORM_HPP__ +#include +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" + +namespace cv +{ + +//! @addtogroup shape +//! @{ + +/** @brief Abstract base class for shape transformation algorithms. + */ +class CV_EXPORTS_W ShapeTransformer : public Algorithm +{ +public: + /** @brief Estimate the transformation parameters of the current transformer algorithm, based on point matches. + + @param transformingShape Contour defining first shape. + @param targetShape Contour defining second shape (Target). + @param matches Standard vector of Matches between points. + */ + CV_WRAP virtual void estimateTransformation(InputArray transformingShape, InputArray targetShape, + std::vector& matches) = 0; + + /** @brief Apply a transformation, given a pre-estimated transformation parameters. + + @param input Contour (set of points) to apply the transformation. + @param output Output contour. + */ + CV_WRAP virtual float applyTransformation(InputArray input, OutputArray output=noArray()) = 0; + + /** @brief Apply a transformation, given a pre-estimated transformation parameters, to an Image. + + @param transformingImage Input image. + @param output Output image. + @param flags Image interpolation method. + @param borderMode border style. + @param borderValue border value. + */ + CV_WRAP virtual void warpImage(InputArray transformingImage, OutputArray output, + int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, + const Scalar& borderValue=Scalar()) const = 0; +}; + +/***********************************************************************************/ +/***********************************************************************************/ + +/** @brief Definition of the transformation + +ocupied in the paper "Principal Warps: Thin-Plate Splines and Decomposition of Deformations", by +F.L. Bookstein (PAMI 1989). : + */ +class CV_EXPORTS_W ThinPlateSplineShapeTransformer : public ShapeTransformer +{ +public: + /** @brief Set the regularization parameter for relaxing the exact interpolation requirements of the TPS + algorithm. + + @param beta value of the regularization parameter. + */ + CV_WRAP virtual void setRegularizationParameter(double beta) = 0; + CV_WRAP virtual double getRegularizationParameter() const = 0; +}; + +/** Complete constructor */ +CV_EXPORTS_W Ptr + createThinPlateSplineShapeTransformer(double regularizationParameter=0); + +/***********************************************************************************/ +/***********************************************************************************/ + +/** @brief Wrapper class for the OpenCV Affine Transformation algorithm. : + */ +class CV_EXPORTS_W AffineTransformer : public ShapeTransformer +{ +public: + CV_WRAP virtual void setFullAffine(bool fullAffine) = 0; + CV_WRAP virtual bool getFullAffine() const = 0; +}; + +/** Complete constructor */ +CV_EXPORTS_W Ptr createAffineTransformer(bool fullAffine); + +//! @} + +} // cv +#endif diff --git a/include/opencv2/stitching.hpp b/include/opencv2/stitching.hpp new file mode 100644 index 0000000..96cde14 --- /dev/null +++ b/include/opencv2/stitching.hpp @@ -0,0 +1,257 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_STITCHER_HPP__ +#define __OPENCV_STITCHING_STITCHER_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/features2d.hpp" +#include "opencv2/stitching/warpers.hpp" +#include "opencv2/stitching/detail/matchers.hpp" +#include "opencv2/stitching/detail/motion_estimators.hpp" +#include "opencv2/stitching/detail/exposure_compensate.hpp" +#include "opencv2/stitching/detail/seam_finders.hpp" +#include "opencv2/stitching/detail/blenders.hpp" +#include "opencv2/stitching/detail/camera.hpp" + +/** +@defgroup stitching Images stitching + +This figure illustrates the stitching module pipeline implemented in the Stitcher class. Using that +class it's possible to configure/remove some steps, i.e. adjust the stitching pipeline according to +the particular needs. All building blocks from the pipeline are available in the detail namespace, +one can combine and use them separately. + +The implemented stitching pipeline is very similar to the one proposed in @cite BL07 . + +![image](StitchingPipeline.jpg) + +@{ + @defgroup stitching_match Features Finding and Images Matching + @defgroup stitching_rotation Rotation Estimation + @defgroup stitching_autocalib Autocalibration + @defgroup stitching_warp Images Warping + @defgroup stitching_seam Seam Estimation + @defgroup stitching_exposure Exposure Compensation + @defgroup stitching_blend Image Blenders +@} + */ + +namespace cv { + +//! @addtogroup stitching +//! @{ + +/** @brief High level image stitcher. + +It's possible to use this class without being aware of the entire stitching pipeline. However, to +be able to achieve higher stitching stability and quality of the final images at least being +familiar with the theory is recommended. + +@note + - A basic example on image stitching can be found at + opencv_source_code/samples/cpp/stitching.cpp + - A detailed example on image stitching can be found at + opencv_source_code/samples/cpp/stitching_detailed.cpp + */ +class CV_EXPORTS_W Stitcher +{ +public: + enum { ORIG_RESOL = -1 }; + enum Status + { + OK = 0, + ERR_NEED_MORE_IMGS = 1, + ERR_HOMOGRAPHY_EST_FAIL = 2, + ERR_CAMERA_PARAMS_ADJUST_FAIL = 3 + }; + + // Stitcher() {} + /** @brief Creates a stitcher with the default parameters. + + @param try_use_gpu Flag indicating whether GPU should be used whenever it's possible. + @return Stitcher class instance. + */ + static Stitcher createDefault(bool try_use_gpu = false); + + CV_WRAP double registrationResol() const { return registr_resol_; } + CV_WRAP void setRegistrationResol(double resol_mpx) { registr_resol_ = resol_mpx; } + + CV_WRAP double seamEstimationResol() const { return seam_est_resol_; } + CV_WRAP void setSeamEstimationResol(double resol_mpx) { seam_est_resol_ = resol_mpx; } + + CV_WRAP double compositingResol() const { return compose_resol_; } + CV_WRAP void setCompositingResol(double resol_mpx) { compose_resol_ = resol_mpx; } + + CV_WRAP double panoConfidenceThresh() const { return conf_thresh_; } + CV_WRAP void setPanoConfidenceThresh(double conf_thresh) { conf_thresh_ = conf_thresh; } + + CV_WRAP bool waveCorrection() const { return do_wave_correct_; } + CV_WRAP void setWaveCorrection(bool flag) { do_wave_correct_ = flag; } + + detail::WaveCorrectKind waveCorrectKind() const { return wave_correct_kind_; } + void setWaveCorrectKind(detail::WaveCorrectKind kind) { wave_correct_kind_ = kind; } + + Ptr featuresFinder() { return features_finder_; } + const Ptr featuresFinder() const { return features_finder_; } + void setFeaturesFinder(Ptr features_finder) + { features_finder_ = features_finder; } + + Ptr featuresMatcher() { return features_matcher_; } + const Ptr featuresMatcher() const { return features_matcher_; } + void setFeaturesMatcher(Ptr features_matcher) + { features_matcher_ = features_matcher; } + + const cv::UMat& matchingMask() const { return matching_mask_; } + void setMatchingMask(const cv::UMat &mask) + { + CV_Assert(mask.type() == CV_8U && mask.cols == mask.rows); + matching_mask_ = mask.clone(); + } + + Ptr bundleAdjuster() { return bundle_adjuster_; } + const Ptr bundleAdjuster() const { return bundle_adjuster_; } + void setBundleAdjuster(Ptr bundle_adjuster) + { bundle_adjuster_ = bundle_adjuster; } + + Ptr warper() { return warper_; } + const Ptr warper() const { return warper_; } + void setWarper(Ptr creator) { warper_ = creator; } + + Ptr exposureCompensator() { return exposure_comp_; } + const Ptr exposureCompensator() const { return exposure_comp_; } + void setExposureCompensator(Ptr exposure_comp) + { exposure_comp_ = exposure_comp; } + + Ptr seamFinder() { return seam_finder_; } + const Ptr seamFinder() const { return seam_finder_; } + void setSeamFinder(Ptr seam_finder) { seam_finder_ = seam_finder; } + + Ptr blender() { return blender_; } + const Ptr blender() const { return blender_; } + void setBlender(Ptr b) { blender_ = b; } + + /** @overload */ + CV_WRAP Status estimateTransform(InputArrayOfArrays images); + /** @brief These functions try to match the given images and to estimate rotations of each camera. + + @note Use the functions only if you're aware of the stitching pipeline, otherwise use + Stitcher::stitch. + + @param images Input images. + @param rois Region of interest rectangles. + @return Status code. + */ + Status estimateTransform(InputArrayOfArrays images, const std::vector > &rois); + + /** @overload */ + CV_WRAP Status composePanorama(OutputArray pano); + /** @brief These functions try to compose the given images (or images stored internally from the other function + calls) into the final pano under the assumption that the image transformations were estimated + before. + + @note Use the functions only if you're aware of the stitching pipeline, otherwise use + Stitcher::stitch. + + @param images Input images. + @param pano Final pano. + @return Status code. + */ + Status composePanorama(InputArrayOfArrays images, OutputArray pano); + + /** @overload */ + CV_WRAP Status stitch(InputArrayOfArrays images, OutputArray pano); + /** @brief These functions try to stitch the given images. + + @param images Input images. + @param rois Region of interest rectangles. + @param pano Final pano. + @return Status code. + */ + Status stitch(InputArrayOfArrays images, const std::vector > &rois, OutputArray pano); + + std::vector component() const { return indices_; } + std::vector cameras() const { return cameras_; } + CV_WRAP double workScale() const { return work_scale_; } + +private: + //Stitcher() {} + + Status matchImages(); + Status estimateCameraParams(); + + double registr_resol_; + double seam_est_resol_; + double compose_resol_; + double conf_thresh_; + Ptr features_finder_; + Ptr features_matcher_; + cv::UMat matching_mask_; + Ptr bundle_adjuster_; + bool do_wave_correct_; + detail::WaveCorrectKind wave_correct_kind_; + Ptr warper_; + Ptr exposure_comp_; + Ptr seam_finder_; + Ptr blender_; + + std::vector imgs_; + std::vector > rois_; + std::vector full_img_sizes_; + std::vector features_; + std::vector pairwise_matches_; + std::vector seam_est_imgs_; + std::vector indices_; + std::vector cameras_; + double work_scale_; + double seam_scale_; + double seam_work_aspect_; + double warped_image_scale_; +}; + +CV_EXPORTS_W Ptr createStitcher(bool try_use_gpu = false); + +//! @} stitching + +} // namespace cv + +#endif // __OPENCV_STITCHING_STITCHER_HPP__ diff --git a/include/opencv2/stitching/detail/autocalib.hpp b/include/opencv2/stitching/detail/autocalib.hpp new file mode 100644 index 0000000..ccc0aa1 --- /dev/null +++ b/include/opencv2/stitching/detail/autocalib.hpp @@ -0,0 +1,86 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_AUTOCALIB_HPP__ +#define __OPENCV_STITCHING_AUTOCALIB_HPP__ + +#include "opencv2/core.hpp" +#include "matchers.hpp" + +namespace cv { +namespace detail { + +//! @addtogroup stitching_autocalib +//! @{ + +/** @brief Tries to estimate focal lengths from the given homography under the assumption that the camera +undergoes rotations around its centre only. + +@param H Homography. +@param f0 Estimated focal length along X axis. +@param f1 Estimated focal length along Y axis. +@param f0_ok True, if f0 was estimated successfully, false otherwise. +@param f1_ok True, if f1 was estimated successfully, false otherwise. + +See "Construction of Panoramic Image Mosaics with Global and Local Alignment" +by Heung-Yeung Shum and Richard Szeliski. + */ +void CV_EXPORTS focalsFromHomography(const Mat &H, double &f0, double &f1, bool &f0_ok, bool &f1_ok); + +/** @brief Estimates focal lengths for each given camera. + +@param features Features of images. +@param pairwise_matches Matches between all image pairs. +@param focals Estimated focal lengths for each camera. + */ +void CV_EXPORTS estimateFocal(const std::vector &features, + const std::vector &pairwise_matches, + std::vector &focals); + +bool CV_EXPORTS calibrateRotatingCamera(const std::vector &Hs, Mat &K); + +//! @} stitching_autocalib + +} // namespace detail +} // namespace cv + +#endif // __OPENCV_STITCHING_AUTOCALIB_HPP__ diff --git a/include/opencv2/stitching/detail/blenders.hpp b/include/opencv2/stitching/detail/blenders.hpp new file mode 100644 index 0000000..0e60725 --- /dev/null +++ b/include/opencv2/stitching/detail/blenders.hpp @@ -0,0 +1,163 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_BLENDERS_HPP__ +#define __OPENCV_STITCHING_BLENDERS_HPP__ + +#include "opencv2/core.hpp" + +namespace cv { +namespace detail { + +//! @addtogroup stitching_blend +//! @{ + +/** @brief Base class for all blenders. + +Simple blender which puts one image over another +*/ +class CV_EXPORTS Blender +{ +public: + virtual ~Blender() {} + + enum { NO, FEATHER, MULTI_BAND }; + static Ptr createDefault(int type, bool try_gpu = false); + + /** @brief Prepares the blender for blending. + + @param corners Source images top-left corners + @param sizes Source image sizes + */ + void prepare(const std::vector &corners, const std::vector &sizes); + /** @overload */ + virtual void prepare(Rect dst_roi); + /** @brief Processes the image. + + @param img Source image + @param mask Source image mask + @param tl Source image top-left corners + */ + virtual void feed(InputArray img, InputArray mask, Point tl); + /** @brief Blends and returns the final pano. + + @param dst Final pano + @param dst_mask Final pano mask + */ + virtual void blend(InputOutputArray dst, InputOutputArray dst_mask); + +protected: + UMat dst_, dst_mask_; + Rect dst_roi_; +}; + +/** @brief Simple blender which mixes images at its borders. + */ +class CV_EXPORTS FeatherBlender : public Blender +{ +public: + FeatherBlender(float sharpness = 0.02f); + + float sharpness() const { return sharpness_; } + void setSharpness(float val) { sharpness_ = val; } + + void prepare(Rect dst_roi); + void feed(InputArray img, InputArray mask, Point tl); + void blend(InputOutputArray dst, InputOutputArray dst_mask); + + //! Creates weight maps for fixed set of source images by their masks and top-left corners. + //! Final image can be obtained by simple weighting of the source images. + Rect createWeightMaps(const std::vector &masks, const std::vector &corners, + std::vector &weight_maps); + +private: + float sharpness_; + UMat weight_map_; + UMat dst_weight_map_; +}; + +inline FeatherBlender::FeatherBlender(float _sharpness) { setSharpness(_sharpness); } + +/** @brief Blender which uses multi-band blending algorithm (see @cite BA83). + */ +class CV_EXPORTS MultiBandBlender : public Blender +{ +public: + MultiBandBlender(int try_gpu = false, int num_bands = 5, int weight_type = CV_32F); + + int numBands() const { return actual_num_bands_; } + void setNumBands(int val) { actual_num_bands_ = val; } + + void prepare(Rect dst_roi); + void feed(InputArray img, InputArray mask, Point tl); + void blend(InputOutputArray dst, InputOutputArray dst_mask); + +private: + int actual_num_bands_, num_bands_; + std::vector dst_pyr_laplace_; + std::vector dst_band_weights_; + Rect dst_roi_final_; + bool can_use_gpu_; + int weight_type_; //CV_32F or CV_16S +}; + + +////////////////////////////////////////////////////////////////////////////// +// Auxiliary functions + +void CV_EXPORTS normalizeUsingWeightMap(InputArray weight, InputOutputArray src); + +void CV_EXPORTS createWeightMap(InputArray mask, float sharpness, InputOutputArray weight); + +void CV_EXPORTS createLaplacePyr(InputArray img, int num_levels, std::vector& pyr); +void CV_EXPORTS createLaplacePyrGpu(InputArray img, int num_levels, std::vector& pyr); + +// Restores source image +void CV_EXPORTS restoreImageFromLaplacePyr(std::vector& pyr); +void CV_EXPORTS restoreImageFromLaplacePyrGpu(std::vector& pyr); + +//! @} + +} // namespace detail +} // namespace cv + +#endif // __OPENCV_STITCHING_BLENDERS_HPP__ diff --git a/include/opencv2/stitching/detail/camera.hpp b/include/opencv2/stitching/detail/camera.hpp new file mode 100644 index 0000000..c231ba5 --- /dev/null +++ b/include/opencv2/stitching/detail/camera.hpp @@ -0,0 +1,78 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_CAMERA_HPP__ +#define __OPENCV_STITCHING_CAMERA_HPP__ + +#include "opencv2/core.hpp" + +namespace cv { +namespace detail { + +//! @addtogroup stitching +//! @{ + +/** @brief Describes camera parameters. + +@note Translation is assumed to be zero during the whole stitching pipeline. : + */ +struct CV_EXPORTS CameraParams +{ + CameraParams(); + CameraParams(const CameraParams& other); + const CameraParams& operator =(const CameraParams& other); + Mat K() const; + + double focal; // Focal length + double aspect; // Aspect ratio + double ppx; // Principal point X + double ppy; // Principal point Y + Mat R; // Rotation + Mat t; // Translation +}; + +//! @} + +} // namespace detail +} // namespace cv + +#endif // #ifndef __OPENCV_STITCHING_CAMERA_HPP__ diff --git a/include/opencv2/stitching/detail/exposure_compensate.hpp b/include/opencv2/stitching/detail/exposure_compensate.hpp new file mode 100644 index 0000000..ef64e12 --- /dev/null +++ b/include/opencv2/stitching/detail/exposure_compensate.hpp @@ -0,0 +1,132 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_EXPOSURE_COMPENSATE_HPP__ +#define __OPENCV_STITCHING_EXPOSURE_COMPENSATE_HPP__ + +#include "opencv2/core.hpp" + +namespace cv { +namespace detail { + +//! @addtogroup stitching_exposure +//! @{ + +/** @brief Base class for all exposure compensators. + */ +class CV_EXPORTS ExposureCompensator +{ +public: + virtual ~ExposureCompensator() {} + + enum { NO, GAIN, GAIN_BLOCKS }; + static Ptr createDefault(int type); + + /** + @param corners Source image top-left corners + @param images Source images + @param masks Image masks to update (second value in pair specifies the value which should be used + to detect where image is) + */ + void feed(const std::vector &corners, const std::vector &images, + const std::vector &masks); + /** @overload */ + virtual void feed(const std::vector &corners, const std::vector &images, + const std::vector > &masks) = 0; + /** @brief Compensate exposure in the specified image. + + @param index Image index + @param corner Image top-left corner + @param image Image to process + @param mask Image mask + */ + virtual void apply(int index, Point corner, InputOutputArray image, InputArray mask) = 0; +}; + +/** @brief Stub exposure compensator which does nothing. + */ +class CV_EXPORTS NoExposureCompensator : public ExposureCompensator +{ +public: + void feed(const std::vector &/*corners*/, const std::vector &/*images*/, + const std::vector > &/*masks*/) { } + void apply(int /*index*/, Point /*corner*/, InputOutputArray /*image*/, InputArray /*mask*/) { } +}; + +/** @brief Exposure compensator which tries to remove exposure related artifacts by adjusting image +intensities, see @cite BL07 and @cite WJ10 for details. + */ +class CV_EXPORTS GainCompensator : public ExposureCompensator +{ +public: + void feed(const std::vector &corners, const std::vector &images, + const std::vector > &masks); + void apply(int index, Point corner, InputOutputArray image, InputArray mask); + std::vector gains() const; + +private: + Mat_ gains_; +}; + +/** @brief Exposure compensator which tries to remove exposure related artifacts by adjusting image block +intensities, see @cite UES01 for details. + */ +class CV_EXPORTS BlocksGainCompensator : public ExposureCompensator +{ +public: + BlocksGainCompensator(int bl_width = 32, int bl_height = 32) + : bl_width_(bl_width), bl_height_(bl_height) {} + void feed(const std::vector &corners, const std::vector &images, + const std::vector > &masks); + void apply(int index, Point corner, InputOutputArray image, InputArray mask); + +private: + int bl_width_, bl_height_; + std::vector gain_maps_; +}; + +//! @} + +} // namespace detail +} // namespace cv + +#endif // __OPENCV_STITCHING_EXPOSURE_COMPENSATE_HPP__ diff --git a/include/opencv2/stitching/detail/matchers.hpp b/include/opencv2/stitching/detail/matchers.hpp new file mode 100644 index 0000000..8f34bd2 --- /dev/null +++ b/include/opencv2/stitching/detail/matchers.hpp @@ -0,0 +1,275 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_MATCHERS_HPP__ +#define __OPENCV_STITCHING_MATCHERS_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/features2d.hpp" + +#include "opencv2/opencv_modules.hpp" + +#ifdef HAVE_OPENCV_XFEATURES2D +# include "opencv2/xfeatures2d/cuda.hpp" +#endif + +namespace cv { +namespace detail { + +//! @addtogroup stitching_match +//! @{ + +/** @brief Structure containing image keypoints and descriptors. */ +struct CV_EXPORTS ImageFeatures +{ + int img_idx; + Size img_size; + std::vector keypoints; + UMat descriptors; +}; + +/** @brief Feature finders base class */ +class CV_EXPORTS FeaturesFinder +{ +public: + virtual ~FeaturesFinder() {} + /** @overload */ + void operator ()(InputArray image, ImageFeatures &features); + /** @brief Finds features in the given image. + + @param image Source image + @param features Found features + @param rois Regions of interest + + @sa detail::ImageFeatures, Rect_ + */ + void operator ()(InputArray image, ImageFeatures &features, const std::vector &rois); + /** @brief Frees unused memory allocated before if there is any. */ + virtual void collectGarbage() {} + +protected: + /** @brief This method must implement features finding logic in order to make the wrappers + detail::FeaturesFinder::operator()_ work. + + @param image Source image + @param features Found features + + @sa detail::ImageFeatures */ + virtual void find(InputArray image, ImageFeatures &features) = 0; +}; + +/** @brief SURF features finder. + +@sa detail::FeaturesFinder, SURF +*/ +class CV_EXPORTS SurfFeaturesFinder : public FeaturesFinder +{ +public: + SurfFeaturesFinder(double hess_thresh = 300., int num_octaves = 3, int num_layers = 4, + int num_octaves_descr = /*4*/3, int num_layers_descr = /*2*/4); + +private: + void find(InputArray image, ImageFeatures &features); + + Ptr detector_; + Ptr extractor_; + Ptr surf; +}; + +/** @brief ORB features finder. : + +@sa detail::FeaturesFinder, ORB +*/ +class CV_EXPORTS OrbFeaturesFinder : public FeaturesFinder +{ +public: + OrbFeaturesFinder(Size _grid_size = Size(3,1), int nfeatures=1500, float scaleFactor=1.3f, int nlevels=5); + +private: + void find(InputArray image, ImageFeatures &features); + + Ptr orb; + Size grid_size; +}; + + +#ifdef HAVE_OPENCV_XFEATURES2D +class CV_EXPORTS SurfFeaturesFinderGpu : public FeaturesFinder +{ +public: + SurfFeaturesFinderGpu(double hess_thresh = 300., int num_octaves = 3, int num_layers = 4, + int num_octaves_descr = 4, int num_layers_descr = 2); + + void collectGarbage(); + +private: + void find(InputArray image, ImageFeatures &features); + + cuda::GpuMat image_; + cuda::GpuMat gray_image_; + cuda::SURF_CUDA surf_; + cuda::GpuMat keypoints_; + cuda::GpuMat descriptors_; + int num_octaves_, num_layers_; + int num_octaves_descr_, num_layers_descr_; +}; +#endif + +/** @brief Structure containing information about matches between two images. + +It's assumed that there is a homography between those images. +*/ +struct CV_EXPORTS MatchesInfo +{ + MatchesInfo(); + MatchesInfo(const MatchesInfo &other); + const MatchesInfo& operator =(const MatchesInfo &other); + + int src_img_idx, dst_img_idx; //!< Images indices (optional) + std::vector matches; + std::vector inliers_mask; //!< Geometrically consistent matches mask + int num_inliers; //!< Number of geometrically consistent matches + Mat H; //!< Estimated homography + double confidence; //!< Confidence two images are from the same panorama +}; + +/** @brief Feature matchers base class. */ +class CV_EXPORTS FeaturesMatcher +{ +public: + virtual ~FeaturesMatcher() {} + + /** @overload + @param features1 First image features + @param features2 Second image features + @param matches_info Found matches + */ + void operator ()(const ImageFeatures &features1, const ImageFeatures &features2, + MatchesInfo& matches_info) { match(features1, features2, matches_info); } + + /** @brief Performs images matching. + + @param features Features of the source images + @param pairwise_matches Found pairwise matches + @param mask Mask indicating which image pairs must be matched + + The function is parallelized with the TBB library. + + @sa detail::MatchesInfo + */ + void operator ()(const std::vector &features, std::vector &pairwise_matches, + const cv::UMat &mask = cv::UMat()); + + /** @return True, if it's possible to use the same matcher instance in parallel, false otherwise + */ + bool isThreadSafe() const { return is_thread_safe_; } + + /** @brief Frees unused memory allocated before if there is any. + */ + virtual void collectGarbage() {} + +protected: + FeaturesMatcher(bool is_thread_safe = false) : is_thread_safe_(is_thread_safe) {} + + /** @brief This method must implement matching logic in order to make the wrappers + detail::FeaturesMatcher::operator()_ work. + + @param features1 first image features + @param features2 second image features + @param matches_info found matches + */ + virtual void match(const ImageFeatures &features1, const ImageFeatures &features2, + MatchesInfo& matches_info) = 0; + + bool is_thread_safe_; +}; + +/** @brief Features matcher which finds two best matches for each feature and leaves the best one only if the +ratio between descriptor distances is greater than the threshold match_conf + +@sa detail::FeaturesMatcher + */ +class CV_EXPORTS BestOf2NearestMatcher : public FeaturesMatcher +{ +public: + /** @brief Constructs a "best of 2 nearest" matcher. + + @param try_use_gpu Should try to use GPU or not + @param match_conf Match distances ration threshold + @param num_matches_thresh1 Minimum number of matches required for the 2D projective transform + estimation used in the inliers classification step + @param num_matches_thresh2 Minimum number of matches required for the 2D projective transform + re-estimation on inliers + */ + BestOf2NearestMatcher(bool try_use_gpu = false, float match_conf = 0.3f, int num_matches_thresh1 = 6, + int num_matches_thresh2 = 6); + + void collectGarbage(); + +protected: + void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo &matches_info); + + int num_matches_thresh1_; + int num_matches_thresh2_; + Ptr impl_; +}; + +class CV_EXPORTS BestOf2NearestRangeMatcher : public BestOf2NearestMatcher +{ +public: + BestOf2NearestRangeMatcher(int range_width = 5, bool try_use_gpu = false, float match_conf = 0.3f, + int num_matches_thresh1 = 6, int num_matches_thresh2 = 6); + + void operator ()(const std::vector &features, std::vector &pairwise_matches, + const cv::UMat &mask = cv::UMat()); + + +protected: + int range_width_; +}; + +//! @} stitching_match + +} // namespace detail +} // namespace cv + +#endif // __OPENCV_STITCHING_MATCHERS_HPP__ diff --git a/include/opencv2/stitching/detail/motion_estimators.hpp b/include/opencv2/stitching/detail/motion_estimators.hpp new file mode 100644 index 0000000..2c86e63 --- /dev/null +++ b/include/opencv2/stitching/detail/motion_estimators.hpp @@ -0,0 +1,274 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_MOTION_ESTIMATORS_HPP__ +#define __OPENCV_STITCHING_MOTION_ESTIMATORS_HPP__ + +#include "opencv2/core.hpp" +#include "matchers.hpp" +#include "util.hpp" +#include "camera.hpp" + +namespace cv { +namespace detail { + +//! @addtogroup stitching_rotation +//! @{ + +/** @brief Rotation estimator base class. + +It takes features of all images, pairwise matches between all images and estimates rotations of all +cameras. + +@note The coordinate system origin is implementation-dependent, but you can always normalize the +rotations in respect to the first camera, for instance. : + */ +class CV_EXPORTS Estimator +{ +public: + virtual ~Estimator() {} + + /** @brief Estimates camera parameters. + + @param features Features of images + @param pairwise_matches Pairwise matches of images + @param cameras Estimated camera parameters + @return True in case of success, false otherwise + */ + bool operator ()(const std::vector &features, + const std::vector &pairwise_matches, + std::vector &cameras) + { return estimate(features, pairwise_matches, cameras); } + +protected: + /** @brief This method must implement camera parameters estimation logic in order to make the wrapper + detail::Estimator::operator()_ work. + + @param features Features of images + @param pairwise_matches Pairwise matches of images + @param cameras Estimated camera parameters + @return True in case of success, false otherwise + */ + virtual bool estimate(const std::vector &features, + const std::vector &pairwise_matches, + std::vector &cameras) = 0; +}; + +/** @brief Homography based rotation estimator. + */ +class CV_EXPORTS HomographyBasedEstimator : public Estimator +{ +public: + HomographyBasedEstimator(bool is_focals_estimated = false) + : is_focals_estimated_(is_focals_estimated) {} + +private: + virtual bool estimate(const std::vector &features, + const std::vector &pairwise_matches, + std::vector &cameras); + + bool is_focals_estimated_; +}; + +/** @brief Base class for all camera parameters refinement methods. + */ +class CV_EXPORTS BundleAdjusterBase : public Estimator +{ +public: + const Mat refinementMask() const { return refinement_mask_.clone(); } + void setRefinementMask(const Mat &mask) + { + CV_Assert(mask.type() == CV_8U && mask.size() == Size(3, 3)); + refinement_mask_ = mask.clone(); + } + + double confThresh() const { return conf_thresh_; } + void setConfThresh(double conf_thresh) { conf_thresh_ = conf_thresh; } + + TermCriteria termCriteria() { return term_criteria_; } + void setTermCriteria(const TermCriteria& term_criteria) { term_criteria_ = term_criteria; } + +protected: + /** @brief Construct a bundle adjuster base instance. + + @param num_params_per_cam Number of parameters per camera + @param num_errs_per_measurement Number of error terms (components) per match + */ + BundleAdjusterBase(int num_params_per_cam, int num_errs_per_measurement) + : num_params_per_cam_(num_params_per_cam), + num_errs_per_measurement_(num_errs_per_measurement) + { + setRefinementMask(Mat::ones(3, 3, CV_8U)); + setConfThresh(1.); + setTermCriteria(TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 1000, DBL_EPSILON)); + } + + // Runs bundle adjustment + virtual bool estimate(const std::vector &features, + const std::vector &pairwise_matches, + std::vector &cameras); + + /** @brief Sets initial camera parameter to refine. + + @param cameras Camera parameters + */ + virtual void setUpInitialCameraParams(const std::vector &cameras) = 0; + /** @brief Gets the refined camera parameters. + + @param cameras Refined camera parameters + */ + virtual void obtainRefinedCameraParams(std::vector &cameras) const = 0; + /** @brief Calculates error vector. + + @param err Error column-vector of length total_num_matches \* num_errs_per_measurement + */ + virtual void calcError(Mat &err) = 0; + /** @brief Calculates the cost function jacobian. + + @param jac Jacobian matrix of dimensions + (total_num_matches \* num_errs_per_measurement) x (num_images \* num_params_per_cam) + */ + virtual void calcJacobian(Mat &jac) = 0; + + // 3x3 8U mask, where 0 means don't refine respective parameter, != 0 means refine + Mat refinement_mask_; + + int num_images_; + int total_num_matches_; + + int num_params_per_cam_; + int num_errs_per_measurement_; + + const ImageFeatures *features_; + const MatchesInfo *pairwise_matches_; + + // Threshold to filter out poorly matched image pairs + double conf_thresh_; + + //Levenberg–Marquardt algorithm termination criteria + TermCriteria term_criteria_; + + // Camera parameters matrix (CV_64F) + Mat cam_params_; + + // Connected images pairs + std::vector > edges_; +}; + + +/** @brief Implementation of the camera parameters refinement algorithm which minimizes sum of the reprojection +error squares + +It can estimate focal length, aspect ratio, principal point. +You can affect only on them via the refinement mask. + */ +class CV_EXPORTS BundleAdjusterReproj : public BundleAdjusterBase +{ +public: + BundleAdjusterReproj() : BundleAdjusterBase(7, 2) {} + +private: + void setUpInitialCameraParams(const std::vector &cameras); + void obtainRefinedCameraParams(std::vector &cameras) const; + void calcError(Mat &err); + void calcJacobian(Mat &jac); + + Mat err1_, err2_; +}; + + +/** @brief Implementation of the camera parameters refinement algorithm which minimizes sum of the distances +between the rays passing through the camera center and a feature. : + +It can estimate focal length. It ignores the refinement mask for now. + */ +class CV_EXPORTS BundleAdjusterRay : public BundleAdjusterBase +{ +public: + BundleAdjusterRay() : BundleAdjusterBase(4, 3) {} + +private: + void setUpInitialCameraParams(const std::vector &cameras); + void obtainRefinedCameraParams(std::vector &cameras) const; + void calcError(Mat &err); + void calcJacobian(Mat &jac); + + Mat err1_, err2_; +}; + + +enum WaveCorrectKind +{ + WAVE_CORRECT_HORIZ, + WAVE_CORRECT_VERT +}; + +/** @brief Tries to make panorama more horizontal (or vertical). + +@param rmats Camera rotation matrices. +@param kind Correction kind, see detail::WaveCorrectKind. + */ +void CV_EXPORTS waveCorrect(std::vector &rmats, WaveCorrectKind kind); + + +////////////////////////////////////////////////////////////////////////////// +// Auxiliary functions + +// Returns matches graph representation in DOT language +String CV_EXPORTS matchesGraphAsString(std::vector &pathes, std::vector &pairwise_matches, + float conf_threshold); + +std::vector CV_EXPORTS leaveBiggestComponent( + std::vector &features, + std::vector &pairwise_matches, + float conf_threshold); + +void CV_EXPORTS findMaxSpanningTree( + int num_images, const std::vector &pairwise_matches, + Graph &span_tree, std::vector ¢ers); + +//! @} stitching_rotation + +} // namespace detail +} // namespace cv + +#endif // __OPENCV_STITCHING_MOTION_ESTIMATORS_HPP__ diff --git a/include/opencv2/stitching/detail/seam_finders.hpp b/include/opencv2/stitching/detail/seam_finders.hpp new file mode 100644 index 0000000..4ff22c4 --- /dev/null +++ b/include/opencv2/stitching/detail/seam_finders.hpp @@ -0,0 +1,285 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_SEAM_FINDERS_HPP__ +#define __OPENCV_STITCHING_SEAM_FINDERS_HPP__ + +#include +#include "opencv2/core.hpp" +#include "opencv2/opencv_modules.hpp" + +namespace cv { +namespace detail { + +//! @addtogroup stitching_seam +//! @{ + +/** @brief Base class for a seam estimator. + */ +class CV_EXPORTS SeamFinder +{ +public: + virtual ~SeamFinder() {} + /** @brief Estimates seams. + + @param src Source images + @param corners Source image top-left corners + @param masks Source image masks to update + */ + virtual void find(const std::vector &src, const std::vector &corners, + std::vector &masks) = 0; +}; + +/** @brief Stub seam estimator which does nothing. + */ +class CV_EXPORTS NoSeamFinder : public SeamFinder +{ +public: + void find(const std::vector&, const std::vector&, std::vector&) {} +}; + +/** @brief Base class for all pairwise seam estimators. + */ +class CV_EXPORTS PairwiseSeamFinder : public SeamFinder +{ +public: + virtual void find(const std::vector &src, const std::vector &corners, + std::vector &masks); + +protected: + void run(); + /** @brief Resolves masks intersection of two specified images in the given ROI. + + @param first First image index + @param second Second image index + @param roi Region of interest + */ + virtual void findInPair(size_t first, size_t second, Rect roi) = 0; + + std::vector images_; + std::vector sizes_; + std::vector corners_; + std::vector masks_; +}; + +/** @brief Voronoi diagram-based seam estimator. + */ +class CV_EXPORTS VoronoiSeamFinder : public PairwiseSeamFinder +{ +public: + virtual void find(const std::vector &src, const std::vector &corners, + std::vector &masks); + virtual void find(const std::vector &size, const std::vector &corners, + std::vector &masks); +private: + void findInPair(size_t first, size_t second, Rect roi); +}; + + +class CV_EXPORTS DpSeamFinder : public SeamFinder +{ +public: + enum CostFunction { COLOR, COLOR_GRAD }; + + DpSeamFinder(CostFunction costFunc = COLOR); + + CostFunction costFunction() const { return costFunc_; } + void setCostFunction(CostFunction val) { costFunc_ = val; } + + virtual void find(const std::vector &src, const std::vector &corners, + std::vector &masks); + +private: + enum ComponentState + { + FIRST = 1, SECOND = 2, INTERS = 4, + INTERS_FIRST = INTERS | FIRST, + INTERS_SECOND = INTERS | SECOND + }; + + class ImagePairLess + { + public: + ImagePairLess(const std::vector &images, const std::vector &corners) + : src_(&images[0]), corners_(&corners[0]) {} + + bool operator() (const std::pair &l, const std::pair &r) const + { + Point c1 = corners_[l.first] + Point(src_[l.first].cols / 2, src_[l.first].rows / 2); + Point c2 = corners_[l.second] + Point(src_[l.second].cols / 2, src_[l.second].rows / 2); + int d1 = (c1 - c2).dot(c1 - c2); + + c1 = corners_[r.first] + Point(src_[r.first].cols / 2, src_[r.first].rows / 2); + c2 = corners_[r.second] + Point(src_[r.second].cols / 2, src_[r.second].rows / 2); + int d2 = (c1 - c2).dot(c1 - c2); + + return d1 < d2; + } + + private: + const Mat *src_; + const Point *corners_; + }; + + class ClosePoints + { + public: + ClosePoints(int minDist) : minDist_(minDist) {} + + bool operator() (const Point &p1, const Point &p2) const + { + int dist2 = (p1.x-p2.x) * (p1.x-p2.x) + (p1.y-p2.y) * (p1.y-p2.y); + return dist2 < minDist_ * minDist_; + } + + private: + int minDist_; + }; + + void process( + const Mat &image1, const Mat &image2, Point tl1, Point tl2, Mat &mask1, Mat &mask2); + + void findComponents(); + + void findEdges(); + + void resolveConflicts( + const Mat &image1, const Mat &image2, Point tl1, Point tl2, Mat &mask1, Mat &mask2); + + void computeGradients(const Mat &image1, const Mat &image2); + + bool hasOnlyOneNeighbor(int comp); + + bool closeToContour(int y, int x, const Mat_ &contourMask); + + bool getSeamTips(int comp1, int comp2, Point &p1, Point &p2); + + void computeCosts( + const Mat &image1, const Mat &image2, Point tl1, Point tl2, + int comp, Mat_ &costV, Mat_ &costH); + + bool estimateSeam( + const Mat &image1, const Mat &image2, Point tl1, Point tl2, int comp, + Point p1, Point p2, std::vector &seam, bool &isHorizontal); + + void updateLabelsUsingSeam( + int comp1, int comp2, const std::vector &seam, bool isHorizontalSeam); + + CostFunction costFunc_; + + // processing images pair data + Point unionTl_, unionBr_; + Size unionSize_; + Mat_ mask1_, mask2_; + Mat_ contour1mask_, contour2mask_; + Mat_ gradx1_, grady1_; + Mat_ gradx2_, grady2_; + + // components data + int ncomps_; + Mat_ labels_; + std::vector states_; + std::vector tls_, brs_; + std::vector > contours_; + std::set > edges_; +}; + +/** @brief Base class for all minimum graph-cut-based seam estimators. + */ +class CV_EXPORTS GraphCutSeamFinderBase +{ +public: + enum CostType { COST_COLOR, COST_COLOR_GRAD }; +}; + +/** @brief Minimum graph cut-based seam estimator. See details in @cite V03 . + */ +class CV_EXPORTS GraphCutSeamFinder : public GraphCutSeamFinderBase, public SeamFinder +{ +public: + GraphCutSeamFinder(int cost_type = COST_COLOR_GRAD, float terminal_cost = 10000.f, + float bad_region_penalty = 1000.f); + + ~GraphCutSeamFinder(); + + void find(const std::vector &src, const std::vector &corners, + std::vector &masks); + +private: + // To avoid GCGraph dependency + class Impl; + Ptr impl_; +}; + + +#ifdef HAVE_OPENCV_CUDALEGACY +class CV_EXPORTS GraphCutSeamFinderGpu : public GraphCutSeamFinderBase, public PairwiseSeamFinder +{ +public: + GraphCutSeamFinderGpu(int cost_type = COST_COLOR_GRAD, float terminal_cost = 10000.f, + float bad_region_penalty = 1000.f) + : cost_type_(cost_type), terminal_cost_(terminal_cost), + bad_region_penalty_(bad_region_penalty) {} + + void find(const std::vector &src, const std::vector &corners, + std::vector &masks); + void findInPair(size_t first, size_t second, Rect roi); + +private: + void setGraphWeightsColor(const cv::Mat &img1, const cv::Mat &img2, const cv::Mat &mask1, const cv::Mat &mask2, + cv::Mat &terminals, cv::Mat &leftT, cv::Mat &rightT, cv::Mat &top, cv::Mat &bottom); + void setGraphWeightsColorGrad(const cv::Mat &img1, const cv::Mat &img2, const cv::Mat &dx1, const cv::Mat &dx2, + const cv::Mat &dy1, const cv::Mat &dy2, const cv::Mat &mask1, const cv::Mat &mask2, + cv::Mat &terminals, cv::Mat &leftT, cv::Mat &rightT, cv::Mat &top, cv::Mat &bottom); + std::vector dx_, dy_; + int cost_type_; + float terminal_cost_; + float bad_region_penalty_; +}; +#endif + +//! @} + +} // namespace detail +} // namespace cv + +#endif // __OPENCV_STITCHING_SEAM_FINDERS_HPP__ diff --git a/include/opencv2/stitching/detail/timelapsers.hpp b/include/opencv2/stitching/detail/timelapsers.hpp new file mode 100644 index 0000000..d64c03c --- /dev/null +++ b/include/opencv2/stitching/detail/timelapsers.hpp @@ -0,0 +1,91 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + +#ifndef __OPENCV_STITCHING_TIMELAPSERS_HPP__ +#define __OPENCV_STITCHING_TIMELAPSERS_HPP__ + +#include "opencv2/core.hpp" + +namespace cv { +namespace detail { + +//! @addtogroup stitching +//! @{ + +// Base Timelapser class, takes a sequence of images, applies appropriate shift, stores result in dst_. + +class CV_EXPORTS Timelapser +{ +public: + + enum {AS_IS, CROP}; + + virtual ~Timelapser() {} + + static Ptr createDefault(int type); + + virtual void initialize(const std::vector &corners, const std::vector &sizes); + virtual void process(InputArray img, InputArray mask, Point tl); + virtual const UMat& getDst() {return dst_;} + +protected: + + virtual bool test_point(Point pt); + + UMat dst_; + Rect dst_roi_; +}; + + +class CV_EXPORTS TimelapserCrop : public Timelapser +{ +public: + virtual void initialize(const std::vector &corners, const std::vector &sizes); +}; + +//! @} + +} // namespace detail +} // namespace cv + +#endif // __OPENCV_STITCHING_TIMELAPSERS_HPP__ diff --git a/include/opencv2/stitching/detail/util.hpp b/include/opencv2/stitching/detail/util.hpp new file mode 100644 index 0000000..3845ba5 --- /dev/null +++ b/include/opencv2/stitching/detail/util.hpp @@ -0,0 +1,171 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_UTIL_HPP__ +#define __OPENCV_STITCHING_UTIL_HPP__ + +#include +#include "opencv2/core.hpp" + +#ifndef ENABLE_LOG +#define ENABLE_LOG 0 +#endif + +// TODO remove LOG macros, add logging class +#if ENABLE_LOG +#ifdef ANDROID + #include + #include + #include + #define LOG_STITCHING_MSG(msg) \ + do { \ + Stringstream _os; \ + _os << msg; \ + __android_log_print(ANDROID_LOG_DEBUG, "STITCHING", "%s", _os.str().c_str()); \ + } while(0); +#else + #include + #define LOG_STITCHING_MSG(msg) for(;;) { std::cout << msg; std::cout.flush(); break; } +#endif +#else + #define LOG_STITCHING_MSG(msg) +#endif + +#define LOG_(_level, _msg) \ + for(;;) \ + { \ + using namespace std; \ + if ((_level) >= ::cv::detail::stitchingLogLevel()) \ + { \ + LOG_STITCHING_MSG(_msg); \ + } \ + break; \ + } + + +#define LOG(msg) LOG_(1, msg) +#define LOG_CHAT(msg) LOG_(0, msg) + +#define LOGLN(msg) LOG(msg << std::endl) +#define LOGLN_CHAT(msg) LOG_CHAT(msg << std::endl) + +//#if DEBUG_LOG_CHAT +// #define LOG_CHAT(msg) LOG(msg) +// #define LOGLN_CHAT(msg) LOGLN(msg) +//#else +// #define LOG_CHAT(msg) do{}while(0) +// #define LOGLN_CHAT(msg) do{}while(0) +//#endif + +namespace cv { +namespace detail { + +//! @addtogroup stitching +//! @{ + +class CV_EXPORTS DisjointSets +{ +public: + DisjointSets(int elem_count = 0) { createOneElemSets(elem_count); } + + void createOneElemSets(int elem_count); + int findSetByElem(int elem); + int mergeSets(int set1, int set2); + + std::vector parent; + std::vector size; + +private: + std::vector rank_; +}; + + +struct CV_EXPORTS GraphEdge +{ + GraphEdge(int from, int to, float weight); + bool operator <(const GraphEdge& other) const { return weight < other.weight; } + bool operator >(const GraphEdge& other) const { return weight > other.weight; } + + int from, to; + float weight; +}; + +inline GraphEdge::GraphEdge(int _from, int _to, float _weight) : from(_from), to(_to), weight(_weight) {} + + +class CV_EXPORTS Graph +{ +public: + Graph(int num_vertices = 0) { create(num_vertices); } + void create(int num_vertices) { edges_.assign(num_vertices, std::list()); } + int numVertices() const { return static_cast(edges_.size()); } + void addEdge(int from, int to, float weight); + template B forEach(B body) const; + template B walkBreadthFirst(int from, B body) const; + +private: + std::vector< std::list > edges_; +}; + + +////////////////////////////////////////////////////////////////////////////// +// Auxiliary functions + +CV_EXPORTS bool overlapRoi(Point tl1, Point tl2, Size sz1, Size sz2, Rect &roi); +CV_EXPORTS Rect resultRoi(const std::vector &corners, const std::vector &images); +CV_EXPORTS Rect resultRoi(const std::vector &corners, const std::vector &sizes); +CV_EXPORTS Rect resultRoiIntersection(const std::vector &corners, const std::vector &sizes); +CV_EXPORTS Point resultTl(const std::vector &corners); + +// Returns random 'count' element subset of the {0,1,...,size-1} set +CV_EXPORTS void selectRandomSubset(int count, int size, std::vector &subset); + +CV_EXPORTS int& stitchingLogLevel(); + +//! @} + +} // namespace detail +} // namespace cv + +#include "util_inl.hpp" + +#endif // __OPENCV_STITCHING_UTIL_HPP__ diff --git a/include/opencv2/stitching/detail/util_inl.hpp b/include/opencv2/stitching/detail/util_inl.hpp new file mode 100644 index 0000000..6ac6f8e --- /dev/null +++ b/include/opencv2/stitching/detail/util_inl.hpp @@ -0,0 +1,131 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_UTIL_INL_HPP__ +#define __OPENCV_STITCHING_UTIL_INL_HPP__ + +#include +#include "opencv2/core.hpp" +#include "util.hpp" // Make your IDE see declarations + +//! @cond IGNORED + +namespace cv { +namespace detail { + +template +B Graph::forEach(B body) const +{ + for (int i = 0; i < numVertices(); ++i) + { + std::list::const_iterator edge = edges_[i].begin(); + for (; edge != edges_[i].end(); ++edge) + body(*edge); + } + return body; +} + + +template +B Graph::walkBreadthFirst(int from, B body) const +{ + std::vector was(numVertices(), false); + std::queue vertices; + + was[from] = true; + vertices.push(from); + + while (!vertices.empty()) + { + int vertex = vertices.front(); + vertices.pop(); + + std::list::const_iterator edge = edges_[vertex].begin(); + for (; edge != edges_[vertex].end(); ++edge) + { + if (!was[edge->to]) + { + body(*edge); + was[edge->to] = true; + vertices.push(edge->to); + } + } + } + + return body; +} + + +////////////////////////////////////////////////////////////////////////////// +// Some auxiliary math functions + +static inline +float normL2(const Point3f& a) +{ + return a.x * a.x + a.y * a.y + a.z * a.z; +} + + +static inline +float normL2(const Point3f& a, const Point3f& b) +{ + return normL2(a - b); +} + + +static inline +double normL2sq(const Mat &r) +{ + return r.dot(r); +} + + +static inline int sqr(int x) { return x * x; } +static inline float sqr(float x) { return x * x; } +static inline double sqr(double x) { return x * x; } + +} // namespace detail +} // namespace cv + +//! @endcond + +#endif // __OPENCV_STITCHING_UTIL_INL_HPP__ diff --git a/include/opencv2/stitching/detail/warpers.hpp b/include/opencv2/stitching/detail/warpers.hpp new file mode 100644 index 0000000..ee8e824 --- /dev/null +++ b/include/opencv2/stitching/detail/warpers.hpp @@ -0,0 +1,586 @@ + /*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_WARPERS_HPP__ +#define __OPENCV_STITCHING_WARPERS_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/core/cuda.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/opencv_modules.hpp" + +namespace cv { +namespace detail { + +//! @addtogroup stitching_warp +//! @{ + +/** @brief Rotation-only model image warper interface. + */ +class CV_EXPORTS RotationWarper +{ +public: + virtual ~RotationWarper() {} + + /** @brief Projects the image point. + + @param pt Source point + @param K Camera intrinsic parameters + @param R Camera rotation matrix + @return Projected point + */ + virtual Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R) = 0; + + /** @brief Builds the projection maps according to the given camera data. + + @param src_size Source image size + @param K Camera intrinsic parameters + @param R Camera rotation matrix + @param xmap Projection map for the x axis + @param ymap Projection map for the y axis + @return Projected image minimum bounding box + */ + virtual Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) = 0; + + /** @brief Projects the image. + + @param src Source image + @param K Camera intrinsic parameters + @param R Camera rotation matrix + @param interp_mode Interpolation mode + @param border_mode Border extrapolation mode + @param dst Projected image + @return Project image top-left corner + */ + virtual Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + OutputArray dst) = 0; + + /** @brief Projects the image backward. + + @param src Projected image + @param K Camera intrinsic parameters + @param R Camera rotation matrix + @param interp_mode Interpolation mode + @param border_mode Border extrapolation mode + @param dst_size Backward-projected image size + @param dst Backward-projected image + */ + virtual void warpBackward(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + Size dst_size, OutputArray dst) = 0; + + /** + @param src_size Source image bounding box + @param K Camera intrinsic parameters + @param R Camera rotation matrix + @return Projected image minimum bounding box + */ + virtual Rect warpRoi(Size src_size, InputArray K, InputArray R) = 0; + + virtual float getScale() const { return 1.f; } + virtual void setScale(float) {} +}; + +/** @brief Base class for warping logic implementation. + */ +struct CV_EXPORTS ProjectorBase +{ + void setCameraParams(InputArray K = Mat::eye(3, 3, CV_32F), + InputArray R = Mat::eye(3, 3, CV_32F), + InputArray T = Mat::zeros(3, 1, CV_32F)); + + float scale; + float k[9]; + float rinv[9]; + float r_kinv[9]; + float k_rinv[9]; + float t[3]; +}; + +/** @brief Base class for rotation-based warper using a detail::ProjectorBase_ derived class. + */ +template +class CV_EXPORTS RotationWarperBase : public RotationWarper +{ +public: + Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R); + + Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap); + + Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + OutputArray dst); + + void warpBackward(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + Size dst_size, OutputArray dst); + + Rect warpRoi(Size src_size, InputArray K, InputArray R); + + float getScale() const { return projector_.scale; } + void setScale(float val) { projector_.scale = val; } + +protected: + + // Detects ROI of the destination image. It's correct for any projection. + virtual void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br); + + // Detects ROI of the destination image by walking over image border. + // Correctness for any projection isn't guaranteed. + void detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br); + + P projector_; +}; + + +struct CV_EXPORTS PlaneProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + +/** @brief Warper that maps an image onto the z = 1 plane. + */ +class CV_EXPORTS PlaneWarper : public RotationWarperBase +{ +public: + /** @brief Construct an instance of the plane warper class. + + @param scale Projected image scale multiplier + */ + PlaneWarper(float scale = 1.f) { projector_.scale = scale; } + + Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R); + Point2f warpPoint(const Point2f &pt, InputArray K, InputArray R, InputArray T); + + virtual Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray xmap, OutputArray ymap); + Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap); + + Point warp(InputArray src, InputArray K, InputArray R, + int interp_mode, int border_mode, OutputArray dst); + virtual Point warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode, + OutputArray dst); + + Rect warpRoi(Size src_size, InputArray K, InputArray R); + Rect warpRoi(Size src_size, InputArray K, InputArray R, InputArray T); + +protected: + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br); +}; + + +struct CV_EXPORTS SphericalProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +/** @brief Warper that maps an image onto the unit sphere located at the origin. + + Projects image onto unit sphere with origin at (0, 0, 0). + Poles are located at (0, -1, 0) and (0, 1, 0) points. +*/ +class CV_EXPORTS SphericalWarper : public RotationWarperBase +{ +public: + /** @brief Construct an instance of the spherical warper class. + + @param scale Projected image scale multiplier + */ + SphericalWarper(float scale) { projector_.scale = scale; } + + Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap); + Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst); +protected: + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br); +}; + + +struct CV_EXPORTS CylindricalProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +/** @brief Warper that maps an image onto the x\*x + z\*z = 1 cylinder. + */ +class CV_EXPORTS CylindricalWarper : public RotationWarperBase +{ +public: + /** @brief Construct an instance of the cylindrical warper class. + + @param scale Projected image scale multiplier + */ + CylindricalWarper(float scale) { projector_.scale = scale; } + + Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap); + Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, OutputArray dst); +protected: + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) + { + RotationWarperBase::detectResultRoiByBorder(src_size, dst_tl, dst_br); + } +}; + + +struct CV_EXPORTS FisheyeProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS FisheyeWarper : public RotationWarperBase +{ +public: + FisheyeWarper(float scale) { projector_.scale = scale; } +}; + + +struct CV_EXPORTS StereographicProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS StereographicWarper : public RotationWarperBase +{ +public: + StereographicWarper(float scale) { projector_.scale = scale; } +}; + + +struct CV_EXPORTS CompressedRectilinearProjector : ProjectorBase +{ + float a, b; + + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS CompressedRectilinearWarper : public RotationWarperBase +{ +public: + CompressedRectilinearWarper(float scale, float A = 1, float B = 1) + { + projector_.a = A; + projector_.b = B; + projector_.scale = scale; + } +}; + + +struct CV_EXPORTS CompressedRectilinearPortraitProjector : ProjectorBase +{ + float a, b; + + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS CompressedRectilinearPortraitWarper : public RotationWarperBase +{ +public: + CompressedRectilinearPortraitWarper(float scale, float A = 1, float B = 1) + { + projector_.a = A; + projector_.b = B; + projector_.scale = scale; + } +}; + + +struct CV_EXPORTS PaniniProjector : ProjectorBase +{ + float a, b; + + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS PaniniWarper : public RotationWarperBase +{ +public: + PaniniWarper(float scale, float A = 1, float B = 1) + { + projector_.a = A; + projector_.b = B; + projector_.scale = scale; + } +}; + + +struct CV_EXPORTS PaniniPortraitProjector : ProjectorBase +{ + float a, b; + + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS PaniniPortraitWarper : public RotationWarperBase +{ +public: + PaniniPortraitWarper(float scale, float A = 1, float B = 1) + { + projector_.a = A; + projector_.b = B; + projector_.scale = scale; + } + +}; + + +struct CV_EXPORTS MercatorProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS MercatorWarper : public RotationWarperBase +{ +public: + MercatorWarper(float scale) { projector_.scale = scale; } +}; + + +struct CV_EXPORTS TransverseMercatorProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS TransverseMercatorWarper : public RotationWarperBase +{ +public: + TransverseMercatorWarper(float scale) { projector_.scale = scale; } +}; + + +class CV_EXPORTS PlaneWarperGpu : public PlaneWarper +{ +public: + PlaneWarperGpu(float scale = 1.f) : PlaneWarper(scale) {} + + Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) + { + Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_); + d_xmap_.download(xmap); + d_ymap_.download(ymap); + return result; + } + + Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, OutputArray xmap, OutputArray ymap) + { + Rect result = buildMaps(src_size, K, R, T, d_xmap_, d_ymap_); + d_xmap_.download(xmap); + d_ymap_.download(ymap); + return result; + } + + Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + OutputArray dst) + { + d_src_.upload(src); + Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_); + d_dst_.download(dst); + return result; + } + + Point warp(InputArray src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode, + OutputArray dst) + { + d_src_.upload(src); + Point result = warp(d_src_, K, R, T, interp_mode, border_mode, d_dst_); + d_dst_.download(dst); + return result; + } + + Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap); + + Rect buildMaps(Size src_size, InputArray K, InputArray R, InputArray T, cuda::GpuMat & xmap, cuda::GpuMat & ymap); + + Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode, + cuda::GpuMat & dst); + + Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, InputArray T, int interp_mode, int border_mode, + cuda::GpuMat & dst); + +private: + cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_; +}; + + +class CV_EXPORTS SphericalWarperGpu : public SphericalWarper +{ +public: + SphericalWarperGpu(float scale) : SphericalWarper(scale) {} + + Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) + { + Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_); + d_xmap_.download(xmap); + d_ymap_.download(ymap); + return result; + } + + Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + OutputArray dst) + { + d_src_.upload(src); + Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_); + d_dst_.download(dst); + return result; + } + + Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap); + + Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode, + cuda::GpuMat & dst); + +private: + cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_; +}; + + +class CV_EXPORTS CylindricalWarperGpu : public CylindricalWarper +{ +public: + CylindricalWarperGpu(float scale) : CylindricalWarper(scale) {} + + Rect buildMaps(Size src_size, InputArray K, InputArray R, OutputArray xmap, OutputArray ymap) + { + Rect result = buildMaps(src_size, K, R, d_xmap_, d_ymap_); + d_xmap_.download(xmap); + d_ymap_.download(ymap); + return result; + } + + Point warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + OutputArray dst) + { + d_src_.upload(src); + Point result = warp(d_src_, K, R, interp_mode, border_mode, d_dst_); + d_dst_.download(dst); + return result; + } + + Rect buildMaps(Size src_size, InputArray K, InputArray R, cuda::GpuMat & xmap, cuda::GpuMat & ymap); + + Point warp(const cuda::GpuMat & src, InputArray K, InputArray R, int interp_mode, int border_mode, + cuda::GpuMat & dst); + +private: + cuda::GpuMat d_xmap_, d_ymap_, d_src_, d_dst_; +}; + + +struct SphericalPortraitProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +// Projects image onto unit sphere with origin at (0, 0, 0). +// Poles are located NOT at (0, -1, 0) and (0, 1, 0) points, BUT at (1, 0, 0) and (-1, 0, 0) points. +class CV_EXPORTS SphericalPortraitWarper : public RotationWarperBase +{ +public: + SphericalPortraitWarper(float scale) { projector_.scale = scale; } + +protected: + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br); +}; + +struct CylindricalPortraitProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS CylindricalPortraitWarper : public RotationWarperBase +{ +public: + CylindricalPortraitWarper(float scale) { projector_.scale = scale; } + +protected: + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) + { + RotationWarperBase::detectResultRoiByBorder(src_size, dst_tl, dst_br); + } +}; + +struct PlanePortraitProjector : ProjectorBase +{ + void mapForward(float x, float y, float &u, float &v); + void mapBackward(float u, float v, float &x, float &y); +}; + + +class CV_EXPORTS PlanePortraitWarper : public RotationWarperBase +{ +public: + PlanePortraitWarper(float scale) { projector_.scale = scale; } + +protected: + void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) + { + RotationWarperBase::detectResultRoiByBorder(src_size, dst_tl, dst_br); + } +}; + +//! @} stitching_warp + +} // namespace detail +} // namespace cv + +#include "warpers_inl.hpp" + +#endif // __OPENCV_STITCHING_WARPERS_HPP__ diff --git a/include/opencv2/stitching/detail/warpers_inl.hpp b/include/opencv2/stitching/detail/warpers_inl.hpp new file mode 100644 index 0000000..0416ecb --- /dev/null +++ b/include/opencv2/stitching/detail/warpers_inl.hpp @@ -0,0 +1,774 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_WARPERS_INL_HPP__ +#define __OPENCV_STITCHING_WARPERS_INL_HPP__ + +#include "opencv2/core.hpp" +#include "warpers.hpp" // Make your IDE see declarations +#include + +//! @cond IGNORED + +namespace cv { +namespace detail { + +template +Point2f RotationWarperBase

::warpPoint(const Point2f &pt, InputArray K, InputArray R) +{ + projector_.setCameraParams(K, R); + Point2f uv; + projector_.mapForward(pt.x, pt.y, uv.x, uv.y); + return uv; +} + + +template +Rect RotationWarperBase

::buildMaps(Size src_size, InputArray K, InputArray R, OutputArray _xmap, OutputArray _ymap) +{ + projector_.setCameraParams(K, R); + + Point dst_tl, dst_br; + detectResultRoi(src_size, dst_tl, dst_br); + + _xmap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); + _ymap.create(dst_br.y - dst_tl.y + 1, dst_br.x - dst_tl.x + 1, CV_32F); + + Mat xmap = _xmap.getMat(), ymap = _ymap.getMat(); + + float x, y; + for (int v = dst_tl.y; v <= dst_br.y; ++v) + { + for (int u = dst_tl.x; u <= dst_br.x; ++u) + { + projector_.mapBackward(static_cast(u), static_cast(v), x, y); + xmap.at(v - dst_tl.y, u - dst_tl.x) = x; + ymap.at(v - dst_tl.y, u - dst_tl.x) = y; + } + } + + return Rect(dst_tl, dst_br); +} + + +template +Point RotationWarperBase

::warp(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + OutputArray dst) +{ + UMat xmap, ymap; + Rect dst_roi = buildMaps(src.size(), K, R, xmap, ymap); + + dst.create(dst_roi.height + 1, dst_roi.width + 1, src.type()); + remap(src, dst, xmap, ymap, interp_mode, border_mode); + + return dst_roi.tl(); +} + + +template +void RotationWarperBase

::warpBackward(InputArray src, InputArray K, InputArray R, int interp_mode, int border_mode, + Size dst_size, OutputArray dst) +{ + projector_.setCameraParams(K, R); + + Point src_tl, src_br; + detectResultRoi(dst_size, src_tl, src_br); + + Size size = src.size(); + CV_Assert(src_br.x - src_tl.x + 1 == size.width && src_br.y - src_tl.y + 1 == size.height); + + Mat xmap(dst_size, CV_32F); + Mat ymap(dst_size, CV_32F); + + float u, v; + for (int y = 0; y < dst_size.height; ++y) + { + for (int x = 0; x < dst_size.width; ++x) + { + projector_.mapForward(static_cast(x), static_cast(y), u, v); + xmap.at(y, x) = u - src_tl.x; + ymap.at(y, x) = v - src_tl.y; + } + } + + dst.create(dst_size, src.type()); + remap(src, dst, xmap, ymap, interp_mode, border_mode); +} + + +template +Rect RotationWarperBase

::warpRoi(Size src_size, InputArray K, InputArray R) +{ + projector_.setCameraParams(K, R); + + Point dst_tl, dst_br; + detectResultRoi(src_size, dst_tl, dst_br); + + return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1)); +} + + +template +void RotationWarperBase

::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br) +{ + float tl_uf = std::numeric_limits::max(); + float tl_vf = std::numeric_limits::max(); + float br_uf = -std::numeric_limits::max(); + float br_vf = -std::numeric_limits::max(); + + float u, v; + for (int y = 0; y < src_size.height; ++y) + { + for (int x = 0; x < src_size.width; ++x) + { + projector_.mapForward(static_cast(x), static_cast(y), u, v); + tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); + br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + } + } + + dst_tl.x = static_cast(tl_uf); + dst_tl.y = static_cast(tl_vf); + dst_br.x = static_cast(br_uf); + dst_br.y = static_cast(br_vf); +} + + +template +void RotationWarperBase

::detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br) +{ + float tl_uf = std::numeric_limits::max(); + float tl_vf = std::numeric_limits::max(); + float br_uf = -std::numeric_limits::max(); + float br_vf = -std::numeric_limits::max(); + + float u, v; + for (float x = 0; x < src_size.width; ++x) + { + projector_.mapForward(static_cast(x), 0, u, v); + tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); + br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + + projector_.mapForward(static_cast(x), static_cast(src_size.height - 1), u, v); + tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); + br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + } + for (int y = 0; y < src_size.height; ++y) + { + projector_.mapForward(0, static_cast(y), u, v); + tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); + br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + + projector_.mapForward(static_cast(src_size.width - 1), static_cast(y), u, v); + tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v); + br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v); + } + + dst_tl.x = static_cast(tl_uf); + dst_tl.y = static_cast(tl_vf); + dst_br.x = static_cast(br_uf); + dst_br.y = static_cast(br_vf); +} + + +inline +void PlaneProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + x_ = t[0] + x_ / z_ * (1 - t[2]); + y_ = t[1] + y_ / z_ * (1 - t[2]); + + u = scale * x_; + v = scale * y_; +} + + +inline +void PlaneProjector::mapBackward(float u, float v, float &x, float &y) +{ + u = u / scale - t[0]; + v = v / scale - t[1]; + + float z; + x = k_rinv[0] * u + k_rinv[1] * v + k_rinv[2] * (1 - t[2]); + y = k_rinv[3] * u + k_rinv[4] * v + k_rinv[5] * (1 - t[2]); + z = k_rinv[6] * u + k_rinv[7] * v + k_rinv[8] * (1 - t[2]); + + x /= z; + y /= z; +} + + +inline +void SphericalProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + u = scale * atan2f(x_, z_); + float w = y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_); + v = scale * (static_cast(CV_PI) - acosf(w == w ? w : 0)); +} + + +inline +void SphericalProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= scale; + v /= scale; + + float sinv = sinf(static_cast(CV_PI) - v); + float x_ = sinv * sinf(u); + float y_ = cosf(static_cast(CV_PI) - v); + float z_ = sinv * cosf(u); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + + +inline +void CylindricalProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + u = scale * atan2f(x_, z_); + v = scale * y_ / sqrtf(x_ * x_ + z_ * z_); +} + + +inline +void CylindricalProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= scale; + v /= scale; + + float x_ = sinf(u); + float y_ = v; + float z_ = cosf(u); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void FisheyeProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float u_ = atan2f(x_, z_); + float v_ = (float)CV_PI - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)); + + u = scale * v_ * cosf(u_); + v = scale * v_ * sinf(u_); +} + +inline +void FisheyeProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= scale; + v /= scale; + + float u_ = atan2f(v, u); + float v_ = sqrtf(u*u + v*v); + + float sinv = sinf((float)CV_PI - v_); + float x_ = sinv * sinf(u_); + float y_ = cosf((float)CV_PI - v_); + float z_ = sinv * cosf(u_); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void StereographicProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float u_ = atan2f(x_, z_); + float v_ = (float)CV_PI - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)); + + float r = sinf(v_) / (1 - cosf(v_)); + + u = scale * r * cos(u_); + v = scale * r * sin(u_); +} + +inline +void StereographicProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= scale; + v /= scale; + + float u_ = atan2f(v, u); + float r = sqrtf(u*u + v*v); + float v_ = 2 * atanf(1.f / r); + + float sinv = sinf((float)CV_PI - v_); + float x_ = sinv * sinf(u_); + float y_ = cosf((float)CV_PI - v_); + float z_ = sinv * cosf(u_); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void CompressedRectilinearProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float u_ = atan2f(x_, z_); + float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)); + + u = scale * a * tanf(u_ / a); + v = scale * b * tanf(v_) / cosf(u_); +} + +inline +void CompressedRectilinearProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= scale; + v /= scale; + + float aatg = a * atanf(u / a); + float u_ = aatg; + float v_ = atanf(v * cosf(aatg) / b); + + float cosv = cosf(v_); + float x_ = cosv * sinf(u_); + float y_ = sinf(v_); + float z_ = cosv * cosf(u_); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void CompressedRectilinearPortraitProjector::mapForward(float x, float y, float &u, float &v) +{ + float y_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float x_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float u_ = atan2f(x_, z_); + float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)); + + u = - scale * a * tanf(u_ / a); + v = scale * b * tanf(v_) / cosf(u_); +} + +inline +void CompressedRectilinearPortraitProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= - scale; + v /= scale; + + float aatg = a * atanf(u / a); + float u_ = aatg; + float v_ = atanf(v * cosf( aatg ) / b); + + float cosv = cosf(v_); + float y_ = cosv * sinf(u_); + float x_ = sinf(v_); + float z_ = cosv * cosf(u_); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void PaniniProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float u_ = atan2f(x_, z_); + float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)); + + float tg = a * tanf(u_ / a); + u = scale * tg; + + float sinu = sinf(u_); + if ( fabs(sinu) < 1E-7 ) + v = scale * b * tanf(v_); + else + v = scale * b * tg * tanf(v_) / sinu; +} + +inline +void PaniniProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= scale; + v /= scale; + + float lamda = a * atanf(u / a); + float u_ = lamda; + + float v_; + if ( fabs(lamda) > 1E-7) + v_ = atanf(v * sinf(lamda) / (b * a * tanf(lamda / a))); + else + v_ = atanf(v / b); + + float cosv = cosf(v_); + float x_ = cosv * sinf(u_); + float y_ = sinf(v_); + float z_ = cosv * cosf(u_); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void PaniniPortraitProjector::mapForward(float x, float y, float &u, float &v) +{ + float y_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float x_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float u_ = atan2f(x_, z_); + float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)); + + float tg = a * tanf(u_ / a); + u = - scale * tg; + + float sinu = sinf( u_ ); + if ( fabs(sinu) < 1E-7 ) + v = scale * b * tanf(v_); + else + v = scale * b * tg * tanf(v_) / sinu; +} + +inline +void PaniniPortraitProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= - scale; + v /= scale; + + float lamda = a * atanf(u / a); + float u_ = lamda; + + float v_; + if ( fabs(lamda) > 1E-7) + v_ = atanf(v * sinf(lamda) / (b * a * tanf(lamda/a))); + else + v_ = atanf(v / b); + + float cosv = cosf(v_); + float y_ = cosv * sinf(u_); + float x_ = sinf(v_); + float z_ = cosv * cosf(u_); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void MercatorProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float u_ = atan2f(x_, z_); + float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)); + + u = scale * u_; + v = scale * logf( tanf( (float)(CV_PI/4) + v_/2 ) ); +} + +inline +void MercatorProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= scale; + v /= scale; + + float v_ = atanf( sinhf(v) ); + float u_ = u; + + float cosv = cosf(v_); + float x_ = cosv * sinf(u_); + float y_ = sinf(v_); + float z_ = cosv * cosf(u_); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void TransverseMercatorProjector::mapForward(float x, float y, float &u, float &v) +{ + float x_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float u_ = atan2f(x_, z_); + float v_ = asinf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_)); + + float B = cosf(v_) * sinf(u_); + + u = scale / 2 * logf( (1+B) / (1-B) ); + v = scale * atan2f(tanf(v_), cosf(u_)); +} + +inline +void TransverseMercatorProjector::mapBackward(float u, float v, float &x, float &y) +{ + u /= scale; + v /= scale; + + float v_ = asinf( sinf(v) / coshf(u) ); + float u_ = atan2f( sinhf(u), cos(v) ); + + float cosv = cosf(v_); + float x_ = cosv * sinf(u_); + float y_ = sinf(v_); + float z_ = cosv * cosf(u_); + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void SphericalPortraitProjector::mapForward(float x, float y, float &u0, float &v0) +{ + float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float x_ = y0_; + float y_ = x0_; + float u, v; + + u = scale * atan2f(x_, z_); + v = scale * (static_cast(CV_PI) - acosf(y_ / sqrtf(x_ * x_ + y_ * y_ + z_ * z_))); + + u0 = -u;//v; + v0 = v;//u; +} + + +inline +void SphericalPortraitProjector::mapBackward(float u0, float v0, float &x, float &y) +{ + float u, v; + u = -u0;//v0; + v = v0;//u0; + + u /= scale; + v /= scale; + + float sinv = sinf(static_cast(CV_PI) - v); + float x0_ = sinv * sinf(u); + float y0_ = cosf(static_cast(CV_PI) - v); + float z_ = sinv * cosf(u); + + float x_ = y0_; + float y_ = x0_; + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void CylindricalPortraitProjector::mapForward(float x, float y, float &u0, float &v0) +{ + float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float x_ = y0_; + float y_ = x0_; + float u, v; + + u = scale * atan2f(x_, z_); + v = scale * y_ / sqrtf(x_ * x_ + z_ * z_); + + u0 = -u;//v; + v0 = v;//u; +} + + +inline +void CylindricalPortraitProjector::mapBackward(float u0, float v0, float &x, float &y) +{ + float u, v; + u = -u0;//v0; + v = v0;//u0; + + u /= scale; + v /= scale; + + float x0_ = sinf(u); + float y0_ = v; + float z_ = cosf(u); + + float x_ = y0_; + float y_ = x0_; + + float z; + x = k_rinv[0] * x_ + k_rinv[1] * y_ + k_rinv[2] * z_; + y = k_rinv[3] * x_ + k_rinv[4] * y_ + k_rinv[5] * z_; + z = k_rinv[6] * x_ + k_rinv[7] * y_ + k_rinv[8] * z_; + + if (z > 0) { x /= z; y /= z; } + else x = y = -1; +} + +inline +void PlanePortraitProjector::mapForward(float x, float y, float &u0, float &v0) +{ + float x0_ = r_kinv[0] * x + r_kinv[1] * y + r_kinv[2]; + float y0_ = r_kinv[3] * x + r_kinv[4] * y + r_kinv[5]; + float z_ = r_kinv[6] * x + r_kinv[7] * y + r_kinv[8]; + + float x_ = y0_; + float y_ = x0_; + + x_ = t[0] + x_ / z_ * (1 - t[2]); + y_ = t[1] + y_ / z_ * (1 - t[2]); + + float u,v; + u = scale * x_; + v = scale * y_; + + u0 = -u; + v0 = v; +} + + +inline +void PlanePortraitProjector::mapBackward(float u0, float v0, float &x, float &y) +{ + float u, v; + u = -u0; + v = v0; + + u = u / scale - t[0]; + v = v / scale - t[1]; + + float z; + x = k_rinv[0] * v + k_rinv[1] * u + k_rinv[2] * (1 - t[2]); + y = k_rinv[3] * v + k_rinv[4] * u + k_rinv[5] * (1 - t[2]); + z = k_rinv[6] * v + k_rinv[7] * u + k_rinv[8] * (1 - t[2]); + + x /= z; + y /= z; +} + + +} // namespace detail +} // namespace cv + +//! @endcond + +#endif // __OPENCV_STITCHING_WARPERS_INL_HPP__ diff --git a/include/opencv2/stitching/warpers.hpp b/include/opencv2/stitching/warpers.hpp new file mode 100644 index 0000000..7e570d3 --- /dev/null +++ b/include/opencv2/stitching/warpers.hpp @@ -0,0 +1,183 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_STITCHING_WARPER_CREATORS_HPP__ +#define __OPENCV_STITCHING_WARPER_CREATORS_HPP__ + +#include "opencv2/stitching/detail/warpers.hpp" + +namespace cv { + +//! @addtogroup stitching_warp +//! @{ + +/** @brief Image warper factories base class. + */ +class WarperCreator +{ +public: + virtual ~WarperCreator() {} + virtual Ptr create(float scale) const = 0; +}; + +/** @brief Plane warper factory class. + @sa detail::PlaneWarper + */ +class PlaneWarper : public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + +/** @brief Cylindrical warper factory class. +@sa detail::CylindricalWarper +*/ +class CylindricalWarper: public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + +/** @brief Spherical warper factory class */ +class SphericalWarper: public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + +class FisheyeWarper : public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + +class StereographicWarper: public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + +class CompressedRectilinearWarper: public WarperCreator +{ + float a, b; +public: + CompressedRectilinearWarper(float A = 1, float B = 1) + { + a = A; b = B; + } + Ptr create(float scale) const { return makePtr(scale, a, b); } +}; + +class CompressedRectilinearPortraitWarper: public WarperCreator +{ + float a, b; +public: + CompressedRectilinearPortraitWarper(float A = 1, float B = 1) + { + a = A; b = B; + } + Ptr create(float scale) const { return makePtr(scale, a, b); } +}; + +class PaniniWarper: public WarperCreator +{ + float a, b; +public: + PaniniWarper(float A = 1, float B = 1) + { + a = A; b = B; + } + Ptr create(float scale) const { return makePtr(scale, a, b); } +}; + +class PaniniPortraitWarper: public WarperCreator +{ + float a, b; +public: + PaniniPortraitWarper(float A = 1, float B = 1) + { + a = A; b = B; + } + Ptr create(float scale) const { return makePtr(scale, a, b); } +}; + +class MercatorWarper: public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + +class TransverseMercatorWarper: public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + + + +#ifdef HAVE_OPENCV_CUDAWARPING +class PlaneWarperGpu: public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + + +class CylindricalWarperGpu: public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; + + +class SphericalWarperGpu: public WarperCreator +{ +public: + Ptr create(float scale) const { return makePtr(scale); } +}; +#endif + +//! @} stitching_warp + +} // namespace cv + +#endif // __OPENCV_STITCHING_WARPER_CREATORS_HPP__ diff --git a/include/opencv2/superres.hpp b/include/opencv2/superres.hpp new file mode 100644 index 0000000..dec8e4e --- /dev/null +++ b/include/opencv2/superres.hpp @@ -0,0 +1,207 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_SUPERRES_HPP__ +#define __OPENCV_SUPERRES_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/superres/optical_flow.hpp" + +/** + @defgroup superres Super Resolution + +The Super Resolution module contains a set of functions and classes that can be used to solve the +problem of resolution enhancement. There are a few methods implemented, most of them are descibed in +the papers @cite Farsiu03 and @cite Mitzel09 . + + */ + +namespace cv +{ + namespace superres + { + +//! @addtogroup superres +//! @{ + + class CV_EXPORTS FrameSource + { + public: + virtual ~FrameSource(); + + virtual void nextFrame(OutputArray frame) = 0; + virtual void reset() = 0; + }; + + CV_EXPORTS Ptr createFrameSource_Empty(); + + CV_EXPORTS Ptr createFrameSource_Video(const String& fileName); + CV_EXPORTS Ptr createFrameSource_Video_CUDA(const String& fileName); + + CV_EXPORTS Ptr createFrameSource_Camera(int deviceId = 0); + + /** @brief Base class for Super Resolution algorithms. + + The class is only used to define the common interface for the whole family of Super Resolution + algorithms. + */ + class CV_EXPORTS SuperResolution : public cv::Algorithm, public FrameSource + { + public: + /** @brief Set input frame source for Super Resolution algorithm. + + @param frameSource Input frame source + */ + void setInput(const Ptr& frameSource); + + /** @brief Process next frame from input and return output result. + + @param frame Output result + */ + void nextFrame(OutputArray frame); + void reset(); + + /** @brief Clear all inner buffers. + */ + virtual void collectGarbage(); + + //! @brief Scale factor + /** @see setScale */ + virtual int getScale() const = 0; + /** @copybrief getScale @see getScale */ + virtual void setScale(int val) = 0; + + //! @brief Iterations count + /** @see setIterations */ + virtual int getIterations() const = 0; + /** @copybrief getIterations @see getIterations */ + virtual void setIterations(int val) = 0; + + //! @brief Asymptotic value of steepest descent method + /** @see setTau */ + virtual double getTau() const = 0; + /** @copybrief getTau @see getTau */ + virtual void setTau(double val) = 0; + + //! @brief Weight parameter to balance data term and smoothness term + /** @see setLabmda */ + virtual double getLabmda() const = 0; + /** @copybrief getLabmda @see getLabmda */ + virtual void setLabmda(double val) = 0; + + //! @brief Parameter of spacial distribution in Bilateral-TV + /** @see setAlpha */ + virtual double getAlpha() const = 0; + /** @copybrief getAlpha @see getAlpha */ + virtual void setAlpha(double val) = 0; + + //! @brief Kernel size of Bilateral-TV filter + /** @see setKernelSize */ + virtual int getKernelSize() const = 0; + /** @copybrief getKernelSize @see getKernelSize */ + virtual void setKernelSize(int val) = 0; + + //! @brief Gaussian blur kernel size + /** @see setBlurKernelSize */ + virtual int getBlurKernelSize() const = 0; + /** @copybrief getBlurKernelSize @see getBlurKernelSize */ + virtual void setBlurKernelSize(int val) = 0; + + //! @brief Gaussian blur sigma + /** @see setBlurSigma */ + virtual double getBlurSigma() const = 0; + /** @copybrief getBlurSigma @see getBlurSigma */ + virtual void setBlurSigma(double val) = 0; + + //! @brief Radius of the temporal search area + /** @see setTemporalAreaRadius */ + virtual int getTemporalAreaRadius() const = 0; + /** @copybrief getTemporalAreaRadius @see getTemporalAreaRadius */ + virtual void setTemporalAreaRadius(int val) = 0; + + //! @brief Dense optical flow algorithm + /** @see setOpticalFlow */ + virtual Ptr getOpticalFlow() const = 0; + /** @copybrief getOpticalFlow @see getOpticalFlow */ + virtual void setOpticalFlow(const Ptr &val) = 0; + + protected: + SuperResolution(); + + virtual void initImpl(Ptr& frameSource) = 0; + virtual void processImpl(Ptr& frameSource, OutputArray output) = 0; + + bool isUmat_; + + private: + Ptr frameSource_; + bool firstCall_; + }; + + /** @brief Create Bilateral TV-L1 Super Resolution. + + This class implements Super Resolution algorithm described in the papers @cite Farsiu03 and + @cite Mitzel09 . + + Here are important members of the class that control the algorithm, which you can set after + constructing the class instance: + + - **int scale** Scale factor. + - **int iterations** Iteration count. + - **double tau** Asymptotic value of steepest descent method. + - **double lambda** Weight parameter to balance data term and smoothness term. + - **double alpha** Parameter of spacial distribution in Bilateral-TV. + - **int btvKernelSize** Kernel size of Bilateral-TV filter. + - **int blurKernelSize** Gaussian blur kernel size. + - **double blurSigma** Gaussian blur sigma. + - **int temporalAreaRadius** Radius of the temporal search area. + - **Ptr\ opticalFlow** Dense optical flow algorithm. + */ + CV_EXPORTS Ptr createSuperResolution_BTVL1(); + CV_EXPORTS Ptr createSuperResolution_BTVL1_CUDA(); + +//! @} superres + + } +} + +#endif // __OPENCV_SUPERRES_HPP__ diff --git a/include/opencv2/superres/optical_flow.hpp b/include/opencv2/superres/optical_flow.hpp new file mode 100644 index 0000000..d2f29a3 --- /dev/null +++ b/include/opencv2/superres/optical_flow.hpp @@ -0,0 +1,203 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_SUPERRES_OPTICAL_FLOW_HPP__ +#define __OPENCV_SUPERRES_OPTICAL_FLOW_HPP__ + +#include "opencv2/core.hpp" + +namespace cv +{ + namespace superres + { + +//! @addtogroup superres +//! @{ + + class CV_EXPORTS DenseOpticalFlowExt : public cv::Algorithm + { + public: + virtual void calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2 = noArray()) = 0; + virtual void collectGarbage() = 0; + }; + + + class CV_EXPORTS FarnebackOpticalFlow : public virtual DenseOpticalFlowExt + { + public: + /** @see setPyrScale */ + virtual double getPyrScale() const = 0; + /** @copybrief getPyrScale @see getPyrScale */ + virtual void setPyrScale(double val) = 0; + /** @see setLevelsNumber */ + virtual int getLevelsNumber() const = 0; + /** @copybrief getLevelsNumber @see getLevelsNumber */ + virtual void setLevelsNumber(int val) = 0; + /** @see setWindowSize */ + virtual int getWindowSize() const = 0; + /** @copybrief getWindowSize @see getWindowSize */ + virtual void setWindowSize(int val) = 0; + /** @see setIterations */ + virtual int getIterations() const = 0; + /** @copybrief getIterations @see getIterations */ + virtual void setIterations(int val) = 0; + /** @see setPolyN */ + virtual int getPolyN() const = 0; + /** @copybrief getPolyN @see getPolyN */ + virtual void setPolyN(int val) = 0; + /** @see setPolySigma */ + virtual double getPolySigma() const = 0; + /** @copybrief getPolySigma @see getPolySigma */ + virtual void setPolySigma(double val) = 0; + /** @see setFlags */ + virtual int getFlags() const = 0; + /** @copybrief getFlags @see getFlags */ + virtual void setFlags(int val) = 0; + }; + CV_EXPORTS Ptr createOptFlow_Farneback(); + CV_EXPORTS Ptr createOptFlow_Farneback_CUDA(); + + +// CV_EXPORTS Ptr createOptFlow_Simple(); + + + class CV_EXPORTS DualTVL1OpticalFlow : public virtual DenseOpticalFlowExt + { + public: + /** @see setTau */ + virtual double getTau() const = 0; + /** @copybrief getTau @see getTau */ + virtual void setTau(double val) = 0; + /** @see setLambda */ + virtual double getLambda() const = 0; + /** @copybrief getLambda @see getLambda */ + virtual void setLambda(double val) = 0; + /** @see setTheta */ + virtual double getTheta() const = 0; + /** @copybrief getTheta @see getTheta */ + virtual void setTheta(double val) = 0; + /** @see setScalesNumber */ + virtual int getScalesNumber() const = 0; + /** @copybrief getScalesNumber @see getScalesNumber */ + virtual void setScalesNumber(int val) = 0; + /** @see setWarpingsNumber */ + virtual int getWarpingsNumber() const = 0; + /** @copybrief getWarpingsNumber @see getWarpingsNumber */ + virtual void setWarpingsNumber(int val) = 0; + /** @see setEpsilon */ + virtual double getEpsilon() const = 0; + /** @copybrief getEpsilon @see getEpsilon */ + virtual void setEpsilon(double val) = 0; + /** @see setIterations */ + virtual int getIterations() const = 0; + /** @copybrief getIterations @see getIterations */ + virtual void setIterations(int val) = 0; + /** @see setUseInitialFlow */ + virtual bool getUseInitialFlow() const = 0; + /** @copybrief getUseInitialFlow @see getUseInitialFlow */ + virtual void setUseInitialFlow(bool val) = 0; + }; + CV_EXPORTS Ptr createOptFlow_DualTVL1(); + CV_EXPORTS Ptr createOptFlow_DualTVL1_CUDA(); + + + class CV_EXPORTS BroxOpticalFlow : public virtual DenseOpticalFlowExt + { + public: + //! @brief Flow smoothness + /** @see setAlpha */ + virtual double getAlpha() const = 0; + /** @copybrief getAlpha @see getAlpha */ + virtual void setAlpha(double val) = 0; + //! @brief Gradient constancy importance + /** @see setGamma */ + virtual double getGamma() const = 0; + /** @copybrief getGamma @see getGamma */ + virtual void setGamma(double val) = 0; + //! @brief Pyramid scale factor + /** @see setScaleFactor */ + virtual double getScaleFactor() const = 0; + /** @copybrief getScaleFactor @see getScaleFactor */ + virtual void setScaleFactor(double val) = 0; + //! @brief Number of lagged non-linearity iterations (inner loop) + /** @see setInnerIterations */ + virtual int getInnerIterations() const = 0; + /** @copybrief getInnerIterations @see getInnerIterations */ + virtual void setInnerIterations(int val) = 0; + //! @brief Number of warping iterations (number of pyramid levels) + /** @see setOuterIterations */ + virtual int getOuterIterations() const = 0; + /** @copybrief getOuterIterations @see getOuterIterations */ + virtual void setOuterIterations(int val) = 0; + //! @brief Number of linear system solver iterations + /** @see setSolverIterations */ + virtual int getSolverIterations() const = 0; + /** @copybrief getSolverIterations @see getSolverIterations */ + virtual void setSolverIterations(int val) = 0; + }; + CV_EXPORTS Ptr createOptFlow_Brox_CUDA(); + + + class PyrLKOpticalFlow : public virtual DenseOpticalFlowExt + { + public: + /** @see setWindowSize */ + virtual int getWindowSize() const = 0; + /** @copybrief getWindowSize @see getWindowSize */ + virtual void setWindowSize(int val) = 0; + /** @see setMaxLevel */ + virtual int getMaxLevel() const = 0; + /** @copybrief getMaxLevel @see getMaxLevel */ + virtual void setMaxLevel(int val) = 0; + /** @see setIterations */ + virtual int getIterations() const = 0; + /** @copybrief getIterations @see getIterations */ + virtual void setIterations(int val) = 0; + }; + CV_EXPORTS Ptr createOptFlow_PyrLK_CUDA(); + +//! @} + + } +} + +#endif // __OPENCV_SUPERRES_OPTICAL_FLOW_HPP__ diff --git a/include/opencv2/video.hpp b/include/opencv2/video.hpp new file mode 100644 index 0000000..a593815 --- /dev/null +++ b/include/opencv2/video.hpp @@ -0,0 +1,63 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEO_HPP__ +#define __OPENCV_VIDEO_HPP__ + +/** + @defgroup video Video Analysis + @{ + @defgroup video_motion Motion Analysis + @defgroup video_track Object Tracking + @defgroup video_c C API + @} +*/ + +#include "opencv2/video/tracking.hpp" +#include "opencv2/video/background_segm.hpp" + +#ifndef DISABLE_OPENCV_24_COMPATIBILITY +#include "opencv2/video/tracking_c.h" +#endif + +#endif //__OPENCV_VIDEO_HPP__ diff --git a/include/opencv2/video/background_segm.hpp b/include/opencv2/video/background_segm.hpp new file mode 100644 index 0000000..dbeccbd --- /dev/null +++ b/include/opencv2/video/background_segm.hpp @@ -0,0 +1,306 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_BACKGROUND_SEGM_HPP__ +#define __OPENCV_BACKGROUND_SEGM_HPP__ + +#include "opencv2/core.hpp" + +namespace cv +{ + +//! @addtogroup video_motion +//! @{ + +/** @brief Base class for background/foreground segmentation. : + +The class is only used to define the common interface for the whole family of background/foreground +segmentation algorithms. + */ +class CV_EXPORTS_W BackgroundSubtractor : public Algorithm +{ +public: + /** @brief Computes a foreground mask. + + @param image Next video frame. + @param fgmask The output foreground mask as an 8-bit binary image. + @param learningRate The value between 0 and 1 that indicates how fast the background model is + learnt. Negative parameter value makes the algorithm to use some automatically chosen learning + rate. 0 means that the background model is not updated at all, 1 means that the background model + is completely reinitialized from the last frame. + */ + CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate=-1) = 0; + + /** @brief Computes a background image. + + @param backgroundImage The output background image. + + @note Sometimes the background image can be very blurry, as it contain the average background + statistics. + */ + CV_WRAP virtual void getBackgroundImage(OutputArray backgroundImage) const = 0; +}; + + +/** @brief Gaussian Mixture-based Background/Foreground Segmentation Algorithm. + +The class implements the Gaussian mixture model background subtraction described in @cite Zivkovic2004 +and @cite Zivkovic2006 . + */ +class CV_EXPORTS_W BackgroundSubtractorMOG2 : public BackgroundSubtractor +{ +public: + /** @brief Returns the number of last frames that affect the background model + */ + CV_WRAP virtual int getHistory() const = 0; + /** @brief Sets the number of last frames that affect the background model + */ + CV_WRAP virtual void setHistory(int history) = 0; + + /** @brief Returns the number of gaussian components in the background model + */ + CV_WRAP virtual int getNMixtures() const = 0; + /** @brief Sets the number of gaussian components in the background model. + + The model needs to be reinitalized to reserve memory. + */ + CV_WRAP virtual void setNMixtures(int nmixtures) = 0;//needs reinitialization! + + /** @brief Returns the "background ratio" parameter of the algorithm + + If a foreground pixel keeps semi-constant value for about backgroundRatio\*history frames, it's + considered background and added to the model as a center of a new component. It corresponds to TB + parameter in the paper. + */ + CV_WRAP virtual double getBackgroundRatio() const = 0; + /** @brief Sets the "background ratio" parameter of the algorithm + */ + CV_WRAP virtual void setBackgroundRatio(double ratio) = 0; + + /** @brief Returns the variance threshold for the pixel-model match + + The main threshold on the squared Mahalanobis distance to decide if the sample is well described by + the background model or not. Related to Cthr from the paper. + */ + CV_WRAP virtual double getVarThreshold() const = 0; + /** @brief Sets the variance threshold for the pixel-model match + */ + CV_WRAP virtual void setVarThreshold(double varThreshold) = 0; + + /** @brief Returns the variance threshold for the pixel-model match used for new mixture component generation + + Threshold for the squared Mahalanobis distance that helps decide when a sample is close to the + existing components (corresponds to Tg in the paper). If a pixel is not close to any component, it + is considered foreground or added as a new component. 3 sigma =\> Tg=3\*3=9 is default. A smaller Tg + value generates more components. A higher Tg value may result in a small number of components but + they can grow too large. + */ + CV_WRAP virtual double getVarThresholdGen() const = 0; + /** @brief Sets the variance threshold for the pixel-model match used for new mixture component generation + */ + CV_WRAP virtual void setVarThresholdGen(double varThresholdGen) = 0; + + /** @brief Returns the initial variance of each gaussian component + */ + CV_WRAP virtual double getVarInit() const = 0; + /** @brief Sets the initial variance of each gaussian component + */ + CV_WRAP virtual void setVarInit(double varInit) = 0; + + CV_WRAP virtual double getVarMin() const = 0; + CV_WRAP virtual void setVarMin(double varMin) = 0; + + CV_WRAP virtual double getVarMax() const = 0; + CV_WRAP virtual void setVarMax(double varMax) = 0; + + /** @brief Returns the complexity reduction threshold + + This parameter defines the number of samples needed to accept to prove the component exists. CT=0.05 + is a default value for all the samples. By setting CT=0 you get an algorithm very similar to the + standard Stauffer&Grimson algorithm. + */ + CV_WRAP virtual double getComplexityReductionThreshold() const = 0; + /** @brief Sets the complexity reduction threshold + */ + CV_WRAP virtual void setComplexityReductionThreshold(double ct) = 0; + + /** @brief Returns the shadow detection flag + + If true, the algorithm detects shadows and marks them. See createBackgroundSubtractorMOG2 for + details. + */ + CV_WRAP virtual bool getDetectShadows() const = 0; + /** @brief Enables or disables shadow detection + */ + CV_WRAP virtual void setDetectShadows(bool detectShadows) = 0; + + /** @brief Returns the shadow value + + Shadow value is the value used to mark shadows in the foreground mask. Default value is 127. Value 0 + in the mask always means background, 255 means foreground. + */ + CV_WRAP virtual int getShadowValue() const = 0; + /** @brief Sets the shadow value + */ + CV_WRAP virtual void setShadowValue(int value) = 0; + + /** @brief Returns the shadow threshold + + A shadow is detected if pixel is a darker version of the background. The shadow threshold (Tau in + the paper) is a threshold defining how much darker the shadow can be. Tau= 0.5 means that if a pixel + is more than twice darker then it is not shadow. See Prati, Mikic, Trivedi and Cucchiarra, + *Detecting Moving Shadows...*, IEEE PAMI,2003. + */ + CV_WRAP virtual double getShadowThreshold() const = 0; + /** @brief Sets the shadow threshold + */ + CV_WRAP virtual void setShadowThreshold(double threshold) = 0; +}; + +/** @brief Creates MOG2 Background Subtractor + +@param history Length of the history. +@param varThreshold Threshold on the squared Mahalanobis distance between the pixel and the model +to decide whether a pixel is well described by the background model. This parameter does not +affect the background update. +@param detectShadows If true, the algorithm will detect shadows and mark them. It decreases the +speed a bit, so if you do not need this feature, set the parameter to false. + */ +CV_EXPORTS_W Ptr + createBackgroundSubtractorMOG2(int history=500, double varThreshold=16, + bool detectShadows=true); + +/** @brief K-nearest neigbours - based Background/Foreground Segmentation Algorithm. + +The class implements the K-nearest neigbours background subtraction described in @cite Zivkovic2006 . +Very efficient if number of foreground pixels is low. + */ +class CV_EXPORTS_W BackgroundSubtractorKNN : public BackgroundSubtractor +{ +public: + /** @brief Returns the number of last frames that affect the background model + */ + CV_WRAP virtual int getHistory() const = 0; + /** @brief Sets the number of last frames that affect the background model + */ + CV_WRAP virtual void setHistory(int history) = 0; + + /** @brief Returns the number of data samples in the background model + */ + CV_WRAP virtual int getNSamples() const = 0; + /** @brief Sets the number of data samples in the background model. + + The model needs to be reinitalized to reserve memory. + */ + CV_WRAP virtual void setNSamples(int _nN) = 0;//needs reinitialization! + + /** @brief Returns the threshold on the squared distance between the pixel and the sample + + The threshold on the squared distance between the pixel and the sample to decide whether a pixel is + close to a data sample. + */ + CV_WRAP virtual double getDist2Threshold() const = 0; + /** @brief Sets the threshold on the squared distance + */ + CV_WRAP virtual void setDist2Threshold(double _dist2Threshold) = 0; + + /** @brief Returns the number of neighbours, the k in the kNN. + + K is the number of samples that need to be within dist2Threshold in order to decide that that + pixel is matching the kNN background model. + */ + CV_WRAP virtual int getkNNSamples() const = 0; + /** @brief Sets the k in the kNN. How many nearest neigbours need to match. + */ + CV_WRAP virtual void setkNNSamples(int _nkNN) = 0; + + /** @brief Returns the shadow detection flag + + If true, the algorithm detects shadows and marks them. See createBackgroundSubtractorKNN for + details. + */ + CV_WRAP virtual bool getDetectShadows() const = 0; + /** @brief Enables or disables shadow detection + */ + CV_WRAP virtual void setDetectShadows(bool detectShadows) = 0; + + /** @brief Returns the shadow value + + Shadow value is the value used to mark shadows in the foreground mask. Default value is 127. Value 0 + in the mask always means background, 255 means foreground. + */ + CV_WRAP virtual int getShadowValue() const = 0; + /** @brief Sets the shadow value + */ + CV_WRAP virtual void setShadowValue(int value) = 0; + + /** @brief Returns the shadow threshold + + A shadow is detected if pixel is a darker version of the background. The shadow threshold (Tau in + the paper) is a threshold defining how much darker the shadow can be. Tau= 0.5 means that if a pixel + is more than twice darker then it is not shadow. See Prati, Mikic, Trivedi and Cucchiarra, + *Detecting Moving Shadows...*, IEEE PAMI,2003. + */ + CV_WRAP virtual double getShadowThreshold() const = 0; + /** @brief Sets the shadow threshold + */ + CV_WRAP virtual void setShadowThreshold(double threshold) = 0; +}; + +/** @brief Creates KNN Background Subtractor + +@param history Length of the history. +@param dist2Threshold Threshold on the squared distance between the pixel and the sample to decide +whether a pixel is close to that sample. This parameter does not affect the background update. +@param detectShadows If true, the algorithm will detect shadows and mark them. It decreases the +speed a bit, so if you do not need this feature, set the parameter to false. + */ +CV_EXPORTS_W Ptr + createBackgroundSubtractorKNN(int history=500, double dist2Threshold=400.0, + bool detectShadows=true); + +//! @} video_motion + +} // cv + +#endif diff --git a/include/opencv2/video/tracking.hpp b/include/opencv2/video/tracking.hpp new file mode 100644 index 0000000..217a26a --- /dev/null +++ b/include/opencv2/video/tracking.hpp @@ -0,0 +1,515 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_TRACKING_HPP__ +#define __OPENCV_TRACKING_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" + +namespace cv +{ + +//! @addtogroup video_track +//! @{ + +enum { OPTFLOW_USE_INITIAL_FLOW = 4, + OPTFLOW_LK_GET_MIN_EIGENVALS = 8, + OPTFLOW_FARNEBACK_GAUSSIAN = 256 + }; + +/** @brief Finds an object center, size, and orientation. + +@param probImage Back projection of the object histogram. See calcBackProject. +@param window Initial search window. +@param criteria Stop criteria for the underlying meanShift. +returns +(in old interfaces) Number of iterations CAMSHIFT took to converge +The function implements the CAMSHIFT object tracking algorithm @cite Bradski98 . First, it finds an +object center using meanShift and then adjusts the window size and finds the optimal rotation. The +function returns the rotated rectangle structure that includes the object position, size, and +orientation. The next position of the search window can be obtained with RotatedRect::boundingRect() + +See the OpenCV sample camshiftdemo.c that tracks colored objects. + +@note +- (Python) A sample explaining the camshift tracking algorithm can be found at + opencv_source_code/samples/python2/camshift.py + */ +CV_EXPORTS_W RotatedRect CamShift( InputArray probImage, CV_IN_OUT Rect& window, + TermCriteria criteria ); + +/** @brief Finds an object on a back projection image. + +@param probImage Back projection of the object histogram. See calcBackProject for details. +@param window Initial search window. +@param criteria Stop criteria for the iterative search algorithm. +returns +: Number of iterations CAMSHIFT took to converge. +The function implements the iterative object search algorithm. It takes the input back projection of +an object and the initial position. The mass center in window of the back projection image is +computed and the search window center shifts to the mass center. The procedure is repeated until the +specified number of iterations criteria.maxCount is done or until the window center shifts by less +than criteria.epsilon. The algorithm is used inside CamShift and, unlike CamShift , the search +window size or orientation do not change during the search. You can simply pass the output of +calcBackProject to this function. But better results can be obtained if you pre-filter the back +projection and remove the noise. For example, you can do this by retrieving connected components +with findContours , throwing away contours with small area ( contourArea ), and rendering the +remaining contours with drawContours. + +@note +- A mean-shift tracking sample can be found at opencv_source_code/samples/cpp/camshiftdemo.cpp + */ +CV_EXPORTS_W int meanShift( InputArray probImage, CV_IN_OUT Rect& window, TermCriteria criteria ); + +/** @brief Constructs the image pyramid which can be passed to calcOpticalFlowPyrLK. + +@param img 8-bit input image. +@param pyramid output pyramid. +@param winSize window size of optical flow algorithm. Must be not less than winSize argument of +calcOpticalFlowPyrLK. It is needed to calculate required padding for pyramid levels. +@param maxLevel 0-based maximal pyramid level number. +@param withDerivatives set to precompute gradients for the every pyramid level. If pyramid is +constructed without the gradients then calcOpticalFlowPyrLK will calculate them internally. +@param pyrBorder the border mode for pyramid layers. +@param derivBorder the border mode for gradients. +@param tryReuseInputImage put ROI of input image into the pyramid if possible. You can pass false +to force data copying. +@return number of levels in constructed pyramid. Can be less than maxLevel. + */ +CV_EXPORTS_W int buildOpticalFlowPyramid( InputArray img, OutputArrayOfArrays pyramid, + Size winSize, int maxLevel, bool withDerivatives = true, + int pyrBorder = BORDER_REFLECT_101, + int derivBorder = BORDER_CONSTANT, + bool tryReuseInputImage = true ); + +/** @brief Calculates an optical flow for a sparse feature set using the iterative Lucas-Kanade method with +pyramids. + +@param prevImg first 8-bit input image or pyramid constructed by buildOpticalFlowPyramid. +@param nextImg second input image or pyramid of the same size and the same type as prevImg. +@param prevPts vector of 2D points for which the flow needs to be found; point coordinates must be +single-precision floating-point numbers. +@param nextPts output vector of 2D points (with single-precision floating-point coordinates) +containing the calculated new positions of input features in the second image; when +OPTFLOW_USE_INITIAL_FLOW flag is passed, the vector must have the same size as in the input. +@param status output status vector (of unsigned chars); each element of the vector is set to 1 if +the flow for the corresponding features has been found, otherwise, it is set to 0. +@param err output vector of errors; each element of the vector is set to an error for the +corresponding feature, type of the error measure can be set in flags parameter; if the flow wasn't +found then the error is not defined (use the status parameter to find such cases). +@param winSize size of the search window at each pyramid level. +@param maxLevel 0-based maximal pyramid level number; if set to 0, pyramids are not used (single +level), if set to 1, two levels are used, and so on; if pyramids are passed to input then +algorithm will use as many levels as pyramids have but no more than maxLevel. +@param criteria parameter, specifying the termination criteria of the iterative search algorithm +(after the specified maximum number of iterations criteria.maxCount or when the search window +moves by less than criteria.epsilon. +@param flags operation flags: + - **OPTFLOW_USE_INITIAL_FLOW** uses initial estimations, stored in nextPts; if the flag is + not set, then prevPts is copied to nextPts and is considered the initial estimate. + - **OPTFLOW_LK_GET_MIN_EIGENVALS** use minimum eigen values as an error measure (see + minEigThreshold description); if the flag is not set, then L1 distance between patches + around the original and a moved point, divided by number of pixels in a window, is used as a + error measure. +@param minEigThreshold the algorithm calculates the minimum eigen value of a 2x2 normal matrix of +optical flow equations (this matrix is called a spatial gradient matrix in @cite Bouguet00), divided +by number of pixels in a window; if this value is less than minEigThreshold, then a corresponding +feature is filtered out and its flow is not processed, so it allows to remove bad points and get a +performance boost. + +The function implements a sparse iterative version of the Lucas-Kanade optical flow in pyramids. See +@cite Bouguet00 . The function is parallelized with the TBB library. + +@note + +- An example using the Lucas-Kanade optical flow algorithm can be found at + opencv_source_code/samples/cpp/lkdemo.cpp +- (Python) An example using the Lucas-Kanade optical flow algorithm can be found at + opencv_source_code/samples/python2/lk_track.py +- (Python) An example using the Lucas-Kanade tracker for homography matching can be found at + opencv_source_code/samples/python2/lk_homography.py + */ +CV_EXPORTS_W void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg, + InputArray prevPts, InputOutputArray nextPts, + OutputArray status, OutputArray err, + Size winSize = Size(21,21), int maxLevel = 3, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), + int flags = 0, double minEigThreshold = 1e-4 ); + +/** @brief Computes a dense optical flow using the Gunnar Farneback's algorithm. + +@param prev first 8-bit single-channel input image. +@param next second input image of the same size and the same type as prev. +@param flow computed flow image that has the same size as prev and type CV_32FC2. +@param pyr_scale parameter, specifying the image scale (\<1) to build pyramids for each image; +pyr_scale=0.5 means a classical pyramid, where each next layer is twice smaller than the previous +one. +@param levels number of pyramid layers including the initial image; levels=1 means that no extra +layers are created and only the original images are used. +@param winsize averaging window size; larger values increase the algorithm robustness to image +noise and give more chances for fast motion detection, but yield more blurred motion field. +@param iterations number of iterations the algorithm does at each pyramid level. +@param poly_n size of the pixel neighborhood used to find polynomial expansion in each pixel; +larger values mean that the image will be approximated with smoother surfaces, yielding more +robust algorithm and more blurred motion field, typically poly_n =5 or 7. +@param poly_sigma standard deviation of the Gaussian that is used to smooth derivatives used as a +basis for the polynomial expansion; for poly_n=5, you can set poly_sigma=1.1, for poly_n=7, a +good value would be poly_sigma=1.5. +@param flags operation flags that can be a combination of the following: + - **OPTFLOW_USE_INITIAL_FLOW** uses the input flow as an initial flow approximation. + - **OPTFLOW_FARNEBACK_GAUSSIAN** uses the Gaussian \f$\texttt{winsize}\times\texttt{winsize}\f$ + filter instead of a box filter of the same size for optical flow estimation; usually, this + option gives z more accurate flow than with a box filter, at the cost of lower speed; + normally, winsize for a Gaussian window should be set to a larger value to achieve the same + level of robustness. + +The function finds an optical flow for each prev pixel using the @cite Farneback2003 algorithm so that + +\f[\texttt{prev} (y,x) \sim \texttt{next} ( y + \texttt{flow} (y,x)[1], x + \texttt{flow} (y,x)[0])\f] + +@note + +- An example using the optical flow algorithm described by Gunnar Farneback can be found at + opencv_source_code/samples/cpp/fback.cpp +- (Python) An example using the optical flow algorithm described by Gunnar Farneback can be + found at opencv_source_code/samples/python2/opt_flow.py + */ +CV_EXPORTS_W void calcOpticalFlowFarneback( InputArray prev, InputArray next, InputOutputArray flow, + double pyr_scale, int levels, int winsize, + int iterations, int poly_n, double poly_sigma, + int flags ); + +/** @brief Computes an optimal affine transformation between two 2D point sets. + +@param src First input 2D point set stored in std::vector or Mat, or an image stored in Mat. +@param dst Second input 2D point set of the same size and the same type as A, or another image. +@param fullAffine If true, the function finds an optimal affine transformation with no additional +restrictions (6 degrees of freedom). Otherwise, the class of transformations to choose from is +limited to combinations of translation, rotation, and uniform scaling (5 degrees of freedom). + +The function finds an optimal affine transform *[A|b]* (a 2 x 3 floating-point matrix) that +approximates best the affine transformation between: + +* Two point sets +* Two raster images. In this case, the function first finds some features in the src image and + finds the corresponding features in dst image. After that, the problem is reduced to the first + case. +In case of point sets, the problem is formulated as follows: you need to find a 2x2 matrix *A* and +2x1 vector *b* so that: + +\f[[A^*|b^*] = arg \min _{[A|b]} \sum _i \| \texttt{dst}[i] - A { \texttt{src}[i]}^T - b \| ^2\f] +where src[i] and dst[i] are the i-th points in src and dst, respectively +\f$[A|b]\f$ can be either arbitrary (when fullAffine=true ) or have a form of +\f[\begin{bmatrix} a_{11} & a_{12} & b_1 \\ -a_{12} & a_{11} & b_2 \end{bmatrix}\f] +when fullAffine=false. + +@sa +getAffineTransform, getPerspectiveTransform, findHomography + */ +CV_EXPORTS_W Mat estimateRigidTransform( InputArray src, InputArray dst, bool fullAffine ); + + +enum +{ + MOTION_TRANSLATION = 0, + MOTION_EUCLIDEAN = 1, + MOTION_AFFINE = 2, + MOTION_HOMOGRAPHY = 3 +}; + +/** @brief Finds the geometric transform (warp) between two images in terms of the ECC criterion @cite EP08 . + +@param templateImage single-channel template image; CV_8U or CV_32F array. +@param inputImage single-channel input image which should be warped with the final warpMatrix in +order to provide an image similar to templateImage, same type as temlateImage. +@param warpMatrix floating-point \f$2\times 3\f$ or \f$3\times 3\f$ mapping matrix (warp). +@param motionType parameter, specifying the type of motion: + - **MOTION_TRANSLATION** sets a translational motion model; warpMatrix is \f$2\times 3\f$ with + the first \f$2\times 2\f$ part being the unity matrix and the rest two parameters being + estimated. + - **MOTION_EUCLIDEAN** sets a Euclidean (rigid) transformation as motion model; three + parameters are estimated; warpMatrix is \f$2\times 3\f$. + - **MOTION_AFFINE** sets an affine motion model (DEFAULT); six parameters are estimated; + warpMatrix is \f$2\times 3\f$. + - **MOTION_HOMOGRAPHY** sets a homography as a motion model; eight parameters are + estimated;\`warpMatrix\` is \f$3\times 3\f$. +@param criteria parameter, specifying the termination criteria of the ECC algorithm; +criteria.epsilon defines the threshold of the increment in the correlation coefficient between two +iterations (a negative criteria.epsilon makes criteria.maxcount the only termination criterion). +Default values are shown in the declaration above. +@param inputMask An optional mask to indicate valid values of inputImage. + +The function estimates the optimum transformation (warpMatrix) with respect to ECC criterion +(@cite EP08), that is + +\f[\texttt{warpMatrix} = \texttt{warpMatrix} = \arg\max_{W} \texttt{ECC}(\texttt{templateImage}(x,y),\texttt{inputImage}(x',y'))\f] + +where + +\f[\begin{bmatrix} x' \\ y' \end{bmatrix} = W \cdot \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}\f] + +(the equation holds with homogeneous coordinates for homography). It returns the final enhanced +correlation coefficient, that is the correlation coefficient between the template image and the +final warped input image. When a \f$3\times 3\f$ matrix is given with motionType =0, 1 or 2, the third +row is ignored. + +Unlike findHomography and estimateRigidTransform, the function findTransformECC implements an +area-based alignment that builds on intensity similarities. In essence, the function updates the +initial transformation that roughly aligns the images. If this information is missing, the identity +warp (unity matrix) should be given as input. Note that if images undergo strong +displacements/rotations, an initial transformation that roughly aligns the images is necessary +(e.g., a simple euclidean/similarity transform that allows for the images showing the same image +content approximately). Use inverse warping in the second image to take an image close to the first +one, i.e. use the flag WARP_INVERSE_MAP with warpAffine or warpPerspective. See also the OpenCV +sample image_alignment.cpp that demonstrates the use of the function. Note that the function throws +an exception if algorithm does not converges. + +@sa +estimateRigidTransform, findHomography + */ +CV_EXPORTS_W double findTransformECC( InputArray templateImage, InputArray inputImage, + InputOutputArray warpMatrix, int motionType = MOTION_AFFINE, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 50, 0.001), + InputArray inputMask = noArray()); + +/** @brief Kalman filter class. + +The class implements a standard Kalman filter , +@cite Welch95 . However, you can modify transitionMatrix, controlMatrix, and measurementMatrix to get +an extended Kalman filter functionality. See the OpenCV sample kalman.cpp. + +@note + +- An example using the standard Kalman filter can be found at + opencv_source_code/samples/cpp/kalman.cpp + */ +class CV_EXPORTS_W KalmanFilter +{ +public: + /** @brief The constructors. + + @note In C API when CvKalman\* kalmanFilter structure is not needed anymore, it should be released + with cvReleaseKalman(&kalmanFilter) + */ + CV_WRAP KalmanFilter(); + /** @overload + @param dynamParams Dimensionality of the state. + @param measureParams Dimensionality of the measurement. + @param controlParams Dimensionality of the control vector. + @param type Type of the created matrices that should be CV_32F or CV_64F. + */ + CV_WRAP KalmanFilter( int dynamParams, int measureParams, int controlParams = 0, int type = CV_32F ); + + /** @brief Re-initializes Kalman filter. The previous content is destroyed. + + @param dynamParams Dimensionality of the state. + @param measureParams Dimensionality of the measurement. + @param controlParams Dimensionality of the control vector. + @param type Type of the created matrices that should be CV_32F or CV_64F. + */ + void init( int dynamParams, int measureParams, int controlParams = 0, int type = CV_32F ); + + /** @brief Computes a predicted state. + + @param control The optional input control + */ + CV_WRAP const Mat& predict( const Mat& control = Mat() ); + + /** @brief Updates the predicted state from the measurement. + + @param measurement The measured system parameters + */ + CV_WRAP const Mat& correct( const Mat& measurement ); + + CV_PROP_RW Mat statePre; //!< predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k) + CV_PROP_RW Mat statePost; //!< corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) + CV_PROP_RW Mat transitionMatrix; //!< state transition matrix (A) + CV_PROP_RW Mat controlMatrix; //!< control matrix (B) (not used if there is no control) + CV_PROP_RW Mat measurementMatrix; //!< measurement matrix (H) + CV_PROP_RW Mat processNoiseCov; //!< process noise covariance matrix (Q) + CV_PROP_RW Mat measurementNoiseCov;//!< measurement noise covariance matrix (R) + CV_PROP_RW Mat errorCovPre; //!< priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/ + CV_PROP_RW Mat gain; //!< Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R) + CV_PROP_RW Mat errorCovPost; //!< posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k) + + // temporary matrices + Mat temp1; + Mat temp2; + Mat temp3; + Mat temp4; + Mat temp5; +}; + + +class CV_EXPORTS_W DenseOpticalFlow : public Algorithm +{ +public: + /** @brief Calculates an optical flow. + + @param I0 first 8-bit single-channel input image. + @param I1 second input image of the same size and the same type as prev. + @param flow computed flow image that has the same size as prev and type CV_32FC2. + */ + CV_WRAP virtual void calc( InputArray I0, InputArray I1, InputOutputArray flow ) = 0; + /** @brief Releases all inner buffers. + */ + CV_WRAP virtual void collectGarbage() = 0; +}; + +/** @brief "Dual TV L1" Optical Flow Algorithm. + +The class implements the "Dual TV L1" optical flow algorithm described in @cite Zach2007 and +@cite Javier2012 . +Here are important members of the class that control the algorithm, which you can set after +constructing the class instance: + +- member double tau + Time step of the numerical scheme. + +- member double lambda + Weight parameter for the data term, attachment parameter. This is the most relevant + parameter, which determines the smoothness of the output. The smaller this parameter is, + the smoother the solutions we obtain. It depends on the range of motions of the images, so + its value should be adapted to each image sequence. + +- member double theta + Weight parameter for (u - v)\^2, tightness parameter. It serves as a link between the + attachment and the regularization terms. In theory, it should have a small value in order + to maintain both parts in correspondence. The method is stable for a large range of values + of this parameter. + +- member int nscales + Number of scales used to create the pyramid of images. + +- member int warps + Number of warpings per scale. Represents the number of times that I1(x+u0) and grad( + I1(x+u0) ) are computed per scale. This is a parameter that assures the stability of the + method. It also affects the running time, so it is a compromise between speed and + accuracy. + +- member double epsilon + Stopping criterion threshold used in the numerical scheme, which is a trade-off between + precision and running time. A small value will yield more accurate solutions at the + expense of a slower convergence. + +- member int iterations + Stopping criterion iterations number used in the numerical scheme. + +C. Zach, T. Pock and H. Bischof, "A Duality Based Approach for Realtime TV-L1 Optical Flow". +Javier Sanchez, Enric Meinhardt-Llopis and Gabriele Facciolo. "TV-L1 Optical Flow Estimation". +*/ +class CV_EXPORTS_W DualTVL1OpticalFlow : public DenseOpticalFlow +{ +public: + //! @brief Time step of the numerical scheme + /** @see setTau */ + virtual double getTau() const = 0; + /** @copybrief getTau @see getTau */ + virtual void setTau(double val) = 0; + //! @brief Weight parameter for the data term, attachment parameter + /** @see setLambda */ + virtual double getLambda() const = 0; + /** @copybrief getLambda @see getLambda */ + virtual void setLambda(double val) = 0; + //! @brief Weight parameter for (u - v)^2, tightness parameter + /** @see setTheta */ + virtual double getTheta() const = 0; + /** @copybrief getTheta @see getTheta */ + virtual void setTheta(double val) = 0; + //! @brief coefficient for additional illumination variation term + /** @see setGamma */ + virtual double getGamma() const = 0; + /** @copybrief getGamma @see getGamma */ + virtual void setGamma(double val) = 0; + //! @brief Number of scales used to create the pyramid of images + /** @see setScalesNumber */ + virtual int getScalesNumber() const = 0; + /** @copybrief getScalesNumber @see getScalesNumber */ + virtual void setScalesNumber(int val) = 0; + //! @brief Number of warpings per scale + /** @see setWarpingsNumber */ + virtual int getWarpingsNumber() const = 0; + /** @copybrief getWarpingsNumber @see getWarpingsNumber */ + virtual void setWarpingsNumber(int val) = 0; + //! @brief Stopping criterion threshold used in the numerical scheme, which is a trade-off between precision and running time + /** @see setEpsilon */ + virtual double getEpsilon() const = 0; + /** @copybrief getEpsilon @see getEpsilon */ + virtual void setEpsilon(double val) = 0; + //! @brief Inner iterations (between outlier filtering) used in the numerical scheme + /** @see setInnerIterations */ + virtual int getInnerIterations() const = 0; + /** @copybrief getInnerIterations @see getInnerIterations */ + virtual void setInnerIterations(int val) = 0; + //! @brief Outer iterations (number of inner loops) used in the numerical scheme + /** @see setOuterIterations */ + virtual int getOuterIterations() const = 0; + /** @copybrief getOuterIterations @see getOuterIterations */ + virtual void setOuterIterations(int val) = 0; + //! @brief Use initial flow + /** @see setUseInitialFlow */ + virtual bool getUseInitialFlow() const = 0; + /** @copybrief getUseInitialFlow @see getUseInitialFlow */ + virtual void setUseInitialFlow(bool val) = 0; + //! @brief Step between scales (<1) + /** @see setScaleStep */ + virtual double getScaleStep() const = 0; + /** @copybrief getScaleStep @see getScaleStep */ + virtual void setScaleStep(double val) = 0; + //! @brief Median filter kernel size (1 = no filter) (3 or 5) + /** @see setMedianFiltering */ + virtual int getMedianFiltering() const = 0; + /** @copybrief getMedianFiltering @see getMedianFiltering */ + virtual void setMedianFiltering(int val) = 0; +}; + +/** @brief Creates instance of cv::DenseOpticalFlow +*/ +CV_EXPORTS_W Ptr createOptFlow_DualTVL1(); + +//! @} video_track + +} // cv + +#endif diff --git a/include/opencv2/video/tracking_c.h b/include/opencv2/video/tracking_c.h new file mode 100644 index 0000000..b355352 --- /dev/null +++ b/include/opencv2/video/tracking_c.h @@ -0,0 +1,232 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_TRACKING_C_H__ +#define __OPENCV_TRACKING_C_H__ + +#include "opencv2/imgproc/types_c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup video_c + @{ +*/ + +/****************************************************************************************\ +* Motion Analysis * +\****************************************************************************************/ + +/************************************ optical flow ***************************************/ + +#define CV_LKFLOW_PYR_A_READY 1 +#define CV_LKFLOW_PYR_B_READY 2 +#define CV_LKFLOW_INITIAL_GUESSES 4 +#define CV_LKFLOW_GET_MIN_EIGENVALS 8 + +/* It is Lucas & Kanade method, modified to use pyramids. + Also it does several iterations to get optical flow for + every point at every pyramid level. + Calculates optical flow between two images for certain set of points (i.e. + it is a "sparse" optical flow, which is opposite to the previous 3 methods) */ +CVAPI(void) cvCalcOpticalFlowPyrLK( const CvArr* prev, const CvArr* curr, + CvArr* prev_pyr, CvArr* curr_pyr, + const CvPoint2D32f* prev_features, + CvPoint2D32f* curr_features, + int count, + CvSize win_size, + int level, + char* status, + float* track_error, + CvTermCriteria criteria, + int flags ); + + +/* Modification of a previous sparse optical flow algorithm to calculate + affine flow */ +CVAPI(void) cvCalcAffineFlowPyrLK( const CvArr* prev, const CvArr* curr, + CvArr* prev_pyr, CvArr* curr_pyr, + const CvPoint2D32f* prev_features, + CvPoint2D32f* curr_features, + float* matrices, int count, + CvSize win_size, int level, + char* status, float* track_error, + CvTermCriteria criteria, int flags ); + +/* Estimate rigid transformation between 2 images or 2 point sets */ +CVAPI(int) cvEstimateRigidTransform( const CvArr* A, const CvArr* B, + CvMat* M, int full_affine ); + +/* Estimate optical flow for each pixel using the two-frame G. Farneback algorithm */ +CVAPI(void) cvCalcOpticalFlowFarneback( const CvArr* prev, const CvArr* next, + CvArr* flow, double pyr_scale, int levels, + int winsize, int iterations, int poly_n, + double poly_sigma, int flags ); + +/********************************* motion templates *************************************/ + +/****************************************************************************************\ +* All the motion template functions work only with single channel images. * +* Silhouette image must have depth IPL_DEPTH_8U or IPL_DEPTH_8S * +* Motion history image must have depth IPL_DEPTH_32F, * +* Gradient mask - IPL_DEPTH_8U or IPL_DEPTH_8S, * +* Motion orientation image - IPL_DEPTH_32F * +* Segmentation mask - IPL_DEPTH_32F * +* All the angles are in degrees, all the times are in milliseconds * +\****************************************************************************************/ + +/* Updates motion history image given motion silhouette */ +CVAPI(void) cvUpdateMotionHistory( const CvArr* silhouette, CvArr* mhi, + double timestamp, double duration ); + +/* Calculates gradient of the motion history image and fills + a mask indicating where the gradient is valid */ +CVAPI(void) cvCalcMotionGradient( const CvArr* mhi, CvArr* mask, CvArr* orientation, + double delta1, double delta2, + int aperture_size CV_DEFAULT(3)); + +/* Calculates average motion direction within a selected motion region + (region can be selected by setting ROIs and/or by composing a valid gradient mask + with the region mask) */ +CVAPI(double) cvCalcGlobalOrientation( const CvArr* orientation, const CvArr* mask, + const CvArr* mhi, double timestamp, + double duration ); + +/* Splits a motion history image into a few parts corresponding to separate independent motions + (e.g. left hand, right hand) */ +CVAPI(CvSeq*) cvSegmentMotion( const CvArr* mhi, CvArr* seg_mask, + CvMemStorage* storage, + double timestamp, double seg_thresh ); + +/****************************************************************************************\ +* Tracking * +\****************************************************************************************/ + +/* Implements CAMSHIFT algorithm - determines object position, size and orientation + from the object histogram back project (extension of meanshift) */ +CVAPI(int) cvCamShift( const CvArr* prob_image, CvRect window, + CvTermCriteria criteria, CvConnectedComp* comp, + CvBox2D* box CV_DEFAULT(NULL) ); + +/* Implements MeanShift algorithm - determines object position + from the object histogram back project */ +CVAPI(int) cvMeanShift( const CvArr* prob_image, CvRect window, + CvTermCriteria criteria, CvConnectedComp* comp ); + +/* +standard Kalman filter (in G. Welch' and G. Bishop's notation): + + x(k)=A*x(k-1)+B*u(k)+w(k) p(w)~N(0,Q) + z(k)=H*x(k)+v(k), p(v)~N(0,R) +*/ +typedef struct CvKalman +{ + int MP; /* number of measurement vector dimensions */ + int DP; /* number of state vector dimensions */ + int CP; /* number of control vector dimensions */ + + /* backward compatibility fields */ +#if 1 + float* PosterState; /* =state_pre->data.fl */ + float* PriorState; /* =state_post->data.fl */ + float* DynamMatr; /* =transition_matrix->data.fl */ + float* MeasurementMatr; /* =measurement_matrix->data.fl */ + float* MNCovariance; /* =measurement_noise_cov->data.fl */ + float* PNCovariance; /* =process_noise_cov->data.fl */ + float* KalmGainMatr; /* =gain->data.fl */ + float* PriorErrorCovariance;/* =error_cov_pre->data.fl */ + float* PosterErrorCovariance;/* =error_cov_post->data.fl */ + float* Temp1; /* temp1->data.fl */ + float* Temp2; /* temp2->data.fl */ +#endif + + CvMat* state_pre; /* predicted state (x'(k)): + x(k)=A*x(k-1)+B*u(k) */ + CvMat* state_post; /* corrected state (x(k)): + x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) */ + CvMat* transition_matrix; /* state transition matrix (A) */ + CvMat* control_matrix; /* control matrix (B) + (it is not used if there is no control)*/ + CvMat* measurement_matrix; /* measurement matrix (H) */ + CvMat* process_noise_cov; /* process noise covariance matrix (Q) */ + CvMat* measurement_noise_cov; /* measurement noise covariance matrix (R) */ + CvMat* error_cov_pre; /* priori error estimate covariance matrix (P'(k)): + P'(k)=A*P(k-1)*At + Q)*/ + CvMat* gain; /* Kalman gain matrix (K(k)): + K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)*/ + CvMat* error_cov_post; /* posteriori error estimate covariance matrix (P(k)): + P(k)=(I-K(k)*H)*P'(k) */ + CvMat* temp1; /* temporary matrices */ + CvMat* temp2; + CvMat* temp3; + CvMat* temp4; + CvMat* temp5; +} CvKalman; + +/* Creates Kalman filter and sets A, B, Q, R and state to some initial values */ +CVAPI(CvKalman*) cvCreateKalman( int dynam_params, int measure_params, + int control_params CV_DEFAULT(0)); + +/* Releases Kalman filter state */ +CVAPI(void) cvReleaseKalman( CvKalman** kalman); + +/* Updates Kalman filter by time (predicts future state of the system) */ +CVAPI(const CvMat*) cvKalmanPredict( CvKalman* kalman, + const CvMat* control CV_DEFAULT(NULL)); + +/* Updates Kalman filter by measurement + (corrects state of the system and internal matrices) */ +CVAPI(const CvMat*) cvKalmanCorrect( CvKalman* kalman, const CvMat* measurement ); + +#define cvKalmanUpdateByTime cvKalmanPredict +#define cvKalmanUpdateByMeasurement cvKalmanCorrect + +/** @} video_c */ + +#ifdef __cplusplus +} // extern "C" +#endif + + +#endif // __OPENCV_TRACKING_C_H__ diff --git a/include/opencv2/video/video.hpp b/include/opencv2/video/video.hpp new file mode 100644 index 0000000..8267b85 --- /dev/null +++ b/include/opencv2/video/video.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/video.hpp" diff --git a/include/opencv2/videoio.hpp b/include/opencv2/videoio.hpp new file mode 100644 index 0000000..2547e4c --- /dev/null +++ b/include/opencv2/videoio.hpp @@ -0,0 +1,648 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOIO_HPP__ +#define __OPENCV_VIDEOIO_HPP__ + +#include "opencv2/core.hpp" + +/** + @defgroup videoio Media I/O + @{ + @defgroup videoio_c C API + @defgroup videoio_ios iOS glue + @defgroup videoio_winrt WinRT glue + @} +*/ + +////////////////////////////////// video io ///////////////////////////////// + +typedef struct CvCapture CvCapture; +typedef struct CvVideoWriter CvVideoWriter; + +namespace cv +{ + +//! @addtogroup videoio +//! @{ + +// Camera API +enum { CAP_ANY = 0, // autodetect + CAP_VFW = 200, // platform native + CAP_V4L = 200, + CAP_V4L2 = CAP_V4L, + CAP_FIREWARE = 300, // IEEE 1394 drivers + CAP_FIREWIRE = CAP_FIREWARE, + CAP_IEEE1394 = CAP_FIREWARE, + CAP_DC1394 = CAP_FIREWARE, + CAP_CMU1394 = CAP_FIREWARE, + CAP_QT = 500, // QuickTime + CAP_UNICAP = 600, // Unicap drivers + CAP_DSHOW = 700, // DirectShow (via videoInput) + CAP_PVAPI = 800, // PvAPI, Prosilica GigE SDK + CAP_OPENNI = 900, // OpenNI (for Kinect) + CAP_OPENNI_ASUS = 910, // OpenNI (for Asus Xtion) + CAP_ANDROID = 1000, // Android - not used + CAP_XIAPI = 1100, // XIMEA Camera API + CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) + CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK + CAP_MSMF = 1400, // Microsoft Media Foundation (via videoInput) + CAP_WINRT = 1410, // Microsoft Windows Runtime using Media Foundation + CAP_INTELPERC = 1500, // Intel Perceptual Computing SDK + CAP_OPENNI2 = 1600, // OpenNI2 (for Kinect) + CAP_OPENNI2_ASUS = 1610, // OpenNI2 (for Asus Xtion and Occipital Structure sensors) + CAP_GPHOTO2 = 1700 // gPhoto2 connection + }; + +// generic properties (based on DC1394 properties) +enum { CAP_PROP_POS_MSEC =0, + CAP_PROP_POS_FRAMES =1, + CAP_PROP_POS_AVI_RATIO =2, + CAP_PROP_FRAME_WIDTH =3, + CAP_PROP_FRAME_HEIGHT =4, + CAP_PROP_FPS =5, + CAP_PROP_FOURCC =6, + CAP_PROP_FRAME_COUNT =7, + CAP_PROP_FORMAT =8, + CAP_PROP_MODE =9, + CAP_PROP_BRIGHTNESS =10, + CAP_PROP_CONTRAST =11, + CAP_PROP_SATURATION =12, + CAP_PROP_HUE =13, + CAP_PROP_GAIN =14, + CAP_PROP_EXPOSURE =15, + CAP_PROP_CONVERT_RGB =16, + CAP_PROP_WHITE_BALANCE_BLUE_U =17, + CAP_PROP_RECTIFICATION =18, + CAP_PROP_MONOCHROME =19, + CAP_PROP_SHARPNESS =20, + CAP_PROP_AUTO_EXPOSURE =21, // DC1394: exposure control done by camera, user can adjust refernce level using this feature + CAP_PROP_GAMMA =22, + CAP_PROP_TEMPERATURE =23, + CAP_PROP_TRIGGER =24, + CAP_PROP_TRIGGER_DELAY =25, + CAP_PROP_WHITE_BALANCE_RED_V =26, + CAP_PROP_ZOOM =27, + CAP_PROP_FOCUS =28, + CAP_PROP_GUID =29, + CAP_PROP_ISO_SPEED =30, + CAP_PROP_BACKLIGHT =32, + CAP_PROP_PAN =33, + CAP_PROP_TILT =34, + CAP_PROP_ROLL =35, + CAP_PROP_IRIS =36, + CAP_PROP_SETTINGS =37 + }; + + +// Generic camera output modes. +// Currently, these are supported through the libv4l interface only. +enum { CAP_MODE_BGR = 0, // BGR24 (default) + CAP_MODE_RGB = 1, // RGB24 + CAP_MODE_GRAY = 2, // Y8 + CAP_MODE_YUYV = 3 // YUYV + }; + + +// DC1394 only +// modes of the controlling registers (can be: auto, manual, auto single push, absolute Latter allowed with any other mode) +// every feature can have only one mode turned on at a time +enum { CAP_PROP_DC1394_OFF = -4, //turn the feature off (not controlled manually nor automatically) + CAP_PROP_DC1394_MODE_MANUAL = -3, //set automatically when a value of the feature is set by the user + CAP_PROP_DC1394_MODE_AUTO = -2, + CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO = -1, + CAP_PROP_DC1394_MAX = 31 + }; + + +// OpenNI map generators +enum { CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, + CAP_OPENNI_IMAGE_GENERATOR = 1 << 30, + CAP_OPENNI_GENERATORS_MASK = CAP_OPENNI_DEPTH_GENERATOR + CAP_OPENNI_IMAGE_GENERATOR + }; + +// Properties of cameras available through OpenNI interfaces +enum { CAP_PROP_OPENNI_OUTPUT_MODE = 100, + CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm + CAP_PROP_OPENNI_BASELINE = 102, // in mm + CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels + CAP_PROP_OPENNI_REGISTRATION = 104, // flag that synchronizes the remapping depth map to image map + // by changing depth generator's view point (if the flag is "on") or + // sets this view point to its normal one (if the flag is "off"). + CAP_PROP_OPENNI_REGISTRATION_ON = CAP_PROP_OPENNI_REGISTRATION, + CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, + CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, + CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, + CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, + CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, + CAP_PROP_OPENNI2_SYNC = 110, + CAP_PROP_OPENNI2_MIRROR = 111 + }; + +// OpenNI shortcats +enum { CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_GENERATOR_PRESENT, + CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_OUTPUT_MODE, + CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_BASELINE, + CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_FOCAL_LENGTH, + CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_REGISTRATION, + CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION_ON = CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION + }; + +// OpenNI data given from depth generator +enum { CAP_OPENNI_DEPTH_MAP = 0, // Depth values in mm (CV_16UC1) + CAP_OPENNI_POINT_CLOUD_MAP = 1, // XYZ in meters (CV_32FC3) + CAP_OPENNI_DISPARITY_MAP = 2, // Disparity in pixels (CV_8UC1) + CAP_OPENNI_DISPARITY_MAP_32F = 3, // Disparity in pixels (CV_32FC1) + CAP_OPENNI_VALID_DEPTH_MASK = 4, // CV_8UC1 + + // Data given from RGB image generator + CAP_OPENNI_BGR_IMAGE = 5, + CAP_OPENNI_GRAY_IMAGE = 6 + }; + +// Supported output modes of OpenNI image generator +enum { CAP_OPENNI_VGA_30HZ = 0, + CAP_OPENNI_SXGA_15HZ = 1, + CAP_OPENNI_SXGA_30HZ = 2, + CAP_OPENNI_QVGA_30HZ = 3, + CAP_OPENNI_QVGA_60HZ = 4 + }; + + +// GStreamer +enum { CAP_PROP_GSTREAMER_QUEUE_LENGTH = 200 // default is 1 + }; + + +// PVAPI +enum { CAP_PROP_PVAPI_MULTICASTIP = 300, // ip for anable multicast master mode. 0 for disable multicast + CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE = 301, // FrameStartTriggerMode: Determines how a frame is initiated + CAP_PROP_PVAPI_DECIMATIONHORIZONTAL = 302, // Horizontal sub-sampling of the image + CAP_PROP_PVAPI_DECIMATIONVERTICAL = 303, // Vertical sub-sampling of the image + CAP_PROP_PVAPI_BINNINGX = 304, // Horizontal binning factor + CAP_PROP_PVAPI_BINNINGY = 305, // Vertical binning factor + CAP_PROP_PVAPI_PIXELFORMAT = 306 // Pixel format + }; + +// PVAPI: FrameStartTriggerMode +enum { CAP_PVAPI_FSTRIGMODE_FREERUN = 0, // Freerun + CAP_PVAPI_FSTRIGMODE_SYNCIN1 = 1, // SyncIn1 + CAP_PVAPI_FSTRIGMODE_SYNCIN2 = 2, // SyncIn2 + CAP_PVAPI_FSTRIGMODE_FIXEDRATE = 3, // FixedRate + CAP_PVAPI_FSTRIGMODE_SOFTWARE = 4 // Software + }; + +// PVAPI: DecimationHorizontal, DecimationVertical +enum { CAP_PVAPI_DECIMATION_OFF = 1, // Off + CAP_PVAPI_DECIMATION_2OUTOF4 = 2, // 2 out of 4 decimation + CAP_PVAPI_DECIMATION_2OUTOF8 = 4, // 2 out of 8 decimation + CAP_PVAPI_DECIMATION_2OUTOF16 = 8 // 2 out of 16 decimation + }; + +// PVAPI: PixelFormat +enum { CAP_PVAPI_PIXELFORMAT_MONO8 = 1, // Mono8 + CAP_PVAPI_PIXELFORMAT_MONO16 = 2, // Mono16 + CAP_PVAPI_PIXELFORMAT_BAYER8 = 3, // Bayer8 + CAP_PVAPI_PIXELFORMAT_BAYER16 = 4, // Bayer16 + CAP_PVAPI_PIXELFORMAT_RGB24 = 5, // Rgb24 + CAP_PVAPI_PIXELFORMAT_BGR24 = 6, // Bgr24 + CAP_PVAPI_PIXELFORMAT_RGBA32 = 7, // Rgba32 + CAP_PVAPI_PIXELFORMAT_BGRA32 = 8, // Bgra32 + }; + +// Properties of cameras available through XIMEA SDK interface +enum { CAP_PROP_XI_DOWNSAMPLING = 400, // Change image resolution by binning or skipping. + CAP_PROP_XI_DATA_FORMAT = 401, // Output data format. + CAP_PROP_XI_OFFSET_X = 402, // Horizontal offset from the origin to the area of interest (in pixels). + CAP_PROP_XI_OFFSET_Y = 403, // Vertical offset from the origin to the area of interest (in pixels). + CAP_PROP_XI_TRG_SOURCE = 404, // Defines source of trigger. + CAP_PROP_XI_TRG_SOFTWARE = 405, // Generates an internal trigger. PRM_TRG_SOURCE must be set to TRG_SOFTWARE. + CAP_PROP_XI_GPI_SELECTOR = 406, // Selects general purpose input + CAP_PROP_XI_GPI_MODE = 407, // Set general purpose input mode + CAP_PROP_XI_GPI_LEVEL = 408, // Get general purpose level + CAP_PROP_XI_GPO_SELECTOR = 409, // Selects general purpose output + CAP_PROP_XI_GPO_MODE = 410, // Set general purpose output mode + CAP_PROP_XI_LED_SELECTOR = 411, // Selects camera signalling LED + CAP_PROP_XI_LED_MODE = 412, // Define camera signalling LED functionality + CAP_PROP_XI_MANUAL_WB = 413, // Calculates White Balance(must be called during acquisition) + CAP_PROP_XI_AUTO_WB = 414, // Automatic white balance + CAP_PROP_XI_AEAG = 415, // Automatic exposure/gain + CAP_PROP_XI_EXP_PRIORITY = 416, // Exposure priority (0.5 - exposure 50%, gain 50%). + CAP_PROP_XI_AE_MAX_LIMIT = 417, // Maximum limit of exposure in AEAG procedure + CAP_PROP_XI_AG_MAX_LIMIT = 418, // Maximum limit of gain in AEAG procedure + CAP_PROP_XI_AEAG_LEVEL = 419, // Average intensity of output signal AEAG should achieve(in %) + CAP_PROP_XI_TIMEOUT = 420 // Image capture timeout in milliseconds + }; + +// Properties of cameras available through AVFOUNDATION interface +enum { CAP_PROP_IOS_DEVICE_FOCUS = 9001, + CAP_PROP_IOS_DEVICE_EXPOSURE = 9002, + CAP_PROP_IOS_DEVICE_FLASH = 9003, + CAP_PROP_IOS_DEVICE_WHITEBALANCE = 9004, + CAP_PROP_IOS_DEVICE_TORCH = 9005 + }; + + +// Properties of cameras available through Smartek Giganetix Ethernet Vision interface +/* --- Vladimir Litvinenko (litvinenko.vladimir@gmail.com) --- */ +enum { CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, + CAP_PROP_GIGA_FRAME_OFFSET_Y = 10002, + CAP_PROP_GIGA_FRAME_WIDTH_MAX = 10003, + CAP_PROP_GIGA_FRAME_HEIGH_MAX = 10004, + CAP_PROP_GIGA_FRAME_SENS_WIDTH = 10005, + CAP_PROP_GIGA_FRAME_SENS_HEIGH = 10006 + }; + +enum { CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, + CAP_PROP_INTELPERC_PROFILE_IDX = 11002, + CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE = 11003, + CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE = 11004, + CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD = 11005, + CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ = 11006, + CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT = 11007 + }; + +// Intel PerC streams +enum { CAP_INTELPERC_DEPTH_GENERATOR = 1 << 29, + CAP_INTELPERC_IMAGE_GENERATOR = 1 << 28, + CAP_INTELPERC_GENERATORS_MASK = CAP_INTELPERC_DEPTH_GENERATOR + CAP_INTELPERC_IMAGE_GENERATOR + }; + +enum { CAP_INTELPERC_DEPTH_MAP = 0, // Each pixel is a 16-bit integer. The value indicates the distance from an object to the camera's XY plane or the Cartesian depth. + CAP_INTELPERC_UVDEPTH_MAP = 1, // Each pixel contains two 32-bit floating point values in the range of 0-1, representing the mapping of depth coordinates to the color coordinates. + CAP_INTELPERC_IR_MAP = 2, // Each pixel is a 16-bit integer. The value indicates the intensity of the reflected laser beam. + CAP_INTELPERC_IMAGE = 3 + }; + +enum { VIDEOWRITER_PROP_QUALITY = 1, // Quality (0..100%) of the videostream encoded + VIDEOWRITER_PROP_FRAMEBYTES = 2, // (Read-only): Size of just encoded video frame + }; + +// gPhoto2 properties, if propertyId is less than 0 then work on widget with that __additive inversed__ camera setting ID +// Get IDs by using CAP_PROP_GPHOTO2_WIDGET_ENUMERATE. +// @see CvCaptureCAM_GPHOTO2 for more info +enum { CAP_PROP_GPHOTO2_PREVIEW = 17001, // Capture only preview from liveview mode. + CAP_PROP_GPHOTO2_WIDGET_ENUMERATE = 17002, // Readonly, returns (const char *). + CAP_PROP_GPHOTO2_RELOAD_CONFIG = 17003, // Trigger, only by set. Reload camera settings. + CAP_PROP_GPHOTO2_RELOAD_ON_CHANGE = 17004, // Reload all settings on set. + CAP_PROP_GPHOTO2_COLLECT_MSGS = 17005, // Collect messages with details. + CAP_PROP_GPHOTO2_FLUSH_MSGS = 17006, // Readonly, returns (const char *). + CAP_PROP_SPEED = 17007, // Exposure speed. Can be readonly, depends on camera program. + CAP_PROP_APERTURE = 17008, // Aperture. Can be readonly, depends on camera program. + CAP_PROP_EXPOSUREPROGRAM = 17009, // Camera exposure program. + CAP_PROP_VIEWFINDER = 17010 // Enter liveview mode. + }; + +//enum { + +class IVideoCapture; + +/** @brief Class for video capturing from video files, image sequences or cameras. The class provides C++ API +for capturing video from cameras or for reading video files and image sequences. Here is how the +class can be used: : +@code + #include "opencv2/opencv.hpp" + + using namespace cv; + + int main(int, char**) + { + VideoCapture cap(0); // open the default camera + if(!cap.isOpened()) // check if we succeeded + return -1; + + Mat edges; + namedWindow("edges",1); + for(;;) + { + Mat frame; + cap >> frame; // get a new frame from camera + cvtColor(frame, edges, COLOR_BGR2GRAY); + GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5); + Canny(edges, edges, 0, 30, 3); + imshow("edges", edges); + if(waitKey(30) >= 0) break; + } + // the camera will be deinitialized automatically in VideoCapture destructor + return 0; + } +@endcode +@note In C API the black-box structure CvCapture is used instead of VideoCapture. + +@note +- A basic sample on using the VideoCapture interface can be found at + opencv_source_code/samples/cpp/starter_video.cpp +- Another basic video processing sample can be found at + opencv_source_code/samples/cpp/video_dmtx.cpp +- (Python) A basic sample on using the VideoCapture interface can be found at + opencv_source_code/samples/python2/video.py +- (Python) Another basic video processing sample can be found at + opencv_source_code/samples/python2/video_dmtx.py +- (Python) A multi threaded video processing sample can be found at + opencv_source_code/samples/python2/video_threaded.py + */ +class CV_EXPORTS_W VideoCapture +{ +public: + /** @brief + @note In C API, when you finished working with video, release CvCapture structure with + cvReleaseCapture(), or use Ptr\ that calls cvReleaseCapture() automatically in the + destructor. + */ + CV_WRAP VideoCapture(); + + /** @overload + @param filename name of the opened video file (eg. video.avi) or image sequence (eg. + img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...) + */ + CV_WRAP VideoCapture(const String& filename); + + /** @overload + @param device id of the opened video capturing device (i.e. a camera index). If there is a single + camera connected, just pass 0. + */ + CV_WRAP VideoCapture(int device); + + virtual ~VideoCapture(); + + /** @brief Open video file or a capturing device for video capturing + + @param filename name of the opened video file (eg. video.avi) or image sequence (eg. + img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...) + + The methods first call VideoCapture::release to close the already opened file or camera. + */ + CV_WRAP virtual bool open(const String& filename); + + /** @overload + @param device id of the opened video capturing device (i.e. a camera index). + */ + CV_WRAP virtual bool open(int device); + + /** @brief Returns true if video capturing has been initialized already. + + If the previous call to VideoCapture constructor or VideoCapture::open succeeded, the method returns + true. + */ + CV_WRAP virtual bool isOpened() const; + + /** @brief Closes video file or capturing device. + + The methods are automatically called by subsequent VideoCapture::open and by VideoCapture + destructor. + + The C function also deallocates memory and clears \*capture pointer. + */ + CV_WRAP virtual void release(); + + /** @brief Grabs the next frame from video file or capturing device. + + The methods/functions grab the next frame from video file or camera and return true (non-zero) in + the case of success. + + The primary use of the function is in multi-camera environments, especially when the cameras do not + have hardware synchronization. That is, you call VideoCapture::grab() for each camera and after that + call the slower method VideoCapture::retrieve() to decode and get frame from each camera. This way + the overhead on demosaicing or motion jpeg decompression etc. is eliminated and the retrieved frames + from different cameras will be closer in time. + + Also, when a connected camera is multi-head (for example, a stereo camera or a Kinect device), the + correct way of retrieving data from it is to call VideoCapture::grab first and then call + VideoCapture::retrieve one or more times with different values of the channel parameter. See + + */ + CV_WRAP virtual bool grab(); + + /** @brief Decodes and returns the grabbed video frame. + + The methods/functions decode and return the just grabbed frame. If no frames has been grabbed + (camera has been disconnected, or there are no more frames in video file), the methods return false + and the functions return NULL pointer. + + @note OpenCV 1.x functions cvRetrieveFrame and cv.RetrieveFrame return image stored inside the video + capturing structure. It is not allowed to modify or release the image! You can copy the frame using + :ocvcvCloneImage and then do whatever you want with the copy. + */ + CV_WRAP virtual bool retrieve(OutputArray image, int flag = 0); + virtual VideoCapture& operator >> (CV_OUT Mat& image); + virtual VideoCapture& operator >> (CV_OUT UMat& image); + + /** @brief Grabs, decodes and returns the next video frame. + + The methods/functions combine VideoCapture::grab and VideoCapture::retrieve in one call. This is the + most convenient method for reading video files or capturing data from decode and return the just + grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more + frames in video file), the methods return false and the functions return NULL pointer. + + @note OpenCV 1.x functions cvRetrieveFrame and cv.RetrieveFrame return image stored inside the video + capturing structure. It is not allowed to modify or release the image! You can copy the frame using + :ocvcvCloneImage and then do whatever you want with the copy. + */ + CV_WRAP virtual bool read(OutputArray image); + + /** @brief Sets a property in the VideoCapture. + + @param propId Property identifier. It can be one of the following: + - **CAP_PROP_POS_MSEC** Current position of the video file in milliseconds. + - **CAP_PROP_POS_FRAMES** 0-based index of the frame to be decoded/captured next. + - **CAP_PROP_POS_AVI_RATIO** Relative position of the video file: 0 - start of the + film, 1 - end of the film. + - **CAP_PROP_FRAME_WIDTH** Width of the frames in the video stream. + - **CAP_PROP_FRAME_HEIGHT** Height of the frames in the video stream. + - **CAP_PROP_FPS** Frame rate. + - **CAP_PROP_FOURCC** 4-character code of codec. + - **CAP_PROP_FRAME_COUNT** Number of frames in the video file. + - **CAP_PROP_FORMAT** Format of the Mat objects returned by retrieve() . + - **CAP_PROP_MODE** Backend-specific value indicating the current capture mode. + - **CAP_PROP_BRIGHTNESS** Brightness of the image (only for cameras). + - **CAP_PROP_CONTRAST** Contrast of the image (only for cameras). + - **CAP_PROP_SATURATION** Saturation of the image (only for cameras). + - **CAP_PROP_HUE** Hue of the image (only for cameras). + - **CAP_PROP_GAIN** Gain of the image (only for cameras). + - **CAP_PROP_EXPOSURE** Exposure (only for cameras). + - **CAP_PROP_CONVERT_RGB** Boolean flags indicating whether images should be converted + to RGB. + - **CAP_PROP_WHITE_BALANCE** Currently unsupported + - **CAP_PROP_RECTIFICATION** Rectification flag for stereo cameras (note: only supported + by DC1394 v 2.x backend currently) + @param value Value of the property. + */ + CV_WRAP virtual bool set(int propId, double value); + + /** @brief Returns the specified VideoCapture property + + @param propId Property identifier. It can be one of the following: + - **CAP_PROP_POS_MSEC** Current position of the video file in milliseconds or video + capture timestamp. + - **CAP_PROP_POS_FRAMES** 0-based index of the frame to be decoded/captured next. + - **CAP_PROP_POS_AVI_RATIO** Relative position of the video file: 0 - start of the + film, 1 - end of the film. + - **CAP_PROP_FRAME_WIDTH** Width of the frames in the video stream. + - **CAP_PROP_FRAME_HEIGHT** Height of the frames in the video stream. + - **CAP_PROP_FPS** Frame rate. + - **CAP_PROP_FOURCC** 4-character code of codec. + - **CAP_PROP_FRAME_COUNT** Number of frames in the video file. + - **CAP_PROP_FORMAT** Format of the Mat objects returned by retrieve() . + - **CAP_PROP_MODE** Backend-specific value indicating the current capture mode. + - **CAP_PROP_BRIGHTNESS** Brightness of the image (only for cameras). + - **CAP_PROP_CONTRAST** Contrast of the image (only for cameras). + - **CAP_PROP_SATURATION** Saturation of the image (only for cameras). + - **CAP_PROP_HUE** Hue of the image (only for cameras). + - **CAP_PROP_GAIN** Gain of the image (only for cameras). + - **CAP_PROP_EXPOSURE** Exposure (only for cameras). + - **CAP_PROP_CONVERT_RGB** Boolean flags indicating whether images should be converted + to RGB. + - **CAP_PROP_WHITE_BALANCE** Currently not supported + - **CAP_PROP_RECTIFICATION** Rectification flag for stereo cameras (note: only supported + by DC1394 v 2.x backend currently) + + @note When querying a property that is not supported by the backend used by the VideoCapture + class, value 0 is returned. + */ + CV_WRAP virtual double get(int propId) const; + +protected: + Ptr cap; + Ptr icap; +}; + +class IVideoWriter; + +/** @brief Video writer class. + */ +class CV_EXPORTS_W VideoWriter +{ +public: + /** @brief VideoWriter constructors + + The constructors/functions initialize video writers. On Linux FFMPEG is used to write videos; on + Windows FFMPEG or VFW is used; on MacOSX QTKit is used. + */ + CV_WRAP VideoWriter(); + + /** @overload + @param filename Name of the output video file. + @param fourcc 4-character code of codec used to compress the frames. For example, + VideoWriter::fourcc('P','I','M','1') is a MPEG-1 codec, VideoWriter::fourcc('M','J','P','G') is a + motion-jpeg codec etc. List of codes can be obtained at [Video Codecs by + FOURCC](http://www.fourcc.org/codecs.php) page. + @param fps Framerate of the created video stream. + @param frameSize Size of the video frames. + @param isColor If it is not zero, the encoder will expect and encode color frames, otherwise it + will work with grayscale frames (the flag is currently supported on Windows only). + */ + CV_WRAP VideoWriter(const String& filename, int fourcc, double fps, + Size frameSize, bool isColor = true); + + virtual ~VideoWriter(); + + /** @brief Initializes or reinitializes video writer. + + The method opens video writer. Parameters are the same as in the constructor + VideoWriter::VideoWriter. + */ + CV_WRAP virtual bool open(const String& filename, int fourcc, double fps, + Size frameSize, bool isColor = true); + + /** @brief Returns true if video writer has been successfully initialized. + */ + CV_WRAP virtual bool isOpened() const; + + /** @brief Closes the video writer. + + The methods are automatically called by subsequent VideoWriter::open and by the VideoWriter + destructor. + */ + CV_WRAP virtual void release(); + virtual VideoWriter& operator << (const Mat& image); + + /** @brief Writes the next video frame + + @param image The written frame + + The functions/methods write the specified image to video file. It must have the same size as has + been specified when opening the video writer. + */ + CV_WRAP virtual void write(const Mat& image); + + /** @brief Sets a property in the VideoWriter. + + @param propId Property identifier. It can be one of the following: + - **VIDEOWRITER_PROP_QUALITY** Quality (0..100%) of the videostream encoded. Can be adjusted dynamically in some codecs. + @param value Value of the property. + */ + CV_WRAP virtual bool set(int propId, double value); + + /** @brief Returns the specified VideoWriter property + + @param propId Property identifier. It can be one of the following: + - **VIDEOWRITER_PROP_QUALITY** Current quality of the encoded videostream. + - **VIDEOWRITER_PROP_FRAMEBYTES** (Read-only) Size of just encoded video frame; note that the encoding order may be different from representation order. + + @note When querying a property that is not supported by the backend used by the VideoWriter + class, value 0 is returned. + */ + CV_WRAP virtual double get(int propId) const; + + /** @brief Concatenates 4 chars to a fourcc code + + This static method constructs the fourcc code of the codec to be used in the constructor + VideoWriter::VideoWriter or VideoWriter::open. + */ + CV_WRAP static int fourcc(char c1, char c2, char c3, char c4); + +protected: + Ptr writer; + Ptr iwriter; + + static Ptr create(const String& filename, int fourcc, double fps, + Size frameSize, bool isColor = true); +}; + +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvCapture* obj) const; +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvVideoWriter* obj) const; + +//! @} videoio + +} // cv + +#endif //__OPENCV_VIDEOIO_HPP__ diff --git a/include/opencv2/videoio/cap_ios.h b/include/opencv2/videoio/cap_ios.h new file mode 100644 index 0000000..cf7f2e4 --- /dev/null +++ b/include/opencv2/videoio/cap_ios.h @@ -0,0 +1,174 @@ +/* For iOS video I/O + * by Eduard Feicho on 29/07/12 + * Copyright 2012. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#import +#import +#import +#import +#include "opencv2/core.hpp" + +//! @addtogroup videoio_ios +//! @{ + +/////////////////////////////////////// CvAbstractCamera ///////////////////////////////////// + +@class CvAbstractCamera; + +@interface CvAbstractCamera : NSObject +{ + AVCaptureSession* captureSession; + AVCaptureConnection* videoCaptureConnection; + AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; + + UIDeviceOrientation currentDeviceOrientation; + + BOOL cameraAvailable; + BOOL captureSessionLoaded; + BOOL running; + BOOL useAVCaptureVideoPreviewLayer; + + AVCaptureDevicePosition defaultAVCaptureDevicePosition; + AVCaptureVideoOrientation defaultAVCaptureVideoOrientation; + NSString *const defaultAVCaptureSessionPreset; + + int defaultFPS; + + UIView* parentView; + + int imageWidth; + int imageHeight; +} + +@property (nonatomic, retain) AVCaptureSession* captureSession; +@property (nonatomic, retain) AVCaptureConnection* videoCaptureConnection; + +@property (nonatomic, readonly) BOOL running; +@property (nonatomic, readonly) BOOL captureSessionLoaded; + +@property (nonatomic, assign) int defaultFPS; +@property (nonatomic, assign) AVCaptureDevicePosition defaultAVCaptureDevicePosition; +@property (nonatomic, assign) AVCaptureVideoOrientation defaultAVCaptureVideoOrientation; +@property (nonatomic, assign) BOOL useAVCaptureVideoPreviewLayer; +@property (nonatomic, strong) NSString *const defaultAVCaptureSessionPreset; + +@property (nonatomic, assign) int imageWidth; +@property (nonatomic, assign) int imageHeight; + +@property (nonatomic, retain) UIView* parentView; + +- (void)start; +- (void)stop; +- (void)switchCameras; + +- (id)initWithParentView:(UIView*)parent; + +- (void)createCaptureOutput; +- (void)createVideoPreviewLayer; +- (void)updateOrientation; + +- (void)lockFocus; +- (void)unlockFocus; +- (void)lockExposure; +- (void)unlockExposure; +- (void)lockBalance; +- (void)unlockBalance; + +@end + +///////////////////////////////// CvVideoCamera /////////////////////////////////////////// + +@class CvVideoCamera; + +@protocol CvVideoCameraDelegate + +#ifdef __cplusplus +// delegate method for processing image frames +- (void)processImage:(cv::Mat&)image; +#endif + +@end + +@interface CvVideoCamera : CvAbstractCamera +{ + AVCaptureVideoDataOutput *videoDataOutput; + + dispatch_queue_t videoDataOutputQueue; + CALayer *customPreviewLayer; + + BOOL grayscaleMode; + + BOOL recordVideo; + BOOL rotateVideo; + AVAssetWriterInput* recordAssetWriterInput; + AVAssetWriterInputPixelBufferAdaptor* recordPixelBufferAdaptor; + AVAssetWriter* recordAssetWriter; + + CMTime lastSampleTime; + +} + +@property (nonatomic, assign) id delegate; +@property (nonatomic, assign) BOOL grayscaleMode; + +@property (nonatomic, assign) BOOL recordVideo; +@property (nonatomic, assign) BOOL rotateVideo; +@property (nonatomic, retain) AVAssetWriterInput* recordAssetWriterInput; +@property (nonatomic, retain) AVAssetWriterInputPixelBufferAdaptor* recordPixelBufferAdaptor; +@property (nonatomic, retain) AVAssetWriter* recordAssetWriter; + +- (void)adjustLayoutToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; +- (void)layoutPreviewLayer; +- (void)saveVideo; +- (NSURL *)videoFileURL; + + +@end + +///////////////////////////////// CvPhotoCamera /////////////////////////////////////////// + +@class CvPhotoCamera; + +@protocol CvPhotoCameraDelegate + +- (void)photoCamera:(CvPhotoCamera*)photoCamera capturedImage:(UIImage *)image; +- (void)photoCameraCancel:(CvPhotoCamera*)photoCamera; + +@end + +@interface CvPhotoCamera : CvAbstractCamera +{ + AVCaptureStillImageOutput *stillImageOutput; +} + +@property (nonatomic, assign) id delegate; + +- (void)takePicture; + +@end + +//! @} videoio_ios diff --git a/include/opencv2/videoio/videoio.hpp b/include/opencv2/videoio/videoio.hpp new file mode 100644 index 0000000..ec84cf7 --- /dev/null +++ b/include/opencv2/videoio/videoio.hpp @@ -0,0 +1,48 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef __OPENCV_BUILD +#error this is a compatibility header which should not be used inside the OpenCV library +#endif + +#include "opencv2/videoio.hpp" diff --git a/include/opencv2/videoio/videoio_c.h b/include/opencv2/videoio/videoio_c.h new file mode 100644 index 0000000..b897385 --- /dev/null +++ b/include/opencv2/videoio/videoio_c.h @@ -0,0 +1,405 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOIO_H__ +#define __OPENCV_VIDEOIO_H__ + +#include "opencv2/core/core_c.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + @addtogroup videoio_c + @{ +*/ + +/****************************************************************************************\ +* Working with Video Files and Cameras * +\****************************************************************************************/ + +/* "black box" capture structure */ +typedef struct CvCapture CvCapture; + +/* start capturing frames from video file */ +CVAPI(CvCapture*) cvCreateFileCapture( const char* filename ); + +enum +{ + CV_CAP_ANY =0, // autodetect + + CV_CAP_MIL =100, // MIL proprietary drivers + + CV_CAP_VFW =200, // platform native + CV_CAP_V4L =200, + CV_CAP_V4L2 =200, + + CV_CAP_FIREWARE =300, // IEEE 1394 drivers + CV_CAP_FIREWIRE =300, + CV_CAP_IEEE1394 =300, + CV_CAP_DC1394 =300, + CV_CAP_CMU1394 =300, + + CV_CAP_STEREO =400, // TYZX proprietary drivers + CV_CAP_TYZX =400, + CV_TYZX_LEFT =400, + CV_TYZX_RIGHT =401, + CV_TYZX_COLOR =402, + CV_TYZX_Z =403, + + CV_CAP_QT =500, // QuickTime + + CV_CAP_UNICAP =600, // Unicap drivers + + CV_CAP_DSHOW =700, // DirectShow (via videoInput) + CV_CAP_MSMF =1400, // Microsoft Media Foundation (via videoInput) + + CV_CAP_PVAPI =800, // PvAPI, Prosilica GigE SDK + + CV_CAP_OPENNI =900, // OpenNI (for Kinect) + CV_CAP_OPENNI_ASUS =910, // OpenNI (for Asus Xtion) + + CV_CAP_ANDROID =1000, // Android - not used + CV_CAP_ANDROID_BACK =CV_CAP_ANDROID+99, // Android back camera - not used + CV_CAP_ANDROID_FRONT =CV_CAP_ANDROID+98, // Android front camera - not used + + CV_CAP_XIAPI =1100, // XIMEA Camera API + + CV_CAP_AVFOUNDATION = 1200, // AVFoundation framework for iOS (OS X Lion will have the same API) + + CV_CAP_GIGANETIX = 1300, // Smartek Giganetix GigEVisionSDK + + CV_CAP_INTELPERC = 1500, // Intel Perceptual Computing + + CV_CAP_OPENNI2 = 1600, // OpenNI2 (for Kinect) + + CV_CAP_GPHOTO2 = 1700 +}; + +/* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */ +CVAPI(CvCapture*) cvCreateCameraCapture( int index ); + +/* grab a frame, return 1 on success, 0 on fail. + this function is thought to be fast */ +CVAPI(int) cvGrabFrame( CvCapture* capture ); + +/* get the frame grabbed with cvGrabFrame(..) + This function may apply some frame processing like + frame decompression, flipping etc. + !!!DO NOT RELEASE or MODIFY the retrieved frame!!! */ +CVAPI(IplImage*) cvRetrieveFrame( CvCapture* capture, int streamIdx CV_DEFAULT(0) ); + +/* Just a combination of cvGrabFrame and cvRetrieveFrame + !!!DO NOT RELEASE or MODIFY the retrieved frame!!! */ +CVAPI(IplImage*) cvQueryFrame( CvCapture* capture ); + +/* stop capturing/reading and free resources */ +CVAPI(void) cvReleaseCapture( CvCapture** capture ); + +enum +{ + // modes of the controlling registers (can be: auto, manual, auto single push, absolute Latter allowed with any other mode) + // every feature can have only one mode turned on at a time + CV_CAP_PROP_DC1394_OFF = -4, //turn the feature off (not controlled manually nor automatically) + CV_CAP_PROP_DC1394_MODE_MANUAL = -3, //set automatically when a value of the feature is set by the user + CV_CAP_PROP_DC1394_MODE_AUTO = -2, + CV_CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO = -1, + CV_CAP_PROP_POS_MSEC =0, + CV_CAP_PROP_POS_FRAMES =1, + CV_CAP_PROP_POS_AVI_RATIO =2, + CV_CAP_PROP_FRAME_WIDTH =3, + CV_CAP_PROP_FRAME_HEIGHT =4, + CV_CAP_PROP_FPS =5, + CV_CAP_PROP_FOURCC =6, + CV_CAP_PROP_FRAME_COUNT =7, + CV_CAP_PROP_FORMAT =8, + CV_CAP_PROP_MODE =9, + CV_CAP_PROP_BRIGHTNESS =10, + CV_CAP_PROP_CONTRAST =11, + CV_CAP_PROP_SATURATION =12, + CV_CAP_PROP_HUE =13, + CV_CAP_PROP_GAIN =14, + CV_CAP_PROP_EXPOSURE =15, + CV_CAP_PROP_CONVERT_RGB =16, + CV_CAP_PROP_WHITE_BALANCE_BLUE_U =17, + CV_CAP_PROP_RECTIFICATION =18, + CV_CAP_PROP_MONOCHROME =19, + CV_CAP_PROP_SHARPNESS =20, + CV_CAP_PROP_AUTO_EXPOSURE =21, // exposure control done by camera, + // user can adjust refernce level + // using this feature + CV_CAP_PROP_GAMMA =22, + CV_CAP_PROP_TEMPERATURE =23, + CV_CAP_PROP_TRIGGER =24, + CV_CAP_PROP_TRIGGER_DELAY =25, + CV_CAP_PROP_WHITE_BALANCE_RED_V =26, + CV_CAP_PROP_ZOOM =27, + CV_CAP_PROP_FOCUS =28, + CV_CAP_PROP_GUID =29, + CV_CAP_PROP_ISO_SPEED =30, + CV_CAP_PROP_MAX_DC1394 =31, + CV_CAP_PROP_BACKLIGHT =32, + CV_CAP_PROP_PAN =33, + CV_CAP_PROP_TILT =34, + CV_CAP_PROP_ROLL =35, + CV_CAP_PROP_IRIS =36, + CV_CAP_PROP_SETTINGS =37, + CV_CAP_PROP_BUFFERSIZE =38, + + CV_CAP_PROP_AUTOGRAB =1024, // property for videoio class CvCapture_Android only + CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING=1025, // readonly, tricky property, returns cpnst char* indeed + CV_CAP_PROP_PREVIEW_FORMAT=1026, // readonly, tricky property, returns cpnst char* indeed + + // OpenNI map generators + CV_CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, + CV_CAP_OPENNI_IMAGE_GENERATOR = 1 << 30, + CV_CAP_OPENNI_GENERATORS_MASK = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_OPENNI_IMAGE_GENERATOR, + + // Properties of cameras available through OpenNI interfaces + CV_CAP_PROP_OPENNI_OUTPUT_MODE = 100, + CV_CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, // in mm + CV_CAP_PROP_OPENNI_BASELINE = 102, // in mm + CV_CAP_PROP_OPENNI_FOCAL_LENGTH = 103, // in pixels + CV_CAP_PROP_OPENNI_REGISTRATION = 104, // flag + CV_CAP_PROP_OPENNI_REGISTRATION_ON = CV_CAP_PROP_OPENNI_REGISTRATION, // flag that synchronizes the remapping depth map to image map + // by changing depth generator's view point (if the flag is "on") or + // sets this view point to its normal one (if the flag is "off"). + CV_CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, + CV_CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, + CV_CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, + CV_CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, + + CV_CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, + CV_CAP_PROP_OPENNI2_SYNC = 110, + CV_CAP_PROP_OPENNI2_MIRROR = 111, + + CV_CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_GENERATOR_PRESENT, + CV_CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CV_CAP_OPENNI_IMAGE_GENERATOR + CV_CAP_PROP_OPENNI_OUTPUT_MODE, + CV_CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_BASELINE, + CV_CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_FOCAL_LENGTH, + CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CV_CAP_OPENNI_DEPTH_GENERATOR + CV_CAP_PROP_OPENNI_REGISTRATION, + CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION_ON = CV_CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION, + + // Properties of cameras available through GStreamer interface + CV_CAP_GSTREAMER_QUEUE_LENGTH = 200, // default is 1 + + // PVAPI + CV_CAP_PROP_PVAPI_MULTICASTIP = 300, // ip for anable multicast master mode. 0 for disable multicast + CV_CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE = 301, // FrameStartTriggerMode: Determines how a frame is initiated + CV_CAP_PROP_PVAPI_DECIMATIONHORIZONTAL = 302, // Horizontal sub-sampling of the image + CV_CAP_PROP_PVAPI_DECIMATIONVERTICAL = 303, // Vertical sub-sampling of the image + CV_CAP_PROP_PVAPI_BINNINGX = 304, // Horizontal binning factor + CV_CAP_PROP_PVAPI_BINNINGY = 305, // Vertical binning factor + CV_CAP_PROP_PVAPI_PIXELFORMAT = 306, // Pixel format + + // Properties of cameras available through XIMEA SDK interface + CV_CAP_PROP_XI_DOWNSAMPLING = 400, // Change image resolution by binning or skipping. + CV_CAP_PROP_XI_DATA_FORMAT = 401, // Output data format. + CV_CAP_PROP_XI_OFFSET_X = 402, // Horizontal offset from the origin to the area of interest (in pixels). + CV_CAP_PROP_XI_OFFSET_Y = 403, // Vertical offset from the origin to the area of interest (in pixels). + CV_CAP_PROP_XI_TRG_SOURCE = 404, // Defines source of trigger. + CV_CAP_PROP_XI_TRG_SOFTWARE = 405, // Generates an internal trigger. PRM_TRG_SOURCE must be set to TRG_SOFTWARE. + CV_CAP_PROP_XI_GPI_SELECTOR = 406, // Selects general purpose input + CV_CAP_PROP_XI_GPI_MODE = 407, // Set general purpose input mode + CV_CAP_PROP_XI_GPI_LEVEL = 408, // Get general purpose level + CV_CAP_PROP_XI_GPO_SELECTOR = 409, // Selects general purpose output + CV_CAP_PROP_XI_GPO_MODE = 410, // Set general purpose output mode + CV_CAP_PROP_XI_LED_SELECTOR = 411, // Selects camera signalling LED + CV_CAP_PROP_XI_LED_MODE = 412, // Define camera signalling LED functionality + CV_CAP_PROP_XI_MANUAL_WB = 413, // Calculates White Balance(must be called during acquisition) + CV_CAP_PROP_XI_AUTO_WB = 414, // Automatic white balance + CV_CAP_PROP_XI_AEAG = 415, // Automatic exposure/gain + CV_CAP_PROP_XI_EXP_PRIORITY = 416, // Exposure priority (0.5 - exposure 50%, gain 50%). + CV_CAP_PROP_XI_AE_MAX_LIMIT = 417, // Maximum limit of exposure in AEAG procedure + CV_CAP_PROP_XI_AG_MAX_LIMIT = 418, // Maximum limit of gain in AEAG procedure + CV_CAP_PROP_XI_AEAG_LEVEL = 419, // Average intensity of output signal AEAG should achieve(in %) + CV_CAP_PROP_XI_TIMEOUT = 420, // Image capture timeout in milliseconds + + // Properties for Android cameras + CV_CAP_PROP_ANDROID_FLASH_MODE = 8001, + CV_CAP_PROP_ANDROID_FOCUS_MODE = 8002, + CV_CAP_PROP_ANDROID_WHITE_BALANCE = 8003, + CV_CAP_PROP_ANDROID_ANTIBANDING = 8004, + CV_CAP_PROP_ANDROID_FOCAL_LENGTH = 8005, + CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_NEAR = 8006, + CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_OPTIMAL = 8007, + CV_CAP_PROP_ANDROID_FOCUS_DISTANCE_FAR = 8008, + CV_CAP_PROP_ANDROID_EXPOSE_LOCK = 8009, + CV_CAP_PROP_ANDROID_WHITEBALANCE_LOCK = 8010, + + // Properties of cameras available through AVFOUNDATION interface + CV_CAP_PROP_IOS_DEVICE_FOCUS = 9001, + CV_CAP_PROP_IOS_DEVICE_EXPOSURE = 9002, + CV_CAP_PROP_IOS_DEVICE_FLASH = 9003, + CV_CAP_PROP_IOS_DEVICE_WHITEBALANCE = 9004, + CV_CAP_PROP_IOS_DEVICE_TORCH = 9005, + + // Properties of cameras available through Smartek Giganetix Ethernet Vision interface + /* --- Vladimir Litvinenko (litvinenko.vladimir@gmail.com) --- */ + CV_CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, + CV_CAP_PROP_GIGA_FRAME_OFFSET_Y = 10002, + CV_CAP_PROP_GIGA_FRAME_WIDTH_MAX = 10003, + CV_CAP_PROP_GIGA_FRAME_HEIGH_MAX = 10004, + CV_CAP_PROP_GIGA_FRAME_SENS_WIDTH = 10005, + CV_CAP_PROP_GIGA_FRAME_SENS_HEIGH = 10006, + + CV_CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, + CV_CAP_PROP_INTELPERC_PROFILE_IDX = 11002, + CV_CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE = 11003, + CV_CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE = 11004, + CV_CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD = 11005, + CV_CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ = 11006, + CV_CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT = 11007, + + // Intel PerC streams + CV_CAP_INTELPERC_DEPTH_GENERATOR = 1 << 29, + CV_CAP_INTELPERC_IMAGE_GENERATOR = 1 << 28, + CV_CAP_INTELPERC_GENERATORS_MASK = CV_CAP_INTELPERC_DEPTH_GENERATOR + CV_CAP_INTELPERC_IMAGE_GENERATOR +}; + +// Generic camera output modes. +// Currently, these are supported through the libv4l interface only. +enum +{ + CV_CAP_MODE_BGR = 0, // BGR24 (default) + CV_CAP_MODE_RGB = 1, // RGB24 + CV_CAP_MODE_GRAY = 2, // Y8 + CV_CAP_MODE_YUYV = 3 // YUYV +}; + +enum +{ + // Data given from depth generator. + CV_CAP_OPENNI_DEPTH_MAP = 0, // Depth values in mm (CV_16UC1) + CV_CAP_OPENNI_POINT_CLOUD_MAP = 1, // XYZ in meters (CV_32FC3) + CV_CAP_OPENNI_DISPARITY_MAP = 2, // Disparity in pixels (CV_8UC1) + CV_CAP_OPENNI_DISPARITY_MAP_32F = 3, // Disparity in pixels (CV_32FC1) + CV_CAP_OPENNI_VALID_DEPTH_MASK = 4, // CV_8UC1 + + // Data given from RGB image generator. + CV_CAP_OPENNI_BGR_IMAGE = 5, + CV_CAP_OPENNI_GRAY_IMAGE = 6 +}; + +// Supported output modes of OpenNI image generator +enum +{ + CV_CAP_OPENNI_VGA_30HZ = 0, + CV_CAP_OPENNI_SXGA_15HZ = 1, + CV_CAP_OPENNI_SXGA_30HZ = 2, + CV_CAP_OPENNI_QVGA_30HZ = 3, + CV_CAP_OPENNI_QVGA_60HZ = 4 +}; + +enum +{ + CV_CAP_INTELPERC_DEPTH_MAP = 0, // Each pixel is a 16-bit integer. The value indicates the distance from an object to the camera's XY plane or the Cartesian depth. + CV_CAP_INTELPERC_UVDEPTH_MAP = 1, // Each pixel contains two 32-bit floating point values in the range of 0-1, representing the mapping of depth coordinates to the color coordinates. + CV_CAP_INTELPERC_IR_MAP = 2, // Each pixel is a 16-bit integer. The value indicates the intensity of the reflected laser beam. + CV_CAP_INTELPERC_IMAGE = 3 +}; + +// gPhoto2 properties, if propertyId is less than 0 then work on widget with that __additive inversed__ camera setting ID +// Get IDs by using CAP_PROP_GPHOTO2_WIDGET_ENUMERATE. +// @see CvCaptureCAM_GPHOTO2 for more info +enum +{ + CV_CAP_PROP_GPHOTO2_PREVIEW = 17001, // Capture only preview from liveview mode. + CV_CAP_PROP_GPHOTO2_WIDGET_ENUMERATE = 17002, // Readonly, returns (const char *). + CV_CAP_PROP_GPHOTO2_RELOAD_CONFIG = 17003, // Trigger, only by set. Reload camera settings. + CV_CAP_PROP_GPHOTO2_RELOAD_ON_CHANGE = 17004, // Reload all settings on set. + CV_CAP_PROP_GPHOTO2_COLLECT_MSGS = 17005, // Collect messages with details. + CV_CAP_PROP_GPHOTO2_FLUSH_MSGS = 17006, // Readonly, returns (const char *). + CV_CAP_PROP_SPEED = 17007, // Exposure speed. Can be readonly, depends on camera program. + CV_CAP_PROP_APERTURE = 17008, // Aperture. Can be readonly, depends on camera program. + CV_CAP_PROP_EXPOSUREPROGRAM = 17009, // Camera exposure program. + CV_CAP_PROP_VIEWFINDER = 17010 // Enter liveview mode. +}; + +/* retrieve or set capture properties */ +CVAPI(double) cvGetCaptureProperty( CvCapture* capture, int property_id ); +CVAPI(int) cvSetCaptureProperty( CvCapture* capture, int property_id, double value ); + +// Return the type of the capturer (eg, CV_CAP_V4W, CV_CAP_UNICAP), which is unknown if created with CV_CAP_ANY +CVAPI(int) cvGetCaptureDomain( CvCapture* capture); + +/* "black box" video file writer structure */ +typedef struct CvVideoWriter CvVideoWriter; + +#define CV_FOURCC_MACRO(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24)) + +CV_INLINE int CV_FOURCC(char c1, char c2, char c3, char c4) +{ + return CV_FOURCC_MACRO(c1, c2, c3, c4); +} + +#define CV_FOURCC_PROMPT -1 /* Open Codec Selection Dialog (Windows only) */ +#define CV_FOURCC_DEFAULT CV_FOURCC('I', 'Y', 'U', 'V') /* Use default codec for specified filename (Linux only) */ + +/* initialize video file writer */ +CVAPI(CvVideoWriter*) cvCreateVideoWriter( const char* filename, int fourcc, + double fps, CvSize frame_size, + int is_color CV_DEFAULT(1)); + +/* write frame to video file */ +CVAPI(int) cvWriteFrame( CvVideoWriter* writer, const IplImage* image ); + +/* close video file writer */ +CVAPI(void) cvReleaseVideoWriter( CvVideoWriter** writer ); + +/****************************************************************************************\ +* Obsolete functions/synonyms * +\****************************************************************************************/ + +#define cvCaptureFromFile cvCreateFileCapture +#define cvCaptureFromCAM cvCreateCameraCapture +#define cvCaptureFromAVI cvCaptureFromFile +#define cvCreateAVIWriter cvCreateVideoWriter +#define cvWriteToAVI cvWriteFrame + +/** @} videoio_c */ + +#ifdef __cplusplus +} +#endif + +#endif //__OPENCV_VIDEOIO_H__ diff --git a/include/opencv2/videostab.hpp b/include/opencv2/videostab.hpp new file mode 100644 index 0000000..17b061f --- /dev/null +++ b/include/opencv2/videostab.hpp @@ -0,0 +1,81 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_HPP__ +#define __OPENCV_VIDEOSTAB_HPP__ + +/** + @defgroup videostab Video Stabilization + +The video stabilization module contains a set of functions and classes that can be used to solve the +problem of video stabilization. There are a few methods implemented, most of them are descibed in +the papers @cite OF06 and @cite G11 . However, there are some extensions and deviations from the orginal +paper methods. + +### References + + 1. "Full-Frame Video Stabilization with Motion Inpainting" + Yasuyuki Matsushita, Eyal Ofek, Weina Ge, Xiaoou Tang, Senior Member, and Heung-Yeung Shum + 2. "Auto-Directed Video Stabilization with Robust L1 Optimal Camera Paths" + Matthias Grundmann, Vivek Kwatra, Irfan Essa + + @{ + @defgroup videostab_motion Global Motion Estimation + +The video stabilization module contains a set of functions and classes for global motion estimation +between point clouds or between images. In the last case features are extracted and matched +internally. For the sake of convenience the motion estimation functions are wrapped into classes. +Both the functions and the classes are available. + + @defgroup videostab_marching Fast Marching Method + +The Fast Marching Method @cite Telea04 is used in of the video stabilization routines to do motion and +color inpainting. The method is implemented is a flexible way and it's made public for other users. + + @} + +*/ + +#include "opencv2/videostab/stabilizer.hpp" +#include "opencv2/videostab/ring_buffer.hpp" + +#endif diff --git a/include/opencv2/videostab/deblurring.hpp b/include/opencv2/videostab/deblurring.hpp new file mode 100644 index 0000000..8028c1d --- /dev/null +++ b/include/opencv2/videostab/deblurring.hpp @@ -0,0 +1,116 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_DEBLURRING_HPP__ +#define __OPENCV_VIDEOSTAB_DEBLURRING_HPP__ + +#include +#include "opencv2/core.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +CV_EXPORTS float calcBlurriness(const Mat &frame); + +class CV_EXPORTS DeblurerBase +{ +public: + DeblurerBase() : radius_(0), frames_(0), motions_(0), blurrinessRates_(0) {} + + virtual ~DeblurerBase() {} + + virtual void setRadius(int val) { radius_ = val; } + virtual int radius() const { return radius_; } + + virtual void deblur(int idx, Mat &frame) = 0; + + + // data from stabilizer + + virtual void setFrames(const std::vector &val) { frames_ = &val; } + virtual const std::vector& frames() const { return *frames_; } + + virtual void setMotions(const std::vector &val) { motions_ = &val; } + virtual const std::vector& motions() const { return *motions_; } + + virtual void setBlurrinessRates(const std::vector &val) { blurrinessRates_ = &val; } + virtual const std::vector& blurrinessRates() const { return *blurrinessRates_; } + +protected: + int radius_; + const std::vector *frames_; + const std::vector *motions_; + const std::vector *blurrinessRates_; +}; + +class CV_EXPORTS NullDeblurer : public DeblurerBase +{ +public: + virtual void deblur(int /*idx*/, Mat &/*frame*/) {} +}; + +class CV_EXPORTS WeightingDeblurer : public DeblurerBase +{ +public: + WeightingDeblurer(); + + void setSensitivity(float val) { sensitivity_ = val; } + float sensitivity() const { return sensitivity_; } + + virtual void deblur(int idx, Mat &frame); + +private: + float sensitivity_; + Mat_ bSum_, gSum_, rSum_, wSum_; +}; + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/fast_marching.hpp b/include/opencv2/videostab/fast_marching.hpp new file mode 100644 index 0000000..c0c7985 --- /dev/null +++ b/include/opencv2/videostab/fast_marching.hpp @@ -0,0 +1,121 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_FAST_MARCHING_HPP__ +#define __OPENCV_VIDEOSTAB_FAST_MARCHING_HPP__ + +#include +#include +#include +#include "opencv2/core.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab_marching +//! @{ + +/** @brief Describes the Fast Marching Method implementation. + + See http://iwi.eldoc.ub.rug.nl/FILES/root/2004/JGraphToolsTelea/2004JGraphToolsTelea.pdf + */ +class CV_EXPORTS FastMarchingMethod +{ +public: + FastMarchingMethod() : inf_(1e6f) {} + + /** @brief Template method that runs the Fast Marching Method. + + @param mask Image mask. 0 value indicates that the pixel value must be inpainted, 255 indicates + that the pixel value is known, other values aren't acceptable. + @param inpaint Inpainting functor that overloads void operator ()(int x, int y). + @return Inpainting functor. + */ + template + Inpaint run(const Mat &mask, Inpaint inpaint); + + /** + @return Distance map that's created during working of the method. + */ + Mat distanceMap() const { return dist_; } + +private: + enum { INSIDE = 0, BAND = 1, KNOWN = 255 }; + + struct DXY + { + float dist; + int x, y; + + DXY() : dist(0), x(0), y(0) {} + DXY(float _dist, int _x, int _y) : dist(_dist), x(_x), y(_y) {} + bool operator <(const DXY &dxy) const { return dist < dxy.dist; } + }; + + float solve(int x1, int y1, int x2, int y2) const; + int& indexOf(const DXY &dxy) { return index_(dxy.y, dxy.x); } + + void heapUp(int idx); + void heapDown(int idx); + void heapAdd(const DXY &dxy); + void heapRemoveMin(); + + float inf_; + + cv::Mat_ flag_; // flag map + cv::Mat_ dist_; // distance map + + cv::Mat_ index_; // index of point in the narrow band + std::vector narrowBand_; // narrow band heap + int size_; // narrow band size +}; + +//! @} + +} // namespace videostab +} // namespace cv + +#include "fast_marching_inl.hpp" + +#endif diff --git a/include/opencv2/videostab/fast_marching_inl.hpp b/include/opencv2/videostab/fast_marching_inl.hpp new file mode 100644 index 0000000..6388e69 --- /dev/null +++ b/include/opencv2/videostab/fast_marching_inl.hpp @@ -0,0 +1,165 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_FAST_MARCHING_INL_HPP__ +#define __OPENCV_VIDEOSTAB_FAST_MARCHING_INL_HPP__ + +#include "opencv2/videostab/fast_marching.hpp" + +namespace cv +{ +namespace videostab +{ + +template +Inpaint FastMarchingMethod::run(const cv::Mat &mask, Inpaint inpaint) +{ + using namespace cv; + + CV_Assert(mask.type() == CV_8U); + + static const int lut[4][2] = {{-1,0}, {0,-1}, {1,0}, {0,1}}; + + mask.copyTo(flag_); + flag_.create(mask.size()); + dist_.create(mask.size()); + index_.create(mask.size()); + narrowBand_.clear(); + size_ = 0; + + // init + for (int y = 0; y < flag_.rows; ++y) + { + for (int x = 0; x < flag_.cols; ++x) + { + if (flag_(y,x) == KNOWN) + dist_(y,x) = 0.f; + else + { + int n = 0; + int nunknown = 0; + + for (int i = 0; i < 4; ++i) + { + int xn = x + lut[i][0]; + int yn = y + lut[i][1]; + + if (xn >= 0 && xn < flag_.cols && yn >= 0 && yn < flag_.rows) + { + n++; + if (flag_(yn,xn) != KNOWN) + nunknown++; + } + } + + if (n>0 && nunknown == n) + { + dist_(y,x) = inf_; + flag_(y,x) = INSIDE; + } + else + { + dist_(y,x) = 0.f; + flag_(y,x) = BAND; + inpaint(x, y); + + narrowBand_.push_back(DXY(0.f,x,y)); + index_(y,x) = size_++; + } + } + } + } + + // make heap + for (int i = size_/2-1; i >= 0; --i) + heapDown(i); + + // main cycle + while (size_ > 0) + { + int x = narrowBand_[0].x; + int y = narrowBand_[0].y; + heapRemoveMin(); + + flag_(y,x) = KNOWN; + for (int n = 0; n < 4; ++n) + { + int xn = x + lut[n][0]; + int yn = y + lut[n][1]; + + if (xn >= 0 && xn < flag_.cols && yn >= 0 && yn < flag_.rows && flag_(yn,xn) != KNOWN) + { + dist_(yn,xn) = std::min(std::min(solve(xn-1, yn, xn, yn-1), solve(xn+1, yn, xn, yn-1)), + std::min(solve(xn-1, yn, xn, yn+1), solve(xn+1, yn, xn, yn+1))); + + if (flag_(yn,xn) == INSIDE) + { + flag_(yn,xn) = BAND; + inpaint(xn, yn); + heapAdd(DXY(dist_(yn,xn),xn,yn)); + } + else + { + int i = index_(yn,xn); + if (dist_(yn,xn) < narrowBand_[i].dist) + { + narrowBand_[i].dist = dist_(yn,xn); + heapUp(i); + } + // works better if it's commented out + /*else if (dist(yn,xn) > narrowBand[i].dist) + { + narrowBand[i].dist = dist(yn,xn); + heapDown(i); + }*/ + } + } + } + } + + return inpaint; +} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/frame_source.hpp b/include/opencv2/videostab/frame_source.hpp new file mode 100644 index 0000000..612fbdb --- /dev/null +++ b/include/opencv2/videostab/frame_source.hpp @@ -0,0 +1,94 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_FRAME_SOURCE_HPP__ +#define __OPENCV_VIDEOSTAB_FRAME_SOURCE_HPP__ + +#include +#include "opencv2/core.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +class CV_EXPORTS IFrameSource +{ +public: + virtual ~IFrameSource() {} + virtual void reset() = 0; + virtual Mat nextFrame() = 0; +}; + +class CV_EXPORTS NullFrameSource : public IFrameSource +{ +public: + virtual void reset() {} + virtual Mat nextFrame() { return Mat(); } +}; + +class CV_EXPORTS VideoFileSource : public IFrameSource +{ +public: + VideoFileSource(const String &path, bool volatileFrame = false); + + virtual void reset(); + virtual Mat nextFrame(); + + int width(); + int height(); + int count(); + double fps(); + +private: + Ptr impl; +}; + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/global_motion.hpp b/include/opencv2/videostab/global_motion.hpp new file mode 100644 index 0000000..5d51e42 --- /dev/null +++ b/include/opencv2/videostab/global_motion.hpp @@ -0,0 +1,299 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_GLOBAL_MOTION_HPP__ +#define __OPENCV_VIDEOSTAB_GLOBAL_MOTION_HPP__ + +#include +#include +#include "opencv2/core.hpp" +#include "opencv2/features2d.hpp" +#include "opencv2/opencv_modules.hpp" +#include "opencv2/videostab/optical_flow.hpp" +#include "opencv2/videostab/motion_core.hpp" +#include "opencv2/videostab/outlier_rejection.hpp" + +#ifdef HAVE_OPENCV_CUDAIMGPROC +# include "opencv2/cudaimgproc.hpp" +#endif + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab_motion +//! @{ + +/** @brief Estimates best global motion between two 2D point clouds in the least-squares sense. + +@note Works in-place and changes input point arrays. + +@param points0 Source set of 2D points (32F). +@param points1 Destination set of 2D points (32F). +@param model Motion model (up to MM_AFFINE). +@param rmse Final root-mean-square error. +@return 3x3 2D transformation matrix (32F). + */ +CV_EXPORTS Mat estimateGlobalMotionLeastSquares( + InputOutputArray points0, InputOutputArray points1, int model = MM_AFFINE, + float *rmse = 0); + +/** @brief Estimates best global motion between two 2D point clouds robustly (using RANSAC method). + +@param points0 Source set of 2D points (32F). +@param points1 Destination set of 2D points (32F). +@param model Motion model. See cv::videostab::MotionModel. +@param params RANSAC method parameters. See videostab::RansacParams. +@param rmse Final root-mean-square error. +@param ninliers Final number of inliers. + */ +CV_EXPORTS Mat estimateGlobalMotionRansac( + InputArray points0, InputArray points1, int model = MM_AFFINE, + const RansacParams ¶ms = RansacParams::default2dMotion(MM_AFFINE), + float *rmse = 0, int *ninliers = 0); + +/** @brief Base class for all global motion estimation methods. + */ +class CV_EXPORTS MotionEstimatorBase +{ +public: + virtual ~MotionEstimatorBase() {} + + /** @brief Sets motion model. + + @param val Motion model. See cv::videostab::MotionModel. + */ + virtual void setMotionModel(MotionModel val) { motionModel_ = val; } + + /** + @return Motion model. See cv::videostab::MotionModel. + */ + virtual MotionModel motionModel() const { return motionModel_; } + + /** @brief Estimates global motion between two 2D point clouds. + + @param points0 Source set of 2D points (32F). + @param points1 Destination set of 2D points (32F). + @param ok Indicates whether motion was estimated successfully. + @return 3x3 2D transformation matrix (32F). + */ + virtual Mat estimate(InputArray points0, InputArray points1, bool *ok = 0) = 0; + +protected: + MotionEstimatorBase(MotionModel model) { setMotionModel(model); } + +private: + MotionModel motionModel_; +}; + +/** @brief Describes a robust RANSAC-based global 2D motion estimation method which minimizes L2 error. + */ +class CV_EXPORTS MotionEstimatorRansacL2 : public MotionEstimatorBase +{ +public: + MotionEstimatorRansacL2(MotionModel model = MM_AFFINE); + + void setRansacParams(const RansacParams &val) { ransacParams_ = val; } + RansacParams ransacParams() const { return ransacParams_; } + + void setMinInlierRatio(float val) { minInlierRatio_ = val; } + float minInlierRatio() const { return minInlierRatio_; } + + virtual Mat estimate(InputArray points0, InputArray points1, bool *ok = 0); + +private: + RansacParams ransacParams_; + float minInlierRatio_; +}; + +/** @brief Describes a global 2D motion estimation method which minimizes L1 error. + +@note To be able to use this method you must build OpenCV with CLP library support. : + */ +class CV_EXPORTS MotionEstimatorL1 : public MotionEstimatorBase +{ +public: + MotionEstimatorL1(MotionModel model = MM_AFFINE); + + virtual Mat estimate(InputArray points0, InputArray points1, bool *ok = 0); + +private: + std::vector obj_, collb_, colub_; + std::vector elems_, rowlb_, rowub_; + std::vector rows_, cols_; + + void set(int row, int col, double coef) + { + rows_.push_back(row); + cols_.push_back(col); + elems_.push_back(coef); + } +}; + +/** @brief Base class for global 2D motion estimation methods which take frames as input. + */ +class CV_EXPORTS ImageMotionEstimatorBase +{ +public: + virtual ~ImageMotionEstimatorBase() {} + + virtual void setMotionModel(MotionModel val) { motionModel_ = val; } + virtual MotionModel motionModel() const { return motionModel_; } + + virtual Mat estimate(const Mat &frame0, const Mat &frame1, bool *ok = 0) = 0; + +protected: + ImageMotionEstimatorBase(MotionModel model) { setMotionModel(model); } + +private: + MotionModel motionModel_; +}; + +class CV_EXPORTS FromFileMotionReader : public ImageMotionEstimatorBase +{ +public: + FromFileMotionReader(const String &path); + + virtual Mat estimate(const Mat &frame0, const Mat &frame1, bool *ok = 0); + +private: + std::ifstream file_; +}; + +class CV_EXPORTS ToFileMotionWriter : public ImageMotionEstimatorBase +{ +public: + ToFileMotionWriter(const String &path, Ptr estimator); + + virtual void setMotionModel(MotionModel val) { motionEstimator_->setMotionModel(val); } + virtual MotionModel motionModel() const { return motionEstimator_->motionModel(); } + + virtual Mat estimate(const Mat &frame0, const Mat &frame1, bool *ok = 0); + +private: + std::ofstream file_; + Ptr motionEstimator_; +}; + +/** @brief Describes a global 2D motion estimation method which uses keypoints detection and optical flow for +matching. + */ +class CV_EXPORTS KeypointBasedMotionEstimator : public ImageMotionEstimatorBase +{ +public: + KeypointBasedMotionEstimator(Ptr estimator); + + virtual void setMotionModel(MotionModel val) { motionEstimator_->setMotionModel(val); } + virtual MotionModel motionModel() const { return motionEstimator_->motionModel(); } + + void setDetector(Ptr val) { detector_ = val; } + Ptr detector() const { return detector_; } + + void setOpticalFlowEstimator(Ptr val) { optFlowEstimator_ = val; } + Ptr opticalFlowEstimator() const { return optFlowEstimator_; } + + void setOutlierRejector(Ptr val) { outlierRejector_ = val; } + Ptr outlierRejector() const { return outlierRejector_; } + + virtual Mat estimate(const Mat &frame0, const Mat &frame1, bool *ok = 0); + +private: + Ptr motionEstimator_; + Ptr detector_; + Ptr optFlowEstimator_; + Ptr outlierRejector_; + + std::vector status_; + std::vector keypointsPrev_; + std::vector pointsPrev_, points_; + std::vector pointsPrevGood_, pointsGood_; +}; + +#if defined(HAVE_OPENCV_CUDAIMGPROC) && defined(HAVE_OPENCV_CUDAOPTFLOW) + +class CV_EXPORTS KeypointBasedMotionEstimatorGpu : public ImageMotionEstimatorBase +{ +public: + KeypointBasedMotionEstimatorGpu(Ptr estimator); + + virtual void setMotionModel(MotionModel val) { motionEstimator_->setMotionModel(val); } + virtual MotionModel motionModel() const { return motionEstimator_->motionModel(); } + + void setOutlierRejector(Ptr val) { outlierRejector_ = val; } + Ptr outlierRejector() const { return outlierRejector_; } + + virtual Mat estimate(const Mat &frame0, const Mat &frame1, bool *ok = 0); + Mat estimate(const cuda::GpuMat &frame0, const cuda::GpuMat &frame1, bool *ok = 0); + +private: + Ptr motionEstimator_; + Ptr detector_; + SparsePyrLkOptFlowEstimatorGpu optFlowEstimator_; + Ptr outlierRejector_; + + cuda::GpuMat frame0_, grayFrame0_, frame1_; + cuda::GpuMat pointsPrev_, points_; + cuda::GpuMat status_; + + Mat hostPointsPrev_, hostPoints_; + std::vector hostPointsPrevTmp_, hostPointsTmp_; + std::vector rejectionStatus_; +}; + +#endif // defined(HAVE_OPENCV_CUDAIMGPROC) && defined(HAVE_OPENCV_CUDAOPTFLOW) + +/** @brief Computes motion between two frames assuming that all the intermediate motions are known. + +@param from Source frame index. +@param to Destination frame index. +@param motions Pair-wise motions. motions[i] denotes motion from the frame i to the frame i+1 +@return Motion from the frame from to the frame to. + */ +CV_EXPORTS Mat getMotion(int from, int to, const std::vector &motions); + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/inpainting.hpp b/include/opencv2/videostab/inpainting.hpp new file mode 100644 index 0000000..844c68c --- /dev/null +++ b/include/opencv2/videostab/inpainting.hpp @@ -0,0 +1,212 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_INPAINTINT_HPP__ +#define __OPENCV_VIDEOSTAB_INPAINTINT_HPP__ + +#include +#include "opencv2/core.hpp" +#include "opencv2/videostab/optical_flow.hpp" +#include "opencv2/videostab/fast_marching.hpp" +#include "opencv2/videostab/global_motion.hpp" +#include "opencv2/photo.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +class CV_EXPORTS InpainterBase +{ +public: + InpainterBase() + : radius_(0), motionModel_(MM_UNKNOWN), frames_(0), motions_(0), + stabilizedFrames_(0), stabilizationMotions_(0) {} + + virtual ~InpainterBase() {} + + virtual void setRadius(int val) { radius_ = val; } + virtual int radius() const { return radius_; } + + virtual void setMotionModel(MotionModel val) { motionModel_ = val; } + virtual MotionModel motionModel() const { return motionModel_; } + + virtual void inpaint(int idx, Mat &frame, Mat &mask) = 0; + + + // data from stabilizer + + virtual void setFrames(const std::vector &val) { frames_ = &val; } + virtual const std::vector& frames() const { return *frames_; } + + virtual void setMotions(const std::vector &val) { motions_ = &val; } + virtual const std::vector& motions() const { return *motions_; } + + virtual void setStabilizedFrames(const std::vector &val) { stabilizedFrames_ = &val; } + virtual const std::vector& stabilizedFrames() const { return *stabilizedFrames_; } + + virtual void setStabilizationMotions(const std::vector &val) { stabilizationMotions_ = &val; } + virtual const std::vector& stabilizationMotions() const { return *stabilizationMotions_; } + +protected: + int radius_; + MotionModel motionModel_; + const std::vector *frames_; + const std::vector *motions_; + const std::vector *stabilizedFrames_; + const std::vector *stabilizationMotions_; +}; + +class CV_EXPORTS NullInpainter : public InpainterBase +{ +public: + virtual void inpaint(int /*idx*/, Mat &/*frame*/, Mat &/*mask*/) {} +}; + +class CV_EXPORTS InpaintingPipeline : public InpainterBase +{ +public: + void pushBack(Ptr inpainter) { inpainters_.push_back(inpainter); } + bool empty() const { return inpainters_.empty(); } + + virtual void setRadius(int val); + virtual void setMotionModel(MotionModel val); + virtual void setFrames(const std::vector &val); + virtual void setMotions(const std::vector &val); + virtual void setStabilizedFrames(const std::vector &val); + virtual void setStabilizationMotions(const std::vector &val); + + virtual void inpaint(int idx, Mat &frame, Mat &mask); + +private: + std::vector > inpainters_; +}; + +class CV_EXPORTS ConsistentMosaicInpainter : public InpainterBase +{ +public: + ConsistentMosaicInpainter(); + + void setStdevThresh(float val) { stdevThresh_ = val; } + float stdevThresh() const { return stdevThresh_; } + + virtual void inpaint(int idx, Mat &frame, Mat &mask); + +private: + float stdevThresh_; +}; + +class CV_EXPORTS MotionInpainter : public InpainterBase +{ +public: + MotionInpainter(); + + void setOptFlowEstimator(Ptr val) { optFlowEstimator_ = val; } + Ptr optFlowEstimator() const { return optFlowEstimator_; } + + void setFlowErrorThreshold(float val) { flowErrorThreshold_ = val; } + float flowErrorThreshold() const { return flowErrorThreshold_; } + + void setDistThreshold(float val) { distThresh_ = val; } + float distThresh() const { return distThresh_; } + + void setBorderMode(int val) { borderMode_ = val; } + int borderMode() const { return borderMode_; } + + virtual void inpaint(int idx, Mat &frame, Mat &mask); + +private: + FastMarchingMethod fmm_; + Ptr optFlowEstimator_; + float flowErrorThreshold_; + float distThresh_; + int borderMode_; + + Mat frame1_, transformedFrame1_; + Mat_ grayFrame_, transformedGrayFrame1_; + Mat_ mask1_, transformedMask1_; + Mat_ flowX_, flowY_, flowErrors_; + Mat_ flowMask_; +}; + +class CV_EXPORTS ColorAverageInpainter : public InpainterBase +{ +public: + virtual void inpaint(int idx, Mat &frame, Mat &mask); + +private: + FastMarchingMethod fmm_; +}; + +class CV_EXPORTS ColorInpainter : public InpainterBase +{ +public: + ColorInpainter(int method = INPAINT_TELEA, double radius = 2.); + + virtual void inpaint(int idx, Mat &frame, Mat &mask); + +private: + int method_; + double radius_; + Mat invMask_; +}; + +inline ColorInpainter::ColorInpainter(int _method, double _radius) + : method_(_method), radius_(_radius) {} + +CV_EXPORTS void calcFlowMask( + const Mat &flowX, const Mat &flowY, const Mat &errors, float maxError, + const Mat &mask0, const Mat &mask1, Mat &flowMask); + +CV_EXPORTS void completeFrameAccordingToFlow( + const Mat &flowMask, const Mat &flowX, const Mat &flowY, const Mat &frame1, const Mat &mask1, + float distThresh, Mat& frame0, Mat &mask0); + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/log.hpp b/include/opencv2/videostab/log.hpp new file mode 100644 index 0000000..28625ed --- /dev/null +++ b/include/opencv2/videostab/log.hpp @@ -0,0 +1,80 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_LOG_HPP__ +#define __OPENCV_VIDEOSTAB_LOG_HPP__ + +#include "opencv2/core.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +class CV_EXPORTS ILog +{ +public: + virtual ~ILog() {} + virtual void print(const char *format, ...) = 0; +}; + +class CV_EXPORTS NullLog : public ILog +{ +public: + virtual void print(const char * /*format*/, ...) {} +}; + +class CV_EXPORTS LogToStdout : public ILog +{ +public: + virtual void print(const char *format, ...); +}; + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/motion_core.hpp b/include/opencv2/videostab/motion_core.hpp new file mode 100644 index 0000000..17448e3 --- /dev/null +++ b/include/opencv2/videostab/motion_core.hpp @@ -0,0 +1,129 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_MOTION_CORE_HPP__ +#define __OPENCV_VIDEOSTAB_MOTION_CORE_HPP__ + +#include +#include "opencv2/core.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab_motion +//! @{ + +/** @brief Describes motion model between two point clouds. + */ +enum MotionModel +{ + MM_TRANSLATION = 0, + MM_TRANSLATION_AND_SCALE = 1, + MM_ROTATION = 2, + MM_RIGID = 3, + MM_SIMILARITY = 4, + MM_AFFINE = 5, + MM_HOMOGRAPHY = 6, + MM_UNKNOWN = 7 +}; + +/** @brief Describes RANSAC method parameters. + */ +struct CV_EXPORTS RansacParams +{ + int size; //!< subset size + float thresh; //!< max error to classify as inlier + float eps; //!< max outliers ratio + float prob; //!< probability of success + + RansacParams() : size(0), thresh(0), eps(0), prob(0) {} + /** @brief Constructor + @param size Subset size. + @param thresh Maximum re-projection error value to classify as inlier. + @param eps Maximum ratio of incorrect correspondences. + @param prob Required success probability. + */ + RansacParams(int size, float thresh, float eps, float prob); + + /** + @return Number of iterations that'll be performed by RANSAC method. + */ + int niters() const + { + return static_cast( + std::ceil(std::log(1 - prob) / std::log(1 - std::pow(1 - eps, size)))); + } + + /** + @param model Motion model. See cv::videostab::MotionModel. + @return Default RANSAC method parameters for the given motion model. + */ + static RansacParams default2dMotion(MotionModel model) + { + CV_Assert(model < MM_UNKNOWN); + if (model == MM_TRANSLATION) + return RansacParams(1, 0.5f, 0.5f, 0.99f); + if (model == MM_TRANSLATION_AND_SCALE) + return RansacParams(2, 0.5f, 0.5f, 0.99f); + if (model == MM_ROTATION) + return RansacParams(1, 0.5f, 0.5f, 0.99f); + if (model == MM_RIGID) + return RansacParams(2, 0.5f, 0.5f, 0.99f); + if (model == MM_SIMILARITY) + return RansacParams(2, 0.5f, 0.5f, 0.99f); + if (model == MM_AFFINE) + return RansacParams(3, 0.5f, 0.5f, 0.99f); + return RansacParams(4, 0.5f, 0.5f, 0.99f); + } +}; + +inline RansacParams::RansacParams(int _size, float _thresh, float _eps, float _prob) + : size(_size), thresh(_thresh), eps(_eps), prob(_prob) {} + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/motion_stabilizing.hpp b/include/opencv2/videostab/motion_stabilizing.hpp new file mode 100644 index 0000000..3bdbfbd --- /dev/null +++ b/include/opencv2/videostab/motion_stabilizing.hpp @@ -0,0 +1,174 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_MOTION_STABILIZING_HPP__ +#define __OPENCV_VIDEOSTAB_MOTION_STABILIZING_HPP__ + +#include +#include +#include "opencv2/core.hpp" +#include "opencv2/videostab/global_motion.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab_motion +//! @{ + +class CV_EXPORTS IMotionStabilizer +{ +public: + virtual ~IMotionStabilizer() {} + + //! assumes that [0, size-1) is in or equals to [range.first, range.second) + virtual void stabilize( + int size, const std::vector &motions, std::pair range, + Mat *stabilizationMotions) = 0; +}; + +class CV_EXPORTS MotionStabilizationPipeline : public IMotionStabilizer +{ +public: + void pushBack(Ptr stabilizer) { stabilizers_.push_back(stabilizer); } + bool empty() const { return stabilizers_.empty(); } + + virtual void stabilize( + int size, const std::vector &motions, std::pair range, + Mat *stabilizationMotions); + +private: + std::vector > stabilizers_; +}; + +class CV_EXPORTS MotionFilterBase : public IMotionStabilizer +{ +public: + virtual ~MotionFilterBase() {} + + virtual Mat stabilize( + int idx, const std::vector &motions, std::pair range) = 0; + + virtual void stabilize( + int size, const std::vector &motions, std::pair range, + Mat *stabilizationMotions); +}; + +class CV_EXPORTS GaussianMotionFilter : public MotionFilterBase +{ +public: + GaussianMotionFilter(int radius = 15, float stdev = -1.f); + + void setParams(int radius, float stdev = -1.f); + int radius() const { return radius_; } + float stdev() const { return stdev_; } + + virtual Mat stabilize( + int idx, const std::vector &motions, std::pair range); + +private: + int radius_; + float stdev_; + std::vector weight_; +}; + +inline GaussianMotionFilter::GaussianMotionFilter(int _radius, float _stdev) { setParams(_radius, _stdev); } + +class CV_EXPORTS LpMotionStabilizer : public IMotionStabilizer +{ +public: + LpMotionStabilizer(MotionModel model = MM_SIMILARITY); + + void setMotionModel(MotionModel val) { model_ = val; } + MotionModel motionModel() const { return model_; } + + void setFrameSize(Size val) { frameSize_ = val; } + Size frameSize() const { return frameSize_; } + + void setTrimRatio(float val) { trimRatio_ = val; } + float trimRatio() const { return trimRatio_; } + + void setWeight1(float val) { w1_ = val; } + float weight1() const { return w1_; } + + void setWeight2(float val) { w2_ = val; } + float weight2() const { return w2_; } + + void setWeight3(float val) { w3_ = val; } + float weight3() const { return w3_; } + + void setWeight4(float val) { w4_ = val; } + float weight4() const { return w4_; } + + virtual void stabilize( + int size, const std::vector &motions, std::pair range, + Mat *stabilizationMotions); + +private: + MotionModel model_; + Size frameSize_; + float trimRatio_; + float w1_, w2_, w3_, w4_; + + std::vector obj_, collb_, colub_; + std::vector rows_, cols_; + std::vector elems_, rowlb_, rowub_; + + void set(int row, int col, double coef) + { + rows_.push_back(row); + cols_.push_back(col); + elems_.push_back(coef); + } +}; + +CV_EXPORTS Mat ensureInclusionConstraint(const Mat &M, Size size, float trimRatio); + +CV_EXPORTS float estimateOptimalTrimRatio(const Mat &M, Size size); + +//! @} + +} // namespace videostab +} // namespace + +#endif diff --git a/include/opencv2/videostab/optical_flow.hpp b/include/opencv2/videostab/optical_flow.hpp new file mode 100644 index 0000000..41d1953 --- /dev/null +++ b/include/opencv2/videostab/optical_flow.hpp @@ -0,0 +1,150 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_OPTICAL_FLOW_HPP__ +#define __OPENCV_VIDEOSTAB_OPTICAL_FLOW_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/opencv_modules.hpp" + +#ifdef HAVE_OPENCV_CUDAOPTFLOW + #include "opencv2/cudaoptflow.hpp" +#endif + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +class CV_EXPORTS ISparseOptFlowEstimator +{ +public: + virtual ~ISparseOptFlowEstimator() {} + virtual void run( + InputArray frame0, InputArray frame1, InputArray points0, InputOutputArray points1, + OutputArray status, OutputArray errors) = 0; +}; + +class CV_EXPORTS IDenseOptFlowEstimator +{ +public: + virtual ~IDenseOptFlowEstimator() {} + virtual void run( + InputArray frame0, InputArray frame1, InputOutputArray flowX, InputOutputArray flowY, + OutputArray errors) = 0; +}; + +class CV_EXPORTS PyrLkOptFlowEstimatorBase +{ +public: + PyrLkOptFlowEstimatorBase() { setWinSize(Size(21, 21)); setMaxLevel(3); } + + virtual void setWinSize(Size val) { winSize_ = val; } + virtual Size winSize() const { return winSize_; } + + virtual void setMaxLevel(int val) { maxLevel_ = val; } + virtual int maxLevel() const { return maxLevel_; } + virtual ~PyrLkOptFlowEstimatorBase() {} + +protected: + Size winSize_; + int maxLevel_; +}; + +class CV_EXPORTS SparsePyrLkOptFlowEstimator + : public PyrLkOptFlowEstimatorBase, public ISparseOptFlowEstimator +{ +public: + virtual void run( + InputArray frame0, InputArray frame1, InputArray points0, InputOutputArray points1, + OutputArray status, OutputArray errors); +}; + +#ifdef HAVE_OPENCV_CUDAOPTFLOW + +class CV_EXPORTS SparsePyrLkOptFlowEstimatorGpu + : public PyrLkOptFlowEstimatorBase, public ISparseOptFlowEstimator +{ +public: + SparsePyrLkOptFlowEstimatorGpu(); + + virtual void run( + InputArray frame0, InputArray frame1, InputArray points0, InputOutputArray points1, + OutputArray status, OutputArray errors); + + void run(const cuda::GpuMat &frame0, const cuda::GpuMat &frame1, const cuda::GpuMat &points0, cuda::GpuMat &points1, + cuda::GpuMat &status, cuda::GpuMat &errors); + + void run(const cuda::GpuMat &frame0, const cuda::GpuMat &frame1, const cuda::GpuMat &points0, cuda::GpuMat &points1, + cuda::GpuMat &status); + +private: + Ptr optFlowEstimator_; + cuda::GpuMat frame0_, frame1_, points0_, points1_, status_, errors_; +}; + +class CV_EXPORTS DensePyrLkOptFlowEstimatorGpu + : public PyrLkOptFlowEstimatorBase, public IDenseOptFlowEstimator +{ +public: + DensePyrLkOptFlowEstimatorGpu(); + + virtual void run( + InputArray frame0, InputArray frame1, InputOutputArray flowX, InputOutputArray flowY, + OutputArray errors); + +private: + Ptr optFlowEstimator_; + cuda::GpuMat frame0_, frame1_, flowX_, flowY_, errors_; +}; + +#endif + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/outlier_rejection.hpp b/include/opencv2/videostab/outlier_rejection.hpp new file mode 100644 index 0000000..9e40f85 --- /dev/null +++ b/include/opencv2/videostab/outlier_rejection.hpp @@ -0,0 +1,101 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_OUTLIER_REJECTION_HPP__ +#define __OPENCV_VIDEOSTAB_OUTLIER_REJECTION_HPP__ + +#include +#include "opencv2/core.hpp" +#include "opencv2/videostab/motion_core.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +class CV_EXPORTS IOutlierRejector +{ +public: + virtual ~IOutlierRejector() {} + + virtual void process( + Size frameSize, InputArray points0, InputArray points1, OutputArray mask) = 0; +}; + +class CV_EXPORTS NullOutlierRejector : public IOutlierRejector +{ +public: + virtual void process( + Size frameSize, InputArray points0, InputArray points1, OutputArray mask); +}; + +class CV_EXPORTS TranslationBasedLocalOutlierRejector : public IOutlierRejector +{ +public: + TranslationBasedLocalOutlierRejector(); + + void setCellSize(Size val) { cellSize_ = val; } + Size cellSize() const { return cellSize_; } + + void setRansacParams(RansacParams val) { ransacParams_ = val; } + RansacParams ransacParams() const { return ransacParams_; } + + virtual void process( + Size frameSize, InputArray points0, InputArray points1, OutputArray mask); + +private: + Size cellSize_; + RansacParams ransacParams_; + + typedef std::vector Cell; + std::vector grid_; +}; + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/ring_buffer.hpp b/include/opencv2/videostab/ring_buffer.hpp new file mode 100644 index 0000000..7cc3f03 --- /dev/null +++ b/include/opencv2/videostab/ring_buffer.hpp @@ -0,0 +1,72 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_RING_BUFFER_HPP__ +#define __OPENCV_VIDEOSTAB_RING_BUFFER_HPP__ + +#include +#include "opencv2/imgproc.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +template inline T& at(int idx, std::vector &items) +{ + return items[cv::borderInterpolate(idx, static_cast(items.size()), cv::BORDER_WRAP)]; +} + +template inline const T& at(int idx, const std::vector &items) +{ + return items[cv::borderInterpolate(idx, static_cast(items.size()), cv::BORDER_WRAP)]; +} + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/stabilizer.hpp b/include/opencv2/videostab/stabilizer.hpp new file mode 100644 index 0000000..c18d314 --- /dev/null +++ b/include/opencv2/videostab/stabilizer.hpp @@ -0,0 +1,200 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_STABILIZER_HPP__ +#define __OPENCV_VIDEOSTAB_STABILIZER_HPP__ + +#include +#include +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/videostab/global_motion.hpp" +#include "opencv2/videostab/motion_stabilizing.hpp" +#include "opencv2/videostab/frame_source.hpp" +#include "opencv2/videostab/log.hpp" +#include "opencv2/videostab/inpainting.hpp" +#include "opencv2/videostab/deblurring.hpp" +#include "opencv2/videostab/wobble_suppression.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +class CV_EXPORTS StabilizerBase +{ +public: + virtual ~StabilizerBase() {} + + void setLog(Ptr ilog) { log_ = ilog; } + Ptr log() const { return log_; } + + void setRadius(int val) { radius_ = val; } + int radius() const { return radius_; } + + void setFrameSource(Ptr val) { frameSource_ = val; } + Ptr frameSource() const { return frameSource_; } + + void setMotionEstimator(Ptr val) { motionEstimator_ = val; } + Ptr motionEstimator() const { return motionEstimator_; } + + void setDeblurer(Ptr val) { deblurer_ = val; } + Ptr deblurrer() const { return deblurer_; } + + void setTrimRatio(float val) { trimRatio_ = val; } + float trimRatio() const { return trimRatio_; } + + void setCorrectionForInclusion(bool val) { doCorrectionForInclusion_ = val; } + bool doCorrectionForInclusion() const { return doCorrectionForInclusion_; } + + void setBorderMode(int val) { borderMode_ = val; } + int borderMode() const { return borderMode_; } + + void setInpainter(Ptr val) { inpainter_ = val; } + Ptr inpainter() const { return inpainter_; } + +protected: + StabilizerBase(); + + void reset(); + Mat nextStabilizedFrame(); + bool doOneIteration(); + virtual void setUp(const Mat &firstFrame); + virtual Mat estimateMotion() = 0; + virtual Mat estimateStabilizationMotion() = 0; + void stabilizeFrame(); + virtual Mat postProcessFrame(const Mat &frame); + void logProcessingTime(); + + Ptr log_; + Ptr frameSource_; + Ptr motionEstimator_; + Ptr deblurer_; + Ptr inpainter_; + int radius_; + float trimRatio_; + bool doCorrectionForInclusion_; + int borderMode_; + + Size frameSize_; + Mat frameMask_; + int curPos_; + int curStabilizedPos_; + bool doDeblurring_; + Mat preProcessedFrame_; + bool doInpainting_; + Mat inpaintingMask_; + Mat finalFrame_; + std::vector frames_; + std::vector motions_; // motions_[i] is the motion from i-th to i+1-th frame + std::vector blurrinessRates_; + std::vector stabilizedFrames_; + std::vector stabilizedMasks_; + std::vector stabilizationMotions_; + clock_t processingStartTime_; +}; + +class CV_EXPORTS OnePassStabilizer : public StabilizerBase, public IFrameSource +{ +public: + OnePassStabilizer(); + + void setMotionFilter(Ptr val) { motionFilter_ = val; } + Ptr motionFilter() const { return motionFilter_; } + + virtual void reset(); + virtual Mat nextFrame() { return nextStabilizedFrame(); } + +protected: + virtual void setUp(const Mat &firstFrame); + virtual Mat estimateMotion(); + virtual Mat estimateStabilizationMotion(); + virtual Mat postProcessFrame(const Mat &frame); + + Ptr motionFilter_; +}; + +class CV_EXPORTS TwoPassStabilizer : public StabilizerBase, public IFrameSource +{ +public: + TwoPassStabilizer(); + + void setMotionStabilizer(Ptr val) { motionStabilizer_ = val; } + Ptr motionStabilizer() const { return motionStabilizer_; } + + void setWobbleSuppressor(Ptr val) { wobbleSuppressor_ = val; } + Ptr wobbleSuppressor() const { return wobbleSuppressor_; } + + void setEstimateTrimRatio(bool val) { mustEstTrimRatio_ = val; } + bool mustEstimateTrimaRatio() const { return mustEstTrimRatio_; } + + virtual void reset(); + virtual Mat nextFrame(); + +protected: + void runPrePassIfNecessary(); + + virtual void setUp(const Mat &firstFrame); + virtual Mat estimateMotion(); + virtual Mat estimateStabilizationMotion(); + virtual Mat postProcessFrame(const Mat &frame); + + Ptr motionStabilizer_; + Ptr wobbleSuppressor_; + bool mustEstTrimRatio_; + + int frameCount_; + bool isPrePassDone_; + bool doWobbleSuppression_; + std::vector motions2_; + Mat suppressedFrame_; +}; + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/videostab/wobble_suppression.hpp b/include/opencv2/videostab/wobble_suppression.hpp new file mode 100644 index 0000000..3f0a943 --- /dev/null +++ b/include/opencv2/videostab/wobble_suppression.hpp @@ -0,0 +1,140 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_VIDEOSTAB_WOBBLE_SUPPRESSION_HPP__ +#define __OPENCV_VIDEOSTAB_WOBBLE_SUPPRESSION_HPP__ + +#include +#include "opencv2/core.hpp" +#include "opencv2/core/cuda.hpp" +#include "opencv2/videostab/global_motion.hpp" +#include "opencv2/videostab/log.hpp" + +namespace cv +{ +namespace videostab +{ + +//! @addtogroup videostab +//! @{ + +class CV_EXPORTS WobbleSuppressorBase +{ +public: + WobbleSuppressorBase(); + + virtual ~WobbleSuppressorBase() {} + + void setMotionEstimator(Ptr val) { motionEstimator_ = val; } + Ptr motionEstimator() const { return motionEstimator_; } + + virtual void suppress(int idx, const Mat &frame, Mat &result) = 0; + + + // data from stabilizer + + virtual void setFrameCount(int val) { frameCount_ = val; } + virtual int frameCount() const { return frameCount_; } + + virtual void setMotions(const std::vector &val) { motions_ = &val; } + virtual const std::vector& motions() const { return *motions_; } + + virtual void setMotions2(const std::vector &val) { motions2_ = &val; } + virtual const std::vector& motions2() const { return *motions2_; } + + virtual void setStabilizationMotions(const std::vector &val) { stabilizationMotions_ = &val; } + virtual const std::vector& stabilizationMotions() const { return *stabilizationMotions_; } + +protected: + Ptr motionEstimator_; + int frameCount_; + const std::vector *motions_; + const std::vector *motions2_; + const std::vector *stabilizationMotions_; +}; + +class CV_EXPORTS NullWobbleSuppressor : public WobbleSuppressorBase +{ +public: + virtual void suppress(int idx, const Mat &frame, Mat &result); +}; + +class CV_EXPORTS MoreAccurateMotionWobbleSuppressorBase : public WobbleSuppressorBase +{ +public: + virtual void setPeriod(int val) { period_ = val; } + virtual int period() const { return period_; } + +protected: + MoreAccurateMotionWobbleSuppressorBase() { setPeriod(30); } + + int period_; +}; + +class CV_EXPORTS MoreAccurateMotionWobbleSuppressor : public MoreAccurateMotionWobbleSuppressorBase +{ +public: + virtual void suppress(int idx, const Mat &frame, Mat &result); + +private: + Mat_ mapx_, mapy_; +}; + +#if defined(HAVE_OPENCV_CUDAWARPING) +class CV_EXPORTS MoreAccurateMotionWobbleSuppressorGpu : public MoreAccurateMotionWobbleSuppressorBase +{ +public: + void suppress(int idx, const cuda::GpuMat &frame, cuda::GpuMat &result); + virtual void suppress(int idx, const Mat &frame, Mat &result); + +private: + cuda::GpuMat frameDevice_, resultDevice_; + cuda::GpuMat mapx_, mapy_; +}; +#endif + +//! @} + +} // namespace videostab +} // namespace cv + +#endif diff --git a/include/opencv2/world.hpp b/include/opencv2/world.hpp new file mode 100644 index 0000000..2442f2c --- /dev/null +++ b/include/opencv2/world.hpp @@ -0,0 +1,58 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_WORLD_HPP__ +#define __OPENCV_WORLD_HPP__ + +#include "opencv2/core.hpp" + +#ifdef __cplusplus +namespace cv +{ + +CV_EXPORTS_W bool initAll(); + +} + +#endif + +#endif diff --git a/include/platform/alloc/ialloc.h b/include/platform/alloc/ialloc.h new file mode 100644 index 0000000..e69ec3e --- /dev/null +++ b/include/platform/alloc/ialloc.h @@ -0,0 +1,218 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NALLOCATOR_INTERFACE__ +#define __NALLOCATOR_INTERFACE__ + + + #include "ntypes.h" + #include + + +namespace GS { + namespace Alloc { + +// Allocator systems. +enum System +{ + General, + + ListItem, + StringBuffer, + + Filesystem, + Metatag, + + Curve, + Motion, + AnimationSource, + + Vector, + Matrix, + + Physics, + + Item3d, + + Geometry, + Material, + Texture, + Picture, + + Mixer, + Sound, + + Renderer, + RendererJob, + RendererTerrain, + + VertexBuffer, + + Global, + SystemCount +}; + +struct SystemDesc +{ + const char *group; + const char *name; +}; + +/* + Allocators can be changed per system by editing the following defines. +*/ +#define MemAllocListItem GS::Alloc::DefaultAllocator +#define MemAllocStringBuffer GS::Alloc::DefaultAllocator + +#define MemAllocFilesystem GS::Alloc::DefaultAllocator +#define MemAllocMetatag GS::Alloc::DefaultAllocator + +#define MemAllocCurve GS::Alloc::DefaultAllocator +#define MemAllocMotion GS::Alloc::DefaultAllocator +#define MemAllocAnimationSource GS::Alloc::DefaultAllocator + +#define MemAllocVector GS::Alloc::DefaultAllocator +#define MemAllocMatrix GS::Alloc::DefaultAllocator + +#define MemAllocPhysics GS::Alloc::DefaultAllocator + +#define MemAllocItem3d GS::Alloc::DefaultAllocator + +#define MemAllocGeometry GS::Alloc::DefaultAllocator +#define MemAllocMaterial GS::Alloc::DefaultAllocator +#define MemAllocTexture GS::Alloc::DefaultAllocator +#define MemAllocPicture GS::Alloc::DefaultAllocator + +#define MemAllocMixer GS::Alloc::DefaultAllocator +#define MemAllocSound GS::Alloc::DefaultAllocator + +#define MemAllocRenderer GS::Alloc::DefaultAllocator +#define MemAllocRendererJob GS::Alloc::DefaultAllocator +#define MemAllocRendererTerrain GS::Alloc::DefaultAllocator + +#define MemAllocVertexBuffer GS::Alloc::DefaultAllocator + +#if __ENABLE_ALLOCATION_STAT__ + +struct Header +{ + size_t size; +}; + +struct Stat +{ + uint alloc_count, alloc_avg; + uint alive_count, alive_count_peak; + size_t size, size_peak; + + Stat() : alloc_count(0), alloc_avg(0), alive_count(0), alive_count_peak(0), size(0), size_peak(0) {} +}; + + /// Per system statistics. +extern Stat system_stat[SystemCount]; +extern SystemDesc system_desc[SystemCount]; + + size_t GetAdjustedAllocationSize(size_t); + void *SetupAllocationStat(void *, size_t); + void *GetAllocationStat(void *, Header *&); + + void UpdateStatAlloc(size_t, System); + void UpdateStatDelete(size_t, System); + +#endif + +/// Standard C++ allocator. +struct DefaultAllocator +{ +static void *Alloc(size_t size, System sys = General); +static void Delete(void *addr, System sys = General); +}; + + } // Alloc +} // GS + +//------------------------------------------------------------------------------ +#if __ENABLE_ALLOCATION_STAT__ + + #define __NSTAT_WRAPALLOC(__WRAPPED_CALL, __SYSTEM)\ + GS::Alloc::UpdateStatAlloc(size, __SYSTEM);\ + size_t __raw_size = size;\ + size = GS::Alloc::GetAdjustedAllocationSize(size);\ + return GS::Alloc::SetupAllocationStat(__WRAPPED_CALL, __raw_size); + + #define __NSTAT_WRAPDELETE(__WRAPPED_CALL, __SYSTEM)\ + if (addr)\ + {\ + GS::Alloc::Header *h;\ + addr = GS::Alloc::GetAllocationStat(addr, h);\ + GS::Alloc::UpdateStatDelete(h->size, __SYSTEM);\ + __WRAPPED_CALL;\ + } + + #define __NSTAT_ALLOC(__SIZE, __SYSTEM) GS::Alloc::UpdateStatAlloc(__SIZE, __SYSTEM) + #define __NSTAT_DELETE(__SIZE, __SYSTEM) GS::Alloc::UpdateStatDelete(__SIZE, __SYSTEM) + +#else + + #define __NSTAT_WRAPALLOC(__WRAPPED_CALL, __SYSTEM) return __WRAPPED_CALL; + #define __NSTAT_WRAPDELETE(__WRAPPED_CALL, __SYSTEM) __WRAPPED_CALL; + + #define __NSTAT_ALLOC(__SIZE, __SYSTEM) + #define __NSTAT_DELETE(__SIZE, __SYSTEM) + +#endif +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +#if __PLATFORM_EMSCRIPTEN__ + +#define NPLACEMENT_NEW(__SYSTEM) + +#else + +#define NPLACEMENT_NEW(__SYSTEM)\ + void *operator new (size_t size)\ + { return MemAlloc##__SYSTEM::Alloc(size, GS::Alloc::__SYSTEM); }\ + void operator delete(void *addr)\ + { MemAlloc##__SYSTEM::Delete(addr, GS::Alloc::__SYSTEM); }\ + void *operator new [] (size_t size)\ + { return MemAlloc##__SYSTEM::Alloc(size, GS::Alloc::__SYSTEM); }\ + void operator delete [] (void *addr)\ + { MemAlloc##__SYSTEM::Delete(addr, GS::Alloc::__SYSTEM); } + +#endif +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +void *_align_alloc(size_t, size_t); +void _align_free(void *); + +template T *_align_new(size_t align) +{ return ::new (_align_alloc(sizeof(T), align)) T(); } +template T *_align_new(P0 &p0, size_t align) +{ return ::new (_align_alloc(sizeof(T), align)) T(p0); } +template void _align_delete(T *p) +{ + p->~T(); + _align_free(p); +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +template void _safe_delete(T *&p) +{ + delete p; + p = 0; +} +template void _safe_delete_array(T *&p) +{ + delete [] p; + p = 0; +} +//------------------------------------------------------------------------------ + + +#endif // __NALLOCATOR_INTERFACE__ diff --git a/include/platform/analytics/analytics.h b/include/platform/analytics/analytics.h new file mode 100644 index 0000000..2a2863d --- /dev/null +++ b/include/platform/analytics/analytics.h @@ -0,0 +1,30 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ANALYTICS__ +#define __ANALYTICS__ + + +namespace GS { + +/*! + @short Analytics system interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct IAnalytics +{ + /// Log an analytics event. +virtual void logEvent(const char *) = 0; + /// Serve a fullscreen advertisement. +virtual void serveFullscreenAd(const char *) = 0; + +virtual ~IAnalytics() {} +}; + +} // GS + + +#endif // __ANALYTICS__ diff --git a/include/platform/assert/nassert.h b/include/platform/assert/nassert.h new file mode 100644 index 0000000..5a04a63 --- /dev/null +++ b/include/platform/assert/nassert.h @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NASSERT__ +#define __NASSERT__ + + +namespace GS { + namespace Assert { + + /// Trigger a system assertion. +extern void Trigger(const char *source, int line, const char *condition, const char *message = 0); + + } // Assert +} // GS + + // Portable assert. +#ifdef _DEBUG + #define __ASSERT__(_EXP_) if (!(_EXP_)) GS::Assert::Trigger(__FILE__, __LINE__, #_EXP_) + #define __ASSERT_MSG__(_EXP_, _MSG_) if (!(_EXP_)) GS::Assert::Trigger(__FILE__, __LINE__, #_EXP_, _MSG_) + #define __ASSERT_ALWAYS__ GS::Assert::Trigger(__FILE__, __LINE__, "Unconditional") +#else + #define __ASSERT__(_EXP_) + #define __ASSERT_MSG__(_EXP_, _MSG_) + #define __ASSERT_ALWAYS__ +#endif + + #define __RASSERT__(_EXP_) if (!(_EXP_)) GS::Assert::Trigger(__FILE__, __LINE__, #_EXP_) + #define __RASSERT_MSG__(_EXP_, _MSG_) if (!(_EXP_)) GS::Assert::Trigger(__FILE__, __LINE__, #_EXP_, _MSG_) + + +#endif // __NASSERT__ diff --git a/include/platform/async/async_call_queue.h b/include/platform/async/async_call_queue.h new file mode 100644 index 0000000..8a0a47d --- /dev/null +++ b/include/platform/async/async_call_queue.h @@ -0,0 +1,201 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ASYNC_CALL_QUEUE__ +#define __ASYNC_CALL_QUEUE__ + + + #include "async/future.h" + #include "thread/thread.h" + #include "thread/mutex.h" + #include "container/nlist.h" + + +namespace GS { + namespace ASync { + +/*! + @short Asynchronous call queue. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class CallQueue +{ + struct BaseCall + { + virtual void Execute() = 0; + virtual ~BaseCall() {} + }; + + Threading::Mutex queue_mutex; + List call_queue; + + /// Post a call to the queue. + void Queue(BaseCall *m) + { + Threading::MutexLock lock(&queue_mutex); + call_queue.Append(m); + } + +private: + + // Call a member function, ignore the return value. + template struct MemberCall : public BaseCall + { + I i; F fn; + void Execute() { (i->*fn)(); } + MemberCall(I _i, F _fn) : i(_i), fn(_fn) {} + }; + template struct MemberCall1 : public BaseCall + { + I i; F fn; A1 a1; + void Execute() { (i->*fn)(a1); } + MemberCall1(I _i, F _fn, const A1 &_a1) : i(_i), fn(_fn), a1(_a1) {} + }; + template struct MemberCall2 : public BaseCall + { + I i; F fn; A1 a1; A2 a2; + void Execute() { (i->*fn)(a1, a2); } + MemberCall2(I _i, F _fn, const A1 &_a1, const A2 &_a2) : i(_i), fn(_fn), a1(_a1), a2(_a2) {} + }; + template struct MemberCall3 : public BaseCall + { + I i; F fn; A1 a1; A2 a2; A3 a3; + void Execute() { (i->*fn)(a1, a2, a3); } + MemberCall3(I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {} + }; + template struct MemberCall4 : public BaseCall + { + I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4; + void Execute() { (i->*fn)(a1, a2, a3, a4); } + MemberCall4(I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {} + }; + +public: + +template void QueueMemberCall(I i, F fn) + { Queue(new MemberCall (i, fn)); } +template void QueueMemberCall(I i, F fn, const A1 &a1) + { Queue(new MemberCall1 (i, fn, a1)); } +template void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2) + { Queue(new MemberCall2 (i, fn, a1, a2)); } +template void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3) + { Queue(new MemberCall3 (i, fn, a1, a2, a3)); } +template void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) + { Queue(new MemberCall4 (i, fn, a1, a2, a3, a4)); } + +private: + + // Generic return value calls. + template struct RValMemberCall : public BaseCall + { + Future &future; I i; F fn; + void Execute() { future.Set((i->*fn)()); } + RValMemberCall(Future &_future, I _i, F _fn) : future(_future), i(_i), fn(_fn) {} + }; + template struct RValMemberCall1 : public BaseCall + { + Future &future; I i; F fn; A1 a1; + void Execute() { future.Set((i->*fn)(a1)); } + RValMemberCall1(Future &_future, I _i, F _fn, const A1 &_a1) : future(_future), i(_i), fn(_fn), a1(_a1) {} + }; + template struct RValMemberCall2 : public BaseCall + { + Future &future; I i; F fn; A1 a1; A2 a2; + void Execute() { future.Set((i->*fn)(a1, a2)); } + RValMemberCall2(Future &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2) {} + }; + template struct RValMemberCall3 : public BaseCall + { + Future &future; I i; F fn; A1 a1; A2 a2; A3 a3; + void Execute() { future.Set((i->*fn)(a1, a2, a3)); } + RValMemberCall3(Future &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {} + }; + template struct RValMemberCall4 : public BaseCall + { + Future &future; I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4; + void Execute() { future.Set((i->*fn)(a1, a2, a3, a4)); } + RValMemberCall4(Future &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {} + }; + + // No return value specialized calls. + template struct RValMemberCall : public BaseCall + { + Future &future; I i; F fn; + void Execute() { (i->*fn)(); future.Set(); } + RValMemberCall(Future &_future, I _i, F _fn) : future(_future), i(_i), fn(_fn) {} + }; + template struct RValMemberCall1 : public BaseCall + { + Future &future; I i; F fn; A1 a1; + void Execute() { (i->*fn)(a1); future.Set(); } + RValMemberCall1(Future &_future, I _i, F _fn, const A1 &_a1) : future(_future), i(_i), fn(_fn), a1(_a1) {} + }; + template struct RValMemberCall2 : public BaseCall + { + Future &future; I i; F fn; A1 a1; A2 a2; + void Execute() { (i->*fn)(a1, a2); future.Set(); } + RValMemberCall2(Future &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2) {} + }; + template struct RValMemberCall3 : public BaseCall + { + Future &future; I i; F fn; A1 a1; A2 a2; A3 a3; + void Execute() { (i->*fn)(a1, a2, a3); future.Set(); } + RValMemberCall3(Future &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {} + }; + template struct RValMemberCall4 : public BaseCall + { + Future &future; I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4; + void Execute() { (i->*fn)(a1, a2, a3, a4); future.Set(); } + RValMemberCall4(Future &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {} + }; + +public: + + /// Queue a member call, return the value in a future. +template void QueueMemberCall(Future &f, I i, F fn) + { Queue(new RValMemberCall (f, i, fn)); } +template void QueueMemberCall(Future &f, I i, F fn, const A1 &a1) + { Queue(new RValMemberCall1 (f, i, fn, a1)); } +template void QueueMemberCall(Future &f, I i, F fn, const A1 &a1, const A2 &a2) + { Queue(new RValMemberCall2 (f, i, fn, a1, a2)); } +template void QueueMemberCall(Future &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3) + { Queue(new RValMemberCall3 (f, i, fn, a1, a2, a3)); } +template void QueueMemberCall(Future &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) + { Queue(new RValMemberCall4 (f, i, fn, a1, a2, a3, a4)); } + +public: + + bool Execute() + { + BaseCall *c = NULL; + { + Threading::MutexLock lock(&queue_mutex); + + if (call_queue.GetCount() == 0) + return false; + + c = call_queue[0]; + call_queue.RemoveAt(0); + } + + if (c) + { + c->Execute(); + delete c; + } + return asbool(c); + } + void ExecuteAll() + { + while (Execute() == true) {} + } +}; + + } // ASync +} // GS + + +#endif // __ASYNC_CALL_QUEUE__ diff --git a/include/platform/async/async_call_queue_thread.h b/include/platform/async/async_call_queue_thread.h new file mode 100644 index 0000000..cc54f95 --- /dev/null +++ b/include/platform/async/async_call_queue_thread.h @@ -0,0 +1,84 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ASYNC_CALL_QUEUE_THREAD__ +#define __ASYNC_CALL_QUEUE_THREAD__ + + + #include "async/async_call_queue.h" + #include "thread/thread_event.h" + + +namespace GS { + namespace Threading { + +/*! + @short A worker thread whose sole purpose is to process its async call queue. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class ASyncCallQueueThread : public Thread +{ + Atomic32 acqt_running; + Event queue_event; + + ASync::CallQueue call_queue; + +public: + +virtual void OnIdle() {} + +virtual void Execute() + { + for (acqt_running.Set(1); acqt_running.Get() != 2; ) + { + call_queue.ExecuteAll(); + OnIdle(); + queue_event.Wait(); + } + acqt_running.Set(0); + } + void Stop() + { + if (acqt_running.Get() != 0) + { + acqt_running.Set(2); + queue_event.Trigger(); + while (acqt_running.Get() != 0); // spinlock + } + } + +template void QueueMemberCall(I i, F fn) + { call_queue.QueueMemberCall(i, fn); queue_event.Trigger(); } +template void QueueMemberCall(I i, F fn, const A1 &a1) + { call_queue.QueueMemberCall(i, fn, a1); queue_event.Trigger(); } +template void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2) + { call_queue.QueueMemberCall(i, fn, a1, a2); queue_event.Trigger(); } +template void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3) + { call_queue.QueueMemberCall(i, fn, a1, a2, a3); queue_event.Trigger(); } +template void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) + { call_queue.QueueMemberCall(i, fn, a1, a2, a3, a4); queue_event.Trigger(); } + + /// Queue a member call, return the value in a future. +template void QueueMemberCall(ASync::Future &f, I i, F fn) + { call_queue.QueueMemberCall(f, i, fn); queue_event.Trigger(); } +template void QueueMemberCall(ASync::Future &f, I i, F fn, const A1 &a1) + { call_queue.QueueMemberCall(f, i, fn, a1); queue_event.Trigger(); } +template void QueueMemberCall(ASync::Future &f, I i, F fn, const A1 &a1, const A2 &a2) + { call_queue.QueueMemberCall(f, i, fn, a1, a2); queue_event.Trigger(); } +template void QueueMemberCall(ASync::Future &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3) + { call_queue.QueueMemberCall(f, i, fn, a1, a2, a3); queue_event.Trigger(); } +template void QueueMemberCall(ASync::Future &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) + { call_queue.QueueMemberCall(f, i, fn, a1, a2, a3, a4); queue_event.Trigger(); } + +virtual ~ASyncCallQueueThread() + { Stop(); } +}; + + } // Threading +} // GS + + +#endif // __ASYNC_CALL_QUEUE_THREAD__ diff --git a/include/platform/async/future.h b/include/platform/async/future.h new file mode 100644 index 0000000..f392937 --- /dev/null +++ b/include/platform/async/future.h @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NFUTURE__ +#define __NFUTURE__ + + + #include "thread/atomic_value.h" + #include "memory/nshared_ptr.h" + + +namespace GS { + namespace ASync { + +/* + @short Future. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +template class Future +{ + T value; + Threading::Atomic32 set; + +public: + + bool IsSet() const + { return set.Get() == 1; } + void Set(const T &_value) + { + value = _value; + set.Set(1); + } + + void Wait() + { while (!IsSet()); } + + T &Get() + { + Wait(); + return value; + } +}; + +// +template <> class Future +{ + Threading::Atomic32 set; + +public: + + bool IsSet() const + { return set.Get() == 1; } + void Set() + { set.Set(1); } + + void Wait() + { while (!IsSet()); } +}; + + } // ASync +} // GS + + +#endif // __NFUTURE__ \ No newline at end of file diff --git a/include/platform/async/job.h b/include/platform/async/job.h new file mode 100644 index 0000000..ab0e684 --- /dev/null +++ b/include/platform/async/job.h @@ -0,0 +1,131 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __JOB_SYSTEM__ +#define __JOB_SYSTEM__ + + + #define __USE_LOCK_FREE_JOB_QUEUE__ 1 + + #include "thread/thread_event.h" + #include "thread/thread.h" + #include "thread/mutex.h" + #include "container/nlist.h" + #if __USE_LOCK_FREE_JOB_QUEUE__ + #include "container/mpmc_bounded_queue.h" + #else + #include "container/nstack.h" + #endif + #include "container/narray.h" + #include "memory/nauto_ptr.h" + #include "nstring/nstring.h" + #include "time/ntime.h" + + +namespace GS { + namespace ASync { + class JobManager; + +// +class JobWorkerThread : public Threading::Thread +{ +protected: + + JobManager &manager; + + Threading::Atomic32 running; + uint worker_id; + +public: + + /// Get worker id. + int GetWorkerId() const { return worker_id; } + /// Worker loop. +virtual void Execute(); + + /// Stop worker thread. + void Stop(); + /// Is the worker thread running. + bool IsRunning() const; + + JobWorkerThread(JobManager &m, uint id) : manager(m), worker_id(id) {} +}; + +/// Parallel job. +struct Job +{ + String name; + Time time_start, time_end; + + Threading::Atomic32 done; + + /// Execute job. +virtual void Execute(uint worker_id) = 0; + + Job(const char *_name) : name(_name), done(1) {} +virtual ~Job() {} +}; + +/// Job group. +class JobGroup +{ +friend class JobManager; + + AutoPtr job_list_mutex; + List job_list; + +public: + + JobGroup(); +}; + +// +class JobManager +{ +friend class JobWorkerThread; + +protected: + + Array pool; + + #if __USE_LOCK_FREE_JOB_QUEUE__ + mpmc_bounded_queue pending_queue; + #else + AutoPtr pending_queue_mutex; + Stack pending_queue; + #endif + +public: + + Threading::Event job_queued_event; + + /// Wait for a job to complete. + bool JoinJob(Job *, bool blocking = true); + /// Wait for a job group to complete. + bool JoinGroup(JobGroup *, bool blocking = true); + + /// Execute a pending job on the caller thread. + bool ExecutePendingJob(uint worker_id); + + bool EnqueueJob(Job * = 0, JobGroup * = 0); + + /// Get the number of worker. + uint GetWorkerPoolSize() const; + + /// Create the job worker thread pool. + bool CreateJobThreadPool(uint count = 0); + /// Free the job worker thread pool. + void FreeJobThreadPool(); + + JobManager(); + ~JobManager(); +}; + + } // ASync +} // GS + + +#endif // __JOB_SYSTEM__ diff --git a/include/platform/async/job_perf.h b/include/platform/async/job_perf.h new file mode 100644 index 0000000..aaa0a2c --- /dev/null +++ b/include/platform/async/job_perf.h @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __JOB_PERF__ +#define __JOB_PERF__ + + + #include "async/job.h" + + +namespace GS { + namespace ASync { + +// +struct JobPerf +{ + Time slice_duration; + Time tasks_duration; + + void Reset() + { + slice_duration.setSec(0); + tasks_duration.setSec(0); + } +}; + +// +template void CollectJobsPerf(const Container &jobs, uint count, JobPerf &perf) +{ + if (count == 0) + return; + + Time slice_start = jobs[0]->time_start, slice_end = jobs[0]->time_end; + + perf.tasks_duration += jobs[0]->time_end - jobs[0]->time_start; + + for (uint n = 1; n < count; ++n) + { + slice_start = Types::Min(jobs[n]->time_start, slice_start); + slice_end = Types::Max(jobs[n]->time_end, slice_end); + + perf.tasks_duration += jobs[n]->time_end - jobs[n]->time_start; + } + + perf.slice_duration += slice_end - slice_start; +}; + + } // ASync +} // GS + + +#endif // __JOB_PERF__ diff --git a/include/platform/async/task_loop.h b/include/platform/async/task_loop.h new file mode 100644 index 0000000..efe34d4 --- /dev/null +++ b/include/platform/async/task_loop.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NTASKLOOP__ +#define __NTASKLOOP__ + + +//------------------------------------------------------------------------------ +#define StartTaskLoop(_CONDITION, _TIMEOUT)\ +{\ + using namespace GS;\ +\ + int ref_clock = Platform::Get().GetClock();\ + bool timeout = false;\ +\ + while (_CONDITION)\ + {\ + if ((Platform::Get().GetClock() - ref_clock) >= _TIMEOUT)\ + {\ + timeout = true;\ + break;\ + } + +#define EndTaskLoop } } + +#define EndTaskLoopOnTimeout(_ON_TIMEOUT)\ + }\ +\ + if (timeout)\ + {\ + _ON_TIMEOUT\ + }\ +} +//------------------------------------------------------------------------------ + + +#endif // __NTASKLOOP__ diff --git a/include/platform/billing/billing.h b/include/platform/billing/billing.h new file mode 100644 index 0000000..18e9e8a --- /dev/null +++ b/include/platform/billing/billing.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __BILLING__ +#define __BILLING__ + + +namespace GS { + +/*! + @short Billing system abstract interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct IBilling +{ + // Process a billing event. +virtual void onBillingEvent(const char *event, const char *item) = 0; + + /// Returns true if the platform supports billing. +virtual bool isBillingServiceSupported() = 0; + /// Request a new purchase. +virtual bool requestPurchase(const char *) = 0; + /// Confirm a purchase. +virtual bool confirmPurchase(const char *) = 0; + /// Restore managed purchase states. +virtual bool restorePurchases() = 0; + +virtual ~IBilling() {} +}; + +} // GS + + +#endif // __BILLING__ diff --git a/include/platform/container/container_sort.h b/include/platform/container/container_sort.h new file mode 100644 index 0000000..713fbc1 --- /dev/null +++ b/include/platform/container/container_sort.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __CONTAINER_SORT__ +#define __CONTAINER_SORT__ + + +namespace GS { + +class ContainerSort +{ + template static inline void Swap(L &t, int i, int j) + { + if (i != j) + { T swap = t[j]; t[j] = t[i]; t[i] = swap; } + } + template static int QuickSortPartition(L &t, C compare, int first, int last, int pivot) + { + Swap (t, pivot, last); + + int j = first; + for (int i = first; i < last; ++i) + if (compare(t[i], t[last]) > 0) + { + Swap (t, i, j); + ++j; + } + + Swap (t, j, last); + return j; + } + template static void QuickSortStep(L &t, C compare, int first, int last) + { + if (first < last) + { + int pivot = (first + last) / 2; + pivot = QuickSortPartition (t, compare, first, last, pivot); + + QuickSortStep (t, compare, first, pivot - 1); + QuickSortStep (t, compare, pivot + 1, last); + } + } + +public: + + /// Quick-sort a container in-place. + template static void QuickSort(L &t, C compare) + { QuickSortStep (t, compare, 0, t.GetCount() - 1); } +}; + +} // GS + + +#endif // __CONTAINER_SORT__ diff --git a/include/platform/container/mpmc_bounded_queue.h b/include/platform/container/mpmc_bounded_queue.h new file mode 100644 index 0000000..b969850 --- /dev/null +++ b/include/platform/container/mpmc_bounded_queue.h @@ -0,0 +1,136 @@ +/* + Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + The views and conclusions contained in the software and documentation are + those of the authors and should not be interpreted as representing official + policies, either expressed or implied, of Dmitry Vyukov. +*/ + + +#ifndef __MPMC_BOUNDED_QUEUE__ +#define __MPMC_BOUNDED_QUEUE__ + + + #include "thread/atomic_value.h" + + +// Adapted from https://sites.google.com/site/1024cores/home/lock-free-algorithms/queues/bounded-mpmc-queue +template class mpmc_bounded_queue +{ + struct cell_t + { + GS::Threading::Atomic32 sequence_; + T data_; + }; + + static size_t const cacheline_size = 64; + typedef char cacheline_pad_t[cacheline_size]; + + cacheline_pad_t pad0_; + cell_t * const buffer_; + size_t const buffer_mask_; + + cacheline_pad_t pad1_; + GS::Threading::Atomic32 enqueue_pos_; + cacheline_pad_t pad2_; + GS::Threading::Atomic32 dequeue_pos_; + cacheline_pad_t pad3_; + + void operator = (mpmc_bounded_queue const&); + + mpmc_bounded_queue(mpmc_bounded_queue const&); + +public: + + bool enqueue(T const &data) + { + cell_t *cell; + int pos = enqueue_pos_.Get(); + + for (;;) + { + cell = &buffer_[pos & buffer_mask_]; + size_t seq = cell->sequence_.Get(); + + intptr_t dif = (intptr_t)seq - (intptr_t)pos; + + if (dif == 0) + { + if (enqueue_pos_.Cas(pos, pos + 1) == pos) + break; + } + else if (dif < 0) + return false; + else + pos = enqueue_pos_.Get(); + } + + cell->data_ = data; + cell->sequence_.Set(pos + 1); + return true; + } + bool dequeue(T &data) + { + cell_t *cell; + int pos = dequeue_pos_.Get(); + + for (;;) + { + cell = &buffer_[pos & buffer_mask_]; + size_t seq = cell->sequence_.Get(); + + intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1); + + if (dif == 0) + { + if (dequeue_pos_.Cas(pos, pos + 1) == pos) + break; + } + else if (dif < 0) + return false; + else + pos = dequeue_pos_.Get(); + } + data = cell->data_; + cell->sequence_.Set(pos + buffer_mask_ + 1); + + return true; + } + + mpmc_bounded_queue(size_t buffer_size) : buffer_(new cell_t [buffer_size]), buffer_mask_(buffer_size - 1) + { + for (size_t i = 0; i != buffer_size; i += 1) + buffer_[i].sequence_.Set(i); + + enqueue_pos_.Set(0); + dequeue_pos_.Set(0); + } + ~mpmc_bounded_queue() + { + delete [] buffer_; + } +}; + + +#endif // __MPMC_BOUNDED_QUEUE__ diff --git a/include/platform/container/narray.h b/include/platform/container/narray.h new file mode 100644 index 0000000..599d0c9 --- /dev/null +++ b/include/platform/container/narray.h @@ -0,0 +1,215 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NARRAY__ +#define __NARRAY__ + + + #include "alloc/ialloc.h" + #include "memory/memory.h" + #include "assert/nassert.h" + + +namespace GS { + +/*! + @short Managed array. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class Array +{ + uint count; + T *data; + + #if __ENABLE_ALLOCATION_STAT__ + Alloc::System system; + #endif + +public: + +inline operator T *() const + { return data; } +inline T *c_ptr() const + { return data; } + +inline T &operator [] (int n) const + { return data[n]; } +inline T &operator [] (uint n) const + { return data[n]; } + + void operator = (Array &o) ///< Transfer assignation. + { Transfer(o); } + +inline T *Start() const + { return data; } +inline T *End() const + { return &data[count]; } + +inline bool IsValid() const + { return data ? true : false; } +inline bool IsNull() const + { return data ? false : true; } + + /// Return the number of elements of type T in the buffer. +inline uint GetCount() const + { return count; } + /// Return the buffer size in bytes. +inline size_t GetSize() const + { return count * sizeof(T); } + + void Free() + { + if (data) + __NSTAT_DELETE(count * sizeof(T), system); + // _safe_delete_array(data); + delete[] data; + data = 0; + count = 0; + } + + /// Reallocate buffer elements. + bool Reallocate(uint new_count) + { + if (new_count == count) + return true; + + if (T *new_data = new T[new_count]) + { + __NSTAT_ALLOC(new_count * sizeof(T), system); + Memory::Copy(new_data, data, GetSize()); + + if (data) + __NSTAT_DELETE(count * sizeof(T), system); + // _safe_delete_array(data); + delete[] data; + data = 0; + + data = new_data; + count = new_count; + } + else + return false; + + return true; + } + + /// Allocate buffer elements. + bool Allocate(uint _count) + { + /// @note We could add a small tolerance here to potentially reduce fragmentation? + if (_count == count) + return true; + + Free(); + + if (_count && ((data = new T[_count]) == 0)) + return false; + + __NSTAT_ALLOC(_count * sizeof(T), system); + count = _count; + return true; + } + + /// Relinquish ownership of the managed memory block. + T *Detach() + { + T *r = data; + data = 0; + count = 0; + return r; + } + /// Take ownership of a managed memory block. + void Attach(uint _count, T *_data) + { + Free(); + count = _count; + data = _data; + } + + /// Transfer data buffer. + void Transfer(Array &b) + { + Free(); + count = b.GetCount(); + data = b.Detach(); + #if __ENABLE_ALLOCATION_STAT__ + __NSTAT_DELETE(count * sizeof(T), b.system); + __NSTAT_ALLOC(count * sizeof(T), system); + #endif + } + /// Clone data buffer. + bool Clone(const Array &b) + { + Free(); + if (!Allocate(b.GetCount())) + return false; + for (uint n = 0; n < GetCount(); ++n) + data[n] = b[n]; + return true; + } + + /// Fill data buffer. + void Fill(const T &v, uint from = 0, uint to = 0) + { + if (to <= 0) + to = count + to; + + __ASSERT__(from <= count); + __ASSERT__(to <= count); + for (uint n = from; n < to; ++n) + data[n] = v; + } + + /// Swap two data buffer. +static void Swap(Array &a, Array &b) + { + uint count_a = a.GetCount(), count_b = b.GetCount(); + T *data_a = a.Detach(), *data_b = b.Detach(); + a.Attach(count_b, data_b); + b.Attach(count_a, data_a); + } + + Array(uint _count, Alloc::System sys = Alloc::General) + { + data = 0; count = 0; + #if __ENABLE_ALLOCATION_STAT__ + system = sys; + #endif + Allocate(_count); + } + Array(uint _count, const T *_data, Alloc::System sys = Alloc::General) + { + data = 0; count = 0; + #if __ENABLE_ALLOCATION_STAT__ + system = sys; + #endif + if (Allocate(_count)) + Memory::Copy(data, _data, sizeof(T) * _count); + } + Array(const Array &array, Alloc::System sys = Alloc::General) ///< Copy constructor. + { + data = 0; count = 0; + #if __ENABLE_ALLOCATION_STAT__ + system = sys; + #endif + Allocate(array.GetCount()); + Memory::Copy(data, array.c_ptr(), array.GetSize()); + } + Array(Alloc::System sys = Alloc::General) + { + data = 0; count = 0; + #if __ENABLE_ALLOCATION_STAT__ + system = sys; + #endif + } + ~Array() + { Free(); } +}; + +} // GS + + +#endif // __NARRAY__ diff --git a/include/platform/container/narray_list.h b/include/platform/container/narray_list.h new file mode 100644 index 0000000..6b48e2d --- /dev/null +++ b/include/platform/container/narray_list.h @@ -0,0 +1,268 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NARRAYLIST__ +#define __NARRAYLIST__ + + + #include "container/narray.h" + #include "log/log.h" + + +namespace GS { + +/*! + @short Array list. + + A flexible structure with faster access time (both linear and random) and + tighter memory usage than lists. + + Especially suited for small types such as pointers. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class ArrayList +{ + Array array; + Array usage_map; + + uint usage; ///< Array usage. + uint grow_step; + + //---------------------------------------------------------------------- +inline bool Grow() + { + if (int(usage) >= int(array.GetCount() - 1)) + return Resize(array.GetCount() + grow_step); + return true; + } +inline bool Shrink() + { + if (((int)array.GetCount() - 1) > (int)grow_step) + if ((int)usage < ((int)array.GetCount() - 1 - (int)grow_step)) + return Resize(array.GetCount() - grow_step); + return true; + } + //---------------------------------------------------------------------- + +public: + + //---------------------------------------------------------------------- + class Iterator + { + const ArrayList &list; + uint i; + + public: + + inline void Reset(uint from = 0) { i = from; } + inline bool IsOver() const { return i < list.GetCount() ? false : true; } + + inline void operator++() { ++i; } + + inline T &Object() { return list[i]; } + inline T ObjectPtr() { return list[i]; } + + Iterator(const ArrayList &_list, uint from = 0) : list(_list), i(from) {} + }; + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- +inline uint GetCount() const + { return usage; } + +inline T &ObjectAt(int n) const + { return array[usage_map[n]]; } +inline T &ObjectAt(uint n) const + { return array[usage_map[n]]; } + +inline T &operator [] (int n) const + { return array[usage_map[n]]; } +inline T &operator [] (uint n) const + { return array[usage_map[n]]; } + +inline void SetGrowStep(uint step) + { grow_step = step; } + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + /// Insert a new value in the list. +virtual bool Insert(const T &v, uint at) + { + Grow(); + + // Claim entry... + uint claimed = usage_map[usage]; + + // ...and shift usage map. + for (int n = (int)usage - 1; n >= (int)at; --n) + usage_map[n + 1] = usage_map[n]; + + usage_map[at] = claimed; + usage++; + + array[claimed] = v; + array[usage_map[usage]] = 0; // enforce terminator + return true; + } + /// Add a new value to the end of the list. + bool Add(const T &v) + { + return Insert(v, usage); + } + /// Return the index at which a value is first found in the list. + int IndexOf(const T &v, uint from = 0) + { + for (uint i = from; i < usage; ++i) + if (array[usage_map[i]] == v) + return i; + return -1; + } + /// Remove an entry from the list. +virtual bool RemoveAt(uint i) + { + if (usage == 0) + return false; + + // Reclaim entry... + uint reclaimed = usage_map[i]; + + // ...and shift usage map. + for (uint n = i + 1; n < usage; ++n) + usage_map[n - 1] = usage_map[n]; + + usage_map[usage - 1] = reclaimed; + usage--; + + array[reclaimed] = 0; // enforce terminator + + Shrink(); + return true; + } + bool Remove(const T &v) + { + int i = IndexOf(v); + return i != -1 ? RemoveAt(i) : false; + } + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + ArrayList &operator = (const T &v) + { + if (this != &v) + { + Clear(); + for (uint n = 0; n < v.GetCount(); ++n) + Add(v[n]); + } + return *this; + } + ArrayList &operator << (const T &v) + { + Add(v); + return *this; + } + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + bool Resize(uint new_size) + { + if ((int)new_size == (int)array.GetCount() - 1) + return true; + + Array _array(new_size + 1); + if (_array.IsNull()) + __ERR__(__LOG_E__ << "Failed to allocate new array.\n", false) + + for (uint n = 0; n < usage; ++n) + _array[n] = array[usage_map[n]]; + array.Transfer(_array); + + if (!usage_map.Allocate(new_size + 1)) + __ERR__(__LOG_E__ << "Failed to allocate array bookkeeping structures.\n", false) + + for (uint n = 0; n < (new_size + 1); ++n) + usage_map[n] = n; + + array[usage_map[usage]] = 0; // enforce terminator + return true; + } + /*! + @short Clear the container. + + Pass false to prevent the internal structures from being released, + the array list will keep its current capacity and only its usage map + will be reset. + */ +virtual void Clear(bool free_internals = true) + { + usage = 0; + + if (free_internals) + Resize(0); + else + { + for (uint n = 0; n < array.GetCount(); ++n) + usage_map[n] = n; + array[0] = 0; // enforce terminator + } + } + //---------------------------------------------------------------------- + + ArrayList(uint initial_size = 0, uint step = 64) : usage(0), grow_step(step) { Resize(initial_size); } +virtual ~ArrayList() {} +}; + +/* + @short Shared object array list. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template struct SharedArrayList : public ArrayList +{ +virtual bool Insert(const T &v, uint at) + { + v->AddRef(); + return ArrayList ::Insert(v, at); + } +virtual bool RemoveAt(uint i) + { + (*this)[i]->RemoveRef(); + return ArrayList :: RemoveAt(i); + } +virtual void Clear(bool free_internals = true) + { + for (uint n = 0; n < this->GetCount(); ++n) + (*this)[n]->RemoveRef(); + return ArrayList ::Clear(free_internals); + } +virtual ~SharedArrayList() + { Clear(); } +}; + +//------------------------------------------------------------------------------ + // Delete all list entries. +#define ArrayListDeleteAllPtr(T, L) { for (uint __n = 0; __n < (L).GetCount(); ++__n) delete (L)[__n]; (L).Clear(); } + // Iterate over a list of pointers. +#define ArrayListForeachPtr(T, V, L) \ + for (ArrayList ::Iterator iterator(L); T V = iterator.ObjectPtr(); ++iterator) + // Iterate over a list of objects. +#define ArrayListForeach(T, V, L) \ + for (ArrayList ::Iterator V(L); V.IsOver() == false; ++V) + + /// Find item by using a template identification class. +template T ArrayListFindEx(const ArrayList &list, F filter, const P &what) +{ + for (uint __n = 0; __n < list.GetCount(); ++__n) + if (filter(list[__n], what)) + return list[__n]; + return 0; +} +//------------------------------------------------------------------------------ + +} // GS + + +#endif // __NARRAYLIST__ diff --git a/include/platform/container/nlist.h b/include/platform/container/nlist.h new file mode 100644 index 0000000..eef4a4a --- /dev/null +++ b/include/platform/container/nlist.h @@ -0,0 +1,604 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NLIST__ +#define __NLIST__ + + + #include "alloc/ialloc.h" + #include "assert/nassert.h" + + +namespace GS { + +/* + @short List. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class List +{ +public: + + //---------------------------------------------------------------------- + class Item + { + friend class List ; + + T o; + Item *p, *n; + + public: + + NPLACEMENT_NEW(ListItem) + + /// Return the previous list link. + inline Item *Previous() const { return p; } + /// Return the next list link. + inline Item *Next() const { return n; } + + /// Retrieve a reference to the item object. + inline T &Object() { return o; } + + Item(const T &obj) + { + o = obj; + p = n = 0; + } + }; + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + class Iterator + { + Item *c, *n; + + public: + + inline void operator++() + { + if ((c = c ? n : 0) != 0) + n = c->n; + } + + inline bool IsOver() const { return c ? false : true; } + inline Item *Next() const { return n; } + + inline Item *GetItem() const { return c; } + inline T &Object() { return c->Object(); } + + /// Only use when using a pointer type. + inline T ObjectPtr() { return c ? c->Object() : 0; } + + void Reset(Item *start = 0) + { + c = start; + n = c ? c->Next() : 0; + } + Iterator(Item *start = 0) + { Reset(start); } + }; + //---------------------------------------------------------------------- + +protected: + + uint count; + Item *root, *last; + +public: + + /// Get item count in list. +inline uint GetCount() const { return count; } + /// Get root item. +inline Item *GetRoot() const { return root; } + /// Get last item. +inline Item *GetLast() const { return last; } + + /// Clone list. + void Clone(List &clone_list) const + { + clone_list.Clear(); + for (Item *_i = root; _i; _i = _i->Next()) + clone_list.Add(_i->Object()); + } + + /// Get item from position. + Item *ItemAt(uint n) const + { + if (n > count) + return 0; + + Item *p = root; + while (n--) + p = p->n; + + return p; + } +inline T &ObjectAt(uint n) const + { return ItemAt(n)->Object(); } +inline T &operator[] (uint n) const + { return ItemAt(n)->Object(); } + + /// Get index of a given item. + int Index(const T &o) const + { + int pos = 0; + for (Item *p = root; p; p = p->n) + { + if (p->Object() == o) + return pos; + pos++; + } + return -1; + } + + /// Check whether a given item belongs to this list or not. + bool Belongs(Item *i) const + { + for (Item *s = root; s; s = s->n) + if (s == i) + return true; + return false; + } + + /// Insert item after a given reference item (defaults to last). +virtual Item *Append(const T &o, Item *rfr = 0) + { + Item *i = new Item(o); + if (!i) + return 0; + + if (!rfr) + { + i->p = last; + if (last) + last->n = i; + else + root = i; + last = i; + } + else + { + if (rfr->n) + rfr->n->p = i; + i->n = rfr->n; + rfr->n = i; + i->p = rfr; + + if (last == rfr) // Update last. + last = i; + } + + count++; + return i; + } + + /// Insert item before a given reference item (defaults to root). +virtual Item *Prepend(const T &o, Item *rfr = 0) + { + Item *i = new Item(o); + if (!i) + return 0; + + if (!rfr) + { + i->n = root; + if (root) + root->p = i; + else + last = i; + root = i; + } + else + { + if (rfr->p) + rfr->p->n = i; + i->p = rfr->p; + rfr->p = i; + i->n = rfr; + + if (root == rfr) // Update root. + root = i; + } + + count++; + return i; + } + + /// Insert a value at a given position. + Item *Insert(const T &v, uint at) + { + Item *rfr = ItemAt(at); + return rfr ? Prepend(v, rfr) : 0; + } + + /// Add item to list. + Item *Add(const T &o, bool append, bool allow_duplicate) + { + if (!allow_duplicate) + if (Item *i = Find(o)) + return i; + return append ? Append(o) : Prepend(o); + } + /// Add item to list. + Item *Add(const T &o) + { return Append(o); } + + /// Add item to list. + List &operator << (const T &o) + { + Add(o); + return *this; + } + + /// Find item by reference to object. + Item *Find(const T &o) const + { + for (Item *p = root; p; p = p->n) + if (p->Object() == o) + return p; + return 0; + } + + /// Find item by object value. + Item *FindByValue(const T &o) const + { + for (Item *p = root; p; p = p->n) + if (*p->Object() == *o) + return p; + return 0; + } + + /*! + @short Subtract two given lists by object value. + @warning The resulting list holds pointers to the original objects. + */ +static List *SubtractByValue(const List &what, const List &from) + { + List *list = new List ; + if (list) + for (Item *f_p = from.root; f_p; f_p = f_p->n) + if (!what.FindByValue(f_p->Object())) + list->Add(f_p->Object()); + return list; + } + + /*! + @short Subtract two given lists by object address. + @warning The resulting list holds pointers to the original objects. + */ +static List *SubtractByAddress(const List &what, const List &from) + { + List *list = new List ; + if (list) + for (Item *f_p = from.root; f_p; f_p = f_p->n) + if (!what.Find(f_p->Object())) + list->Add(f_p->Object()); + return list; + } + + /// Filter out linked-list item function. + template void FilterOut(F filter) + { + for (Item *c = GetRoot(); c; ) + { + Item *n = c->Next(); + if (filter(c->Object())) + Remove(c); + c = n; + } + } + + /// Build a new list from select items. + template uint Select(List &out, F filter, const P &filter_param) const + { + out.Clear(); + for (Item *c = GetRoot(); c; ) + if (filter(c->Object(), filter_param)) + out.Add(c->Object()); + return out.GetCount(); + } + + /// Sort linked-list function. + template void Sort(C compare) + { + for (bool swapped = true; swapped; ) + { + swapped = false; + + for (Item *c = GetRoot(); c; ) + { + Item *n = c->Next(); + if (!n) + break; + + if (compare(c->Object(), n->Object()) < 0) + { + swapped = true; + + c->n = n->n; + n->n = c; + n->p = c->p; + c->p = n; + + if (n->p) + n->p->n = n; + else root = n; + + if (c->n) + c->n->p = c; + else last = c; + } + else + c = n; + } + } + } + + /// Merge sort linked-list function. + template void MergeSort(C compare) + { + Item *list = root, *tail = 0; + if (!list) + return; + + for (int insize = 1; ; insize *= 2) + { + Item *p = list; + list = 0; + tail = 0; + + int merge_count = 0; // Count number of merges we do in this pass. + + while (p) + { + merge_count++; + + // Step along from p. + Item *q = p; + int psize = 0; + for ( ; q && (psize < insize); ++psize) + q = q->Next(); + + // If q hasn't fallen off end, we have two lists to merge. + int qsize = insize; + + // Now we have two lists, merge them. + while (psize > 0 || (qsize > 0 && q)) + { + Item *e; + + if (!psize) // p is empty, e must come from q. + { e = q; q = q->Next(); qsize--; } + else if (!qsize || !q) // q is empty, e must come from p. + { e = p; p = p->Next(); psize--; } + else if (compare(p->Object(), q->Object()) <= 0) // First element of p is lower (or same), e must come from p. + { e = p; p = p->Next(); psize--; } + else // First element of q is lower; e must come from q. + { e = q; q = q->Next(); qsize--; } + + // Add the next element to the merged list. + if (tail) + tail->n = e; + else list = e; + + e->p = tail; + tail = e; + } + + // Now p has stepped `insize' places along, and q has too. + p = q; + } + + tail->n = 0; + + // If we have done only one merge, we're done. + if (merge_count <= 1) + break; + } + + root = list; + last = tail; + } + + /// Extract object from list. + Item *ExtractItem(const T &o) + { + Item*i = Find(o); + return i ? ExtractItem(i) : 0; + } + + /// Extract item from list. + Item *ExtractItem(Item *i) + { + if (!i) + return 0; + + __ASSERT__(Belongs(i)); + + if (i->p) + i->p->n = i->n; + else + { + if (i->n) + i->n->p = 0; + root = i->n; + } + + if (i->n) + i->n->p = i->p; + else + { + if (i->p) + i->p->n = 0; + last = i->p; + } + + i->p = i->n = 0; + + --count; + return i; + } + /// Extract item at position. + Item *ExtractAt(uint n) + { + Item *i = ItemAt(n); + return i ? ExtractItem(i) : 0; + } + + /// Remove item from list. +virtual bool Remove(Item *i) + { + if (ExtractItem(i) == 0) + return false; + + delete i; + return true; + } + + /// Remove item from list. +virtual bool Remove(const T &o) + { + return Remove(Find(o)); + } + + /// Remove item at position. + bool RemoveAt(uint n) + { + Item *i = ItemAt(n); + return i ? Remove(i) : false; + } + + /// Remove all items from the list. +virtual void Clear() + { + for (Item *p = root, *n; p; p = n) + { + n = p->n; + delete p; + } + + count = 0; + root = last = 0; + } + + List() + { + count = 0; + root = last = 0; + } +virtual ~List() + { Clear(); } +}; + +/* + @short Auto linked-list. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template struct AutoList : public List +{ +virtual bool Remove(class List ::Item *i) + { + T o = i->Object(); + if (!List ::Remove(i)) + return false; + delete o; + return true; + } +virtual bool Remove(const T &o) + { + class List ::Item *i = this->Find(o); + return i ? this->Remove(i) : false; + } + +virtual void Clear() + { + for (class List ::Item *p = this->root; p; p = p->Next()) + delete p->Object(); + List ::Clear(); + } +virtual ~AutoList() + { this->Clear(); } +}; + +/* + @short Shared object linked-list. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template struct SharedList : public List +{ +virtual class List ::Item *Append(const T &o, class List ::Item *rfr = 0) + { + class List ::Item *i = List ::Append(o, rfr); + if (i) + o->AddRef(); + return i; + } +virtual class List ::Item *Prepend(const T &o, class List ::Item *rfr = 0) + { + class List ::Item *i = List ::Prepend(o, rfr); + if (i) + o->AddRef(); + return i; + } + +virtual bool Remove(class List ::Item *i) + { + T o = i->Object(); + if (!List ::Remove(i)) + return false; + o->RemoveRef(); + return true; + } +virtual bool Remove(const T &o) + { + class List ::Item *i = this->Find(o); + return i ? this->Remove(i) : false; + } + +virtual void Clear() + { + for (class List ::Item *p = this->root; p; p = p->Next()) + p->Object()->RemoveRef(); + List ::Clear(); + } +virtual ~SharedList() + { Clear(); } +}; + + +//------------------------------------------------------------------------------ + // Delete all list entries. +#define ListDeleteAllPtr(T, L) { class GS::List ::Item *t; while ((t = (L).GetRoot()) != 0) { T _o = t->Object(); (L).Remove(t); delete(_o); } } + // Iterate over a list of pointers. +#define ListForeachPtr(T, V, L) \ + for (class GS::List ::Iterator iterator((L).GetRoot()); T V = iterator.ObjectPtr(); ++iterator) + // Iterate over a list of objects. +#define ListForeach(T, V, L) \ + for (class GS::List ::Iterator V((L).GetRoot()); V.IsOver() == false; ++V) + + /// Find item by using a template identification class. +template T ListFindEx(const List &list, F filter, const P &what) +{ + for (class List ::Item *p = list.GetRoot(); p; p = p->Next()) + if (filter(p->Object(), what)) + return p->Object(); + return 0; +} + /// Remove all items with a reference count of 1 from a shared list. +template uint PurgeSharedList(SharedList &list) +{ + uint c = list.GetCount(); + ListForeachPtr(T *, t, list) + if (t->GetRefCount() == 1) + list.Remove(iterator.GetItem()); + return c - list.GetCount(); +} +//------------------------------------------------------------------------------ + +} // GS + + +#endif // __NLIST__ diff --git a/include/platform/container/nmap.h b/include/platform/container/nmap.h new file mode 100644 index 0000000..459acd1 --- /dev/null +++ b/include/platform/container/nmap.h @@ -0,0 +1,68 @@ +/*------------------------------------------------------------------------------ + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMAP__ +#define __NMAP__ + + + #include "container/nlist.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + +// +template struct Pair +{ + KType key; + VType value; + + Pair(const KType _key, const VType _value) : key(_key), value(_value) {} +}; + +/*! + @short Very naive map. + @todo Red-black tree. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +template class Map +{ + AutoList *> pairs; + +public: + + Pair *Get(const KType &key) const + { + for (typename List *> ::Item *p = pairs.GetRoot(); p; p = p->Next()) + if (p->Object()->key == key) + return p->Object(); + return 0; + } + + uint GetCount() const + { return pairs.GetCount(); } + + bool HasKey(const KType &key) const + { return asbool(Get(key)); } + VType &operator [] (const KType &key) const + { return Get(key)->value; } + + Pair *Add(const KType &key, const VType &value) + { + AutoPtr > pair(new Pair (key, value)); + return pair.IsValid() && pairs.Add(pair) ? pair.Detach() : 0; + } + + bool Delete(Pair *pair) + { return pairs.Remove(pair); } + bool Delete(const KType &key) + { return Delete(Get(key)); } +}; + +} // GS + + +#endif // __NMAP__ \ No newline at end of file diff --git a/include/platform/container/nstack.h b/include/platform/container/nstack.h new file mode 100644 index 0000000..f677534 --- /dev/null +++ b/include/platform/container/nstack.h @@ -0,0 +1,150 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSTACK__ +#define __NSTACK__ + + + #include "container/narray.h" + + +namespace GS { + +/*! + @short Simple value stack. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +template class Stack +{ +protected: + + Array data; + + uint usage; + uint grow_step; + +public: + +inline const T &operator [] (int n) const + { return data[n]; } +inline const T &Top() const + { return data[usage - 1]; } + + //---------------------------------------------------------------------- + T *Detach() + { + usage = 0; + return data.Detach(); + } +virtual void Transfer(Stack &from) + { + usage = from.GetCount(); + data.Transfer(from.data); + } + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + /// Push a value on top of the stack. +virtual bool Push(const T &v) + { + if (usage == data.GetCount()) + if (!data.Reallocate(usage + 64)) + return false; + + data[usage++] = v; + return true; + } + /// Pop a value from the stack. +virtual void Pop() + { + if (usage > 0) + --usage; + } +inline bool Add(const T &v) + { return Push(v); } +inline Stack &operator << (const T &v) + { + Add(v); + return *this; + } + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- +inline uint GetCount() const + { return usage; } +inline void SetGrowStep(uint step) + { grow_step = step; } +virtual void Clear(bool free_internals = true) + { + if (free_internals) + data.Free(); + usage = 0; + } + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- +inline int Index(const T &v) const + { + for (uint n = 0; n < usage; ++n) + if (data[n] == v) + return n; + return -1; + } + //---------------------------------------------------------------------- + + Stack(uint size = 0, uint step = 64) : usage(0), grow_step(step) { data.Allocate(size); } +virtual ~Stack() {} +}; + +/// Auto-stack. +template struct AutoStack : public Stack +{ + //---------------------------------------------------------------------- +virtual void Transfer(Stack &from) + { + for (uint n = 0; n < this->usage; ++n) + delete this->data[n]; + Stack ::Transfer(from); + } + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- +virtual void Pop() + { + if (this->usage > 0) + delete this->data[--this->usage]; + } +virtual void Clear(bool free_internals = true) + { + for (uint n = 0; n < this->usage; ++n) + delete this->data[n]; + Stack ::Clear(free_internals); + } + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + /*! + @short Drop all pointers managed by this stack, does not free the storage. + + The dropped pointers are expected to have been taken care of as this + container will completely forget about them. + */ + void DropContentOwnership() + { + for (uint n = 0; n < this->usage; ++n) + this->data[n] = 0; + this->usage = 0; + } + //---------------------------------------------------------------------- + + AutoStack(uint size = 0, uint step = 64) : Stack (size, step) {} +virtual ~AutoStack() { Clear(); } +}; + +} // GS + + +#endif // __NSTACK__ diff --git a/include/platform/container/pair.h b/include/platform/container/pair.h new file mode 100644 index 0000000..71d8469 --- /dev/null +++ b/include/platform/container/pair.h @@ -0,0 +1,161 @@ +/* +*/ + + +#ifndef __TMPL_PAIRLIST__ +#define __TMPL_PAIRLIST__ + + + #include "data/array_list.h" + #include "platform_config.h" + + +// +template class ntPairList; + + +/* + @short Pair item. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class ntPairItem : public nArrayEntry +{ +protected: + + int hash; + +public: + + TYPE *a, *b; ///< Object pair. + void *pair_data; ///< Pair associated data block. + + /// Compute pair hash value. +static int ComputeHash(TYPE *_a, TYPE *_b) + { + int hash = (((uintptr_t)_a) & 0xf0f0f0f0) | (((uintptr_t)_b) & 0x0f0f0f0f); + hash = (hash + 0x7ed55d16) + (hash << 12); + hash = (hash ^ 0xc761c23c) ^ (hash >> 19); + hash = (hash + 0x165667b1) + (hash << 5); + hash = (hash + 0xd3a2646c) ^ (hash << 9); + hash = (hash + 0xfd7046c5) + (hash << 3); + hash = (hash ^ 0xb55a4f09) ^ (hash >> 16); + return hash; + } + + /// Get pair hash. + int Hash() const { return hash; } + + ntPairItem(TYPE *_a, TYPE *_b) + { + a = _a; b = _b; + hash = ComputeHash(a, b); + } +}; + + +/* +*/ +struct ntPairListPool +{ + uint bucket, + entry; + + void Reset() + { bucket = entry = 0; } + + ntPairListPool() + { Reset(); } +}; + +/* + @short Pair list. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class ntPairList +{ + +#define PairListBucketCount 64 +#define OrderPairItems(_A_, _B_) { if (_A_ > _B_) { TYPE *t = _A_; _A_ = _B_; _B_ = t; } } + +protected: + + uint count; + nArrayList bucket[PairListBucketCount]; + +public: + + /// Get item count in list. + uint GetCount() const + { return count; } + + /// Pool list. + PAIR *Pool(ntPairListPool &pool) const + { + while (pool.bucket < PairListBucketCount) + { + if (pool.entry < bucket[pool.bucket].GetCount()) + break; + + pool.entry = 0; + pool.bucket++; + } + if (pool.bucket == PairListBucketCount) + return 0; + return (PAIR *)bucket[pool.bucket][pool.entry++]; + } + + /// Add a pair. + PAIR *Add(TYPE *a, TYPE *b) + { + OrderPairItems(a, b); + + PAIR *pair = new PAIR(a, b); + if (pair && !bucket[pair->Hash() & (PairListBucketCount - 1)].Add(pair)) + _safe_delete(pair); + else + count++; + return pair; + } + + /// Find a pair. + PAIR *Find(TYPE *a, TYPE *b) + { + OrderPairItems(a, b); + + int hash = PAIR::ComputeHash(a, b); + nArrayList &h_bucket = bucket[hash & (PairListBucketCount - 1)]; + + for (uint n = 0; n < h_bucket.GetCount(); ++n) + { + PAIR *pair = (PAIR *)h_bucket[n]; + if ((pair->a == a) && (pair->b == b)) + return pair; + } + return 0; + } + + /// Remove pair. + bool Remove(PAIR *pair) + { + if (bucket[pair->Hash() & (PairListBucketCount - 1)].Delete(pair)) + { + count--; + return false; + } + return true; + } + + /// Delete all pair. + void DeleteAll(bool freedata = true) + { + for (int n = 0; n < PairListBucketCount; ++n) + bucket[n].DeleteAll(freedata); + count = 0; + } + + ntPairList() + { count = 0; } +}; + + +#endif // __TMPL_PAIRLIST__ diff --git a/include/platform/container/smart_median_average.h b/include/platform/container/smart_median_average.h new file mode 100644 index 0000000..7ca855a --- /dev/null +++ b/include/platform/container/smart_median_average.h @@ -0,0 +1,62 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SMARTMEDIANAVG__ +#define __SMARTMEDIANAVG__ + + + #include "sort/sort.h" + + +namespace GS { + +// +template class SmartMedianAverage +{ + T history[Size]; + int count; + +public: + + void LogValue(T v) + { + if (count < Size) + count++; // fill up + else + for (int n = 1; n < Size; ++n) // scroll + history[n - 1] = history[n]; + + history[count - 1] = v; + } + T GetMedian() const + { + if (count == 0) + return 0; + if (count < Size) + return history[0]; // unfiltered + + // Sort current histogram values. + typename Sort ::Entry entries[Size]; + for (int n = 0; n < Size; ++n) + entries[n].v = history[n]; + Sort ::QuickSort(Size, entries); + + // Compute average of the safe values. + T avg = 0; + for (int n = (Size / SafeGuard); n < (Size - Size / SafeGuard); ++n) + avg += entries[n].v; + + return avg / (Size - (Size / SafeGuard) * 2); + } + void Reset() { count = 0; } + + SmartMedianAverage() : count(0) {} +}; + +} // GS + + +#endif // __SMARTMEDIANAVG__ diff --git a/include/platform/filesystem/data_store.h b/include/platform/filesystem/data_store.h new file mode 100644 index 0000000..cd0d487 --- /dev/null +++ b/include/platform/filesystem/data_store.h @@ -0,0 +1,85 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIODATASTORE__ +#define __NIODATASTORE__ + + + #include "filesystem/io_handle.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + #include "thread/mutex.h" + #include "unit/nunit.h" + + +namespace GS { + namespace IO { + +/*! + @short Data store. +*/ +class DataStore +{ + Threading::Mutex mutex; + + SharedPtr io; + size_t limit; + + uint id_seed; + String GetNewId(); + +public: + + struct Entry + { + String id; + size_t size; + String user; + + Entry() : size(0) {} + }; + +private: + + AutoList entries; + + Entry *GetEntry(const String &id) const; + +public: + + Base *GetIO() const { return io.c_ptr(); } + + const AutoList &GetEntries() const { return entries; } + + /// Reserve space on the store, an empty id is returned if the store is full. +virtual String Reserve(size_t size); + /// Free a store alias. +virtual bool Free(const String &id); + + /// Store data on a reserved id. + bool Store(const String &id, const void *data, size_t size, const char *user_data = 0); + + /// Get entry size. + size_t GetEntrySize(const String &id) const; + + /// Get the current store size. + size_t GetStoreSize() const; + /// Get the store free space size. + size_t GetFreeStore() const; + + /// Restore store content from the storage fs. + bool Load(const char *path = "store.db"); + /// Save store content to the storage fs. + bool Save(const char *path = "store.db"); + + DataStore(Base *storage, size_t storage_limit = Units::MB(32)) : io(storage), limit(storage_limit), id_seed(0) {} +}; + + } // IO +} // GS + + +#endif // __NIODATASTORE__ diff --git a/include/platform/filesystem/filesystem.h b/include/platform/filesystem/filesystem.h new file mode 100644 index 0000000..c1f2cc9 --- /dev/null +++ b/include/platform/filesystem/filesystem.h @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NFILESYSTEM__ +#define __NFILESYSTEM__ + + + #include "container/nlist.h" + #include "filesystem/io_base.h" + #include "nstring/nstring.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace IO { + class Handle; + struct Base; + +// +struct MountPoint +{ + String mount_point; + SharedPtr io_sys; + + MountPoint(const char *mount, Base *io) : mount_point(mount), io_sys(io) {} +}; + +/*! + @short I/O system. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Filesystem +{ + AutoList mount_list; + SharedList root_mount; +public: + + String MapToAbsolute(const char *) const; + String StripRootPath(const char *) const; + + bool Mount(Base *, const char *mount_point = 0); + void Unmount(const char *); + void Unmount(Base *); + void UnmountAll(); + + Base *GetIOSystem(const char *mount_point) const; + const char *GetMountPoint(const Base *) const; + + Handle *Open(const char *, Mode = ModeRead) const; + void Close(Handle *) const; + + bool MkDir(const char *) const; + + bool Exists(const char *) const; + bool Delete(const char *) const; + + size_t FileSize(const char *) const; + bool FileLoad(const char *, Array &, bool verbose = true) const; + bool FileSave(const char *, const Array &) const; + bool FileCopy(const char *src, const char *dst) const; + bool FileMove(const char *src, const char *dst) const; + ~Filesystem() { UnmountAll(); } + +}; + + } // IO +} // GS + + +#endif // __NFILESYSTEM__ diff --git a/include/platform/filesystem/ftp_lib.h b/include/platform/filesystem/ftp_lib.h new file mode 100644 index 0000000..757e047 --- /dev/null +++ b/include/platform/filesystem/ftp_lib.h @@ -0,0 +1,173 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __FTPLIB__ +#define __FTPLIB__ + + + #if __PLATFORM_WINDOWS__ + #include + #endif + #include "ntypes.h" + + +/// FTP connection. +struct FtpConnection +{ +enum Direction +{ + Upload = 0, + Download +}; + + int handle; + bool ready; + + char *buffer; + int buffer_usage; + + Direction direction; + + void FreeBuffer(); + bool AllocateBuffer(); + + FtpConnection(); + ~FtpConnection() + { FreeBuffer(); } +}; + +/* + @short FTP Library. +*/ +class FtpLibrary +{ +public: + +enum ConnectionMode +{ + ConnectionPORT = 0, + ConnectionPASV +}; + +enum TransferMode +{ + TransferASCII = 'A', + TransferBinary = 'I' +}; + +enum AccessType +{ + AccessDir = 0, + AccessDirVerbose, + AccessFileRead, + AccessFileWrite, + AccessFileReadAppend, + AccessFileWriteAppend +}; + +enum State +{ + FtpError = 0, + FtpOk, + FtpSocketTimeout +}; + +protected: + + char response[256]; + + FtpConnection master_connection; + ConnectionMode connection_mode; + + size_t offset; + bool correctpasv; + + /// Check server PASV support. + bool CheckPASVResponse(unsigned char *v); + /// Read and verify a response from the server. + bool CheckResponse(char c); + + /// Wait for the socket to receive or flush data. + State WaitSocket(FtpConnection *socket); + /// Read a line of text. + State ReadASCII(char *buf, int max, FtpConnection *socket, int &line_length); + /// Write a line of text. + State WriteASCII(char *buf, int length, FtpConnection *socket, int &wrote_length); + + /// Send a command and wait for expected response. + bool FtpSendCmd(const char *cmd, char expresp); + /// Accept connection from server. + bool FtpAcceptConnection(FtpConnection *connection); + + /// Create a PORT connection for data transfer. + FtpConnection *CreatePORTConnection(TransferMode mode, FtpConnection::Direction direction, char *connection_command); + /// Create a PASV connection for data transfer. + FtpConnection *CreatePASVConnection(TransferMode mode, FtpConnection::Direction direction, char *connection_command); + /// Create a connection for data transfer. + FtpConnection *CreateConnection(const char *path, AccessType type, TransferMode mode); + /// Close connection. + bool CloseConnection(FtpConnection *connection); + + /// Generic data transfer function. + State DataTransfer(const char *local_path, const char *remote_path, AccessType type, TransferMode mode); + /// Read data from a connection. + State ReadBinary(void *buffer, int max, FtpConnection *connection, int &length); + /// Write data to a connection. + State WriteBinary(void *buffer, int length, FtpConnection *connection); + +public: + + /// Set data connection transfer mode. + void SetDataConnectionMode(ConnectionMode mode) + { connection_mode = mode; } + + /// Get last server response received. + const char *GetLastResponse() const + { return response; } + + /// Connect to a remote server. + bool Connect(const char *host); + /// Upload file to server. + State Upload(const char *local_path, const char *remote_path, TransferMode mode = TransferBinary, int offset = 0); + /// Download file from server. + State Download(const char *local_path, const char *remote_path, TransferMode mode = TransferBinary, int offset = 0); + /// Quit server, close connection. + bool Quit(); + + /// Change directory. + bool ChangeDirectory(const char *path); + /// Up directory. + bool UpDirectory(); + /// Delete remote file. + bool DeleteFile(const char *path); + /// Get remote file size. + int GetFileSize(const char *path, TransferMode mode = TransferBinary); + + /// Download directory listing to a local file. + bool Nlst(const char *outputfile, const char *path); + + /// Login remote server. + bool Login(const char *user, const char *password); + + +/* + Callback functions. +*/ +virtual bool IdleCallback() + { return true; } +virtual void SendCommandCallback(const char * /*command*/) + {} +virtual bool DataReadCallback(const FtpConnection * /*connection*/) + { return true; } +virtual bool DataWriteCallback(const FtpConnection * /*connection*/) + { return true; } + + FtpLibrary(); +virtual ~FtpLibrary(); +}; + + +#endif // __FTPLIB__ diff --git a/include/platform/filesystem/io_alias.h b/include/platform/filesystem/io_alias.h new file mode 100644 index 0000000..bee8c24 --- /dev/null +++ b/include/platform/filesystem/io_alias.h @@ -0,0 +1,66 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOALIAS__ +#define __NIOALIAS__ + + + #include + #include "nstring/nstring.h" + #include "container/nmap.h" + + +namespace GS { + namespace IO { + class Handle; + +/*! + @short Alias proxy I/O. + A simple proxy I/O to provide filename aliasing to another I/O system. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Alias : public Base +{ + SharedPtr iofs; + +public: + + //---------------------------------------------------------------------- + Map alias_map; + + String ResolveAlias(const char *path) const + { + Pair *alias = alias_map.Get(path); + return alias ? alias->value : path; + } + //---------------------------------------------------------------------- + +virtual Handle *Open(const char *path, Mode mode = IORead) + { return iofs->Open(ResolveAlias(path), mode); } +virtual void Close(Handle *h) + { iofs->Close(h); } + +virtual bool Delete(const char *path) + { return iofs->Delete(ResolveAlias(path)); } + +virtual size_t Tell(Handle *h) + { return iofs->Tell(h); } +virtual size_t Seek(Handle *h, ptrdiff_t offset, SeekRef seek_ref = SeekCurrent) + { return iofs->Seek(h, offset, seek_ref); } + +virtual size_t Read(Handle *h, void *p, size_t size) + { return iofs->Read(h, p, size); } +virtual size_t Write(Handle *h, const void *p, size_t size) + { return iofs->Write(h, p, size); } + + Alias(Base *io) : iofs(io) {} +}; + + } // IO +} // GS + + +#endif // __NIOALIAS__ diff --git a/include/platform/filesystem/io_base.h b/include/platform/filesystem/io_base.h new file mode 100644 index 0000000..88dc79a --- /dev/null +++ b/include/platform/filesystem/io_base.h @@ -0,0 +1,80 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOBASE__ +#define __NIOBASE__ + + + #include + #include "filesystem/io_mode.h" + #include "memory/nshared_ptr.h" + #include "container/narray.h" + #include "alloc/ialloc.h" + + +namespace GS { + class String; + + namespace IO { + class Handle; + +/*! + @short I/O base. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct Base : public SharedObject +{ + NPLACEMENT_NEW(Filesystem) + +enum SeekRef +{ + SeekStart = 0, + SeekCurrent, + SeekEnd +}; + +enum Caps +{ + IsCaseSensitive = (1 << 0), + CanRead = (1 << 1), + CanWrite = (1 << 2), + CanSeek = (1 << 3), + CanDelete = (1 << 4), + CanMkDir = (1 << 5) +}; + + bool FileLoad(const char *uri, Array &buffer); + bool FileSave(const char *uri, const Array &buffer); + + String FileHash(const char *uri); + +virtual bool Exists(const char *); +virtual String Hash(const char *); + +virtual String MapToAbsolute(const char *uri) const; +virtual String MapToRelative(const char *path) const; + +virtual uint GetCaps() const = 0; + +virtual Handle *Open(const char *, Mode = ModeRead) = 0; +virtual void Close(Handle *) = 0; + +virtual bool Delete(const char *) = 0; + +virtual size_t Tell(Handle *) = 0; +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent) = 0; + +virtual size_t Read(Handle *, void *, size_t) = 0; +virtual size_t Write(Handle *, const void *, size_t) = 0; + +virtual bool MkDir(const char *) = 0; +}; + + } // IO +} // GS + + +#endif // __NIOBASE__ diff --git a/include/platform/filesystem/io_buffer.h b/include/platform/filesystem/io_buffer.h new file mode 100644 index 0000000..f9e73c6 --- /dev/null +++ b/include/platform/filesystem/io_buffer.h @@ -0,0 +1,87 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOBUFFER__ +#define __NIOBUFFER__ + + + #include "filesystem/io_handle.h" + #include "nstring/nstring.h" + #include "memory/nauto_ptr.h" + #include "container/narray.h" + #include "unit/nunit.h" + + +namespace GS { + namespace IO { + +// +struct IOBuffer +{ + Array buffer; + + size_t start_pos; + size_t usage; + + IOBuffer() : start_pos(0), usage(0) {} +}; + +// +class BufferHandle : public Handle +{ + friend class Buffer; + + AutoPtr handle; + size_t size; // file size on wrapped fs + size_t pos; // position in source handle + + IOBuffer read_buffer; + +public: + +virtual size_t GetSize() { return size; } + + BufferHandle(Base *io, Handle *h) : Handle(io), handle(h), size(0), pos(0) {} +}; + +/*! + @short Buffered I/O filesystem wrapper. + Implements a transparent read/write buffer on top of another filesystem. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Buffer : public Base +{ + SharedPtr io; + + size_t read_buffer_size, + write_buffer_size; + +public: + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual String Hash(const char *); +virtual bool Delete(const char *); + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t); + +virtual bool MkDir(const char *); + + Buffer(Base *base, size_t read_buffer_size = Units::KB(4), size_t write_buffer_size = Units::KB(4)); +}; + + } // IO +} // GS + + +#endif // __NIOBUFFER__ diff --git a/include/platform/filesystem/io_cache.h b/include/platform/filesystem/io_cache.h new file mode 100644 index 0000000..296905e --- /dev/null +++ b/include/platform/filesystem/io_cache.h @@ -0,0 +1,109 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOCACHE__ +#define __NIOCACHE__ + + + #include "filesystem/data_store.h" + #include "filesystem/io_handle.h" + #include "memory/nauto_ptr.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + #include "time/ntime.h" + #include "unit/nunit.h" + + +namespace GS { + namespace IO { + +// +class CacheHandle : public Handle +{ + friend class Cache; + +protected: + + String path; + AutoPtr handle; + +public: + + CacheHandle(Base *io, const char *p, Handle *h) : Handle(io), path(p), handle(h) {} + ~CacheHandle(); +}; + +/*! + @short Cached I/O filesystem wrapper. + Implements a transparent file cache on top of another filesystem. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Cache : public Base +{ + SharedPtr io; + DataStore store; + +public: + +struct Entry +{ + String path, id; + String hash; + + uint refc; + size_t size; + + Time last_use; + + Entry() : refc(0), size(0) {} +}; + +private: + + Threading::Mutex mutex; + + size_t cache_size; + AutoList entries; + + int ComputeEntryRecyclingScore(const Entry *) const; + String ReserveOnStore(size_t size); + + Entry *GetCacheEntry(const char *path) const; + Entry *CreateCacheEntry(const char *path); + bool UpdateCacheEntry(Entry *entry, Array *preloaded_data = 0); + bool DeleteCacheEntry(Entry *entry); + +public: + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual bool Delete(const char *); + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t); + +virtual bool MkDir(const char *); + + /// Test if a given path is in cache. + bool IsInCache(const char *path) const { return asbool(GetCacheEntry(path)); } + + /// Reload cache state from its store. + bool SynchronizeWithStore(const char *store_path = "store.db"); + + Cache(Base *base, Base *store, size_t cache_size = Units::MB(32)); +}; + + } // IO +} // GS + + +#endif // __NIOCACHE__ diff --git a/include/platform/filesystem/io_cfile.h b/include/platform/filesystem/io_cfile.h new file mode 100644 index 0000000..8073abc --- /dev/null +++ b/include/platform/filesystem/io_cfile.h @@ -0,0 +1,70 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOCFILE__ +#define __NIOCFILE__ + + + #include + #include "filesystem/io_handle.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace IO { + +// +class CFileHandle : public Handle +{ +friend class CFile; + + FILE *file; + + CFileHandle(Base *); + +public: + + ~CFileHandle(); +}; + +/*! + @short C-File I/O. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class CFile : public Base +{ + String root; + +public: + + void SetRootPath(const char *); + +virtual String MapToAbsolute(const char *) const; +virtual String MapToRelative(const char *) const; + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual bool Delete(const char *); + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t); + +virtual bool MkDir(const char *); + + CFile(const char *root_path = 0); +}; + + } // IO +} // GS + + +#endif // __NIOCFILE__ diff --git a/include/platform/filesystem/io_crypto.h b/include/platform/filesystem/io_crypto.h new file mode 100644 index 0000000..feaa272 --- /dev/null +++ b/include/platform/filesystem/io_crypto.h @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOCRYPTO__ +#define __NIOCRYPTO__ + + + #include "filesystem/io_memory.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace IO { + +// +class CryptoHandle : public Handle +{ +friend class Crypto; + + AutoPtr cached_h; + + String path; + Mode io_mode; + + CryptoHandle(Base *, Handle *, const char *, Mode); + +public: + + ~CryptoHandle(); +}; + +/*! + @short I/O Crypto proxy. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Crypto : public Base +{ + String key; + + SharedPtr wrapped_io; + SharedPtr cache_io; + + void Encrypt(Array &); + void Decrypt(Array &); + +public: + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual bool Delete(const char *); + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t); + +virtual bool MkDir(const char *); + + Crypto(Base *, const char *key); +}; + + } // IO +} // GS + + +#endif // __NIOCRYPTO__ diff --git a/include/platform/filesystem/io_dispatcher.h b/include/platform/filesystem/io_dispatcher.h new file mode 100644 index 0000000..18e70da --- /dev/null +++ b/include/platform/filesystem/io_dispatcher.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIODISPATCH__ +#define __NIODISPATCH__ + + + #include + #include "filesystem/io_handle.h" + #include "memory/nauto_ptr.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace IO { + +// +class DispatcherHandle : public Handle +{ + friend class Dispatcher; + + AutoPtr handle; + + DispatcherHandle(Base *, Handle *); + +public: + + ~DispatcherHandle(); +}; + +/*! + @short Dispatcher I/O. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Dispatcher : public Base +{ +struct DispatchFS +{ + String prefix; + SharedPtr fs; +}; + + SharedList roots; + AutoList mounts; + + Base *Dispatch(String &, Mode); + +public: + + bool AddDispatch(Base *, const char *prefix = 0); + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual String Hash(const char *); +virtual bool Delete(const char *); + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t); + +virtual bool MkDir(const char *); +}; + + } // IO +} // GS + + +#endif // __NIODISPATCH__ diff --git a/include/platform/filesystem/io_handle.h b/include/platform/filesystem/io_handle.h new file mode 100644 index 0000000..1c18146 --- /dev/null +++ b/include/platform/filesystem/io_handle.h @@ -0,0 +1,71 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOHANDLE__ +#define __NIOHANDLE__ + + + #include "filesystem/io_base.h" + #include "memory/nweak_ptr.h" + + +namespace GS { + namespace IO { + +// +class Handle +{ + WeakPtr io_sys; + +public: + + NPLACEMENT_NEW(Filesystem) + +virtual size_t GetSize(); + +virtual size_t Rewind(); +virtual bool IsEOF(); + +virtual size_t Tell(); +virtual size_t Seek(ptrdiff_t, Base::SeekRef = Base::SeekCurrent); + +virtual size_t Read(void *, size_t); +virtual size_t Write(const void *, size_t); + +template Handle &operator << (const T &v) + { + io_sys->Write(this, &v, sizeof(T)); + return *this; + } +template Handle &operator >> (T &v) + { + io_sys->Read(this, &v, sizeof(T)); + return *this; + } + Handle &operator << (const char *); + Handle &operator << (char *); + +template bool Write(const T &v) + { return asbool(io_sys->Write(this, &v, sizeof(T))); } +template T Read() + { + T v; + io_sys->Read(this, &v, sizeof(T)); + return v; + } + + Base *GetIOSystem() const + { return io_sys.c_ptr(); } + + Handle(Base *); +virtual ~Handle(); +}; + + } // IO +} // GS + + +#endif // __NIOHANDLE__ diff --git a/include/platform/filesystem/io_handle_endian.h b/include/platform/filesystem/io_handle_endian.h new file mode 100644 index 0000000..20ae38d --- /dev/null +++ b/include/platform/filesystem/io_handle_endian.h @@ -0,0 +1,50 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOHANDLE_ENDIAN__ +#define __NIOHANDLE_ENDIAN__ + + + #include "filesystem/io_handle.h" + #include "memory/endian.h" + + +namespace GS { + namespace IO { + +/// IO Handle endian wrapper. +class HandleEndian +{ + AutoPtr h; + Endian::Config config; + +public: + + bool IsNull() const { return h.IsNull(); } + bool IsValid() const { return h.IsValid(); } + + Handle &GetIOHandle() const { return *h; } + +template const HandleEndian &operator << (const T &v) + { + *h << Endian::ToHost(v, config); + return *this; + } +template const HandleEndian &operator >> (T &v) + { + *h >> v; + Endian::ToHost(&v, sizeof(T), config); + return *this; + } + + HandleEndian(Handle *in_h, Endian::Config in_config = Endian::Little) : h(in_h), config(in_config) {} +}; + + } // IO +} // GS + + +#endif // __NIOHANDLE_ENDIAN__ diff --git a/include/platform/filesystem/io_handle_segment.h b/include/platform/filesystem/io_handle_segment.h new file mode 100644 index 0000000..ca3fc56 --- /dev/null +++ b/include/platform/filesystem/io_handle_segment.h @@ -0,0 +1,42 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOHANDLESEGMENT__ +#define __NIOHANDLESEGMENT__ + + + #include "filesystem/io_handle.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + namespace IO { + +// +class HandleSegment : public Handle +{ + Handle *handle; + size_t offset, size; + size_t cursor; + +public: + +virtual size_t GetSize(); + +virtual size_t Tell(); +virtual size_t Seek(ptrdiff_t, Base::SeekRef = Base::SeekCurrent); + +virtual size_t Read(void *, size_t); +virtual size_t Write(const void *, size_t); + + HandleSegment(Handle *h, size_t o, size_t s) : Handle(0), handle(h), offset(o), size(s), cursor(0) {} +}; + + } // IO +} // GS + + +#endif // __NIOHANDLESEGMENT__ diff --git a/include/platform/filesystem/io_memory.h b/include/platform/filesystem/io_memory.h new file mode 100644 index 0000000..5aebb1b --- /dev/null +++ b/include/platform/filesystem/io_memory.h @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOMEMORY__ +#define __NIOMEMORY__ + + + #include "filesystem/io_handle.h" + #include "container/nlist.h" + #include "nstring/nstring.h" + + +namespace GS { + namespace IO { + +// +class MemoryFile +{ + friend class Memory; + + String uri; + Array data; + size_t size; //< Might be != data.GetSize() + + MemoryFile(const char *_uri = 0) : uri(_uri), size(0) {} + +public: + + const String &GetUri() const { return uri; } + const Array &GetData() const { return data; } + size_t GetSize() const { return size; } +}; + +// +class MemoryHandle : public Handle +{ + friend class Memory; + + MemoryFile *file; + size_t cursor; + Mode mode; + + MemoryHandle(Base *, MemoryFile *, Mode = ModeRead); + +public: + + ~MemoryHandle(); +}; + +/*! + @short Memory I/O. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Memory : public Base +{ + AutoList fat; + +public: + + /// Return the system file allocation table. + const List &GetFat() const { return fat; } + +virtual uint GetCaps() const; + +virtual Handle *Open(const char *, Mode = ModeRead); +virtual void Close(Handle *); + +virtual bool Delete(const char *); + +virtual size_t Tell(Handle *); +virtual size_t Seek(Handle *, ptrdiff_t offset, SeekRef = SeekCurrent); + +virtual size_t Read(Handle *, void *, size_t); +virtual size_t Write(Handle *, const void *, size_t); + +virtual bool MkDir(const char *) { return false; } +}; + + } // IO +} // GS + + +#endif // __NIOMEMORY__ diff --git a/include/platform/filesystem/io_mode.h b/include/platform/filesystem/io_mode.h new file mode 100644 index 0000000..b250a3e --- /dev/null +++ b/include/platform/filesystem/io_mode.h @@ -0,0 +1,25 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NIOMODE__ +#define __NIOMODE__ + + +namespace GS { + namespace IO { + +enum Mode +{ + ModeNone = 0, + ModeRead, + ModeWrite +}; + + } // IO +} // GS + + +#endif // __NIOMODE__ diff --git a/include/platform/hash/md5.h b/include/platform/hash/md5.h new file mode 100644 index 0000000..a90f70f --- /dev/null +++ b/include/platform/hash/md5.h @@ -0,0 +1,114 @@ +/* + + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + +*/ + +/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ + +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Removed support for non-ANSI compilers; removed + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. +*/ + +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + +#ifndef __NMD5__ +#define __NMD5__ + + +namespace GS { + namespace MD5 { + +/* + This package supports both compile-time and run-time determination of CPU + byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + defined as non-zero, the code will be compiled to run only on big-endian + CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + run on either big- or little-endian CPUs, but will run slightly less + efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. +*/ + +typedef unsigned char md5_byte_t; // 8-bit byte +typedef unsigned int md5_word_t; // 32-bit word + +/* + @short MD5 digest. +*/ +class Digest +{ + md5_word_t count[2], ///< Message length in bits, lsw first. + abcd[4]; ///< Digest buffer. + md5_byte_t buf[64]; ///< Accumulate block. + + /// Process. + void Process(const md5_byte_t *data /*[64]*/); + +public: + + void Reset(); + + /// Append data to the message. + void Append(const md5_byte_t *data, int nbytes); + /// Finish the message and return the digest. + void Finish(md5_byte_t digest[16]); + + Digest() { Reset(); } +}; + +/*! + @short Convert a digest to string. + @note The string is not NULL terminated by this function. +*/ +void DigestToString(const md5_byte_t digest[16], char *s); + + } // MD5 +} // GS + + +#endif // __NMD5__ diff --git a/include/platform/hash/nsha1.h b/include/platform/hash/nsha1.h new file mode 100644 index 0000000..aaf2e70 --- /dev/null +++ b/include/platform/hash/nsha1.h @@ -0,0 +1,27 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSHA1__ +#define __NSHA1__ + + +namespace GS { + class String; + template class Array; + + namespace SHA1 { + +void ComputeHash(const String &source, Array &hash); +String ComputeHexa(const String &source); + +void ComputeHash(const Array &data, Array &hash); +String ComputeHexa(const Array &data); + + } // SHA1 +} // GS + + +#endif // __NSHA1__ diff --git a/include/platform/hash/sha1.h b/include/platform/hash/sha1.h new file mode 100644 index 0000000..96d8ce4 --- /dev/null +++ b/include/platform/hash/sha1.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2011, Micael Hildenborg + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Micael Hildenborg nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SHA1_DEFINED +#define SHA1_DEFINED + +namespace sha1 +{ + + /** + @param src points to any kind of data to be hashed. + @param bytelength the number of bytes to hash from the src pointer. + @param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in. + */ + void calc(const void* src, const int bytelength, unsigned char* hash); + + /** + @param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function. + @param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string. + */ + void toHexString(const unsigned char* hash, char* hexstring); + +} // namespace sha1 + +#endif // SHA1_DEFINED diff --git a/include/platform/http/http_interface.h b/include/platform/http/http_interface.h new file mode 100644 index 0000000..eccf209 --- /dev/null +++ b/include/platform/http/http_interface.h @@ -0,0 +1,47 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __HTTPINTERFACE__ +#define __HTTPINTERFACE__ + + + #include "container/narray.h" + + +namespace GS { + namespace HTTP { + +/*! + @short HTTP interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct IHTTP +{ + /// Process a request return value. +virtual void OnRequestComplete(int ticket_id, const Array &data) = 0; + /// Process a request error. +virtual void OnRequestError(int ticket_id) = 0; + + /*! + @short Post an asynchronous HTTP request. + + This function posts an asynchronous HTTP request and returns a ticket + id to the caller. When task result is available the OnRequestComplete + or OnRequestError handler functions will be called. + */ +virtual int Post(const char *url, const char *post) = 0; + + /// Process pending event dispatch in the caller thread. +virtual void Update() = 0; + +virtual ~IHTTP() {} +}; + + } // HTTP +} // GS + + +#endif // __HTTPINTERFACE__ diff --git a/include/platform/input/input_device.h b/include/platform/input/input_device.h new file mode 100644 index 0000000..7257de2 --- /dev/null +++ b/include/platform/input/input_device.h @@ -0,0 +1,136 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __INPUT_DEVICE__ +#define __INPUT_DEVICE__ + + + #include "ntypes.h" + #include "memory/nshared_ptr.h" + + +namespace GS { + namespace Input { + +/* + @short Input device. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Device : public SharedObject +{ +public: + +enum Type +{ + Type_Any = 0, Type_Keyboard, Type_Mouse, Type_Pad, Type_Touch +}; + + // Binary value. +enum KeyCode +{ + Key_None = 0, + + // Keyboard. + Key_LShift, Key_RShift, Key_LCtrl, Key_RCtrl, Key_LAlt, Key_RAlt, Key_LWin, Key_RWin, + Key_Tab, Key_CapsLock, Key_Space, Key_Backspace, Key_Insert, Key_Suppr, Key_Home, Key_End, Key_PageUp, Key_PageDown, + Key_Up, Key_Down, Key_Left, Key_Right, + Key_Escape, + Key_F1, Key_F2, Key_F3, Key_F4, Key_F5, Key_F6, Key_F7, Key_F8, Key_F9, Key_F10, Key_F11, Key_F12, + Key_PrintScreen, Key_ScrollLock, Key_Pause, Key_NumLock, Key_Return, + Key_Numpad0, Key_Numpad1, Key_Numpad2, Key_Numpad3, Key_Numpad4, Key_Numpad5, Key_Numpad6, Key_Numpad7, Key_Numpad8, Key_Numpad9, + Key_Add, Key_Sub, Key_Mul, Key_Div, Key_Enter, + Key_A, Key_B, Key_C, Key_D, Key_E, Key_F, Key_G, Key_H, Key_I, Key_J, Key_K, Key_L, Key_M, Key_N, Key_O, Key_P, Key_Q, Key_R, Key_S, Key_T, Key_U, Key_V, Key_W, Key_X, Key_Y, Key_Z, + + // Mouse/pad. + Key_Button0, Key_Button1, Key_Button2, Key_Button3, Key_Button4, Key_Button5, Key_Button6, Key_Button7, Key_Button8, Key_Button9, + Key_Button10, Key_Button11, Key_Button12, Key_Button13, Key_Button14, Key_Button15, Key_Button16, Key_Button17, Key_Button18, Key_Button19, + Key_Button20, Key_Button21, Key_Button22, Key_Button23, Key_Button24, Key_Button25, Key_Button26, Key_Button27, Key_Button28, Key_Button29, + Key_Button30, Key_Button31, Key_Button32, Key_Button33, Key_Button34, Key_Button35, Key_Button36, Key_Button37, Key_Button38, Key_Button39, + Key_Button40, Key_Button41, Key_Button42, Key_Button43, Key_Button44, Key_Button45, Key_Button46, Key_Button47, Key_Button48, Key_Button49, + Key_Button50, Key_Button51, Key_Button52, Key_Button53, Key_Button54, Key_Button55, Key_Button56, Key_Button57, Key_Button58, Key_Button59, + Key_Button60, Key_Button61, Key_Button62, Key_Button63, Key_Button64, Key_Button65, Key_Button66, Key_Button67, Key_Button68, Key_Button69, + Key_Button70, Key_Button71, Key_Button72, Key_Button73, Key_Button74, Key_Button75, Key_Button76, Key_Button77, Key_Button78, Key_Button79, + Key_Button80, Key_Button81, Key_Button82, Key_Button83, Key_Button84, Key_Button85, Key_Button86, Key_Button87, Key_Button88, Key_Button89, + Key_Button90, Key_Button91, Key_Button92, Key_Button93, Key_Button94, Key_Button95, Key_Button96, Key_Button97, Key_Button98, Key_Button99, + Key_Button100, Key_Button101, Key_Button102, Key_Button103, Key_Button104, Key_Button105, Key_Button106, Key_Button107, Key_Button108, Key_Button109, + Key_Button110, Key_Button111, Key_Button112, Key_Button113, Key_Button114, Key_Button115, Key_Button116, Key_Button117, Key_Button118, Key_Button119, + Key_Button120, Key_Button121, Key_Button122, Key_Button123, Key_Button124, Key_Button125, Key_Button126, Key_Button127, + Key_Back, Key_Start, Key_Select, Key_L1, Key_L2, Key_L3, Key_R1, Key_R2, Key_R3, + Key_Cross_Up, Key_Cross_Down, Key_Cross_Left, Key_Cross_Right, + + Key_Last +}; + + // Ranged-value. +enum InputCode +{ + Input_None = 0, + Input_AxisX, Input_AxisY, Input_AxisZ, Input_AxisS, Input_AxisT, Input_AxisR, + Input_RotX, Input_RotY, Input_RotZ, Input_RotS, Input_RotT, Input_RotR, + Input_Button0, Input_Button1, Input_Button2, Input_Button3, Input_Button4, Input_Button5, Input_Button6, Input_Button7, Input_Button8, Input_Button9, Input_Button10, Input_Button11, Input_Button12, Input_Button13, Input_Button14, Input_Button15 +}; + + // Input semantics. +enum InputSemantic +{ + // Mouse semantics. + Semantic_LeftMouseButton, Semantic_RightMouseButton, Semantic_MiddleMouseButton, + Semantic_MouseAxisX, Semantic_MouseAxisY, Semantic_MouseWheel, + + // Touch semantic. + Semantic_TouchPressure, Semantic_TouchAxisX, Semantic_TouchAxisY, + + // Pad semantics. + Semantic_StartButton, Semantic_SelectButton +}; + +enum Effect +{ + Vibrate, VibrateLeft, VibrateRight, + ConstantForce +}; + + /// Get device type. +virtual Type GetType() const = 0; + /// Get device name. +virtual const char *GetName() const = 0; + + /// Pool state and refresh values. +virtual void Update() = 0; + /// Is device valid. +virtual bool IsValid() const { return true; } + + /// Get input from semantic. +virtual InputCode GetInputFromSemantic(InputSemantic) { return Input_None; } + + /// Test a key state. +virtual bool IsDown(KeyCode) const { return false; } + /// Test a key state during the previous update. +virtual bool WasDown(KeyCode) const { return false; } + + /// Get input range. +virtual bool GetInputRange(InputCode, float &min, float &max) const { return false; } + + /// Get input value. +virtual float GetValue(InputCode) const { return 0; } + /// Get input value during last update. +virtual float GetLastValue(InputCode) const { return 0; } + + /// Set input value, return true if the device supports setting this value. +virtual bool SetValue(InputCode, float) { return false; } + + /// Set device effect. +virtual void SetEffect(Effect effect, float v) {} + + bool WasPressed(KeyCode key) const + { return !WasDown(key) && IsDown(key); } +}; + + } // Input +} // GS + + +#endif // __INPUT_DEVICE__ diff --git a/include/platform/input/input_keyboard.h b/include/platform/input/input_keyboard.h new file mode 100644 index 0000000..c034c08 --- /dev/null +++ b/include/platform/input/input_keyboard.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __KEYBOARD_INPUT__ +#define __KEYBOARD_INPUT__ + + + #include "input/input_device.h" + + +namespace GS { + namespace Input { + +/* + @short Keyboard input device. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Keyboard : public Device +{ +protected: + + bool is_down[Key_Last], + was_down[Key_Last]; + +public: + +virtual Type GetType() const { return Type_Keyboard; } +virtual const char *GetName() const { return "Keyboard"; } + +virtual void Update() = 0; + +virtual bool IsDown(KeyCode k) const { return is_down[k]; } +virtual bool WasDown(KeyCode k) const { return was_down[k]; } + + Keyboard(); +}; + + } // Input +} // GS + + +#endif // __KEYBOARD_INPUT__ diff --git a/include/platform/input/input_mouse.h b/include/platform/input/input_mouse.h new file mode 100644 index 0000000..f8a51ad --- /dev/null +++ b/include/platform/input/input_mouse.h @@ -0,0 +1,56 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __INPUT_MOUSE__ +#define __INPUT_MOUSE__ + + + #include "input/input_device.h" + + +namespace GS { + namespace Input { + +/* + @short Mouse input device. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class Mouse : public Device +{ +protected: + +struct State +{ + float x, y, wheel, hwheel; + bool left_button, right_button, middle_button; +}; + + State state, + last_state; + +public: + +virtual Type GetType() const { return Type_Mouse; } +virtual const char *GetName() const { return "mouse"; } + +virtual void Update() = 0; + +virtual bool IsDown(KeyCode) const; +virtual bool WasDown(KeyCode) const; + +virtual bool GetInputRange(InputCode, float &min, float &max) const; + +virtual float GetValue(InputCode) const; +virtual float GetLastValue(InputCode) const; + + Mouse(); +}; + + } // Input +} // GS + + +#endif // __INPUT_MOUSE__ diff --git a/include/platform/input/input_null.h b/include/platform/input/input_null.h new file mode 100644 index 0000000..c413cc1 --- /dev/null +++ b/include/platform/input/input_null.h @@ -0,0 +1,45 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __INPUT_NULL_DEVICE__ +#define __INPUT_NULL_DEVICE__ + + + #include "input/input_device.h" + + +namespace GS { + namespace Input { + +/* + @short Null input device. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class NullDevice : public Device +{ +public: + +virtual Type GetType() const + { return Type_Any; } +virtual const char *GetName() const + { return "Null"; } + +virtual void Update() {} + +virtual bool IsDown(KeyCode) const { return false; } +virtual bool WasDown(KeyCode) const { return false; } + +virtual bool GetInputRange(InputCode, float &min, float &max) const { return false; } + +virtual float GetValue(InputCode) const { return 0; } +virtual float GetLastValue(InputCode) const { return 0; } +}; + + } // Input +} // GS + + +#endif // __INPUT_NULL_DEVICE__ diff --git a/include/platform/input/input_system.h b/include/platform/input/input_system.h new file mode 100644 index 0000000..74015fa --- /dev/null +++ b/include/platform/input/input_system.h @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __INPUT_SYSTEM__ +#define __INPUT_SYSTEM__ + + + #include "input/input_device.h" + #include "nstring/nstring.h" + #include "container/nlist.h" + + +namespace GS { + namespace Input { + +/* + @short Input system. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct System +{ + /// Return true if the input system is active. +virtual bool IsActive() { return true; } + +virtual void Update() = 0; + + /// Return the current display handle. +virtual void *GetHandle() const { return 0; } + /// Set display handle. +virtual void SetHandle(void *) {} + + /// Return a list of devices available on this system. +virtual bool GetDeviceList(StringList &, Device::Type = Device::Type_Any) const { return true; } + /// Return a list of guid devices available on this system. +virtual bool GetDeviceGuidList(StringList &, Device::Type = Device::Type_Any) const { return true; } + + /// Get a device from its name. +virtual Device *GetDevice(const char *name) = 0; +virtual Device *GetDeviceFromGuid(const char *name) {return NULL;}; + +virtual ~System() {} +}; + + } // Input +} // GS + + +#endif // __INPUT_SYSTEM__ diff --git a/include/platform/input/input_touch.h b/include/platform/input/input_touch.h new file mode 100644 index 0000000..303d25a --- /dev/null +++ b/include/platform/input/input_touch.h @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __INPUT_TOUCH__ +#define __INPUT_TOUCH__ + + + #include "input/input_device.h" + + +namespace GS { + namespace Input { + +/* + @short Touch input device. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +class TouchDevice : public Device +{ +protected: + +struct State +{ + float x, y; + bool button; +}; + + int index; + State state, last_state, pending_state; + +public: + +virtual Type GetType() const; +virtual const char *GetName() const; + +virtual void Update(); + +virtual bool IsDown(KeyCode) const; +virtual bool WasDown(KeyCode) const; + +virtual bool GetInputRange(InputCode, float &min, float &max) const; + +virtual float GetValue(InputCode) const; +virtual float GetLastValue(InputCode) const; + + void SetIndex(int); + void RegisterTouchEvent(float x, float y, float weight); + + TouchDevice(int index = -1); +}; + + } // Input +} // GS + + +#endif // __INPUT_TOUCH__ diff --git a/include/platform/licensing/licensing.h b/include/platform/licensing/licensing.h new file mode 100644 index 0000000..93b458a --- /dev/null +++ b/include/platform/licensing/licensing.h @@ -0,0 +1,30 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __LICENSING__ +#define __LICENSING__ + + +namespace GS { + +/*! + @short License system interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct ILicensing +{ + // Event handler for the license system. +virtual void onLicensingEvent(const char *) = 0; + /// Request an update of the application license. +virtual bool updateLicence(const char *) = 0; + +virtual ~ILicensing() {} +}; + +} // GS + + +#endif // __LICENSING__ \ No newline at end of file diff --git a/include/platform/locale/country.h b/include/platform/locale/country.h new file mode 100644 index 0000000..b725860 --- /dev/null +++ b/include/platform/locale/country.h @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NCOUNTRY__ +#define __NCOUNTRY__ + + + #include "nstring/nstring.h" + + +namespace GS { + namespace Locale { + +struct Info +{ + String continent, region, country, fips, iso2, iso3; + int iso; + String internet; +}; + +// FIPS 10-4: American National Standard Codes for the Representation of Names of Countries, Dependencies, and Areas of Special Sovereignty for Information Interchange. +const Info *GetFIPSCountry(const char *); +// ISO 3166: Two-character. +const Info *GetISO2Country(const char *); +// ISO 3166: Three-character. +const Info *GetISO3Country(const char *); +// ISO 3166: Three-digit. +const Info *GetISOCountry(int); + + } // Locale +} // GS + + +#endif // __NCOUNTRY__ diff --git a/include/platform/log/file_log.h b/include/platform/log/file_log.h new file mode 100644 index 0000000..c3afdf7 --- /dev/null +++ b/include/platform/log/file_log.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NFILELOG__ +#define __NFILELOG__ + + + #include "nstring/nstring.h" + #include "log/log.h" + + +namespace GS { + +/*! + @short File log. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class FileLog : public Log +{ + String path; + + bool do_timestamp; + bool initial_write; + +public: + +virtual void NewLog(const char *log, char entry_level = EngineLogStandard); + + FileLog(const char *path, bool do_timestamp = false); +}; + +} // GS + + +#endif // __NFILELOG__ diff --git a/include/platform/log/log.h b/include/platform/log/log.h new file mode 100644 index 0000000..82b44c3 --- /dev/null +++ b/include/platform/log/log.h @@ -0,0 +1,137 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NLOG__ +#define __NLOG__ + + + #include "ntypes.h" + #include "memory/singleton.h" + #include "memory/nauto_ptr.h" + + +namespace GS { + class String; + + namespace Threading { class Mutex; } + + /*! + Define the maximum log line length. + */ +#define LOG_LINE_MAX_LEN 8192 + +/*! + @short Log. + + The log subsystem provides several log levels to enable activation and + deactivation of a whole log level. + + The following log streams are available to log to the different levels: + + * __LOG_H__: Header (eg: __LOG_H__ << "Physics entry point.\n") + * __LOG_W__: Warning + * __LOG_E__: Error + * __LOG_E__: Non-maskable + + Standard logs may be output to the __LOG__ stream. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Log +{ +protected: + + Threading::Mutex *mutex; + +#if __PLATFORM_LOG_SUPPORT__ + char full_a[LOG_LINE_MAX_LEN], full_b[LOG_LINE_MAX_LEN]; + char *a, *b; +#endif + +#define EngineLogNone 0 ///< Log no log ouput +#define EngineLogStandard 1 +#define EngineLogHeader 2 +#define EngineLogWarning 4 +#define EngineLogError 8 +#define EngineLogVerbose 16 +#define EngineLogScript 32 +#define EngineLogAll ~0 + + uint log_level; + +public: + + /// Set the log level. + void SetLogLevel(uint level = EngineLogAll) + { log_level = level; } + /// Get the current log level. + uint GetLogLevel() const + { return log_level; } + + /// Get the log mutex. + Threading::Mutex &GetMutex() + { return *mutex; } + + Log &operator << (const char); + Log &operator << (const short); + Log &operator << (const int); + Log &operator << (const uchar); + Log &operator << (const ushort); + Log &operator << (const uint); + #if __PLATFORM_IOS__ + Log &operator << (const size_t); + #endif + Log &operator << (const float); + Log &operator << (const bool); + Log &operator << (const void *); + Log &operator << (const char *); + Log &operator << (const String &); + + void LogProcessed(); + + /// Implement to receive new log lines. +virtual void NewLog(const char *log, char entry_level = EngineLogStandard); + + Log(); +virtual ~Log(); +}; + +/// Log system. +class LogSystem : public Singleton +{ + Log *log; + +public: + + /// Set the log object. + void SetLog(Log *log = 0); + /// Get the current log object. + Log &GetLog(); + + LogSystem(); +}; + +//------------------------------------------------------------------------------ +#define __LOG__ GS::LogSystem::Get().GetLog() // Standard +#define __LOG_H__ __LOG__ << "[H] " // Header +#define __LOG_CAM__ __LOG__ << "[WEBCAM] " // Header +#if 0 + #define __LOG_W__ __LOG__ << "[*] " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << ") " // Warning + #define __LOG_E__ __LOG__ << "[!] " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << ") " // Error +#else + #define __LOG_W__ __LOG__ << "[*] " + #define __LOG_E__ __LOG__ << "[!] " +#endif +#define __LOG_V__ __LOG__ << "[V] " // Verbose +#define __LOG_F__ __LOG__ << __FUNCTION__ << ": " + +#define __LOG_FUNC__ __LOG_V__ << __FUNCTION__ << "\n"; +//------------------------------------------------------------------------------ + +} // GS + + +#endif // __NLOG__ diff --git a/include/platform/log/log_scope.h b/include/platform/log/log_scope.h new file mode 100644 index 0000000..b1ea283 --- /dev/null +++ b/include/platform/log/log_scope.h @@ -0,0 +1,26 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NLOGSCOPE__ +#define __NLOGSCOPE__ + + +namespace GS { + +class LogScope +{ + const char *exit; + +public: + + LogScope(const char *enter, const char *exit); + ~LogScope(); +}; + +} // GS + + +#endif // __NFILELOG__ diff --git a/include/platform/math/nmath.h b/include/platform/math/nmath.h new file mode 100644 index 0000000..57862f3 --- /dev/null +++ b/include/platform/math/nmath.h @@ -0,0 +1,78 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMATH__ +#define __NMATH__ + + + #include "unit/nunit.h" + + +/* + @short Math namespace. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +namespace GS { + namespace Math { + +static const float Pi = 3.1415926535f; + + /// Euler angles rotation order. +enum rOrder +{ + rOrder_ZYX = 0, + rOrder_YZX, + rOrder_ZXY, + rOrder_XZY, + rOrder_YXZ, + rOrder_XYZ, + rOrder_XY, + + rOrder_Default = rOrder_YXZ // Y then X then Z. +}; + +enum Axis +{ + AxisX, // Do not modify X, Y and Z order. + AxisY, + AxisZ, + AxisNone +}; + +void Init(); + +/// Return the reverse rotation order from a given input order. +rOrder ReverserRotationOrder(rOrder r); + +float Sqrt(float v); + +float TestEqual(float a, float b, float e = 0.000001f); +bool EqualZero(float v, float e = 0.000001f); + +float Pow(float v, float exp); + +float Ceil(float); +float Floor(float); +float Mod(float); + +float RangeAdjust(float v, float old_min, float old_max, float new_min, float new_max); + +float Quantize(float v, float q); + +float Sin(float); +float ASin(float); +float Cos(float); +float ACos(float); +float Tan(float); +float ATan(float); + +bool IsFinite(float); + + } // Math +} // GS + + +#endif // __NMATH__ diff --git a/include/platform/math/nrange.h b/include/platform/math/nrange.h new file mode 100644 index 0000000..25e7abd --- /dev/null +++ b/include/platform/math/nrange.h @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRANGE__ +#define __NRANGE__ + + + #include "math/nrange.h" + + +namespace GS { + +/*! + @short Range. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template struct Range +{ + T start, end; + + T valueRange() const { return end - start; } + bool inRange(const T &v) const { return (start < end) ? ((v >= start) && (v < end)) : ((v >= end) && (v < start)); } + void sort() { if (start > end) { T t = start; start = end; end = t; } } + +static Range Intersection(const Range &a, const Range &b) + { + if ((a.end < b.start) || (a.start > b.end)) + return Range (); + return Range(a.start > b.start ? a.start : b.start, a.end < b.end ? a.end : b.end); + } +static Range Union(const Range &a, const Range &b) + { return Range(a.start < b.start ? a.start : b.start, a.end > b.end ? a.end : b.end); } + + void Set(const T &s, const T &e) { start = s; end = e; } + +template Range convert() const + { return Range (N(start), N(end)); } + + Range(const T &s, const T &e) : start(s), end(e) {} + Range() : start(0), end(0) {} +}; + +} // GS + + +#endif // __NRANGE__ diff --git a/include/platform/memory/bit_field.h b/include/platform/memory/bit_field.h new file mode 100644 index 0000000..1915e42 --- /dev/null +++ b/include/platform/memory/bit_field.h @@ -0,0 +1,60 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NBITFIELD__ +#define __NBITFIELD__ + + + #include "ntypes.h" + + +namespace GS { + +class BitField +{ + uint v; + +public: + + BitField &operator &= (uint b) { v &= b; return *this; } + BitField &operator |= (uint b) { v |= b; return *this; } + BitField &operator = (uint b) { v = b; return *this; } + + BitField &operator &= (const BitField &b) { v &= b.v; return *this; } + BitField &operator |= (const BitField &b) { v |= b.v; return *this; } + BitField &operator = (const BitField &b) { v = b.v; return *this; } + + bool operator == (const BitField &b) const { return v == b.v; } + bool operator != (const BitField &b) const { return v != b.v; } + +inline uint Get() const + { + return v; + } +inline uint Set(uint b) + { + v |= b; + return v; + } +inline uint Remove(uint b) + { + v &= ~b; + return v; + } + +inline uint Raise(uint b, bool raise = true) + { + return raise ? Set(b) : Remove(b); + } +inline bool IsSet(uint b) const { return asbool(v & b); } + + BitField() : v(0) {} +}; + +} + + +#endif // __NBITFIELD__ diff --git a/include/platform/memory/endian.h b/include/platform/memory/endian.h new file mode 100644 index 0000000..a3beee4 --- /dev/null +++ b/include/platform/memory/endian.h @@ -0,0 +1,52 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NENDIAN__ +#define __NENDIAN__ + + + #include "ntypes.h" + + +namespace GS { + namespace Endian { + +enum Config +{ + Undefined = 0, + + Big, + Little, + + Motorola = Big, + Intel = Little +}; + +/// Swap bytes in memory. +void SwapBytes(void *, size_t); + +/// Return the current host memory configuration. +Config GetHostConfiguration(); + +/// Convert a memory block to the host configuration. +void *ToHost(void *, size_t, Config = Big); + +/// Convert a value to the host configuration. +template T ToHost(const T &v, Config cfg = Big) +{ + if (GetHostConfiguration() == cfg) + return v; + + T host_value = v; + SwapBytes(&host_value, sizeof(T)); + return host_value; +} + + } // Endian +} // GS + + +#endif //__NENDIAN__ diff --git a/include/platform/memory/memory.h b/include/platform/memory/memory.h new file mode 100644 index 0000000..f816535 --- /dev/null +++ b/include/platform/memory/memory.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMEMORY__ +#define __NMEMORY__ + + + #include "ntypes.h" + + +namespace GS { + namespace Memory { + +/// Return smallest number of bits that can be used to represent a value. +uchar GetBitCount(int); +/// Return the position in bit of the first non-zero bit. +uchar GetShiftCount(int); +/// Return the number of bit set in a given value. +uchar CountSetBit(int); + +void WriteBit(uchar *, uint offset_in_bit, uint bit_count, uint value); +uint ReadBit(uchar *, uint offset_in_bit, uint bit_count); + +bool Compare(const void *, const void *, size_t); +void Copy(void *, const void *, size_t); +void Set(void *, char, size_t); + +void Fill(void *, const char *pattern, size_t); + } // Memory +} // GS + + +#endif // __NMEMORY__ diff --git a/include/platform/memory/nauto_ptr.h b/include/platform/memory/nauto_ptr.h new file mode 100644 index 0000000..899dba3 --- /dev/null +++ b/include/platform/memory/nauto_ptr.h @@ -0,0 +1,78 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NAUTO_PTR__ +#define __NAUTO_PTR__ + + + #include "alloc/ialloc.h" + #include "billing/billing.h" + + +namespace GS { + +/*! + @short Auto pointer. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class AutoPtr +{ +private: + + T *o; + +public: + +inline operator T*() const + { return o; } +inline T *c_ptr() const + { return o; } + +inline bool IsNull() const { return o ? false : true; } +inline bool IsValid() const { return o ? true : false; } + + T *operator = (T *p) + { + if (o != p) + { + delete(o); + o = p; + } + return o; + } + +inline T &operator[] (size_t n) { return o[n]; } + +inline bool operator == (const T *p) const + { return o == p; } +inline bool operator != (const T *p) const + { return o != p; } + +inline T *operator -> () const + { return o; } +inline T &operator * () const + { return *o; } + +inline T *Detach() + { + T *p = o; + o = 0; + return p; + } + + explicit AutoPtr(T *p = 0) : o(p) + {} + ~AutoPtr() + { + delete(o); + o = 0; + } +}; + +} // GS + + +#endif // __NAUTO_PTR__ diff --git a/include/platform/memory/nshared_ptr.h b/include/platform/memory/nshared_ptr.h new file mode 100644 index 0000000..e096a84 --- /dev/null +++ b/include/platform/memory/nshared_ptr.h @@ -0,0 +1,150 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSHARED_PTR__ +#define __NSHARED_PTR__ + + + #include "thread/atomic_value.h" + + +namespace GS { + +/// Weak reference to a shared object. +class WeakRef +{ + friend class SharedObject; + + bool is_valid; + Threading::Atomic32 refc; + + WeakRef() : is_valid(true) {} + +public: + + bool IsValid() const { return is_valid; } + + int GetRefCount() const { return refc.Get(); } + + void AddRef() { refc.Inc(); } + void RemoveRef() + { + if ((refc.Dec() == 0) && !is_valid) + delete this; + } +}; + +/*! + @short Reference counted object. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class SharedObject +{ + Threading::Atomic32 refc; + WeakRef *weak_ref; + +protected: + +virtual ~SharedObject() + { + if (weak_ref) + { + if (weak_ref->refc.Get() == 0) + delete weak_ref; + else + weak_ref->is_valid = false; + } + } + +public: + + WeakRef *GetWeakRef() + { + if (!weak_ref) + weak_ref = new WeakRef; // TODO have a specialized, fixed pool allocator for these. + return weak_ref; + } + + int GetRefCount() const { return refc.Get(); } + + void AddRef() { refc.Inc(); } + void RemoveRef() + { + if (refc.Dec() == 0) + { + if (weak_ref) + weak_ref->is_valid = false; + delete this; + } + } + + SharedObject() : weak_ref(0) {} +}; + +/*! + @short Strong smart pointer to a reference counted object. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class SharedPtr +{ + T *rc_o; + +public: + +inline operator T *() const { return rc_o; } +inline T *c_ptr() const { return rc_o; } + +inline bool IsNull() const { return rc_o ? false : true; } +inline bool IsValid() const { return rc_o ? true : false; } + + void Init() + { + if (rc_o) + rc_o->AddRef(); + } + +inline bool operator == (const T *p) const { return rc_o == p; } +inline bool operator != (const T *p) const { return rc_o != p; } +inline bool operator == (T *p) const { return rc_o == p; } +inline bool operator != (T *p) const { return rc_o != p; } + +inline bool operator == (const SharedPtr &p) const { return rc_o == p.rc_o; } +inline bool operator != (const SharedPtr &p) const { return rc_o != p.rc_o; } + + T *operator = (T *p) + { + if (rc_o != p) + { + if (rc_o) + rc_o->RemoveRef(); + rc_o = p; + Init(); + } + return p; + } + SharedPtr &operator = (const SharedPtr &p) + { + *this = p.c_ptr(); + return *this; + } +inline T *operator -> () const { return rc_o; } +inline T &operator * () const { return *rc_o; } + + explicit SharedPtr(T *p) : rc_o(p) { Init(); } + SharedPtr(const SharedPtr &p) : rc_o(p.rc_o) { Init(); } + SharedPtr() : rc_o(0) {} + + ~SharedPtr() + { + if (rc_o) + rc_o->RemoveRef(); + } +}; + +} // GS + + +#endif // __NSHARED_PTR__ diff --git a/include/platform/memory/nweak_ptr.h b/include/platform/memory/nweak_ptr.h new file mode 100644 index 0000000..c1786f3 --- /dev/null +++ b/include/platform/memory/nweak_ptr.h @@ -0,0 +1,101 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NWEAK_PTR__ +#define __NWEAK_PTR__ + + + #include "memory/nshared_ptr.h" + + +namespace GS { + +/*! + @short Weak pointer to a reference counted object. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class WeakPtr +{ +private: + + T *rc_o; + WeakRef *wref; + +public: + + T *c_ptr() const { return wref && wref->IsValid() ? rc_o : 0; } + + bool IsValid() const { return wref && wref->IsValid() ? true : false; } + bool IsNull() const { return !IsValid(); } + + /// Lock pointed object to a strong pointer. + bool Lock(SharedPtr &p) + { + if (IsNull()) + return false; + p = rc_o; + return true; + } + SharedPtr Lock() const { return SharedPtr (IsValid() ? rc_o : 0); } + + void Init() + { + if (!rc_o) + wref = 0; + else + { + wref = rc_o->GetWeakRef(); + wref->AddRef(); + } + } + +inline bool operator == (const T *p) const + { return rc_o == p; } +inline bool operator != (const T *p) const + { return rc_o != p; } +inline bool operator == (T *p) const + { return rc_o == p; } +inline bool operator != (T *p) const + { return rc_o != p; } + +inline bool operator == (const WeakPtr &p) const + { return rc_o == p.rc_o; } +inline bool operator != (const WeakPtr &p) const + { return rc_o != p.rc_o; } + + WeakPtr &operator = (const WeakPtr &p) + { + if (rc_o != p.rc_o) + { + WeakRef *old_wref = wref; + + rc_o = p.rc_o; + Init(); + + if (old_wref) + old_wref->RemoveRef(); + } + return *this; + } +inline T *operator -> () const + { return rc_o; } +inline T &operator * () const + { return *rc_o; } + + WeakPtr(T *p = 0) : rc_o(p) { Init(); } + WeakPtr(const WeakPtr &p) : rc_o(p.rc_o) { Init(); } + WeakPtr(const SharedPtr &p) : rc_o(p.c_ptr()) { Init(); } + ~WeakPtr() + { + if (wref) + wref->RemoveRef(); + } +}; + +} // GS + + +#endif // __NWEAK_PTR__ diff --git a/include/platform/memory/ring_buffer.h b/include/platform/memory/ring_buffer.h new file mode 100644 index 0000000..347648f --- /dev/null +++ b/include/platform/memory/ring_buffer.h @@ -0,0 +1,80 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRINGBUFFER__ +#define __NRINGBUFFER__ + + + #include "container/narray.h" + + +namespace GS { + +/* + @short Ring buffer. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +template class RingBuffer +{ + Array buffer; + uint put, get, usage; + +public: + + /// Get the maximum number of element in buffer. + uint GetCount() const + { return buffer.GetCount(); } + + /// Number of T left to put in the buffer. + uint GetFree() const + { return buffer.GetCount() - usage; } + /// Number of T available to get from the buffer. + uint GetUsage() const + { return usage; } + + /// Increment the put pointer, returns true when successful. + bool Produce() + { + if (usage == buffer.GetCount()) + return false; + + put = (put + 1) % buffer.GetCount(); + usage++; + + return true; + } + /// Increment the get pointer, returns true when successful. + bool Consume() + { + if (usage == 0) + return false; + + get = (get + 1) % buffer.GetCount(); + usage--; + + return true; + } + + /// Retrieve the object at the current get pointer. + T &CurrentGet() + { return buffer[get]; } + /// Retrieve the object at the current put pointer. + T &CurrentPut() + { return buffer[put]; } + + bool Allocate(uint count) + { + put = get = usage = 0; + return buffer.Allocate(count); + } + + RingBuffer() : put(0), get(0), usage(0) {} +}; + +} // GS + + +#endif // __NRINGBUFFER__ diff --git a/include/platform/memory/singleton.h b/include/platform/memory/singleton.h new file mode 100644 index 0000000..4e324b8 --- /dev/null +++ b/include/platform/memory/singleton.h @@ -0,0 +1,28 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SINGLETON__ +#define __SINGLETON__ + + +namespace GS { + +template class Singleton +{ +static T *i; + +public: + +static T &Get() { return *i; } +static void Set(T *s) { i = s; } +static void Free() { delete i; i = nullptr; } + +}; + +} + + +#endif // __SINGLETON__ diff --git a/include/platform/messaging/messaging.h b/include/platform/messaging/messaging.h new file mode 100644 index 0000000..274bdb2 --- /dev/null +++ b/include/platform/messaging/messaging.h @@ -0,0 +1,48 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __MESSAGING__ +#define __MESSAGING__ + + + #include "container/nlist.h" + + +namespace GS { + namespace Messaging { + +/*! + @short Low-level message broadcasting system. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +template class Broadcaster +{ +protected: + + /// Message listener list. + List listener_list; + +public: + + bool RegisterMessageListener(Listener *listener) + { return listener_list.Add(listener) ? true : false; } + bool UnregisterMessageListener(Listener *listener) + { return listener_list.Remove(listener); } + +virtual void BroadcastMessage(const Message &msg, const From &from, const Parm &parm) + { + ListForeachPtr(Listener *, listener, listener_list) + listener->ProcessMessage(msg, from, parm); + } + +virtual ~Broadcaster() {} +}; + + } // Messaging +} // GS + + +#endif // __MESSAGING__ \ No newline at end of file diff --git a/include/platform/nconfig.h b/include/platform/nconfig.h new file mode 100644 index 0000000..c124a8d --- /dev/null +++ b/include/platform/nconfig.h @@ -0,0 +1,73 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __GSCONFIG__ +#define __GSCONFIG__ + + + /// Define to disable all debug/tracking code. +#ifndef __ENGINE_RETAIL__ +#define __ENGINE_RETAIL__ 0 +#endif + + +//------------------------------------------------------------------------------ +// Engine configuration. +//------------------------------------------------------------------------------ + /// Enable logging system support. +#define __PLATFORM_LOG_SUPPORT__ 1 + + /*! + @short Maximum UV channel count. + This value has no limitation, however try to keep it in a reasonable + range to avoid wasting memory and preserve compatibility. + @note The lowest acceptable value is 1. (Default: 3) + */ +#define __UV_PER_GEOMETRY__ 3 + /*! + @short Bone/vertex limit. + */ +#define __PV_BONE_LIMIT__ 4 + /*! + @short Bone/list limit. + */ +#define __PL_BONE_LIMIT__ 48 +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Debug configuration. +//------------------------------------------------------------------------------ +#if __ENGINE_RETAIL__ + + /* + Deactivate unneeded subsystems for a retail build. + */ +#undef __PLATFORM_LOG_SUPPORT__ +#define __PLATFORM_LOG_SUPPORT__ 0 + +#else // __ENGINE_RETAIL__ + + /*! + @short Define to enable per allocation statistics. + @note All allocations are inflated by a monitoring header. + The allocators are adapted to fit the increased allocations + so that their behavior will not change. + @note A 2 bytes long magic word is added to the end of each allocation + and checked for overrun on release. + */ +#define __ENABLE_ALLOCATION_STAT__ 0 + /// Define to enable end of allocation overwrite detection. +#define __ENABLE_ALLOCATION_GUARD__ 0 + + /// Enable the small block allocator system (ialloc.cpp). +#define __ENABLE_GLOBAL_SBA__ 0 + +#endif // __ENGINE_RETAIL__ +//------------------------------------------------------------------------------ + + +#endif // __GSCONFIG__ \ No newline at end of file diff --git a/include/platform/network/network_interface.h b/include/platform/network/network_interface.h new file mode 100644 index 0000000..ca49902 --- /dev/null +++ b/include/platform/network/network_interface.h @@ -0,0 +1,74 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NETWORK_INTERFACE__ +#define __NETWORK_INTERFACE__ + + + #include "container/narray.h" + #include "ntypes.h" + + +namespace GS { + class String; + namespace Network { + +// +struct INetwork +{ +enum Timeout +{ + TimeoutDefault = 0, + TimeoutLong, + TimeoutVeryLong +}; + +virtual bool SendString(void *peer, const String &); +virtual bool BroadcastString(const String &); + +struct Statistics +{ + size_t sent_data; + size_t received_data; +}; + +virtual void GetStatistics(Statistics &) = 0; +virtual int GetPeerPacketLossRatio(void *peer) = 0; + +virtual void OnPeerConnection(void *peer) = 0; +virtual void OnPacketReceived(void *peer, const void *data, size_t size) = 0; +virtual void OnConnectionClosed(void *peer) = 0; + +/*! + @name Communication interface. + @{ +*/ +virtual void UpdateHost() = 0; + +virtual bool Send(void *peer, const void *data, size_t size) = 0; +virtual bool Broadcast(const void *data, size_t size) = 0; +/// @} + +virtual bool IsOpen() const = 0; + +virtual bool GetHostAddress(String &address) = 0; +virtual bool GetPeerAddress(void *peer, String &address) = 0; +virtual void SetPeerTimeout(void *peer, Timeout = TimeoutDefault) = 0; + +virtual bool OpenServer(const char *address, int port) = 0; +virtual bool OpenClient(const char *address, int port) = 0; +virtual void Disconnect(void *peer) = 0; + +virtual void Close() = 0; + +virtual ~INetwork() {} +}; + + } // Network +} // GS + + +#endif // __NETWORK_INTERFACE__ diff --git a/include/platform/nstring/nstring.h b/include/platform/nstring/nstring.h new file mode 100644 index 0000000..484cd51 --- /dev/null +++ b/include/platform/nstring/nstring.h @@ -0,0 +1,310 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSTRING__ +#define __NSTRING__ + + + #include + #include "container/narray.h" + +namespace GS { + template class List; + template class Array; + +/*! + @short String class. + Strings are internally stored as UTF-8. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class String + { + Array _p; + + mutable uint hash; + int len; + + void Touch(); + +public: + +enum CaseSensitivity +{ + CaseSensitive = 0, + CaseInsensitive +}; + +enum EOLConvention +{ + EOLUnix = 0, + EOLWindows +}; + + /*! + @short Compare string object with a C string + Optionally accept a hash value for the input string. + @return True if strings match. + */ + bool equals(const char *s, const uint hash = 0) const; + + bool operator == (const String &) const; + bool operator != (const String &) const; + bool operator == (const char *) const; + bool operator != (const char *) const; + + /// Format a string. +static String Format(const char *format, ...); + + String operator + (const char *) const; + String operator + (const String &) const; + + void operator += (const char *); + void operator += (const String &); + void operator += (float); + void operator += (double); + void operator += (int); + void operator += (uint); + void operator += (bool); + + String &operator = (const String &); + String &operator = (const char *); + + void Set(const char *s, const char *e = 0); + + String &operator << (const String &); + String &operator << (const char *); + String &operator << (float); + String &operator << (double); + String &operator << (int); + String &operator << (uint); + String &operator << (bool); + + /// String hash value. + uint Hash() const; + /// String length. + uint Len() const; + /// String size in bytes. + size_t Size() const; + + /// Is empty. +inline bool IsEmpty() const { return (!_p || !len) ? true : false; } + + /// Normalize the string end of line. + void NormalizeEOL(EOLConvention = EOLUnix); + /// Return a normalized version of this string. + String NormalizedEOL(EOLConvention = EOLUnix) const; + +/*! + @name File system tool set. + @{ +*/ + /// Is absolute path. + bool IsAbsolutePath() const; + + String BeautifyFileName(bool allow_spaces = true) const; + + String CleanFilePath() const; + + String CutFilePath() const; + String CutFileName() const; + String CutFileExtension() const; + + String GetFilePath() const; + String GetFileName() const; + String GetFileNameAndExtension() const; + String GetFileExtension() const; + + /// Return this filename with another file extension. + String GetSwappedExtension(const char *) const; + + void FileCutPath(); + void FileSwapExtension(const char *); + void FileCutPathAndExtension(); + void FileCutExtension(); + void FileCutName(); + + /// Get extension. +static String FileGetExtension(const char *path); + /// Convert backslash to slash, merge redundant slash. + bool FileCleanName(); +/// @} + + /// Return as utf-8 ASCII C string. +inline operator const char *() const { return _p; } + /// Return as utf-8 ASCII C string. +inline const char *c_str() const { return _p; } +inline char *str() const { return _p; } + /// Return a pointer to the end of the string. +inline const char *eos() const { return _p + Len(); } +/*! + @name Unicode tool set. + @{ +*/ + /// Convert an utf-8 character to utf-32, returns the number of consumed bytes. +static size_t Utf8toUtf32(const uchar *utf8, uint *utf32); + /// Get utf-8 character size in byte. +static size_t GetUtf8CharSize(const uchar *utf8); + + /// Create a string from a UCS-2 buffer. +static String FromUcs2(const ushort *); + + /// Return as utf-8 +inline const char *toUtf8() const { return _p; } + /// Return string as UCS-2 (utf-16 compatible up to code point 0xffff). + Array toUcs2() const; + /// Return string as utf-32. + Array toUtf32() const; +/// @} + + /// Remove all occurrences of a given character from the string. + String TrimChar(char); + + /// ASCII to float. +inline float Float(bool support_comma = true) const { return atof(_p, _p + Len(), support_comma); } + /// ASCII to integer. +inline int Integer() const { return atoi(_p); } + /// ASCII header less, 0x or h prefixed hexadecimal to integer. +inline int Hex() const { return atoh(_p); } + + /// Split string against a separator string. + template uint Split(const char *separator, C &container, const char skip = 0) const + { + const char *s = c_str(); + if (!s) + return 0; + size_t ls = strlen(separator); + + for (const char *n = s; s[0]; s = n) + { + // Check the skip char. + if (skip && (n[0] == skip)) + for (++n; n[0] && (n[0] != skip); ++n) + ; + + // Seek the next separator occurrence. + while (n[0] && (strncmp(n, separator, ls) != 0)) + ++n; + + // Append sub-string. + if (skip) + container.Add(String(s, n).TrimChar(skip)); + else + container.Add(String(s, n)); + + if (!n[0]) + break; + + n += ls; + } + return container.GetCount(); + } + /// Get a slice of the string starting at s ending at e. + String Slice(uint s, uint e) const; + + bool Compare(const char *, CaseSensitivity = CaseSensitive) const; + + /// Test if the string starts with another string. + bool StartsWith(const char *, CaseSensitivity = CaseSensitive) const; + /// Test if the string ends with another string. + bool EndsWith(const char *, CaseSensitivity = CaseSensitive) const; + /// Test if the string contains another string. + bool Contains(const char *, CaseSensitivity = CaseSensitive) const; + + String Upper() const; + String Lower() const; + + /// Get the n leftmost characters from the string. + String Left(uint n) const; + /// Get the n rightmost characters from the string. + String Right(uint n) const; + /// Get 'n' characters starting at p from the string. + String Mid(uint p, int n = -1) const; + + /// Return the index of a specific character in string, starting at p. + size_t IndexOf(char c, uint p = 0) const; + + /// Return the address of a substring in string, starting at p. + char *FindString(const char *c, uint p = 0, CaseSensitivity = CaseSensitive) const; + + bool Replace(const char *what, const char *by, CaseSensitivity cs = CaseSensitive); + bool ReplaceAll(const char *what, const char *by, bool match_whole_word = false); + bool ReplaceAll(const char **what, const char **by, bool match_whole_word = false); + +static const char *LocatePattern(const char *s, const char *format, const char **e = 0); + bool Extract(const char *format, List &arg); + +typedef String RewriteFunc(const char *pattern, List &arg); +static String RewritePatternAll(const char *p, const char *pattern, RewriteFunc &rewrite_func); + +/*! + @short C string library. + @{ +*/ + /// Compare two strings, returns -1 if b < a, 0 if a == b, 1 if b > a. +static int Compare(const String &a, const String &b); + + /*! + @short Returns the address where a given character can be found. + + Returns the address where a given character can be found inside the + memory block starting at 'from' and ending at 'to'. + */ +static char *strfindchar(const char *from, const char c, const char *to = 0); + + /*! + @short Compare the shortest C string with the other C string. + Returns false if matching. (eg: 'fore' and 'foremost' do match). + */ +static bool strccmp(const char *, const char *); + /// Compute string hash value. +static uint strhash(const char *); + /// Compute string length. +static size_t strlen(const char *); + + /// Remove path. +static void rmpath(char *); + /// Remove extension. +static void rmext(char *); + /// Remove path and extension. +static void rmpathext(char *); + /// Remove filename. +static void rmname(char *); + + /// Integer to ASCII. +static char *itoa(int); + + /// ASCII to float. +static float atof(const char *s, const char *e = 0, bool support_comma = true); + /// ASCII to integer. +static int atoi(const char *s); + /// ASCII header-less, 0x or h prefixed hexadecimal to integer. +static int atoh(const char *s); + + +/// @} + + //------------------------------------------------------------------- + /*! + @short Reserve space on the string for a number of characters. + @note An extra byte will be allocated to store the string terminator. + */ + bool Allocate(uint size); + void Clear(); + + String(const char *s) : _p(Alloc::StringBuffer) { Clear(); *this = s; } + String(const String &b) : _p(Alloc::StringBuffer) { Clear(); *this = b.c_str(); } + String(const char *s, const char *e) : _p(Alloc::StringBuffer) { Clear(); Set(s, e); } + String(const char *s, size_t l) : _p(Alloc::StringBuffer) { Clear(); Set(s, s + l); } + String() : _p(Alloc::StringBuffer) { Clear(); } + ~String() { Clear(); } +}; + +typedef List StringList; + +} // GS + + +#endif // __NSTRING__ diff --git a/include/platform/ntypes.h b/include/platform/ntypes.h new file mode 100644 index 0000000..ab70ab8 --- /dev/null +++ b/include/platform/ntypes.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + +#define _CRTDBG_MAP_ALLOC +#include +#include + +#ifndef __NTYPES__ +#define __NTYPES__ + + + #include "nconfig.h" + #if __PLATFORM_ANDROID_NDK__ || __PLATFORM_IOS__ || __PLATFORM_POSIX__ + #include + #include + #endif + + /*! + @short __float32 is expected to be 4 byte float. + Platform with no such type will need to port code dependent on this type. + */ +typedef float __float32; + +typedef unsigned char uchar; +typedef signed char schar; +typedef unsigned short ushort; +typedef unsigned int uint; +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +namespace GS { + namespace Types { + +template T inline Abs(T v) { return v < 0 ? -v : v; } + +template T inline Min(T a, T b) { return a < b ? a : b; } +template T inline Max(T a, T b) { return a > b ? a : b; } + +template T inline Clamp(T v, T min = 0, T max = 1) { return v < min ? min : (v > max ? max : v); } + +template T inline Wrap(T v, T range_start, T range_end) +{ + const T dt = range_end - range_start + 1; + + while (v < range_start) + v += dt; + while (v > range_end) + v -= dt; + + return v; +} + +template void inline swap(T &a, T&b) { T t = b; b = a; a = t; } + +uint getPOT(uint v); +bool isPOT(uint v); + + } // Types +} // GS +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +#if defined(__PLATFORM_WINDOWS__) + #define GSEXPORT __declspec(dllexport) + #define GSRESTRICT __restrict +#else + #define GSRESTRICT +#endif +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Helper macros. +//------------------------------------------------------------------------------ +#if __PLATFORM_LOG_SUPPORT__ + #define __ERR__(err_exp, ret_exp) { (err_exp); return (ret_exp); } + #define __ERRRAW__(err_exp) { (err_exp); return; } +#else + #define __ERR__(err_exp, ret_exp) { return (ret_exp); } + #define __ERRRAW__(err_exp) { return; } +#endif + +#define nUnused(__P__) + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef forever +#define forever for(;;) +#endif +#define asbool(v) ((v) ? true : false) + +template inline bool _cached_value_test_and_synch(T &cached, const T &value) +{ bool r = cached != value; cached = value; return r; } +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Disable unwanted warnings. +//------------------------------------------------------------------------------ +#if _MSC_VER +// int to float. +#pragma warning(disable : 4100) +// CRT. +#pragma warning(disable : 4996) +// empty controlled statement found. +#pragma warning(disable : 4390) +#endif +//------------------------------------------------------------------------------ + + +#endif // __NTYPES__ diff --git a/include/platform/platform.h b/include/platform/platform.h new file mode 100644 index 0000000..e560894 --- /dev/null +++ b/include/platform/platform.h @@ -0,0 +1,128 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __PLATFORM__ +#define __PLATFORM__ + + + #include "memory/nauto_ptr.h" + #include "memory/singleton.h" + #include "filesystem/filesystem.h" + #include "input/input_system.h" + #include "async/job.h" + #include "signal/signal.h" + #include "licensing/licensing.h" + #include "analytics/analytics.h" + #include "billing/billing.h" + #include "time/ntime.h" + + +namespace GS { + struct ISharedLib; + +/*! + @short Platform interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class Platform : public Singleton +{ + bool initialized; + +public: + + /// Initialize platform. +virtual void Initialize(); + + AutoPtr job_manager; + AutoPtr io; + AutoPtr billing; + AutoPtr analytics; + AutoPtr licensing; + AutoPtr input_system; + + // Platform signals. +struct Signals +{ + Signal renderer_output_closed; +}; + + Signals signal; + + /// Return the platform name. +virtual String GetName() const = 0; + /// Return the device name the platform is running on. +virtual String GetDeviceName() const = 0; + + /// Get the platform locale as an ISO3166 code. +virtual String GetLocale() = 0; + + /// Return the number of logical thread available. +virtual int GetSystemThreadCount() { return 1; } + /// Return the number of physical processor core available. +virtual int GetSystemCoreCount() { return 1; } + + /// Open a given URL using the platform integrated browser. +virtual bool OpenURL(const char *) { return false; } + /// Open the application page. +virtual bool OpenAppPage() { return false; } + + /// Send to background. +virtual bool SendToBackground(bool kill = false) { return false; } + + /// Return the current user directory. +virtual bool GetUserDir(String &, const char *user = 0) { return false; } + + /// Output a program trace to the platform log. +virtual void Trace(const char *trace, const char *source, int line); + +/*! + @name Application + @{ +*/ +static String app_dir; + +virtual String GetAppPluginPath(const char *) const; +/// @} + +/*! + @name Timer subsystem. + @{ +*/ + /// Get the platform clock. +virtual Time GetTime() = 0; + + /// Return the system clock frequency. +virtual int GetClockFrequency() = 0; + /// Return the current clock. +virtual int GetClock() = 0; + /// Sleep platform for 'n' milliseconds. +virtual void Sleep(uint ms) = 0; + + int GetStartClock() const; + Time GetStartTime() const; + + /// System clock unit macros. + int GetSecond(int t) { return t * GetClockFrequency(); } + int GetMinute(int t) { return t * 60 * GetClockFrequency(); } +/// @} + + /// Load a shared library. +virtual ISharedLib *LoadSharedLibrary(const char *) { return 0; } + + Platform(); +virtual ~Platform() {} +}; + +} // GS + +#ifdef _DEBUG +#define __NTRACE(T) { GS::Platform::Get().Trace(T, __FILE__, __LINE__); } +#else +#define __NTRACE(T) ; +#endif + + +#endif // __PLATFORM__ diff --git a/include/platform/platform_config.h b/include/platform/platform_config.h new file mode 100644 index 0000000..9b72d9d --- /dev/null +++ b/include/platform/platform_config.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __KERNEL_CONFIG__ +#define __KERNEL_CONFIG__ + + + #include "assert/nassert.h" + + +#if __PLATFORM_WINDOWS__ + + #define strupr _strupr + #define strlwr _strlwr + +#elif __PLATFORM_POSIX__ + + #include + #include + + #define _snprintf snprintf + +#elif __PLATFORM_NINTENDO_WII__ + + #include + + using namespace std; + #define _snprintf snprintf + +#elif SN_TARGET_PS3 + + #define _snprintf snprintf + +#endif + + +#endif // __KERNEL_CONFIG__ diff --git a/include/platform/rand/rand.h b/include/platform/rand/rand.h new file mode 100644 index 0000000..20c3503 --- /dev/null +++ b/include/platform/rand/rand.h @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NRAND__ +#define __NRAND__ + + + #include "ntypes.h" + + +namespace GS { + namespace Random { + +#ifndef RAND_MAX +#define RAND_MAX 0x7fff +#endif + +/*! + @short A random number generator class. + + @note The maximum precision of this generator is fixed to 16bit integer. + This means that you cannot get, even with floats, more than 65536 + different values. But this generator has, of course, no query + limit. + + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +/// Set the starting seed of the random number generator. +void Seed(uint s); +/// Return an integer random number in the range [0;r] (default [0;RAND_MAX]. +uint Rand(uint r = RAND_MAX); +/// Return a float random value in the range [0;r] (default [0;1]). +float FRand(float r = 1.0f); +/// Return a float random value un the range [lo, hi] (default [-1, 1]). +float FRRand(float lo = -1, float hi = 1); +/*! + @short Pseudo-unique random number generator. + + A random number generator that tries to feed a different number + than what was returned at the previous call. + This class is a wrapper for Rand(). + + @note The number 'might' still be the same. +*/ +uint CRand(uint r = RAND_MAX); + + } // Random +} // GS + + +#endif // __NRAND__ + diff --git a/include/platform/reflection/c_refl.h b/include/platform/reflection/c_refl.h new file mode 100644 index 0000000..5ad7e8b --- /dev/null +++ b/include/platform/reflection/c_refl.h @@ -0,0 +1,44 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2011 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NREFL_OBJECT__ +#define __NREFL_OBJECT__ + + + #include + #include "reflection/nenum_string.h" + + +namespace GS { + namespace Reflection { + +struct Property +{ + enum PropType + { + InvalidProp, + BoolProp, + CharProp, + ShortProp, + IntProp, + FloatProp, + StringProp, + EnumProp + }; + + PropType type; + + const char *name; + size_t offset_of; + + Enum::Dict *enum_dict; +}; + + } // Reflection +} // GS + + +#endif // __NREFL_OBJECT__ diff --git a/include/platform/reflection/nenum_string.h b/include/platform/reflection/nenum_string.h new file mode 100644 index 0000000..d3b8abf --- /dev/null +++ b/include/platform/reflection/nenum_string.h @@ -0,0 +1,30 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NENUM_STRING__ +#define __NENUM_STRING__ + + +namespace GS { + namespace Reflection { + +struct Enum +{ +struct Dict +{ + int enum_v; + const char *string_v; +}; + +static const char *toString(int, Dict *); +static int fromString(const char *, Dict *); +}; + + } // Reflection +} // GS + + +#endif // __NENUM_STRING__ diff --git a/include/platform/shared/shared_library.h b/include/platform/shared/shared_library.h new file mode 100644 index 0000000..de5c327 --- /dev/null +++ b/include/platform/shared/shared_library.h @@ -0,0 +1,32 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSHAREDLIB__ +#define __NSHAREDLIB__ + +#define _CRTDBG_MAP_ALLOC +#include +#include + + +namespace GS { + +/*! + @short Shared library interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct ISharedLib +{ + /// Lookup for a function exported by the shared library. +virtual void *GetFunctionPointer(const char *s) = 0; + +virtual ~ISharedLib() {} +}; + +} // GS + + +#endif // __NSHAREDLIB__ diff --git a/include/platform/signal/signal.h b/include/platform/signal/signal.h new file mode 100644 index 0000000..fdbfb70 --- /dev/null +++ b/include/platform/signal/signal.h @@ -0,0 +1,175 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __SIGNAL__ +#define __SIGNAL__ + + + #include "container/nlist.h" + + +namespace GS { + +// +template class Signal +{ + /// Base signal listener. + struct IListener + { + virtual void Call(T) = 0; + + virtual bool BelongsToInstance(void *) const = 0; + virtual bool IsFunction(void (*)(T)) const = 0; + + virtual ~IListener() {} + }; + + AutoList listeners; + + /// Pointer to member listener. + template struct InstanceListener : public IListener + { + O *i; + void (O::*f)(T1); + + void Call(T1 t) { (i->*f)(t); } + + bool BelongsToInstance(void *p) const { return asbool(p == (void *)i); } + bool IsFunction(void (*)(T1)) const { return false; } + + InstanceListener(O *_i, void (O::*_f)(T1)) : i(_i), f(_f) {} + }; + + /// Global/static function listener. + template struct FunctionListener : public IListener + { + void (*f)(T1); + + void Call(T1 t) { (*f)(t); } + + bool BelongsToInstance(void *) const { return false; } + bool IsFunction(void (*_f)(T1)) const { return f == _f; } + + FunctionListener(void (*_f)(T1)) : f(_f) {} + }; + +public: + + /// Return the number of listener on this signal. + uint GetListenerCount() const { return listeners.GetCount(); } + + /// Subscribe an instance member function to call when the event is triggered. + template void Connect(O *i, void (O::*f)(T)) + { listeners.Add(new InstanceListener (i, f)); } + /// Remove the subscription of all handlers associated with a specific class instance. + template void Disconnect(O *i) + { + ListForeachPtr(IListener *, l, this->listeners) + if (l->BelongsToInstance((void *)i)) + listeners.Remove(l); + } + + /// Subscribe a function to call when the event is triggered. + void Connect(void (*f)(T)) + { listeners.Add(new FunctionListener (f)); } + /// Remove a function subscription. + void Disconnect(void (*f)(T)) + { + ListForeachPtr(IListener *, l, this->listeners) + if (l->IsFunction(f)) + listeners.Remove(l); + } + + /// Emit the signal, notifies all listeners. + void Emit(T t) const + { + ListForeachPtr(IListener *, l, listeners) + l->Call(t); + } +}; + +// Specialization for void type. Note: I gave up on factoring code => compiler vendor/extension hell. +template <> class Signal +{ + /// Base signal listener. + struct IListener + { + virtual void Call() = 0; + + virtual bool BelongsToInstance(void *) const = 0; + virtual bool IsFunction(void (*)()) const = 0; + + virtual ~IListener() {} + }; + + AutoList listeners; + + /// Pointer to member listener. + template struct InstanceListener : public IListener + { + O *i; + void (O::*f)(); + + void Call() { (i->*f)(); } + + bool BelongsToInstance(void *p) const { return asbool(p == (void *)i); } + bool IsFunction(void (*)()) const { return false; } + + InstanceListener(O *_i, void (O::*_f)()) : i(_i), f(_f) {} + }; + + /// Global/static function listener. + struct FunctionListener : public IListener + { + void (*f)(); + + void Call() { (*f)(); } + + bool BelongsToInstance(void *) const { return false; } + bool IsFunction(void (*_f)()) const { return f == _f; } + + FunctionListener(void (*_f)()) : f(_f) {} + }; + +public: + + /// Return the number of listener on this signal. + uint GetListenerCount() const { return listeners.GetCount(); } + + /// Subscribe an instance member function to call when the event is triggered. + template void Connect(O *i, void (O::*f)()) + { listeners.Add(new InstanceListener (i, f)); } + /// Remove the subscription of all handlers associated with a specific class instance. + template void Disconnect(O *i) + { + ListForeachPtr(IListener *, l, listeners) + if (l->BelongsToInstance((void *)i)) + listeners.Remove(l); + } + + /// Subscribe a function to call when the event is triggered. + void Connect(void (*f)()) + { listeners.Add(new FunctionListener(f)); } + /// Remove a function subscription. + void Disconnect(void (*f)()) + { + ListForeachPtr(IListener *, l, listeners) + if (l->IsFunction(f)) + listeners.Remove(l); + } + + /// Emit the signal, notifies all listeners. + void Emit() const + { + ListForeachPtr(IListener *, l, listeners) + l->Call(); + } +}; + +} // GS + + +#endif // __SIGNAL__ diff --git a/include/platform/social/social.h b/include/platform/social/social.h new file mode 100644 index 0000000..49e2712 --- /dev/null +++ b/include/platform/social/social.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NSOCIAL__ +#define __NSOCIAL__ + + +namespace GS { + namespace Social { + +struct Account +{ + String login; + + String first, middle, last; + String email; + + String address, phone; +}; + +/*! + @short Social system abstract interface. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +struct ISocial +{ +virtual bool Login(const char *login, const char *key) = 0; +virtual bool Logout() = 0; +}; + + } // Social +} // GS + + +#endif // __NSOCIAL__ diff --git a/include/platform/thread/atomic_value.h b/include/platform/thread/atomic_value.h new file mode 100644 index 0000000..e21167b --- /dev/null +++ b/include/platform/thread/atomic_value.h @@ -0,0 +1,49 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __ATOMIC_VALUE__ +#define __ATOMIC_VALUE__ + + +namespace GS { + namespace Threading { + +/*! + @short 32bit atomic value. + @author Emmanuel Julien (ejulien@owloh.com) +*/ +class Atomic32 +{ + void *v; + +public: + + /// Perform atomic increment, return the new value. + int Inc(); + /// Perform atomic decrement, return the new value. + int Dec(); + + /// Return the current value. + int Get() const; + /// Set new value, return the initial value. + int Set(int); + + /*! + @short Perform an atomic compare and swap operation. + Compare the current value with the comparand, if they match set the + new value. Return the initial value. + */ + int Cas(int comparand, int value); + + explicit Atomic32(int value = 0); + ~Atomic32(); +}; + + } // Threading +} // GS + + +#endif // __ATOMIC_VALUE__ diff --git a/include/platform/thread/mutex.h b/include/platform/thread/mutex.h new file mode 100644 index 0000000..5523c44 --- /dev/null +++ b/include/platform/thread/mutex.h @@ -0,0 +1,90 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NMUTEX__ +#define __NMUTEX__ + + +#if __PLATFORM_POSIX__ + #include + #include +#elif __PLATFORM_NINTENDO_WII__ + #include +#endif + #include "ntypes.h" + + +namespace GS { + namespace Threading { + +/// Portable mutex class. +class Mutex +{ +protected: + +#if __PLATFORM_POSIX__ + pthread_mutex_t mutex; +#elif __PLATFORM_WINDOWS__ + void *mutex; +#elif __PLATFORM_NINTENDO_WII__ + OSMutex mutex; +#endif + +public: + + void Lock(); + bool TryLock(); + void Unlock(); + + Mutex(); + ~Mutex(); +}; + +/// Mutex helper class. +class MutexLock +{ +protected: + + Mutex *mutex; + +public: + + bool HasLock() const + { return asbool(mutex); } + + void Lock(Mutex *m, bool try_only) + { + Unlock(); + + if (try_only) + { + if (m && m->TryLock()) + mutex = m; + } + else + { + if (m) + (mutex = m)->Lock(); + } + } + void Unlock() + { + if (mutex) + mutex->Unlock(); + mutex = 0; + } + + MutexLock(Mutex *m, bool try_only = false) : mutex(0) + { Lock(m, try_only); } + ~MutexLock() + { Unlock(); } +}; + + } // Threading +} // GS + + +#endif // __NMUTEX__ diff --git a/include/platform/thread/thread.h b/include/platform/thread/thread.h new file mode 100644 index 0000000..560f29c --- /dev/null +++ b/include/platform/thread/thread.h @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NTHREAD__ +#define __NTHREAD__ + + + #include "thread/atomic_value.h" + + +namespace GS { + namespace Threading { + +/* + @short Thread abstraction class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +struct Thread +{ + void *handle; + +virtual bool Start(); + + void Kill(); + void Join(); + +static void SetName(const char *); + // Yield execution to the next running system thread. +static void Switch(); + + /* + @short Set thread priority. + + Set the thread priority from 0 to 31. + 0 is the highest priority, 31 is the lowest. + + @return False is the required priority was invalid. + */ + bool SetPriority(int priority = 16); + + /// Main thread execution function. +virtual void Execute() = 0; + + Thread(); +virtual ~Thread(); +}; + + } // Threading +} // GS + + +#endif // __NTHREAD__ diff --git a/include/platform/thread/thread_controller.h b/include/platform/thread/thread_controller.h new file mode 100644 index 0000000..36ef930 --- /dev/null +++ b/include/platform/thread/thread_controller.h @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __THREAD_CONTROLLER__ +#define __THREAD_CONTROLLER__ + + + #include "thread/atomic_value.h" + #include "thread/thread_event.h" + #include "thread/future.h" + #include "thread/thread.h" + #include "thread/mutex.h" + #include "container/nlist.h" + + +namespace GS { + namespace Threading { + +//------------------------------------------------------------------------------ +template struct DefaultControllerPolicy +{ +static const bool use_event = true; // use thread event to sleep the worker thread +static const bool own_target = false; // the controller owns the target object and is responsible for deleting it + +static void Update(Target *) {} +}; + +template > class Controller +{ +public: + +struct Command +{ + Atomic32 dispose; +virtual void Execute(Target *target) = 0; + + Command() : dispose(1) {} +virtual ~Command() {} +}; + +template struct CommandWithResult : public Command +{ + Future future_result; + CommandWithResult() { this->dispose.Set(0); } +}; + +private: + +struct WorkerThread : public Thread +{ + Target *target; + + Atomic32 running; + + Mutex command_mutex; + Event command_event; + + AutoList command_queue; + + void Execute() + { + forever + { + Policy::Update(target); + { + MutexLock lock(&command_mutex); + while (command_queue.GetCount() > 0) + { + command_queue[0]->Execute(target); + while (command_queue[0]->dispose.Get() != 1) + ; // spin lock on command dispose flag + command_queue.RemoveAt(0); + } + if (running.Get() != 1) + break; + } + if (Policy::use_event) + command_event.Wait(); + } + running.Set(0); + } + void Stop() + { + running.Set(2); + if (Policy::use_event) + command_event.Trigger(); + while (running.Get() != 0); // spinlock + } + + WorkerThread(Target *t) : target(t), running(1) {} + ~WorkerThread() + { + if (Policy::own_target) + delete target; + } +}; + + WorkerThread worker; + +public: + + void QueueCommand(Command *c) + { + { + MutexLock lock(&worker.command_mutex); + worker.command_queue.Append(c); + } + worker.command_event.Trigger(); + } + template Result QueueCommand(CommandWithResult *c) + { + QueueCommand((Command *)c); + + Result result = c->future_result.Get(); // wait for command result + c->dispose.Set(1); // flag command disposal + return result; // return result + } + + bool Start() + { return worker.Start(); } + void Stop() + { worker.Stop(); } + + Controller(Target *t) : worker(t) {} +}; +//------------------------------------------------------------------------------ + + } // Threading +} // GS + + +#endif // __THREAD_CONTROLLER__ diff --git a/include/platform/thread/thread_event.h b/include/platform/thread/thread_event.h new file mode 100644 index 0000000..4bfc394 --- /dev/null +++ b/include/platform/thread/thread_event.h @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NTHREAD_EVENT__ +#define __NTHREAD_EVENT__ + + + #include "time/ntime.h" + + +namespace GS { + namespace Threading { + +/*! + @short Multi-threaded event. + @author Emmanuel Julien (ejulien@nworks.fr) +*/ +struct Event +{ + void *event; + + /// Thread entering this function will suspend until this event is triggered. + void Wait(Time * = 0); + /// Trigger event. + void Trigger(); + + Event(); + ~Event(); +}; + + } // Threading +} // GS + + +#endif // __NTHREAD_EVENT__ \ No newline at end of file diff --git a/include/platform/time/ntime.h b/include/platform/time/ntime.h new file mode 100644 index 0000000..442c6a4 --- /dev/null +++ b/include/platform/time/ntime.h @@ -0,0 +1,81 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __NTIME__ +#define __NTIME__ + + + #include "nstring/nstring.h" + + +namespace GS { + +/*! + @short Time class. + @author Emmanuel Julien (ejulien@gsworks.fr) +*/ +class Time +{ + int sec, nsec; // second, nanosecond (10^9 -> 1 billionth second) (63+ years loop) + +public: + +static Time Inf; + + void operator += (const Time &); + void operator -= (const Time &); + Time operator + (const Time &) const; + Time operator - (const Time &) const; + +template void operator *= (T k) { sec = int(T(sec) * k); nsec = int(T(nsec) * k); Normalize(); } +template void operator /= (T k) { sec = int(T(sec) / k); nsec = int(T(nsec) / k); Normalize(); } +template Time operator * (T k) const { return Time(int(T(sec) * k), int(T(nsec) * k)); } +template Time operator / (T k) const { return Time(int(T(sec) / k), int(T(nsec) / k)); } + + bool operator > (const Time &) const; + bool operator < (const Time &) const; + bool operator >= (const Time &) const; + bool operator <= (const Time &) const; + bool operator == (const Time &) const; + bool operator != (const Time &) const; + + Time Abs() const; + + int getSec() const { return sec; } + int getNanoSec() const { return nsec; } + + float toDay() const; + float toHour() const; + float toMin() const; + float toSec() const; + float toMs() const; + float toNs() const; + + String toString() const; + + void setSec(float); + void setSec(int); + void setMs(int); + void setNs(int); + +static Time fromSec(float); +static Time fromSec(int); +static Time fromMs(int); +static Time fromNs(int); + + void Normalize(); + Time Normalized() const; + + Time(const int sec, const int nsec); + + explicit Time(const int sec = 0); + explicit Time(const float sec); +}; + +} // GS + + +#endif // __NTIME__ diff --git a/include/platform/time/ntime_range.h b/include/platform/time/ntime_range.h new file mode 100644 index 0000000..7201aed --- /dev/null +++ b/include/platform/time/ntime_range.h @@ -0,0 +1,22 @@ +/* ----------------------------------------------------------------------------- + GSFramework + Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. +----------------------------------------------------------------------------- */ + + +#ifndef __TIMERANGE__ +#define __TIMERANGE__ + + + #include "math/nrange.h" + #include "time/ntime.h" + + +namespace GS { + +typedef Range

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

}O=SQOrZD0O*8DmcRqSFbk5xep#A|sRin| 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ᡴ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 z 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

dis+K~9@y1}t7OJ#?T|9Uzx3Cg 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ΝS1)6_2TmR-u zo-OeG7ItnCkQOni10;Uo-Wk$9c1CpjhF`A7$P!tgTUOBm-N@lbheD!qz+V)Rb@V$g z?n^c#?#o6eJQ01Zr{NCONL16EaTj=}-mg_Q?b zZM4Te^dfYud~~2JCCSn#S+dEJOP0pS(gay5kfkzNnk`EUWNEQ1(QQ5MAH@-uXo-$X zJ0b1I7A??nX)p9~;q1|X15Eb?_FrTB0o#w*e!=z|w*O-L3mdyhftsd~r#&_rcRFLE zCtvzv8-Q&fw!zrwAqN|_Tx|4|CSA`LVx#3^`auDWHZ(5MG8#&pjpw~v-FX(ihD>w} z-4A1n9K1>%Jy;Q+cAIS(nXz)!M4wnHT;?_&UrX5PZLUA-^FYY&DCh>4U%(-V-l4fUEc*qbz@799*YU={}Px^TYA4U9r;b`cA*kLL6J{7 zN@wb)RC3g^{$giIEo%gmsAY|0(g;WwGsz5zM;f&(`pX}@WpUkj=teQ!WEn>->r$qp zmc?;3kS=4oxw7siNXbmMSk^6rWM;aRvTiLTx?K{^ZY^_r8=*^Ky3I0fJ0vU9?UHpL z%hKPeOOXDrN)hmu);z+6{*ba+8Bkr0VbTalywuE)#xh;1tn)z1VY>0MZZf2COjjuD z$|2EXHsL~zteXqz3Z}bB)-8r~CDSdFbt@rV#dK?B-Fiq9m~Nx2+YE`;jPQrCWZf=E zlbG&fStrGCs86cvmOzI}Fvmvv$;_^HmYc_P+TI|Xm2IfpB)!pGX)P?U4=T{fwXJTh zl#7vB%v3p-X-w*YbMDA2l7;Y4MFTzHLA{!Ej-fsyz@c?D9)UiVV?1;`?nXeWVmdRV zY9^&ZqKCD4Z&JggP}U{A(Gs4`tZD0Y4%2DtwVQ4UOSws(MsvMZC)ewAay?r&SEKbh zHy{_P*Yo6h?T2rn5{N2@$S+^e2YNp#L z>o$|bblYX!E=UhB-N&+SKcokl?vSiI2I(QD`%TtS;H+gjx>n+6PFE5SGhGi^7X#@L zrlYwk$I)EuQKqBW2iKV)J;rpYvd#l(9n;bH!*PM}X0-J@!R#nKLl2w@y{sr)sPt7- z<@;hvbG-S!vI_aDJI_~9RFfF+JxTsP##`g7s_+W=Wu=uq?2Ez8FD}cUAygN6XXaLO zYb2MKRrrL`vWk+t;#_vDgqfC9;oQ&c+3 z>hzYCczqSK#&EcU;QjmdsT>&NtH{gu4uGX!jENOH=WS6W);izz9p;U-buWmP`PvY;%69m(_M7b2q+$}pxduM%1j0<8|cs5HN< zq5=^aJKWEyeX9u$^n_f&`B|z zs_p0<6pKneG>g+_HJTP^a5gtM`+s0CFsqq7tC^IQrc5i#sw(p3;?6IVi_2P8N!_fb zV2KT_RHE6s06zK`&GrTi6MO~$z1(RqbNLlsZ)q+@b!pzi+e{3mJ$k_!A2)RBKm;3o zhAkEO&bixA_w>PFtHJK1QVX4K)<33rS@xPi)@(_Mir8-8(G9@!N zri@$HoKlckZbf4lBPE;HjV-OLDyNC0SDJqG6Z%P`IXeYjY&NZAI2#7I30P3mIWUW)+K%lKJCAHZu>8; zx@>51WT&F9Ew9v6eERg9ukIdFxqj91ug|^0TYKZ(&T(;9FE~2S@%||Df_o;uVtMk_ zZqF``?{eh!;vr|hZ_8;>TQKgfj>Edf-d6TlexInnwhZlfDDv~kVF&Me@YT%RSPhyTtKk4xVJ^Eo)!8F}J@gQKP6SC74S(PPJF{_@h`x;^`LJd||l zi6_q6Rl`%d5?5_@0E8vXSWm|k@#-&C0)P!_Q@Be<3ZmG zhhG@^@F%a`HTU*=hdlK7-4d_O@sVGwc;(>(()lIdf8TH8H`m=!@1N80iAwevQ~-p<)K<=D4Y z4v@azBD}VwWaz6ar0;>}72o&09uK}VY4AP!1}zw!WqB{K90SX3_lXr7_TFjozw=ko zuEFK^j=Ma$r0m7c=l788U)}!1$Sa;cr|qP52M@gV>%rxL{^Z;{z_f60()zd7x2@ao z)7 z6YgKp{rcM_`%m9DVs_m ze8jA)x)$bnZts4b$@RnH(WO&vAM^hFjGFZP5560<>b0Bl|Gn9=_QR}456q4Gruxvc z-G98{{5yJ|f0-qG#Eh@joquf2mycErNJ+@Lt90|YU*7m3t^DmT{hhz9&ZrnT`;i%@ zup46DyYF-RWm!M(`C#{pEp}Dx`0dKrZrn})6{s5%(G zbK~bn*1onQ?msWoTz5s%mbq=0Ty%HV#Szm!+B@8qJagCJLr+KS?lN!3qmv%p|NV-k zVO=*~{>{V}dR%p^_j8}c4WIRR=3hTuX8W|_lRi%$@gJJlduQL88&@1yYJci(Tl(l* zf120#tmlsX^6licyWX7Ce#zs$AKTksyv=mDW>42H=WI-RH2)>%(Qng+*3bFjbI0%1 zx4pineCzzBJ)brY`*35z{VCC}pEGg9%B$)Zrd@H*)UM0=-4edE&t*maTf2;Xds+U( z^fh1YY|-cS@5X1R{xGE5$Q5a?W;bH|KTOacNBAZG*>qoVWe7=~1> zVO8?RyE=Cq5HY#OD>rl=aWsEv#QXO@v3ctAIRn0KF=L^-{+EsS-Z$;OH{zbF?0Dy% z+iVH>h4)_FyY<;C)-L(hHu0m!K4`Pxs}Ie`i!)n0g^{Z_?g>vWd$`MkMcc|3bjs?x zYtg|I9ojzl(NFJx{QHp4%umkyIH&&BXZL*3J2C2_%QsbDnX|e>{X1EGK3Tr$&#hm) z-GBU%wbuLvpI$%h`sL66apk1#3y+QZcwd_j&%Sk#+keG`wNK3(v-K9L**Yn!O^vPJWqm@TaiHKmGQcOA4LQ>wfy7Zf)Bec9t&r&+@Ncesh~;J6mPJ-@bIxOrLrLw{O2 zBo>(MSz~QUU3$F!(XqHR*NHnX`nh|*+g9xP^znDQrM2z0cHejJ+}O(U!J;XS$=|LV z`gN^m|H~)-^nMXN`sG36_d32ix}fh9S40-je*H@K_`-kX zr1@{&`0Uba-9J2(nD*IZ(@lRoaB1>PxD z(_*tpiFHC?c505(mpEDoh%G54nXHGI=+Qco9zT2uo_ix6$J9XLx1PdG7mCtzW5(k( zvh>K9+75jWGo6b)d3O86@8U%}+#d&&ShOTe6!wIn)GEjho)-mX9QG}-&CULJa#CcJ!>hq#`QJ5(md$Ran|8He&g6z61bZrlrEQBU+XdO7XY9jFEddx0X?wcY8f>Q{!>q=>6SfV} zd!FbJWQTqT6=tGaQuNE92QGT_=3qNi!iql!ulU&(8DxiY2s62`r*i&v#$$J=?eN&> z%rFx~jPUb2Q-d+|!L zna()OR0=!vki#m^_l3cB=!n)%w;(&Th<>U%rROEJc6tQap`yO-kz$_wi3zgPn_=kDL^`jf4;>jDZ07=v9jf=< zL3UypM)D{7&Yw30+v%gRL;l1D+39P*4&9Jc>Wl334YJdpVd%yXwY2gJmLkBFdgpCt z0K-V<{&=V4SJW6D^A~FJqH`Y*l-ETJvk&H}=I%K3>)K#D)Wa!0Q+vNC$j%^!$-Av4u?N!_1KF4V=Q;z53Bm&QCFvA>2$BPbL_VL{3j-sOt%!{H+>7%}R{P@veOd`Xa2P)OYC+{A)UX9`YBr%K>t5nX3LH^JW z$-_+aUvUhIb9a2&9}B_h&?qo#8=tMlwvpZTVt` zq4TC3D2)uVa|yIzrl+xQi*5CWPN@Dse?~D3MI*&V;iPXnToPpGQid^$=cV6=U&b)% za=tXkPBOzZJf50^>?8--u`o^5 zjX*tL5Vi!{u`!JLysSZX>Oym{Ka&GWG+}$2z$H_1a$6+eN zsQqyU*`ZQV+RnpEGp(VJB$R9Vu%mbC`;^_7-9#q@m{$w)Dm^S!J$dINzZa%5T@U}xeSeR)K_B7JZOYXfO zljVgkEPClv5MtOI7WK)$sx;JJ@FZa@l0s&U7B#J8&GaA)MHNqyoz;>;X1x@o`8-JT z-ylsdlcbU?(}Rta!eq-?qNcU1p$D>fl34EtY3T7GEv6z!^NpzKB3q_c!&B-kYkm+l z{bkKu>Nt=F$eONV*VR|ntQ9rAWldr@XZ4gduZx=VWX(isDoC-i=66vOBWspNaLhC!*$TSu=?S zLZoi8<{MEHDQgO8`j3<-Ykm?n7Fkn6jR&cNtT`!aqGio>G$0^dDr@RR&2U+B4Nd=% z+Q^!dqQ)s}{GB;wsH{1w3)gg#HTQ^`OJq$in(QN`$(qMRO}eZ}q^=feh^%>2)FjB7 zD`@ycijy_pi<&{QW)5`$NN!p4xv0sMHGO+c{9O zW^67hK*RVn0+R-BnQ~>)bVbNlYiM#J+@#iwAk8|pW+Z9eQ)?39@$FNMhGuUVEX2GZ z2tIg7m3SfZkThM-roCG8A~e)g6-+)ZkBHSzX0;HzY(?`BG{jOgE?f)|>jIheC0!nA zG;`16ECq8eCeXw>S7yBk4JAdB7sFYKCcGDC^^sXmKtoB9il)N_oYhNaZG?uB zqA7~yEJbs6AF?V44w>~Rebs1E`f`?n`2-qj;EJZaAO7N-M$;NWLFaChEk6hiB}J1l zfLm5H$DkqBK$$h~LPk<)dR)X=3g!uDh}B+ZnFn%~qWK6Ks#8T%I*7B(GOHdMN{VJF zE>MW2Xa)_&1LDxcGZtcgIK?Wx^%n=w;z&cWTAP|(v1oiMDW3?a<*8V${^=wUwv zLoMzjS%WXaOLP#4=T6dCWKSL{nxoKA?I@aBWJa~4XwF7vF&fR2&`<>_m{ep>=cZ`( zK|^PvXsU6cW7cRo48?olHJUZhQ0<(B98oApLs>te*6f6a&O*WDqvs&jIWp^K)|aR? zemFxc1=AaS39-7%tmjzoqSlPQn6nhjchC?kN@mTbix`cj!zj*DFe{-UR+7vbPM0hi z&2DJOLj`j+I?Nf+q%anuC1Ds!H3qX83$!eL5-1Ypn7D>T3+sDd(`e`lGqQymGZdOD zWDULuE$Gq*iRVSqJ(d5Fl7>(uxH2pQ2x)dHQ3MTswZ=pwaYj;77~Qbc9#D#D?SKccKhwilda_LVP2QQilK1 zXs8UI(`bex4iBpB3_;}xnI@H;A;fx2qoI2(fHlGeRXBEj6*_C zx?Dq2G*3elq0yvgan@xr>mz6=DVpgX&QdggLPKqNgv`3}az;{Vx{l^71+xa4L4dVo zEVSiBs(1Pu&@}aDahOP*)?~GYI#3q9gkh1HNGf_ki^8JVxJj*HJ-{JoWmW>kVWLT` zp*XxjqalCZS8IsGVpXw25k(Jpa}6CIL=6y$pBG6lLPO=OXfja6Q5wx2XsF*%Fhyf| zzoBS;gNDjEm6aF-VQCKS)tZaP@w^nw=g<&qn9Qmf&qyjwk1IG!!EA(v+SVwUMJp1N zxQ6;(YTfg(A=Jcvg9@lzt)U8JcVY;`>WkGNwG>%H)y3L{tYI@)xUFCkh%sH(KoAbX zpXc$J#XO|=NkE0gq9Q2JdHf_Ge|oiutQiuIV_Q&Pq+$NBxdi=H21P@4nyb;!nXc1l z=uD|^QCLHvNkiYFXefT})@Z0W&Tpm0P;oq~(NJ-?(K*R>SkHD)qoLB6(^`!opATs? z(6ceNdUUxrw>6mUBXLkeM_ zmwm9257*tQ(m(%Rwotq7lt0E@vV!;nHaOd*HFHEKKKq1D>q_u~k?q=?&L7*Ysk>iUql zMr{Y(H0+>2*$DLQ*GE6%Yt)4PPGm6*DTM1Wd5*;=*Qo7K=N@LFUM&n;&$C8NtsQ=kp3pU= z+z!K#LTFpYKG-}-8$ak`0_^a66NJAHEIKcSA%!rwoPCHIwLj=|VCNd_+hf~x?VC&a zJuYGQo@7Wu<4q!4CRun$qAwlf(AwDH65Qxm>D zy0sX5PR2&HiFk&F(qwGf^2sBOrk(Qp?@$W~K5mC$NFi*4h7#AP{h{tmTVMPc20~A& z;^)OMq!5lmLy2qDcJiUs`or)25qeHF_lIFfA#|C^KG>?6_PnS?gqc3Yz6Unfz2}$k zdr5?UOk^<(DTK>vcztn=+8^qe6gyiVdJGG}Qh)d^Sd_gP3?NG<0wZre(5x&bDZiiu*fmP5@;u^Ib>X@|k#qVhnIv!z8 zamX;F5T2*NN8%c_9duQ&Lp^zGY_FI*+{d5E!56`PE$#7lXRz@&dPzzULP>#VT!;nHa2@NH#QQJWW7hs3q^Ck51>$x3f1@qVky9U$Rp$;z0G{GdUy`H<~E#>~#Ns+}c%s}Q1ynMJueO~DD z0{r3k?1;7oEUGVtA%*ZAG?Wz0@LH~+eG4J3LSEPwsOtpZu;;xKJy?&vB)Bf zmQ@Z7e=db^<(Zq&7Fv*qbeqT`jFyECPQ`le<9Wjs)&`M97%huBK_#zyzc3$FSf7Y2 z!f094<%OBTv8S|p=J}YUNFM$rvIwJPQ3t26o=+)%USV~cPnNJ=iA~F*?o46*w(WYv zxs+F&$RdoEh3*V28c!$<+|wVeOkz1i7Gbn3>b$~CZHR*O@A0kB9Z4*&$RdoEMO{^x zsS8n%c5JCxs<7Bw@1Z4(mW7T9td7`Ix;^17RF0I_Lt z?IMdXS{8LxVWtj5LArn7>(45z??o12v@GhF!c1+6g7n&*H=^s6JnXoDYYC%eQO6W! zir|NZla7Z`oD%Cokwq9Si#nY!Q&*97#n=7*R9H5VMHnp$oeo%iMb@kSpN}Ogwe97Ls2~3@CB{INayvL$RdoEbpvDd$DY!bxshuWR^*Lb zOBgMSnoyXDdVNX{w@NxoVP%Re!f07kkzuB2q99$fB23l3rim=VXj$ZXn5j2WkPeou zzg5X=naCoHmPH2?4}ZV2{~?97M`Y25mbH+vq`dN9>ky-`eiB)P(Xwu0EUCU;_;Teh z3Tr6AkqDz@ErKS@)Q=7#4UV6Xq_D<_EW&76H$xL<3L^^A4qxs?3hPdhMHns14~wA$!7%i&~8l}f>dsogbg*B9l0f{hL7Ah62 zR&)?)^AqbHR9I6*7Gbn33|CbG~g3>{JnGJrH!WD!Qox(k{xQ%eFN?amKJCnvEsi7disSr|f8 ztlI`YR-~|Yi!8!uS$8wm`Pfr>u8xl%{M)x8i!fT&GH8@Cygy^Ps-;{^!Hz^2Eo(V6 zN^i68z^a!O4}BtwFk03tBr3AA3qi9yw1HhjT<0VYIB3&?x71>+Q2J9gy;RUSttQ%UZ=)=U`7MYsN$A z3hO74MHnsX-_R)M_4caEMk}no)Hxv$M$1|a4Sx!bj^D7U2$KuR!%-rOFk03c#!4Ux z(xk`wT&S>SiY&rtSr0%HW|CNsr;pB8SdWS|TrFk055(C~FpVqJXTtOAAAiG~Fv!f08KK@(=`P6v^OTz3Lp zi&V?$B8xCu);egEi1KIlyIEn)5m|)MvL0tFsR!7b`tK5jb-TzSjFyGwguD{5r}Ulg zepQdXOJos7%UTbO;^7OP6)!4zwYiNf@xPR(WjzV4G8dilMjM2QR2t`tEW&76PchbD z>?zg!UV;LXSh*sLFk05r&?qD9kPq${rLgW6S%lHDHZYdd+ib1LeM4bAA+iXgWj(`K z(u`wA$!7%dAI7%C61%89s4VYQ;cABiwp)^pH=nb15~s-E_%Dx%I6S%lHD zHbTRHZ$-4WcI)#>UK2zXVYIAGj1@r?BwwQIO@(!*$RdoE1=Gl@D^ZXJ_Wbrog|$v( z5k|{;0UBlY)p_{+=#ZpZ-Y2pMqh%rNRIKdq1*$mwU1SkP%fi%C#acXet*Q*W-j0Jv zgwe8If=2Q1vx~xeD;~y+EW&7681liA&g7?Ij(rL%Lu3&~%i64AJw790q{7M-S%lHD zUSTXL4#(XQ*G^&iL>6JRtXCOJ^6=(EKm4w+ZWURC(XzHMR!i(DZG7M*bf}Vz)gp^9 zTGm!*lz!v0S6irR`FW8=7%l5H#tO%t(!0ODG(ySiU6Dl?E$ek?l-bwMBYS%l)?txF z7%giXV?|<5$x(Zksx;2JgKG(+Wud_%uPA<4sNMTwYbCD?kwq9S3!MvCokUij?(I}# z$_*lmFj^KGAy}P7)~)N`o3G^cACW~EEo%p3oh`DCKUv&eVf`Vp2%}}~)UdwuOjh-x zaWwr$B8-;x7BosNuix@!s*=}akwq9S>utvBjXkCPC6k6LtZI=(7%l4^Xq3FpePA!# zk>c>TGno8!c5W(HY2I>0)^G}E*wN6 zjF$BQG)fu1_E+0dg_SC@2%}|v$XMrNPpNbAk7E?pB#}iJE$bs_l)Qf4^dlOsR9}yZ zEW&76A2XIzU;o*DZa0PXipV02mh}l^p%Y}O@9TpvR#@$qaxG!BtUb_#nNV;nefe%A zAd-g{iY&rtS$m;TRsx?$&s(Ih%0w1nw5(4V%Yr?nS(8^*C@jCoB8-;x88phe=taXf z_EcEgMHXSStj`%sIKheZ})v@8r)$V+OK!edw8qOjub#z7>)Xj%KAQToHD zTE5v$VNDZRgwe7NFjgPzDRs?z_z{J5v&bThmh}ZR%9=yLwbwBOc1Sx#7GbokFQHM^ zV6(p8teWYyT1H&_4jh}7br2e5OnG+TdW63m8zPG^TGm&L)dqV?n=bqi6B&s$R%8)I z%laCcFjEZnl;#XQyjo#Zi!8!uS>HgTl*Z_F^Ls0-7ey9fw5&snCAH<){W}ppl865l zS%lHD4l~vT*i%~d#@AkjWnRv;gwe9Tg(l2&9zQIMJ-Z}HVO=k>2%}{kVXVF)tI+(* zXoa;!WD!QoI?7nFBI|>=MOzeBt9!VbFk04kjMYnIz0qUg6AH^CvIwJPea~1J_*weT zGmCmCtYspLFk03R(1e-Ba*{B7@Ui<8*7G8ZFuXQ?7BvLtn%4Ja>%{A`JY=FPu?14Ap>i99x*_Ch0Voj&=jUNKVdmnXhn;_gKcKrFn+g$H$wm zOfX+bdUv3nt8>g(SO|`9xw*NOzJgqzx1yw|G|%S+D3#!7J#jc;5(4SCx61#h#mqLKB^487n44d;xn` z>#6MEB&_@_IGmk@cwVxGY>QUaST5_kh(Iu8niW|#D~W)@RAp+V7apS&)tR$5%r)eJ zJCp}{)_7H&(ha=xx2b#xFlERAyeH3#@F@1sTbY~2k&q_;mP6uuhnv~P()jU1$JpO;g5JsARHY*M z5^U3uOLz-=(*z9+Wr^>vRvR?r1YXjv<}|)yV5refWLHgT8Yf_=(N5q6=1t=S3^m#b zytBM%oPeRmJ5km|lRaCRuhCAhx1cvoSuj(LcZA-q-b9WBnljWxZUb5aaE(Dn}dN((|Rq9w%pPC_$g5GC;8vX>?`rF=E>F?C2S&c88AXA2l zBb)v40PXcz<9*PxX2=cY<@ilg82a`MyF!0Xpy?b5v}VW+J_0F!QlM$vX~^o|aEt#T zgr;;U*rFkK*q>!+>OyM3sBx!)PpI+DO7+Jl)MehVGgzmkMO?l*j6V!hR(k554y&QL znX08>o}0XGtX|5cWzTG{*h(0p(vbb}mXxv5VxAdiKz1BOrA3v6r>2i(OQqZ?;<9z} zVXiX1-Vf*b0(~mkOb*sd3;w}Ju%s`pQS*g=lpR^cmOZP|=Pi+z(qW(ULnvo6ZcTXe zt160ovvTtbz43{v}p-aX&Y=s&r;i zX~ER0()?ntPZty$A7Dr4et;$;aWz~jaOpCf-6S~OIdTI=8;s1L6Fmc+WCa~iA7`SQ z3EFrNT@1Yn-1t5yw9Q6Uc4%||w2KW?^%>-3!xi0B^Ec^)wf0V{g0-ejzjC$q8gk7* z#cGZHqs}#4p?sdE9_&xwxnP?Ol^!}4{r*pikzjNGw2KBR_zZBe;ffA%Z{_rhGKAsN zs`3yvo5fiJm48OL+i)0!x`}oAMH|ZUX$3+kqs`;4flxTZ9M%tpCY_z@7;99O>)2_0 zE$bL-$f*V@R>#sm=N46;{@~cGZVfpz-3qw&6|YgGk_x^feERhmY_p*#J7uW_oBO9- zG|&*v04Mc(wPw9{AF7=;r&A47X0y7bUwzH`)I+H1Yfh&csJ>=(OTYS>^?8v{)z_R( zHBf!c>Xv@>HS3c$p{lProob-^n$<0;KK&_Sv$_>}O4zJ!(UkBEEG@coa|XIK^2~H= z=$Yx(urt%G5oe}b!{L_d#-w<0)~wG~hH8V&=~M&5PP4kDKWo6lq)l_{pfOLShOEA3 zbgH51YfiWHtFPIg=M7bb&FxqN)!6K=g{aEF$Cw+xa%2rO)u=VCAS?fnLk(43;EDZH zF6mbpzhzi7+k3jt$H<2M_A}(6+MjH(*<5R&8qWad^ea^7;rYf#n2xbVwL={{|Cm#; z_@gtSLabT+qNm&RufLkrEefkM(5=wd_RU&ap|96=!@uPb?Xf6An0oK z3~Y&^ukD+)5<{;WHLF|rOKEy*4naRKYy5Z^WU5g^bdZ&Q$e{-2Sk2~A=pnG#Tnat> zHJeMJhrVWWDfF<{Y%YZ!@|w-1(8FD`xfFV+Yc`ic4|C1tQs^PB*<517oBkxF`Fzs9 zGS>M)b>qi49b=6ec6IFhV@@?N^fs$o`qdZoWAw(CQ;?}fRb7ykf5@Q*s;${v(yy|B zAMiK6d;$zLs=5Mf{3FgZP*u(1j(#--yy~FwB@D(G##7G<6#4>@67R0zvm2k zCCX`(V34iTuHhhy&EZ`GwR>jxr(d&r?{;bYSfppIQH@s5&_CxEt4md1*FMcDrk<$q}Gw`M|{l9C53IDrxnDD=Ahzb9@mZVj&TCkz75w8^ZhU2Xj1 z0Dun}X|-C@Jsxv@S!tzD(R=Ln%oKN)6Z&G6dqZtDyEQ#M!*0%} zzm6#5-DXdk#hPVvxy{u@-kG`8+Oryw;`Z2FHjj-RrN6l+GgEA4mo3fXaX4J&(z1$@ zyy9GDp(M{&QB)(tvdj)oTDmJWBV9rT08pkGPDhH}k!CfQlofdO&19PGPJ3p$Bg-a& z0<4ToP50O=cDvh*1G(jS6?rAH3&YcGsdlH+=`s7fHNL6}uY4rMVYb^c-I;Eysy@V` zP9B;ZYjsp6$J$)U!(@ilX--dfS#4Q12f~StCjsv%MMMCZ$w+C{Wkm%{$^ax?%rv*M zxJ)*K({Z>mGE!4B%)Y$RY2H%bRCug$EX$LcnVIIcC^6t>C7T$+u{5*Gn&P%w(=z$< z*V4Uu^$k6^lZMU7J&#WwDmyeR)s>NIby(BP)!qttEFVa*o9!70v@}bW;t7xa5RO>Q zHj6FG<3{+hTVRqS{Dy6i3%-iHd@r==a+br=GF&c~Emevu`GD1GPR~lSIh-!1)-=D; zH()x`?6A5V8E&U|n)vf_>Q-V+HQQZ|6r0Oq(Pp5!*&LjU?B5WpD=WoeMT}Hc%St$H z%S?4z(Bw76F*YaI5-SQ+3ywGnuv5w;CEaXwW_nT`u5_buCmPX&FM27|i`ANvVbM1e z9}w?J>7G;zBEt%}!v&Km_(Yg1rsfa@}oM|?@JHtV((pxMWv}Kqx?J16o40nn-d3Y&W7d6>jSJ_OLx7u5rO{UO` z!xeQX%XE~P+nMgl%1pPJt$C%TW$>eVI#^UEqK(4(RlX2~8Vx?QeJyUmtL zHISaHwwdTkO-Z%5o#@3>U1*BOobF8XWM+BN%%!8fD2`Ix2owtdJ&+hMdO{Mx(gW%g zMU>&la-r~DvgdgPsJ2rV5jq1;nk&tbk*Uk1z)e$5G{xr3LMN7ChILts){&B#mF9L^ zFe31?;oS-D+ll=OuUeehP}R991~8;p(rvEvlr-6i%Bm^UkD#D~&p{@l4P~aMx{!NT zXkx%AWLVu6biy7pa*z$-99`*_OlKN`S91#PqSC5Lab^%yKMFm|oR#HCcRJHEWIsx( zihV`p#j_ed0hc+$W3{@S7FBG^L~)$Kh@^_r#58xBBP|6XjT{sYGR#g3JjhCO2AqIs zEwCcuWh#30v{bvtVRP6eYNSt+}6~zOpFy`&sR`X zT~vS$IJi|5s5-t>b4o@=dWIt{Br%{>IPB?eXO=U~4EypqpkZfZ*sbn#x!ib#;Ra!- zCV?(XrrT`hjPz6+x&~B$=ze}#33_VyUqIb>S-H0&4|8tbhs(r7r`4L8YH`4uGG%%S zZyc!>Ovh0%n)<-&ca6AX^_X2wyDKBhW0l=0E2Rc1JC$EiR*62UyrQh2O7>=Gsx<>$ zq%+IR4$FG<8JQmRxEW~~T7TFbuTUPz^dauFG%IQ-)2wOULsKm_hb7IDifKItMj38( znbR$4DK?u+9x`}kuve9$n{wyr3?MQc;b_mwN=x;q2ldLCMYCrYd#Ut842i?hFQ=r~ zvT&8ev5G-VwB0EwRwrr+bal7Sni1LsAIM}zQo0*sBrb%cd5SV6O-ge(FdcQJNQacM zH7O%2)#1oYrRfTroX=JarnoXOakqJ-Lo?+=3CnR(l8XKIWw}%su&%D zZr_EVAQNmrM}51~Nq! zLeo+(n@(}1q&wMECe%zsH%F^E#cgw@S!`~d9ObOJ5Zu+JWSH%#sR$0x(=f>@DbMp2 z;kN+ELoorZ!iNukq+8Qaz;L=#Z3sb20HeHYrnf?ek%-eu!DXJ!41`?ImCcO677y4QE+hXmn0_R>bZRH6jDd3$q-lX}B~N7g=yOUNz&!Y|&#$ zOHIe9py_($8|2z7)h8r-J2D+>G?}>0GgszUc)g{$s!LpiXu2icifa_rij_E9qjrFv zfmTs8{l08C%WSiH+%Ak8=JLG!8Qy}xH7KhMBY8$vRu&43T|oyeTN`knuEMPzkIj?m z(7jBhtPvcz)T`F6fT3@6q-D7*xY(#F4dI}}oSKrBnuQ4*cTne+gszKn8Ca={x20kM zD@)fqp0nbgOdRg8rDVEsu`BkXs?t`5Aq*h6+{mz}x$Wk$rIl6Xw2tRhF4L1o$o58L zSgjU!N)|@x5n@}>PW{k*Vj0w(PD2H&3?4)L3Lxkt<+Yu_D^R=HmFmvSvZSV|t>j<@ zvH?r7m$)FdyKEUQ8#)i>gqzk48(^~ar9dBS=5$+D3Wk31Oqh{VxS(30%QCxN>CQ|S zoMAo?Q;d1dXn@ufvKX9Zo5N$X+EM?ShA9>#A5m%UFqMzrk|37^h*(XwI5APuTF}l7 zV9&u!1Ph9(6tgwMf+p??=p{m!3Yb#Jc7~;9q+}qPrGb5D^04IC)J)ZM!{IQer+BQX z8R$#2tLe!@$9PN1bJ!Tp)?Im@Va9EM+)8hLRYj3+7MASFW)yj$np*6us`M5>s_^C& zn-izzkEE0r&yz5C=&*!@7$qePAC{CbJbrk>NJU3dLVWzNVZ&l#Mh+V>k{_Df)@6z| z?K`Jm(V|BL;kz(_rMLoG%c=JAZ-VeDgrtk4Z{la$C?T%EJEdw`Y_@b{JA@MfII|Fy z5=U3;u_dJv?pz2j4V1p|&zLCBe(9yeLG;L zh&b(eDCbM%cQY^#i8yV!DCZjs+-txb7I7``T`4~;?oVKP4F&)y6fO@3h61xRf#dq& zL$Rm$mjZpyL_wH@jS`iUf>ZKcgMwHCOzKbu6X?7YoMLYX^wWn4!U}AZT47UgioNkD zu(yHfdkKRH=^C73?47bAWpqm^dq03vKT&9LoV_jE%vBPWaF}4{Aq$ z0n^{kaiRRX$Rr3JVCIM|rgH=K20I1e3T%`@*`qj^2TY$dj%z3moT$`URIx~*%DFG> zJqpab864M;e+yiK@B}tWq5La=y^nyoB$MNM;6tzcsJbr75`+?LltRUQ8`ygqm=`@9 z*N}hZmkYu@*eHea?-|&86_}Y~Pux)XEk~!igF05EP~{f~dw&9RQ4Yt2iWiFe4}fV+ z9T!q4d;4*0Brs=?!_H`Td!T@oh54 zg(^P^lRRLa6mg;QCEO>#49J6k6bknp{JR{O%knwyEPUwsNAWzOKoDkQqZBHhsbAX+ zOb0K6h0K?5LxH*B6u3U{?-5|$nab@&;zQ5Bi=p>U6NG|2}i*V-Fd{5(02mnRT0-#vd89O%K2Uhecw{_<=7~N@{h)k8epo+7_7nZBc@ys z(y>trWsmy%3Shcba9l(E)rd-r{n#i`IqB7J1TtCy%$k`DCZuX`%K7@B_stfBL)a*_ z!KP>LE%=v$!8P()1{1n#aEd*OmtTMxd>zMyikGi&cm^<@>p3n|z7(gA05fbJ$MwL6 z;-5C(zBdTMWNef|0!fnh)vWs6H0lff&R_siE`u2$*(vHjEpH!vlaB zE8;@6Uy8pXVAhGaQ1M6QvJaSxmhgN-l?&mf0rT`JaCE*u0CT}z+@5^C6`Jl!=#Rq| zV2VUsTYP8br-OS7m|sqT>j?f8OL?BsUe8_!9GqqVN8`ND0FKIQjsYB%|2%`Z8x7+8 z262lG;_fnlqk6i>04@r+H3o20ej5zpo;QfwYyj6D`Mz!d*9N%v4B)x|x7PrU;`Dn1 zIOc12}4zsRnSXfXfQPnayzl z{R`E{u^=4gLjgD{zrPIND6S%wVW&!Z^+Ek&v_V{V1Gs3|JKF$`uHWJe;HaDn4dB`V zS7rd$6}Z_3aFM{>W&lV2-ERO#ar%G(9M$jR25@Hsx6uHO+U0u&aMb_pGk~Lb`N{x} z%H@y&9JTWw4B%+o`qcn#5O9AOz|r{*SdN`4>9r49KOAfj=QeXs8wlJb z25{Yhn`Qt<=W(3@9Qk*H0bC+*OAO#B-)#nP6fZjr;06PC&;XA5wJs~LQzgB6I~&K( zGJvE0KG6V<@*QRX*Auu=25_`4J>CG0#*ZokIGPV#YY?}{0FLGncNxI3c5V>&xB(np zXFp{Sx4{7JeAs)|0FLtgz##4;12~GSPYmFw{5~~^+iw6z^N526afc1!zBh>b$pDVp z(QgKDbY1(G0UY%&9q+?VmGt@pYH$4v;CcaPGk~N1#cL3Ey#XA>!EysQI^X*Y;K<&y z25{8QpErP`dC5BlabFt1oeO)v8o-?cT=f0esghp(()kWHfTQzGG=L*}sRnRl&t(8d z*Kc_Sa6N!4Hh`n+sQCtPJ%PK`0FJKDA2EPC54ep6aF+u2p#hu|xGw*~PL<42!RrUT zas0|4T=4n<^&8h1z|nc!VgN_y@rVH&oyRvpxZv}M1ukwScB-To&(uCfuT+5`>ftC( z%R=H}D`^&yTZ!jn zuu&3m;(CsPqw(m#NLVkBqx0AV%m;zE{K6TP!;)~6rnfU3kykP6QnxMFHmfwRq$q#1x7eFk>4kBd-C-H)8skb! zxwv;pWp#deg)czs&d#xp9uuI%PoXm{ZhLm`7>dZ_*j~VPtzhazXJ@^5!q`f0MdgIb zqLQlOJfF9!VuHi*#yvRF&e#liY zh+LV#k#Pk@6%#~HBX)W=YrLA#D9EI)v;|3Di47Zx7q)oFNbL7 zf8Fo?xnL2kUkO)C@_#jP3)zk~(XBrU^23-xh6|TL+DUrB?>=@Ig0Pd);>G?ku@QAC z?fvOLCvIoPE42MKVDzml96k-w$wN}X$!4y zZN)~e2<+)uCJ14ma`UZ)ZA{)mO(7OLRyOQGE)M1Uck$7h3R7ENdd0w z1t%is)03M1?*4bCx0o(W7wSj1^!Ru1!@n)4kDR}h4rfKzzVb)y$)1r5>ABO$XXlaC z`q%~ZQAoQSiQ|l}-TX)GZ$O^MkaOv%h^(L4vd(@G6~!nXmPzf_C{JBRxjMq@+y{C7 z&geysXidE5PPz&a|7wKLuqous8_VgNq9A477&f&#)Cr{hESXFu0UIUhlYhha$nzzX_OoTnmL_bJTJR5fA4YAa4ka7To>k;+ zhE`t=V2c(qvHyZerP$xfa8;0QW72F$*Rzi421xs{MGLeTeLFi!)1Nz-v<}h@4EHpo zZP=n&m-Ggc-o~D`XyG^P7ckskkT{N-9mkyoiQ}x0ZeqAJNE|mo#!)PD9Qo^KxFs^~ zAsP3CjC&W-5Y}aV2&s}W_Cngkbo(K7#1<`lgME7@eJ@K9z%0hMaG^bgM@b)7lT0r~~5?b^TmQ zg2cPGk&wE;13s+C-J7xQ<|M{K-hVB!M=aPJIp2fx@OSgSt?F;y;nDr^g1wRR6V!)I ztUD49v)-yR9nOfpBs1FAi?t3_Ls7Sp!(YJZc_-&$fBjjJ^Vi_h|4Qv4ldo0nq2wbS z81=}Oc_#(fi=0m#8B^6`;O5y$?HxUq*g1LXE2G7OXyQ1nI{WVW%9fDps}3=?)TQgfqH_3*)igam#Up(&Bp%;)LE`bf0uqn!&5+(^jQ1gZ$)wL9?Z*}^e1-j6O!^&r z`i(&}8y>%AxbFDQ+hjjTyzLH##N+Q$SsD*%H)G^N;$BhP-OqGIkhp)Pkhp(Ukhp)> z$Wkq&cG#kYn`NESicY8X#Nym|OBn!ZAFPK9agai^lzB&&;NU837?>B?k71NnCVz|E zi~aTp&m#L;R_TlEOQ_8}hn|K-0^3b*IX$Y*zMe;$-@UeO;`+oBVvsJXdMvTtZ`%}8 z`&+BXg+Id=aqxBccQ7&lwOgW?@x$-ou%7;T=xeXp6or=YB1BALF*g`j?`i3GFBWs% zwcx$T`A-pUc67_CZuJ!{VMuMenuzYT%$3c5)&3S1xo|2}(o~?LWxf5eI{RGalm92U zBsHG)9{<~_wlf!U3+8Tp)qM83%|4&XZkv5BeH^BlC9)@T3(D*3`RrQHVi;rB)e#6r zTXLh%`0$n6T|gq)+{O$s>knWrS)bgH^;V*F0>OH?XuUwOP9nEX7?O^pi>B?%3hBF^ z*R8o-_c9ob;6|%fu+MFFYKABW8c78|>UC>NfT+}+we>9{Z~5iV`g;GwB@0eeb=hW( zMllJ8v$0Ryd)S2!|Fw(#@33sMnYql`zfea*s5E1rA&d1@8|v)K(8Dp1R6UrkvA(Sh zBh@j#+A_Ib^2-`cW6a@$%*Ix-QMDn^OtfgGoytu6Kr<0!=00X-H#4(U$CA|9c2HUB z7-)%>9ggJGR~=+#cGp+wS?VeJ6sfYrTZ(*Ynj%M`#=tI$y$~OQ*euZyQN8tIJJ}L2 zM{^%be2baq^Vm=mF|v1xM7?_%YD?X_(@1>)TeOgdJ@upEY-UD%aJX<4_Ag_L7HY9C zXI$#%N3(ehJe+RAiSL%NDFsE6hZKP1k$2NGvI0Esi+fi#IR_CVr{!;m=RH%OcjhEaht`a#NL z3>q^y!vcvj+>kh9EF{jjA5sBhtbw$jdHM{bS+E{1&=u=6cJvKM+} z8hgWqQIKc|z}ywmOeWbN)i5a)(rhNVAkATt2NK0XxG)CNwMAkR4%%g8Tt&ECf_^(2E>`NKmCuOIWwFQOROWL&Df&ZF9)a;qlMnsb7_z)4V9%! zWyvl}Zdn>DOXZOGEP}3dsZU*j1*^(}DW} zTeLuh%ca$j_#|~Lq~2&^;lesde3JSUBtA*q1WB1hb7?PheHeqL&ik=N3*TY?7L!`Q zBR+|y4!1wU^?}42{ZL46Fq|@V&VY`GCQeyw89Ui$KnqCU9u)Lwg(A1TEX6`nrnL6DyBPajOu~X$wtr$o&bVxKwym)s(onu_r^iV7B8DR(qpVSp zoy_s%Lk!Hq2S)DznLBYlBoA|N6s)Y-R zi?k3dyBK)I9(9U-!;dR+pG|K2d~r~@8utyTy)L@t={ERm<(isS2lb|#V)JKFf=f1h zMd0zZG+cT!HLXPRd8a>c%EcB8sX;Gf;o1XI;ObR6biDCSfW#Yb9;91Y6PpT&H{KbL zc;lrTWW34Fk|nyVyPYv;V!j_+wD1V_OPFpwq-{*M1$*95--Ef`;2|-f~4=m~T7yo~8kB@;(xwz*D8L7$)r4$jvBXt3!mMpU9qL0VyVn{qv z?}Ef5l{znFUZO1S(Zx)-KvB6LTj<5T4h(m?i+in^l{0N|?+7dLIGq3Kb*)o%8wu}P z)8%8qU2B}uwVviYTN-wou2*e|QVHFwriF}Eyk$7&qlvwqIytEUo| zPv&Tp=4Tczotfkm0HGtTe?X*BYdwH1TJU1e>v=k)d)YMU8c6%GMGNz=rv;#JVUet( zs9MEzD(~-qKPG! zk|6OZCM_~Eyz>$d(#32ZWEwp7(6z>*!=MUrjphQ+I#9UJ=z&$$O{c;G&$qnrsF<^>L6A)^h*qW zoiPZ~0c_F2|6%Vvz@sX`a*@ens9q3Nf zIL4Bz8|`}Wt8Ru5ELaT0{2J;dttqg_pSPe;rwY$LYy%BtdN0|~>2SD+jl{NydWU+@p@rr#!iKQjKMiv_lipQP;Y7OJ{2F0uW z5Kz3@pAU*xdm1zIYF`NIN+vNE6qle$X)e(Sic4GtN^U6pNed3%2V(+y*VjTcm@dHc zo-_fJI*0ZywENAW`A^drKYM+oY^?B6UuxKJSUr)ecgq5-8t>6noi4uoSYERmHg^!6 z-&j=PdC{n9tkU=n@>?*hlxq{8Z~=-clx`d%swqoC>1z4-AxQOy`{g?Op1#iVQ3NI7 zh>HfwueTNZz^KmB45;z*dOl(wWhFcb)J`06QX$Sy@KOiGOP!vFc&)qz6fgC=K=D$i zGi}O=Vllk7(R2;J-|qy)wfqc<*B!c}b1j`gaV>HudvteZUSopQovkeA)JB7LyT(&| znr=6&szX(R_lzBNw^j6vVzemVSgEx4gwffBxVOe5Kfz0z+O)Q`Dfhc@#7Qok?`P#i ziz+)AZ!XRcF_xeR=xdG{c{! zqXo?ChofRv zy@Sdm_QPmaMAFoi3IEjy4Jth>)X=a{!-AvaWt!pp<76^*{|PcVf(%mDZ^ZIVfxLDy zXD#v}0;41it& z=RS<0YkH=NlHzfu)iW$_<4jjk5<^ zh9JMYaKuS&oOd&-QlYL;sQW;@%Ie7@p!l2^-H-T8*t4McOxPw+d?suUC_ZcZ8>kPM zEcSehmPPBwuY(`Q+5=t1u}z{MGh8OF`Q2|UD1P^w3hE6eLE~gjT?UG8$)s^Ix9SQ| zZ!;~|fa3Pu0E*jpJ1B17Jqq;@s1tF-v42nS*#C=l>Q9h{-x&L7*Qw7fT?QARiczJO zsAHyU!=>sH=7R)8@5JG^N_@2G4h}!v*`d-6vp2y*xcXSZI*jY#JEcR=_9twzI%YX- z?NQ?O9SU}b#4Mjo@vdlJeVi{RZq%E;A7k==i^>0e)DdsrhL+g6jtxi5-a!p5@paLc z9$5x|dCz1`Zy(jzhJB`(~s0!2`C~NP>REulwjpvzq(Q2@lu-sd<`ms#(fSF22{K zaS81;LHdz$`bdKzXfnfarJ7}Ke@FJC*-FEN!rk>v%~;#nq#*TOIO3$SIPYfEg$hL- z%df2R&@R9KF^ZNUcjAbXe!-a!e(7PGcNlb=G_mP)+AqpGjESI*Fj>0Ca9$-S-igp& zFy3{n2F3NQ1;q!`4}&_)WS=4&qn-!FJC;qLcz5y=DBhjC28wqW^Z@POb?CRcpfL6! z69JFw##>&tvs`zUMgLR~24!w?$!D!qobSK{|> zJ5ZN8S{7*jq9OjD;kR@l?>r8^bm6ndp>;O0zia55uCmv}xak^iYoj>|533^TyqbFV z&qwTT9C6YNoNr}~iqr&PQEWoO z9m<=_DvGkT%o5jdI5KAW79`nlI5uW^BO~Jf#wHZ3Ur|l+n{{RT;I*{_6Fa<*wuJcG zBB?U^2c)|is?f}Mg$9lCmG&pHq=VuCQSk6HEtWA0_3!LFV_XFm$``L z^^#^&?ql_hYUoZJarlF_+&NPXeTv1d0>!)OHK2GmeGMqyIp3sER97Eo5>z{R{iWLt zufJb_;vFy5_D2{l1{BB9vl++H_VNc=EUk<2*l|j1At+ws%Ruo~AkVz{*L?pO9OE@I zZc`VLtK$+-{GXSXg5o2Dm7sXlqsK^I z^{xiRtDd^`>N)Ue4}Fxh8Pp<1QFYphBaUrtS;}}{;+j{fL!fwtqX`CH37TAgcf(Z- zt0ZSbBkvYdH(`q`g^ujZUt>Y!cQ_3G1>bPMaCP-}Wi^d<-UeM=mHSF`X#ooY^cNU( zKa@5rJbtT10r5+@YoU30JD-==zK@`QUPyqfP}f5L+=ybkNUaUE4P~HqQ94amITX^XcwpHo8QXBo93)*6k7dj95i&!L&BtcGR%F zy5SQ1tvS(W`;caJS}u&lKeV4@D0yl*j{i-WKSi>6qQO{3lLtsoVk?^woKGJD-m%H` zB=bs3-81ahH*qg+s)#Z9vXpnIM8VXUreUX&o?LK; zwsydj*_VIey2-T-kZ3@J@jKWr4F_yHz{Nxy_0jlYUOu$dxR9u>*d;(u9MZn+ zq+tfRZ)=<{qG7Lu8A!YkA{M8Z6?Y+$r6JF}@tWXh*cu5NmcF@f35?K4AC6e)6>E1~ ztV>AgF@DmK3y12Yd$g`($G*cyT3T3E_@I6-<%-FPX~9Y2x7l`(qV~N9JP`o_FLep} znwK#DkxV1J39N5WM+?Ki+l50r%UFYJ-t*FE?mTv%UkZx%ahHPPecWnLypOw5p=h+u z@BK6ipvOV}_lQKMg;LsyBTo7Y=VZo<0EUks)UA|*z)NGX>RctwkMi*a{mGA~LGzb< zd_ny!T}83~qfTPfQ#g-dT4-L9r|}M`k&O4D!aE3xYwnExoNMk5ifg8SA9G%g!dnE& z&9u-KsU0jwv@MC_u2*nRgBr$g^o9-#qxOI@GipC5E*pbunt{dZz(DcX(?M|w`a5C{ zjwop$&RoI;iXNDw*gwI!#8mLO#4J!;g8uvL#1SP`;>=|)1!ZTvRXFpKUIU7kD*YRZ zm-G#wc=_I;P>+J5<$);aNl>)R6eT?aY8s<9f||vsO`xVQY7eLaM(qVPolyrs&0y3) zP%|0z3#d7aIt*$yqi9N{h*44`{^iZ6NKhq=QYQ!G4YW`0Ls4K(h5up=pkXIgBf5as zP;%gi%-_l)Iw%o;p@(FGTm7F)9yQz?Mx9bPTW|T3rweFK%>l)y+2(_4VR@(q6?B@- zc>g8t(g)G2X=d6g3}@Q-yu(-}PCM^F+t0j1X``Y!ZVWAU*Ja@D8SNdfnR_UOX}q@% zX9;7BgxXve1ue1Olg3bS)jdHMbq~plKm3hCK1)w@-HijvVU6TQ`X($v+au>w}R z+7$41;o!TTb~CCBXHKmK#hYRisEx>Mlyo&H-W0C~#hd4Cpm?LCy-u8>k;IEk;!99F zal}a{A@v=M*8>#q{04&J9bGagUMZ=ey~J>(3XYb0wlLlm3hypZT=qdwTvnb`k@r^0 zzy8fAygin|X6HUYdVaHW7`=w~zg-7L3iwthRkSfw(W?2bIQj<#-Y11hDzD&R7OqQ^ zJ8o=Kc04OxS}mq{c@u~#hd~2e6H*TGfpRC7QacMNhj>};BoyK0QV1|07k zJ^;lVxPChS1%?YYo&P+GJ-(*%Pi3t|H=Td9%dD~UV&#@fJwYsdW4N|Ei6xbQ=$$zD z9ys1G+pxCVUB3q{9vTf3of$*HHaUT)wjRp1GAKuz5}D4C)nD zqCG%0Gm36tye3gk#BVrfgQ6QuoHSVBfnZB0^ouv3AXbuSE49H?_}KB2)={+X9jA5C zmrsqA{~SX1PdqxJRT05@}HGAKTm zodrsa<3S}eALfHfWYknpui~JW??&$f5wP>%V2H6`Z{YdJt}iHh+R$zi#!3P1Bna|K z0peNs5a&)(>ZYx91!wERe{n^TL1aH-(E**g(YuN3qC>cqRS-j8(y{<|B~6nVzp2;) zE6!sMq|Pd|1H*rN@diH!vVz}AUhB`&0>O%ye&s+@&8(_nP}^|We902;9Qm!bmm$h; zM#jY-{aM9&)I`f4zGKK5vkWPEN3wynH+~F#AlDm}vgvOn6J%#@sA&PJmG?4No&{<> zqs{}B&YYM8iWk`Vp!lC9s5m)~Mi~5WJ(Cn(F(|$Xzf9rL3;{hMpApqz>JrYvLH|A(fMYNY`fmb_hH11;`#neDpebvbZm{FX!I6iJNvppl#G?@GSH`2=OFLL9lpZ~OMM>1`&Slha zQ0Fnq42s*84QdeMc@*9hg_8BkzhrwjK2KyC^*(=%@nlW%Z@3zh3^cxFs8QA||At$N zH1VgcCsc~5jHfTf_d=#hsrlbnp-2f3X0>vdlG;#4QEKUoiU;)}qvRZb!9uvc8lmVO z$*7)?{`7BY9Ia>^qiEduw=~iKo_pJ@Xxzgn$|dzT!2&?7wh!5J)E@RSt<)Z}7)9;D z!YFDFHb$92Ss6v`fwv4<2N*1b>wO2)Lv=r!QRMvtjFL6Vzu{`kRWx$TNaMl3rO|1i z@fV#&mSvp6wJ~4O=w=kzc$iVgx;+16TB$t8GK$J`9HXc_$1}rA|G+jm_aRLyljO>KDw0g zrYO8wpe|!Py^k6gPxa9<;FdGqYEV3lwV+lo-VF-x4p1u@Z@t2k%UAvlx3#Qhdi3{4 zdi8(cm?T_{mm6rLHyo%MNfSUp1I5v3XARR73o2G8FXz$!m-L1+O1e?8@Fqsl9q(pF z(f#!nMhyTJ$5JJ&9dQ*b0It+re~bLDqk-+ow37ZiSV~m0cv(};x}EXN3NIVfZH#xU z?dYx8ahHJ|cN*C7Z^rY_6WIk-K?8(XY2L%6^))S?*$`CJAmVilX`-0E&4`Vn=SzuG zq?uDxV>m@6%c-6UMPRlXiuL&}Y@Tp=8O;~VSK4cWxLeF6Q$%f`D_#6T~ zsq=CFCyXLn-e*)i&Yv=hZ26o~`BgO)h2`<%@ztlo3W;Bhuc)f>mWm5$PI*)g~&gE4#Qc-zT(R^t^S;@iz z$a}#dy1J^yD^)TJ3RoO8)|A!DEOAv)Ra{c8i{~6Uy3kutU04I_!6@*S)JwJV%PI>h zy!F!TDtrt}A_3rBU9yoHr>ODequbC9nRsjxs?gPL6?(*+Zxf-I?E0b1?-bw1@KJj0Pg6r#U%p@CJY=Duer>^W&hfNNOwU=4SBGzpt`EI%v)Af$z4Td zKA?Z?p!np(BnHDL&+v(_02h(@YdCoNEh^-5ijLbE+{N7D~>O#tgiFMd#mETr6utK5ihD={A{XViEvy=eMvd1 zqdZxGOR+NZ<)n+!bg`)+V=Z;FOEl7!!ph1jZ+t~rJx>%~sjBmmX~k7=Dq;$~MWrw$ zi%g0yEvyAsK)^K+FRLu7s;NPjpXefugR{3C^a(uDQTUK4ZC_Lo~S`=a}xuvdL zQO_EA0XUk{kzI!0b9G4yg!8ov`$=VOcyS#s)T=JrSxgN+W6|4s^U5nNmXV1B-VST!V@e?)4RaaA_*jrSkOBk0T;o7oF ztwp#L5lZ*0b`1(kmMy}UAuG{AQ>7E;&n+*o*A&jRR8`d!!#Fsxy0B<|NwIvFXM+ds zbZ9|WLpKn#%%sG0VAbN{k#s!(2$n^jPXaSGBnFWfI|&~O-zdUqdSQYl4K&uE@uJ_| zg)%^Q8KjDqjKZ(044J3FWECZnl9&{br@=&|M+J-ef%^29O)cn+bGbO^DQxJd|+zW?g9NFV7h0gxXC%tDBMxDhnq)*GRL zuu1SQ6k~Vm^pdfTlB$XlZ_T27HUJIRbonuaOsB7g_zmZ26CQtdP%|Ru)+i&~K*|U= zaNM+=^E%&O(s}J`7oU6QvN`TA-bh+`()EWV*CurKzMs^2!;Fo0Twe9?+KW!S{@TbZ-Z<;^{`d8dJ+d{u>)x1K zmYTm@a>xA56IOnI-95$AhkKjOi+UpMsR1#j8{a+svFP~|ziher!!HtD_nvep^~pt@ z@4Pd8*vMah-Vm2L;I$nqx~%uy^tS2!ca}E1`oI%kpYZd5?KhPSUVTL`*B$l#>0EQy z{k1pUGxmTSKhD|EIsKOZd4AYs?NmSZv&$Y#^Gq$Vl|6RT7lT)fb7#JD%GwdpJEvV< z{?S8sZB8BaMb7z=`Sn}>eCj#bZtJMHYSZZJew5SqZCZZ*);D_Xl&=>|O?&8_i$Coc z^Zum#U#;et`I8rKykb@FzvO&1@9mOyWbe9%hc}GqwC%n#`lVm<;3Tj8p8c~@Q(xZy z&?P^N>d@5m$7x-AEj@Gn{ew#1e)QQ}s+NA(wBm)m+Z$54E`B!W(rx8Slg8b@^0A** zFG)J`Tc3j$c3bgNugmAi`5SZSku#d>-<#LGXY++8u6{B8rT52MYHqyFDd*4MfByd3 zH@c+H6A!_x(UBkCJ>s{-A&*;Ecf8`w<}+)W7Y-=8{oFM-{!%;e`Th_3+p%`0rFM`z zWAmM3K3jhO(rFvM{#ANu{+oGcCcbfCKvGQH^tGQ|@pja=8%{cTb;`w;mu1%!d^hcX z1FtRZHnY#W*Y=wA!pgkngr6UK>y=+7bZohE-NmnN_m6*i(11T)`Ep$24`)BpA$k2R z!~eYgoNvGE_~Z=h1(z=VJa59g8H+M)Z(g?S$u$p|3xBf@{#nldx^V~oIP=o$-gd{0 z{N|gdtapC?!xN6tLv6~n%zt{T@0n*~evPR}t?1DF^$m>~JG;+Hx_orJ%$I-V_?TTY z*Q`Hz$pdRgI(J_;_SWA1zon~g`EgZL_0KY2mY08JzKl!%KFSl-(*ee`VaDv^VbPp^#rglvwsd>yyJa2YM(#Xg z&#k8C&wFX;X(Lbm@#LJtbZd&ud#pjt)-@U#2i|?fLT3=oiu_WrpoW9E&O~XbcK3Nny z^S_P*4{s@(-)VYUzfK2kE9*NqXT??dt{yL~F8cST%=Q0``Znjg?{lg)dCs1?;KmcK zTz>e6oj1OIM$?Y-Goyyj|LUPLmtAoG!xud_?VSCuKDM*dNoQPncUe=(&|8br-T$iG zH2K$;f7oB~$Bw(dGQXWyGidSs^Gy+>Gw$9H^X>=tRUF(VsR- zewz2^LQBL$#dUj$1+* zo_D=_Wc1t*J{e}sSoqeEy-!5H*W=PxADH>T&hKxzF5={8#(s10qRwZ`Su+0V#9@mb z&Oh?=`PNTsKI;F(e&601{a!n}e&sFa*goj^)w=19D}KK8?9()(21W|wOp z_Wsnxw(&~S2?dScci-~-XAcy;;5hJYPI}9dA3nGLvEa(>A6IW%eqHY;9((iopAwSx z^vTJ}Ek14F$g^igY?*Un|KiWOKCyjhUgdzU&X-c%FWcXKwCL3yEx$H(-9K&7=(oCW zDm>}cG4ZKa4w>S)G55%-JC>faWW}Akcl~(F#}o3NT$l08zq)r_)!e1$X3MCJ2a2wX ze)qOVHqCi%(!j4f%wM&s#?t4ZTdqoYIdMa6*K0n$(wbaUdh><-It}TtW^Lz;+miNN zaipQ!m%Hn7t|*E9EAGG*8{%Tt+~P?-z2$;ayWZ11`{uaA{U3jR>);RP)qOnUj@Jj| z+?Aj9!!?tqCvO`0{v{Wje)?x?Cg=V!Y2v+u>PPO_J0j!hnv+`Iboc-0#%KT9w)>3% zQ}(Za@ck23eDz=RkLCHD9MXt8pZPc{qw2mM_mnkPujuAJ`>jSx(TYzmnS05N$#q|#Yxbi*z1G_uwR+v|6FW}6_WtEkY=QZjS31nhzBpddeym= zYv!-{pwXA{*5b~Wy;gbce{THh#izem_+NK(Z)<0J+;0aTet+{{>ufh=<=y7|z9o$ZTQcc=a(&Z?>Dcz{e=S` zrPqGdzvq`-KYgL|KGV-%wOn`Q6PtUC`TF%gh9q|Ie*9afRhw=oy7#ZlrTcr#n>D9b z_Om~|dEIL#oDtjd)uIol?fUkbv>rXTe{e7{=b z(=x$XP*t8-QOvenaZX|}O>ZnHAtj_M!n8%`Q-2cK_v#bq|If5|1k4UKQc#IB6Od3* zNtYOC0nX|IfyGNML#hK6>CQMlv$##Hf z_0S-Xr$yFZHRC%>s53p>W;>YJ3qu$h7t7v?3eZC{$q^<(66XG0zDcE1n_lf2U=QUw!bEEYRIWEympvb- zhgSF^OtjmdO76POWwo&Zdb%^r6gVdr)HnBU{XI|*ZNZE%t;U(GU-ZX&tGWm1p}GAC zQwi*$jgCK^E;$4BP>gENo~gfB;{x=Y!Z0qJsl3t_y>g#c5BKw_3^PMuzIyZfBY_xt zPKYqk>mFFSKlSFJKn!hdiZDS~B2P^^xDr$T{$csF^pVSe@t6_QQrVPXEDqP!k!_^Ox8d>2@E6KQ#$k8 zlgTumKR~7y+~B<7u;!Jv$pEr1Wpq@btBm0N+oEM;n zwm?UiXh#(F4hMEGMT1lA;cX|8VQ4EQwTs&;{*7E?%L<@OwcL z!^nQ7wmc-jo@9pc;7n;*ieJ7~tB2b|8X`@f9x9(pl1}roC!VML2Zk= zq%cs=XoivN54HDE0eZ$T4BaazEZB4YD?*Rv-hDn|^!M&D0eUhR<}sW*Fckg<(S9E72uEk6fRry;}nG*cc`nl{p(!!EKlP z6zFF=!+3F~(aA%jXJ^|2^f(yib(9y~$(~sMaaEumNY0cby`BjHdZ=fPFom{f za)6#m0eYq|%xs)V*Npf>MS=dA$}qBjR=o3L@st2P(-?+)Ol8r%!!N%C=Ia86(U#Y= z06o(g<|HVgI$yVZ$Be+b0hT83+h3pgTVPr<1Jato(gK^^W$0Iu;#nEuP2T)c!=ZZ# z4>E>&G(CsfgPud4(sSm@3?(gI=cqo)n%4$ks88fU#=I;u6sbJ{oJf<*lBN0vaA-#_ zg-AsY?YE@RS>ez~jt5x}?IF^0x>4mvh*qSM1m`4$L!Z;-As+h^-vOzpkt3u90y9OC zqEDeyn4oaJ7n~UiXQ*gE;}j0PQjNkSg|kC&rYRiu;a`T5^W{PxO~IpJ8U?3|!g)?` zsJ4`u&{Y}aV!sB%jZKuBrlRNa08WeG^i(j*sR1FJs&FEx`$HJ4aIO}dM1|8onq$sW zI8O`CISMC(x_*Sd3g<1sIZNS`bmo|W3Wt3k8O;6)=T?keDU4A#=XT+o9EJ0c;5Zb{ z`6qGA5QVc@aAFmXl?Js47KPI+IH?LJmj+S@eH6~?f^(+A@lXeYaJs_zKycy|&ZKS} zGfd%pAviXLGrK#-bXPdL1m`q`Q%sM%2$>4!OTihXaAwAFOjm{Tk>KPioHBakMHr!Q zeifWk6pr^4j>%9szYC62;ao~f|IUr2GVdDAw}VA6r5y*SN{m$#L+`A3vwGA7QmSNttD^~HtWLZ-I>=LnOR zCn8mhctd!J81F)gDqcru=H0_DLXXNhUEB;#R4}8#A*rbfXO+OHoDT(Ntb&Q}Ln&gH zIpZWa^ONbG5@({e3=1W2=s`oG`wDUJtq5oSP~sG8Im3u^xt24WIFD*MBZ%`~Ehjk% zSG#naWLzCkI3T1-SV;LAq}Y7o8N}Ce9tMZ1;s6C>p=kph=W}qV!%;Dd;;GNT?tew< zl)kvsah?T-q*ToGe*B44<+Ol9)m7#E`z&sAf}+`yKzb!f<$Mbc4hpqX{ne;z@eO~9BT?ML6!3nIAqTmisn)=*it!vfkT>A&edtWOyd=)zUcrU zsGO(4p>pr7U~*V{(sFi#L#dyvU@BM(({hf0L#eBnE79htIS*H)5?Gtla$W?7q*Tnb zk=z?9=T~qh17l};s82{kPU%$$HgH*=ker5`(o2gJP6`>g%)~jYmq?~ApdJGa!Z1z> znL}?>Q8=kkBmJf2B&WeY^l~Fbb1J!zzGACNk;8iFIFx!{EhiZTC=J$f(x_^T(sGj1 zpom_Oq@yi6(Yx9d2R)&@NXjvlVnlR{D_qi!gAQb?*;$DvZ*qT`UweNZ

`AvM7p6u38tI>Ss?TFxWj(2ZEd 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

SkZNZMU2L+={&1$EgK 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

y&i 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

VIB7GN z$918VW--P1$F2hZ#Nfty`fO_+D}@%`-I|w7&+fdK$irxN(u~qHT=L+(TZAtS_e$X# zg?mW&X5mgNFG*Us_~51;aUa32i8E{4J;LkGi(~(+%@b$%=Hr--1_92CW=E#HD zbDVkbO*lWURSflTP;c+>s+4M9sWrVg1sy+mY*={rmP3v2wC2kU%9k0GFEYq-@@_eg znBHj|yjvo4VzZUmFa$oC_$>HF;!4umO)N(WGKmy24_7RV?&?XDg{Eg6o2SfUJ~(6+ z!6Obi;eXxb!Xr)t*AE^)6pZsV99Nw<`$IyI%SVkmyV3am?ol8?q8{`uwtl*RvB_vr`bJ zwPuUzXBQ+7(z^pvJ4$sHa+KLXK;^jEhrQQA^bn@YWE z6{3(w&>!I{Rg9>uE$b}&?sP?(BZQb0Y4)7(HyMY*`SDv?5;i}L!0-zb53Y{MXxX0- z&QHW))p6lK%BGKejbDGBkQhk9tsoJ%(s#m(`ue{OX`8H|Q&Ps4#5MW>5_rX%(V{%;>y6ewJ-nj~&1F?wQ}8ev#;ovyxUheGY-13G zkQbAXmJ`DwIDb_5+vch98Ltfa59l%D6ViNwe0uh#9Wk5!?O*><_O_!DD6{0y7Rdf}Kw^=L1bYgg!Z(4M{v?K1DxdUi6qCi$myB!r93(JXsGH z9V^J<5PEAbdt?rwXXBHH(BC3_m*Vc|xZDq+F90+Nf0|Y%SS=k__*0ZU9!G7ZiE3#jm*tcZE6@Ufd1Cwy!k6NHb_#tR?IietN2VQ7@k zDBZXwyvl9Fe}Cv<0aXQnmV_sjDjLR;Er)y+9k9s$H1YO`A7( zL8_LO6HMiJIkl=jHMAC+!W%dWrZ2U2)e_jON*$QlYY@d{+P_)T#|YB^H+X5qP5|L`ikyLAAPIt zk&XV8n45Qg`0>42`XQ>JOP;vmhQf=+j~#Q_;}fzz$kPvH?Um8%{y)~GpYf}upT7R_ z$Sdx?x$i$JeedsBs`HKNasB-ZGuJKrxZ&bU4xG?$W^;9)<92>^V)^2MKkYsJjPTl1 zCcGP1e%mo^;@XgAaEZ`Ov=Bf#XlV^MON;#!tw-@cEuwmJ~hu__6DM+;4K@MPJ?! zXqvfg(ZBEc__#hPFN}Qtcc1P0^zI=Sq`f<&ZNpgo5Yqh12mWi$sVCjwbqJ}B`|#@X ztuO+urh5RTh?sS-w%)(|)`|4*PMx?_%7U3x8Ey_d8EyUio(Mfq_;aOG@N;KP==!T4a^ipF^|}(P!#j{ob`$# z^$9|vQ=c0x7#aI-9hBXQB9DHt9)!~qGG)7|T^B}ZU{oP$b^q*&#gW|PBona1?{p(~+20wd%Us?mo@ zsZkUL%M!fUMzI=#N0$Vhc^A`nWHE*_zXKODpP{-DYKF@LM*Kd}-%0}RdKCK<*Xf|y zxj1R%_vz!vinm8$sz6nB?Vw^O#?Hm*Nxx5JmUipAPrqeyB`T$fv2&#gE^0{E^VHRw zO|D^zD-|Jju3n&+#~Jqj$)A2{a?Mm+#Mrrd3ohmqU9bOCO*gsDRb0f_x%z-&rfbK* zdoW$1=fxQGFlB{zl$F4C!C{=;j|CqlY)ii;R~Tth)I#|ie_xJ_{p zW9Q-+&nq{cQe4E?xj2#Jl^Y)^E@GtCCv#|~oTLo0QLM(|Ice?p@dK6JWq`wO{+;Vg z8kUyB(DKTv8hq8!GNq;R+|aU$#uW|XhcIBC&V^8A!pOW~yF6W5<;;~9<{d0jlH_x< zd7e3@s1`QCr9DAdQiJJ1VeH(6UM#GCI`LRfDh;$YP!z7Rb@jCSZ3-oQq%iVlHyrN% z@+d9unx?~TsP>G9+klK+s1Ut4`~D11X;}N%o(b`G_+WwA`noJj&bBwh7H&;~-H^B^ zOj=Sb&sXc3JaHCl%h5uEnB35{x6M$%jvceahznMQMODddT)9dy2rF+kCRnc&Ny1Wk zm>!msF5alj^hjoz&=EGWG8xBBLXmV!dOd;y*2P|(H178uD~`=-PW08l#%64|F|t2P zO&sZ!-)Tk9H8b^n9o$JHt<$-|g!KaJ0@3fBblcL^?<~ctN@sG=7JFwHtr13>_qNEQ zWwJ%&Ruqo4%B~={1+Nh+SM5Evs5V@=YLeB;)v@jN6l1dG>RMa#QpB7a;?bSQk^QnWHoN<`oGhhL4(-mmQo|7|g-4+Po43W@L^w0*eEA#W}f!1%dj^^vuzm zktKI7VSNis86&3#^Gk}j7MU=EJEO3)B&VdPn4$|xGDl^OF@i<~3k$MyvT|}6Yf)z3 zoT)N)1CTQ%FfAvqv?MRLkW-wQqZ=_fn>o6wK6A7&?<>8TqdD^{7-x)f%LTE()fS*H zX|)m6B32igxop)XP+wu|-VdmPu&%Ln2kI)dTh{h>D z-&$~P@+LsPIJ`Aw^UVp46C_^p76G$L;g~OO@;DWCJ}}cc!wAQ*y^tp+7R~ZtzT6GW z9)&aFwM;;ge-5s{1EZg2%-3Bnc_GYLUcy;RI4^np1bHhkpDUbQo>>n*1MW1;Zgx+i zG@b?R9q)O-T&Zwg@p2i%J;3Z&IHO)gq_;N$z67QxXFK7jrdxW)gZ?ZqF+GWr)AuIM zOb3f=3@~{L=M^vB=e1H`c6Na4i5ZdSfq9>^GvvW##%q>u2=tg#oNb7U&Ypj!evJrw zJ{9$^7g6#h*OX`C9)RLS!2Gwj#IahNI5S?pC|}nH?Fbj0SNXn(un&NFh_e=OM!rO> zZe}w7pfCc+o6G8ELjD|q^IF~fEpUT5?*YeGU^iR?=w|`*TZLo4=7t*udMai^W^zUZ zj`hzCHwpAQVD3}67!MpL1zrc{7|xZzdFjV^PX=a+!Wr>Ktd>Sq)+&KnuW-lWx6m&F z$9aPLfcc%m8SzHo$p4JOz$=`aJXVtzqrfEt_h}S3=2zE&B0A&d7B43fyGMaT*P;!H z0+$NhSyAAagoRPyh6A@H3LK|(ABqCU$L@}Ty}w6+V|~+4yoOgexAI_h zZ;L`6`_q1dq#XV3CXe-CVH7yl)5THZmPdi(RP%}`a3g^Wd*bY?*Pj6HWra1`n`P<| zqQsfr9{_URrvA1q}Xw;tJnJjGo%9?``yvNOjkHVKbKYbAz;=;;v&+K z4tdSMJfU#yrK1&?H|#jqbi4=5-#frD9S4Dl=Nv7ZJspz9JL^@d!st}D`WJ`5z7AX< zV4XH4|6D{gGy=zmFoyL1BdhvR)St=Gu+t=%(72U>Q z+g6yp8Evf`4`|~rNM1cPoRbu;j}OOe50APOYh*`@n#xe2oL&ai$+K-`p!SKV1jOf0 zydb&m;c!k&^VFDXUt4KhYmO+ew)!LiY0Z(1BS&OFTYbD@1Wx2dYfc=awA6UHOxWC9 zaxsEqv9dxYI96j{Eh~Nre8squL|v1aRfpf%g4T??%*q?!lc9GTKFf9#XZ7VfldPar z{w7>QLCjajRo#Td0v7vSnDnaowDxE zflrofIeap=*1{)q>pJ*kuKvUbeZcU&WZ*1yp`%)S3z#Bm@x}||wD8NV*&^u;-CKhq zeG5bnp3yQsJ7#r!cuHbZ%*BC;*)errgtOyXAw<)-Y3elmmya4p$xe4I+Pxbu#16O% z;~OS#XYk>dR~WvNzJp8!o`VAYZKvbDo8@l*LGe~*f*ms zahr9QpsEgu$aYNi;j%uy$KvEa zz3?Eyn^Lxiv2!9XDIAO|4{J>^HD7Ji>~v#}3G*;+w+0=2>rI7gV)2BdjI#2)>C8gTW8mUaHpS%x(&9 z7cqggHTX+L96s0@yp^8j;#*Z?5s2AsjgNyQ^_umNXdigwXyfaWR}YXqZZ>jgTR1zu zdDg8nkXJes!|o+{6YG-e-uWZt%9J)YN>P=9BvUj;Pnr5}4U^i$0WHL~HU3ikN26x8 zT!2AJSdShf`KI7DY-YMTJZpP6kcf0b_oibM19JTFiLD8nhk*w{dX+``w+da5{>}6> z7jMP`L2}8&Zx#~5jav~^?L(kn5d6WdrK$)Tw<9C>E{u`9F(SCFQRal$2L*lczdPk8 z4Bw-oR1xy|w7MI*q}mfUO-LBHL+Xuvfq8K<;)5AavxtjD5ub+44+po0XKmZmf+THk znziln*hxbYHpd}g(!_+#Un7o9-}ncOkz(xBx`i1rAM|RI9N)TS zE&4C2h`O+)LHV1T>4T2P3T2QZw@8xI?P2mrg2t9MajC?6%wR2X5CY5 zMzt9A#9#ybGjp%_rjIsak8~ycs@4myOvfJa@1xWIs{s4owsZm2et~qr?H$5L@9NU0 zTX;(aS99=I>FGd*U84P$sr^Tjkujq6el!_zhJ)9K3let+Vzj1$WNg*5J$KRbXFUI* zNVC{#$cI@yF1h7N4pTGn`{#m|i#rF|v0``nox;aqx_so!f=@nj<{Q3q;UhgsY)_pk zd>7!(geGZxrCct2ECTtc`#XGvg4P3dLOv<_z;_>L*clI>)MW&GGTt%pNnIwxCp8Ef zzGC=h2zfK$laJ1`jnGQ?WW1~3WBQV`+u*AbzU}Zy{oXKee}hlz_XT`Y1nyh-iiGdP zV|00^!6)Snfv*b?vD$q2q~yEclXr$Otp3J`-sK~Z_`FsBH{1Vq3_+5q?@jc*>3#!9dPSCaT-EPZT_SKx}(DsW#ZLNWLXzdR>=e$tk<#x5gU$~o%C zAT6AoST?))JRgQ!6ThlI5kH&bx8;R>O<9M5o%mJV#~?M$-+mac3vE-9T4VV7tc9n< zgzJ(yM%%sNgds0*G?$%pVchiaGaoW|;k<1=5kVz>cnrTb9YDk`lN#6=8-oeMf{9-@ zp6oXMj?wZnS~8w)y6`|#5YNaDn~D!M6~Diwts!H&i2D&{X1FzD-&gNFf?RJ)$lhT* zy1=oe1w0ACzcej4*tFn%{e7dQvD+W0_(wP3mhnpS!o=~jlUAP!J+Qes{%VXXIc$l! zF?-_dq`Cv)3lHdXKH;EvbAifGCJ$COgbuC2_bF}ShWN&q@Xq}!^m!vb8*NiZP`gkm z>{K_VDKBwLOXEPHnS6u@>C9APn5mu#Blqo3YuXUsoR^sKG=v_1b=cn&zcp*(i*<)U z3u_Ph!ukkVjgPD4;}R-ej@N-NmNs>#*t3n7-dOxP50~}95W??VTuIsn+;fEQ7r4KN zD^~jx?lRPe&QJP=!6$K(;A5`DYT59q&ICT$l#AfIQ-qemCmZ!V!*@M=QeJcM`=YHy zG_Wb}y0$4fXUX;>+eI(0*jHye7FhKL(?H|8C8+Ij#>xT-!=G6lpD^&5-NEC0 zA}HL2MkeC>hF_fBM)MPSaeT@^(EQ-xO=lez0uz3>FCq6$F_@Hl>3_PPo9Z|3YdAeT zEoI^h4QGb4Vz>jo5I-6}pC=5qJQ=5Lyzn>;768^H8x%e}xHy8JH!nX)_8Cq%hn6Hwi#|naQOfeqh zo{p)C!Nu`Vtk@;JUigx6zee~XCF;K^84q$#r%PtDl#(wJz9if?3STPj?A&6FJnyJn zSqG@COlu;1H{1B}L%5DoZI=@d9x0Kj{wXeYH16&Y$a1Uw9N}Z>vTS4u&k;WAwLtiA zGu%Jmlbj*po7ZbWs+LnxQ&ZcJx}vsXX=+7kP2-9csY}$B{S{U94cKu%t7d6v87yHf zO~ramBXEE=0AVGysY@H{DjKS4Yf_ih)dK0>Fu=7E0)uN;!G0&;1BMPrt*Q|MsYmM4(2^BkVN6z-RV70tR9Ug27Dt0Grx?JC zD`-~Mo&c3Ps{o`awV~qNP(AcCgh9Wd5ZDMC1{zZwS`H;vhm3^KI6-|XOyj23Vd;I{ z>d;c4@+w4{8){Q4pve;KK}oF%tpQI>Lj|(3E)^j%S0l2lrgoLKq87KB(AowsF%@-n z73mp-k&A~w&;jkWUJ1&^>_J$wrO+HP>?O4A*ZSs@9%{eD_<*$qXxL`v0{FApuO>duiiGpC5bA`saGz+d6Q2+N2>1SN!#&p7*`= zCof5y-YvoxZxXmj_G;v z&z|wZ#f`pW&jq)3yRLWdw+4N>`C(2v2p2#Xy(+D0=`~Hq`Zyl(Yk_5nw+Hv*a1E|Jj7L4=mzcHi$rY=9Uk-e1aeaS1u`0%4%77u#bO5=pS@3bX zip#PZyNkfEBO`_`)***a%#P%A6&S0WIENf|rya>*ip{N;_WH-UFt zGv}Q3o-FvMS*Cpx{(>Z$ z`7Gl)MPTZ2XGm!2t^-beP8Argp)Q3lYuADbs~nm3(*%a&HRjL#JzsqBREIt(0>jZf z<9hOhXI=7Hl(>)Urdb2VrKL@>>LcSq(?z-lfD<#&z(6eDq25 z(UD8KR8h_}Z=pM#LVoFV$}pXv>6D2MN|B<_M1y>nSn9xRbWk{smQLr|t`iJ7Oo?VNNx;{;Vh` z8kD@SkDfwh$5J`&FP)RCe$<6YV`rNdvY5XtUV8zwLh-)e+d=8vpP{Imh zQeFmy?dLQDb21-^HcAC3dJbPAvVgJps+XUX~cdK zA4N9GTu|5tnV6q|(jOEWv5~pDLvfjuk3r$H)TD44g+01S39^fXOEBb|t0>Auj4)N- zS9Es0fb;wM3cRL$_Rs6@kk2m?ZctnTW3yb}TW}43G~kn1{dF@FSx1np5JM^dbE1|ZZ-*PT7L+-Dlq`75}XE`gyKtvee9oJkq4D5SEa z@Xg3Zu^OKlh)`*k#Avw2Ti?atia|Irx|s`j;RfOI`|8?x7i$sSS?}m((D>^E#YK#rYbYpwA4`sI!|?cnW?W|+FR8@X zxrTw__c6_M|47>VrO8#IxQMZHrGeu2ar{6xqc-a$hXr7be$a#YK#riz9Hqk9RuX$j1(tT#bs0p>{6u4rSEdeT~Jx zH@WUrT*TP9_`Eb*farDO&x(r}I~S@Qxb#u*KiBob z5LxFssJMu+bDbr)SkvgPUv=e=Os+v{kWGxvC3p7lZOF^uQib9o23(f?F#*AKI_^GP zYrcN^CuUsdD=uQ}ab7#Qc@HG;S7<*iKpm^nmzIT}z zJ6FEoa?g$BDlTH|TDAv;T*T=5 zP^Mg`A)k!=byvpg2lbe+w^DIUK?t}kXOBz;#qZ-jCA;g2$3tf3NO9if+(Kb6DFZ)f zc}e~%pJfdzpREFcbXtL;sSq(o9LN>Z!LXSl&EAYFYpBCqxg=)8`c76h4L6DCMp?tM zg3_duGSO5PY6#ea=OQGXd_|!eTTphea4yK0jbC98Da$HU(qNKmnU$w3tC-TtODIp; zREda;5;I*+<<4}mHsxi7N@k;{6)G1=$Q-4I%%c2I6o#tIyf3uneU$c!jFR)1+1HD* zum;~?8en{+!*2mFZp3n)Zu?R&G9a=;n$O9KUXJ3buR1>zP2AA7yhQNmrgEZDcdo1n zMozZ(rNd&nDZ0Ec8&t4!3_N%fpN6a^ry{=?P0tP%peDlxj@8gQ@) zJ6PGd1qCwUvsR&F4uL^PaY3V3Fk+C#)zV#1%FKRNe4OpnH}ku;9fvC4QBdE}hS4j- zOxbr8m44(zjX83nMjSa&8AndkNQeqm8r7h)J)xucJ1Ia^Luo|KDE7{Zh)6=FS5NEE z)eG6zrKmiyj6EU&o>*2)OJ-+|aOuFEHvP);U0~`dKzYnKo_XBYbpU2ZbiSi7lBZ5j z|4tIDN`A*y9jV867h_eXlXWdpiO#cIBloH&k+HOcvx)PrP7!7bUFwrw?JSk4{d#8? z*&g=D+9~XCcseFq80s4vnMg$!1_`H>7GzB=$Poq!X&Nv)(llUBplE7dez0U(Q9v$B z%N)G|qsz?E6`7;CGA(noTABtr)`S^01+xnSQ;TzRvZqeX4j8M|GDl;iXyM2lXW%n( zit=-EgLwPP9A~p$m_03!msd1(>NH3!sm&a%uWid5jm2&42+YR&WXZJRDZ!!wE;tgg zidAo!qq*$OVmdJ=D^OT4WoiL!FIto{R+}MP3hQy3k~vx}inA%0QxFK|6cq=j78M5c zrE;*@I1c6+$H9nVjna|11MS6Nu+XG4fuW*3Os|#h0uEP>OL&4lBf#PXX^0J{uKrZNmny3}}l0H<*&>9Moi~0<{jQlC3`FS*O ziPd}tbyWV;Y10a`va;Lo6Dm!g`K6y!{un%7>`6yu zdPX7HFu&QMP^S^jC|KGx#aUin7phnh$fy{XF=FJHWq1n7-=WZ`W#bl)9yczOF=pJd z5n4Cc>>N2R)pQ-%?93Q3PQhujGf~*=d^=VicE&k2>uNCmeiGO9k@IgZHajutuW_H1 z)de)?$?=@~J_D17=coxp&Yzk#`b=AXocqV;Mw=5j%c?F0a&nxzobIv6bF(?gncv^J z$&0Y9$S)P&M1kYnZ#pMsEzT_+Oz)y7aHD{`B?=s8R$l_{6qFgASN^dm`Y4P5;^viq z{ec@}k>{3wloyCnUJh_&k@76Fy3}VQt_2bDuuw%qP5vLTJ@qJ3xc=zdo@#8UT`AVT zm)F-e)-4H@FR!a@TyLNnSySP-{NY~BYsS;TNc*f*!Ftu)D0?tSdo;+dh`-v_1xZeQ-)57HacH=_7nKtkh$fr`G!>?G0s!^753CyD|8d*SL58K^%cdW%4Pk^6af zzV)(p-@Gqh7;{5#)7Z;jdtl6-b$^cQe$oCh)xEE|^sy`7`s*KlmG-LzCmnbD(_4@K z*&i>M{%yj5YkLk!-*fK8$G-gN#-hgcssDVx%Tv|&F8XG3cH88F-#vTaz^B_bG(7v; zjMn}B6Bp^fd#-7y+!HKH%u`%F|ADV$h>Q4j*oGJ)djDr}xOXjzfsw#|Ilj#tv#M zcVh5;6&Sr5rezPgR(?LT<`37r*z?D0F?9QKxYEHc$6T(Yj||L(kNtqAGnXFnW2|(k z>SJn+PSAA9O^RYJ5Zt9GT?|Ytvjfgt-pYNUbml2;=P8Q0#Pb)5VxB7ZvZ9zvMUPQU z)m%V1OmDo9ZvO@+p z`c<`fy($w=uRxaZJk!4i&K2Km@J)42sA_p7zN~r!<#{MJf%$wIwkNd+uU*C1tfl07 z;^&MqkU5Rm&lQkgN}w0%9dYBk$IPmgWD=i&!6kmmw0Op8a`Cf|Vk%owv7$q5UGvN{ zo?;z7BeX(nW9uk6^2=LceQquGQni-|el^GEXxkYBV@I2>E2$m5uZ&0^IdY`H^L=HQ zcwdP<31ekd8{OVlQrN>;oy+@53&P)tz`4Dz+yUIr&>QBkw}WE`YmW2R3L0;Naa{z= zZxoIlg^4rYYu1DQGBCyL8R4jci8JMKrOkD~Y*RRPStibuw+ZwYfSJx-6s|paHv;pJ z!gdd%m=Ou`*k?4d?vl0!U!O4Uimx_xN!>Wr61+#=SOrT zF9=z)BIQNc+)sj#a)r_5dD+~rkH86=$(B{$#hoM(HZHmta2lr z?QH=t7bu)8Uw7NyTY$O2j&rq%{c~V`*#RyE@!ki_GYV(u=VIIY9bi6-#6_f|59GyS z)z~0hbnT@h1DG5;&XErGW5vMCRyZ&Hn2u^-E_KCG6Y2Q8__4z1G*NC5^Cp#0{AUrk z|E+nGhmic$Km5GO_ntAq+rHfn@pL!ixG>dOtu>b@i`yTvsC7fgVm7R~q_oniPm__Gf>a%6Sm@pF-yN&L-mQe1c_3`TnD&+V@VDl~ z5d4-o!MEcqq2m@lDG%le zwanTu62E00aOt?rgX!?eJYe0Cc~E80I*|v}VCr-pdsux9>fAhb0{#_0U=$GBn0ls=#)5=7 zPs8r!=LzM-aS3UADCUCGVWcW6(3-`54+g6i($-a0!S1XgAE#zpvjU_W!ImJ*x6=8= zT@J+PWxs+|Lt+!nSBl7yK?Y2+~pM=X8`q+fwFYosY zgJ9|@26{=LIrv2>9*IJb-ak!^ag4#dPEZ(co+HcvMR>LfBzgGci4~I&1;WSJI7*TECw+W&u|Y`d zdu%tcV%#A^@zdcbWj!t_HMOq^wJ9A=(!E zPyEueHUPiwqyo$|y8?PR|5JDvmsIph;loWhp{VOzs0g-etCuGQUW3bCM(Q9EX1J-l zozmf6kb;ARn^>}#4+Pb$Myx@ZyQ|DiC&!!LmI{eMb zAx}Sf@3I*ihb$VD->Yvx|DF5mrx)BaW>cpAyUQCJ{&@L}^t1He;qucyDV^S{`Sq** ze#RFUUA%w(?~gg9=Z|)5KRvN2uiuU5KBIpC`rxLQc0PLP-k$mgqU&<6yz%4kRWCi? ztNGb?raXC>{=rBO*MIB$yMA#|-MQVC{#3V8q+21}gGX?fL_I_j_6K(Qzjq{!`PdtNUd>b>7JJ+fLo_&RMJ0{CD`W*PEU^ z=ke*!oa)p5l38(6%x{M8LuL#2Lw?w5QE{68tRI{B$nyK{z@618_BW~5SwGyY6-=yC zruC5D&z!r)@AzoN4#n?dd*CqtgY>h5@-Zmml5!Y>Y3*grZNGZqSce>P`+b{~oQ6-H z$ad-z=aAFIA&2kwe&0>F6W#OU85oGL0a^9wCNP|(WiC*kt`0fJ3CzQ|Q{tGF58dvR z!v<+j*KrOx^1~K~By5vUowf6)DqWVjM-E@?AFaAOtewa6OgD=ZJXfG(ly@AI zFC7$GO_ffUbB2SG<)AEaP&O+Ht#!zB{ajJZPn>_Sa8>!xHMpeoZG|x{)Wl11u<4{r zE>slLIu9*j(a|!9^xmc@-3`jKib7i<()*>Nn4fM>Qq{rybURv6%#W~V>s1DFs(hu0 z)hFV%-Y&FYWF$8^DEBA|KMKQkn`KrUU*A#d*k0%oAAD@3^zr^D#l_FW()%s`v0vdQ zU`ZLwuG&VKuPFR*EHPUZg`d9>yJZgjG;rE2r^x=95@}tWPGD?YDWKXdgUDW#=y$=z z{#Rf~(Bk=^fRhw!?4lp`4MiC9jTTtsQ-Xi%eNlk&ZPvBu6BQO-BrK-`GNtvN247Km0P6frw!bk{Q z%xYrnT)hMr>C6e~^e8qcE@E^p`JJFQC|;HVZc*&SfXg!5-bZjTPkgxkHl`ZyYqBS(WbCz*Qr^oeA#YK#rt3N1SmI999AOemUJJ$eE zymF(D;vxoImfRR9xR_pQ*!b4L8X~02R$Ro`;~E5t`2@MJOTTQBYl-3_#?CcZaB-}m z$6)$4DlTH|TtfsG+Z4GLop|^$lk2C7ix??$r=ozMD6iWnR!aeFkEYcaa_Bs0-HJ=L zS?iwvVLfL46l+g1Z6*QQU8*8hqLjNYV_}%nXh5!9>Vi#2 z6^$zzvZOiRTA0J7PrNgh33CKJV(V4`g92Xw{O8k%5_&ST4TQV!NO~%JKqGGKFN0 zXa}Lp3Pipe7lT;@mFGL&n-ON&BHdoF+{LZdl0>f8!6t0xl*kF&vK!079XFn+*6g@3 znvsd+I#I4s!tSIFkZL&$m-0lpnkh5gbG?(=vF;vj*|+WquojK$L;{2;OrX5HKD4B< zt_q92mQ;q8oLjyG#-yu4fl+K5IcwMEaVJiJ+`-H(v9_(1ZUwJzax=EOX0}^@>=N70 z6qik)?s*{1Lqu-B#x8NM+;COe3+%Nm)T040g|;1kZn)Y6mkvKwQ48OqM8Sak5Qu+5&Z{xie)Pr8tX$#;S*b& z(v{POj~zE+Oea$Lc8JvRQ@pulA;rM3dwo;3@Ilwe190x>RE3h^IbEO66 zwnB{ZZUW|E3(ia4AAxz%g7cEM7nnm9oR>Vl>?HE_29D|Ql6NXFV=Xu@d0D_rx8U65 zO+Y;JfVn~8jC{7tWKkc!b36#l&M4$P4@{R-a#_mFMP9#De5Sxf=apX0Yi6dxLMSde zzOIP$ie>n6){}IW+vlm!vlo9^;Dgbf2` zl`GC(U#R8(`w>>F9?S*=)Yd!r9Yn%458XfZ3#QUhxul zBQTG4fU5@X1z^VURTr*3{i=bvOyRury9qMx0A?~@l;PrVd8M}*n7b6tOWp$T?*XP? z8l}lMbW@(0FSq=k_Pzu#iX!X3hY4YTKmtTT1qsM0iaEHi%;Y3MLLhQ@kPyfK2_b=G z!l8n?fD(pyt**zex~#k22P)pXE{B?RQP%?%^+RD7PuTTbKt=Qay;s#oP4^r@-0%DT z|9>UjUH$6!UcGvCbX84v6~aaX^QOd6^$Uml0GNxzMUQs@Fl!xgX1om$ zvl*C^vxPhtE@t^taVfyu5Cyjx{I>(+%@Ok2gpoH75uFRnD$14EU{!ir~Wg^`!Ys( z-vAd^AYwJ-S$>xL1JrE(ToZ zNmywg2f1+aNWUV9VIWRU@e-~s1{^)^e+Ar*DDe{REnwPAh6gT^ekV(eKsxJ3^2Pv1 zpBj@3Cy#I!0dr>zxTk^nC<>13@}0y`yyTqhNAaFM1usJ4AQwr$QeZa5fV&Ntzs7)j zAD9k>k>jOwoGvi}>6{Kcva~GV)<|p|?!%?`PGDY_xNzyM0RKn8Oezwwwhtq(8uZ@- zlQdP}I)uTU1$qFO-%6YjZ^)NLJ%QT_%&QXDPL~&g^MHPGF>Hf_TsV2j2ulYhPvWRw z%ytQpN4S;1Y>I+Q0`6I0UXeJ%&JOYp1Jhv|7~sOiOX(d4%xsAZmtMl%2F%k@aAX(S zZrg){TsXUQLRe3UVIWRUb|Jk7$ACjuQX3irj_frr1{|ehK@2#uS4|8!N=HKsIC?%_ z6a%gca2sO4QM@TyNm^#(+x)?pRoy`X%4c60|Wm$Qk9z@+&ma z2jQ3r%o>Rk&uQl``8EJ^lZvx_0Y~=x9WZxA!BPEq7?_tO&d`tRrJ9cY!2CND7m|+C zA+PDUO&ZK1f3bdbD9fO$pYBBf&w zFrTP6$8>xJ%#kQKikDsj?1h6|q;#YKlN*W)Nyl)=I1iYsBrZ}qZUW|R6=zEaJhx+jpFfWJVLekL-^7aGsqr^o@hX<3CJ!qm5PU39op#10y%n*qSryu1< zCNLL7!BKi^fms`h3rWW~;BExw4T+1Cj=jMAQ^ncRLHTh6m}60Jl#ck>NHY#{;nGX# z7y-1^N@BvCX2w*BDE>b$`fmy5KZ0Vrf7K6PFUX(I3@VEPbmAU;%3S3KKXX- za~|>ir{$yOkPmvjD3s!ZUO$RSyp{?nFXKq&55~xTF?>Oo3?a$*LzQK5r@(g-(`E+0 zY*{WoCSChnTyq|EnKhwPDZd!^819Kt{A$M@yvs({r*O2>eu9A4f2x2lf2x4@bpay9 zEz6TQTblEd5P+}P6X?>iTzvIMnU&`e0c@tyomAoPWsA}fN0{mi!$(m1$yPXFw8OYz zqy2;!H@7Ore{hU3ewV&N|1SM7)&T5`uaesZT~)4@;<(^)&-%j+hh#Ah{!RaSnTAB- zJKFF?_)ON93Xv$nL*U!OG@2j!5l1qAq4)sPN)1}n4`a<@y@pxMVr@(AW=PdCo-fAN zmlb!AzZo2M&4VA#F~6lBz(TtMCiLzHpU{y8MnZ3kj>l|^1|$Mz>R201N2m7V+hD$) zCEEghv7Tg=t2nd;$vs9Nv|(+>!wv5@=ZhMg&qcR6pUZ3btT~N!QnTh3rum?It6LY^ z3RrxfELs;^Heij*%@C~QMDW{;!(t_X(JPXdrv~$rf(cuY>|oCgO_N2_gmn?R2D52p zO7{!+e9#@-g+iH>H+DsG-K$j^N@G4ZQKIs4k!)EZt8%`m%EBHkE6l1aOe5{3Sm*+! z6!hUVodl)L())X+<$$&uN3ymQ=l$$kj)#7>Ynm*QUp1_RO@$UMf9#r+y0?RQ2~9-_RM9=b zHH+}P8t7ERo2Di+TUDyD8bNd3A|wv$5zMxJQs1)tLMb0llnVu5Tyq}x+Bl%8Xb@kG z7PhCnr5+yI-5zvlSuUdEc9-*4w##Di1nM-2v>xZ;2@&%AEQdUQlxY(Y>oy$8yp{PD z_FaVYT^xETd|xo_N}NAq-_!%DPje7tiM0sawff4AIf~Q@`=RL z7(^tV9wH*4G_@oWKhL0967Rg6iP=EUh?@A#5UaLbUvj|>*M+haFPiATwK@QEC*G-xXfnx&jYd#KE|n+WxMR&cdv?1Vsm zxCaNiV1u8co_w(R$o{9Od!LxKU91^{VR~a;9D2l_GOR35m8Ee)8P=C4A2rpYVHpqK zRvgK+Wc#$4Rj#Uppm<}zWXwLEgtu<%y@L~On4Qc2T zHfF`)j9z!wMsy5!wB*G#&P?DM>d|l$+|fAGV^XmGJay0;F#rn;zk!G zG`Im`yyVT;COtGrdE$SUmTLK4dnn1dA5M$n#Z^raRrn}beDxt&dDpijuKOj~ng=S5 z1Gc6WN$8I^Hhj`pc%a!QMsz4gn)X8Ou{JETsi>zzm>4YuUjeMGfUOwU*l<9Z*5S~0 z9J+`^247)+u;B}=|K9=~skE(cX&4!#ISq|5d=jv~ST7mdEUgZ9BB0&_WA%B0Js5VR ziZW!`a^ZAdz`qAeDh}=v5{>;9-d}rZoYrufGGpd}CJcimGg^Yp_Gsw=Gm`5X4IV_V zimJFMUi1UM7}s6_pXh1*&hR||-=A?LYr72EtMEO}@~A=hBZq#DGri*(uYCjG+wA)m zzNgqn4prDUgFTH@DURG+U*H;Qcp=bw03)v63S0jOZ&CY*0rQbt-rD^G=Cu;c-`T9 zifMguewKY_8nodC%?sZ)9Ld^5oCU{Ry605-;ky>Tc&!RPV~XIi)gCSQT5}e)&03&S zb1vn!Hiy;D*fu&VZh1m*Qc`2w<=(MbadqDWvpmfN(5S_u5AZ27xSji{g7)iz)JpC= z=D})>hXdUcduxvKWckz<4&>cCPWYtFU^XFHOBC}`_-x(sXwRjKSjZ`0HS!^rRCBue zQ>st&R1{SZ>qIv_m0O*v#sAY%h1HIJda5SbQ#Fk`5g9E_MM;f?$40M7UOu`6yU);M zPxN`Sd~l6jlU(=81@IhnLjYBr<~&jVx?n<0JQDQP=}-sr;+A(tPXSdhSa@t~UR>Q* zh^VYo)I-r_?~nZ2jU!o`kMn-^+2;S&9!hq4UN#nf5p3`*0*}_TW}IyKv5iilq5_q1~G{OYb%me$g}o51F_sZF&%MvIni*hM9{f zEK2!+-+*F4J%^z% zvsi3TG^yu+CZ7JI;luI~DAw6Hi>LoY`2NfsMezNReI@XTe!y(_L_eSmKG6?YVEC56 z_ct8LTEL)DmtFJ?sGmV^wI^$baDJX8e{Im>a4-5Z^wWeGywDuYTg)*QJ~2s|1D}|4 zSOwoV9C`zM;zt*n68JBs{RuwN7oxJ?5l6Ci7-x~n@8Np|N4(~0gWd`I;^F%X`#QoW zQrQ(gk;+pHUkZF8l>-gh82D)8mUztvpGf6o_(W{Q@a^W%ned6&E`U$OHWxk-+d}w6 zY&C|j0X`AiB?c{+`-$0S`b6&np`e;xz1w8zLBTsn0^l7dz5DnY+H?9Z$DUIMq#+sW zFX77_w(+Sr)9;kY8a0rwvyW;bP3R_zWhR*;5BGbSMrBI$oT$`@p3`FZn%Fu^;WM7t zB|MZYifi(n&UPgMid=dQne?1qBx;t|L=%= zKNR4uUI{iwE2p zL#^W+Y1437JYz7@#<-eC+8%YJoq)l%qy&8!|I9CwWE}d1$1Kyo7|G zW2F5b)>6zTbO|D7x?VFnDbOkCMQh&h@APfd@rMBp2fH-pdV*OAb6WPCHi0r;{OFJa^W^*XmC1au%X=vFx?eSri(U#x$yr<)17i6Oqb_iy4Pj} zFG|MTQM>eQWmHLNelZI(WKGLlcnFO>Qr``?O$l4_g04p2F<{3Ysrx5LjTb(73}#+To=}%;I0n%zMX(e#6k4z-E;y4dwF8#=D_JU!Ev1j)wzya}O_c0r zRjeBw;aTv@Af73!JrloIQ0S2dkyVqk_m4@XS_aoX7ch=#Y_rW_8PKm+=j-uUuKP+ znOt{Je?1HR7Yv-l?09qT7sTD1OTB2Vu~crKux?w!AQmfzm0Xml1nFbRnQ};y{@%d> z884z4??@I;*x(!cx4M7B`>4z47|Cu?l|CyOw-Hlw#>OOuS>hqQFISWv@QF5_Mg?M$ zo?aH&iX&OO4d-_m_o5L>y3^<(LADEh3_;S)X3KJd+lEV0>%(F6Ve$hX^0R|%Cq5UaD?-^lgmb%aTk$^3f%N_aJ;i8x?KB+pHUPaVaykyO7rnGa z^^Q6TG_gqI<$*Y;zeUrhXX2odGtI@*ucI{nr(X}~ZQB#MK?20_*UgXPDptJD2PxiI zJwMt83wHj=t>SNMi=TdTh>t0aC(;gfJ%H7DkD(C=Ab;53t*a88ed zUaJy$Rl&a2@|$_R=qK`5Gyl(<5A{D$#}z-3|Ke8h+so0Vt+tV#pZb;T>kd~aKv&~T z07c|*vf)dC?~0$8j*Uh-JdhU70c5ltI)-TEF!jYwzvn?MD5O6*>Wh#g`B!mlgWx-d zeW~!JvTqc8Y3%dDm(IS4@MW;C7`|cbn+@M^_RWQF1pCO6?Qs{*0Tfny3L~fIgnrfO zy7qdmQ7W$ESSb~w*hi@t%|1%S81{ML8_PaQ#W?m+D#o*qQZa#jbK%Qm-y--#4(oAI zx)2oBQ5ad z&kbqsf~MQc2sS)}P*CDo-wzn)!FeD1sBHh8eH815?8C{?buy%UjBug*C+s6BG+`>* zQ0m1x>+++a@8^smJ^sZ$lJEulaB_4smn_oo6~aaAG*2!pNBw0H`%(7c6wy@}(!K*u zNTZ&%koE)n$RfwsNBQt0`zRk=oC-0Y(ms8=t3k?`1J7-C3E zU1Eb zt`?X;`NEVz+TfubG$E;8Ua?piWX-5qTvNNEhEW5xfnZJC9CEL5Q)q^e?pa5L}~OCy#4t;h|(t5bMIk17(h z@6}sG;iRZgfD}~~2vwARB@(qRj(vJKDOy|}STwmJQ0Mo@V$XI8zt%y$4Wp)rp43#M z*VUjaWmb}*W;aDH)SQvoPb@*}qk<<(!;G53692*_{u;4wRyh43iycLAvLcwt^wXGV z0D2mMus%B{qYEu5HL8}x;DqnZQVHMJkWW}qu#Y1>x^k4B{)$M=OaaAUbp#fgPd$Gt|7>pB%)LQ_Yk|ETiWT@(aU^o&!#Yo0f zMXsm>zJ@@pUiyXV*;v!O#$RpbNVpV08as+)x+0p%Gnho#GTR8$6YZ29p(mwB)suud z;prD+@zg9eKxyvZ14EZ?moX?rQe6{f4Bb7<#}(6^RB;T&UW9!J5GN5)3z5+n0M8^nY#SCTT(r% zzuWe$eqZy(bp>a4Y1yt{-@N_i2iMk|z2KXiMUPK@^O|0|9G!mIgkWXG_I1PWSvtH| z)&-l2_3+Sr_Ex`lm;20t!IF25efIsvo!ojJhidm$Q5_|Fzx0aDu)l+e#yb1 z<99rgtzVCgy79X2KD%YEp8nOPMLQ4AdUHs)`}a$|?=`25X*l|z@9vvFyWrN3-&xY^ zS~K{$>+g%Z@Yf%ub$-ow^jBYh zsOj;<&;Pb+-?~|QL`oyK-XL z8HrD31Uh~5?vZ_=_xe78;r0zoD$#!1XTYNYecwQRzd-$}?;EIx>sOtw<8-=yA9~fp zL-}-^PSi0Tczv_I~zwzOuuEz$CUH9}ex$ox3zdfk*_X{6i9PG5a+vU6N zE4^>ure%B9O)sn1{g>|#Z@TB}-+lf{`pb`h_1u^D{blmpz3pq?{muKY&b{s;E%Bot z@BaRjotxTMZk)XF(fG=;ulv1y``(p>H_h1fd3Wvp(R07dd-kFI3lI2q>-wzg`K9*O zx)*MXw%=l``!Xi2eyCy7d1EI;lUG!=?)B+cj{h#){*B*Eduhs#&+gB?Z`;>1{`qM7 zyij?%{`&RrT`s=i?`@_`2`5j-{bp6#Y47GH{3TSL9-odo{e}6vPwijbE1WzXKcMvA zvwvJzJU&#OE=O;#|C9Sq(x_f__WdX40YJ~lw-!GC2QjZ>U2&g6)cqC1?LXNINP2i( zJLjLNQjTTiOd6G&J2K%0GetC4WYwn~V*_mD^a=TXIOu4eZ;rTxHe5a3l)O_z^ zlS8jVxLrP+sgzv4YZs;x&|^{d`J~weQ_jVSN8agXlXDVdF2kAR^j!BQeoPFNb24Kn zFUW?pU+76TIrQCt+qDg6Dkafn{Cszt9D2FM?W#m!Ce2pPP573RJ&#YN%py{WY1i?KBp^kR_`f$y_Zc+Z^mTP z8ONHWw=l&NYUdQj=ys<3>TQ#Q;sTv@Ig5LBd(JMWuT4%Lo18NkQ-U+4t54m?MynjL z5^=v6F#Q=r(kM0lIX_%&motDd z{}6@6j7y}8zGrc}=*tw+r)b?4hrAfV7^^;K+VnY#F*o5%W!`zOT@>GtGIo|t&QQk8 z!I?CDYR((~wCj8hV}64(s)lxS@7$;D7&QHeD>5dHF~5cos?}GO41Zflv_5y}Ybv*^ z2Ir1A9@+a=ZkkQ!48~;QO#0-HZ8P1j&#)LU!x?icopIFP`^|c*9BL==n*$EDo({L^ zGm5L=siouv_HuGJ`8D*0*(k6%A0(ZM2%i*VhtCx(6+KtgRIb&JQ4LFk)Z_HiO zY}H4U!*PuH0|1n}Pi(muOk_=KUW{i<0B6dJ8~?fex^cF+CNQQRXX5r(Ja@<*7v+@O z6&d4Y%vzjD=ZQTIJZ6{UV~k$L?s+2ZE;}YG223_%sKk=n`cnC&b~!l+al0O+GY;=( z4?khWh&;_@j5RNEZ1%}x47DEQCSLL`eoCMeTKhlwxOclysW`6gbE?j;VnkdM8KcKV zZB)K3t^&qHj%!j3aZR?xHOUs&6vi~*O!>Z}>n?{jyf6k#5o0#vOjc?8(oBaob1Gxz zA)?OkeK;_2k=;JUjG@+*o+-E9Id}0?o6gf16Il+L66A$d&NQ2x62?%uAm_X%_PGdA z`(q_GIWrg&S9PNy{K1Vi#|Hp;6u3jNMRuC2k9VnnY?re9Zu(<#$!lv*2QgQWD*bgo-%m?vzM zmn9|D;Ob5V5iZN1%#)N!2IVG6DKIFnOUh`2^1Y;-WKdFMRu3{L1$yR#Qt3i7?T{CB z64S@v+Gybtk!-b5-nCJ_uu(ctRbi)F>}(rlx}*#>Vy~B!b_OMA<9g6WdCf-o#zr}r zx=cnz-mC8fxqd@Lzr z4N7m15YXMAOp}zs2IWdg5wRb1jQvj*jIiP7Hp=Msy0UtSnjtCejkq>S$^?V*iKI+1 zC}(yMa;6%TDoM#ODECN8Cxh~LNjbxy^rnsrJF@B#_+0Ydyj&FVrqiv8~rGtS^THA(1`W>AVG#cfd5Ns6iA?Fwb6Wsj9v5a)JXD1>U)o_5O_(u>QZ zlIwIx7R~2wNttX=PVOS`V+_hgYto-BpZ~|Xi^7mph3AnQgRK-%aSs} zpmaG&aCJ2((A)p&!_iH4C1Wfmw@c}>h_P$(fL3guEzhAEU6L7{Ps$1qOgoW= zCS@roG>2qT9tUNBLOBM?P=%6(p7UshvH_GFh4Kn0Xk&9jl=EgM_#zE zKD+)8VjhX^l1Ldi#why^od>Ghbr#Ol4jkHlSs;E_y&Ph6q@0g)fp~js1KC zsB*-pmhewWIgDWepG!G{VwH1&BIlXqHw+T9g~T?Xr_hHnEN3<-8s_IaSHsSx8_LT>^WrGha;(B74D1jQ<6K0;MFV!nmA2KN?n7()cD3KVjJVwFh3STrqvBtgt0ctA53&uP{;|2Rn9_CRXJi7i_j%~gdD~YLAwbQa)M%&vj|jE4y8-{IzZ_6r5wf(LF?U@ zFT6H`Td_|i0#vJt*=E9*OD@JJTvg094(B)=C;w2nN6fwBM%xH3G_Abmk9bl)Eafnl zB4;shYAVG1D#>{VTvWywLj*1E48BN;)f&|ZaJwk?sRO&R<%Tw5evI&`l8Z4!;Qf31 z;VLLrIZHrwyNFI5*xPH(|5&~yZo|hD&w$X-K_J67c#qFXdOb##Li^oB354hrRB}^M4Xy1pGvlO9j7wI98 zgx2Mx_7`#pqsG1r6t{~y7Hx3|r*joZF2bl>b)bafs+U}ZQMu}wi#mCfCgJqB?vPxB zQMm%3gp2EG$we5ItAV+kt@@?pB8+F6tV%U7c_y zcV0u@C_)HV2`+MkQMp!u;&!#AK)7uWJ#eSV)hM|LqjFsYirYoKE^=?We%xbn-7C2W zqjFsgirb~<)$aN6=q2hJ9*|swQMoQ*F0ux>Yj64VUnWTvWe^OE_KE4$`!QQMopPBHD1m<}ZI|j2YKil8Z1ZSCF}= z?bTy2eX}GNVZddv#wO-E9cR+;A0w(zt#$rol8Z2ETusd7Y>g(#MHrRqD&}&w#vddX zVN|ZGnTy(9yEXnKxd@|jUBg_?)_7lX5e8fqYh24*6c<^eYGiRg5i4%A!;*_IYFyWW zV*Y}lmW`w{i5K4{;ZV7L35ux8_OdZRauG)5x}Le5tuan=5k}>@fw`QmK|9csBMi7K z)<7kMhQo0t4LjBzf?&ODY?54rQRBLix%9HJx?TS)lk3lti!dtJP0ZDv={T{|Yvc|9LZ$~qxTjQYQB8(c>oy_H2Hu|59 zKsdsvTz7#IuHCpmauG)5x|_LlYp7-ZTFFHimFphna<;~+l8Z3lvRLC@<{F7JStIW6 zXP|SWTf;pRBsjvTaoq<>xUw-yauG)5x}Uk6%SNT-B8k;O1&gB~<7h#0f&q)dhB*(Hx-J>jrcBxa{+u+D7EAuZ|8dz1fu)20$d39NZ zzuF)0d%frRW*7Trd(YQ0Gc)8(0o_G}ON65+4$CZ?0bvj6vV9DvZCUw9Ja~mZ~?=t0lr+H zZ)R$mS8`=n`^)RRDquFplco|m^6CD1f51Dl9G_pxZ`ulcxe{)r>dN|-F7?+`cq4os zIm4HWuO7+#f|LnAKE^6o`>4Bn8AN zOdQz;(uR>iBLBN= z(?SG^^o*END+_Z-(af}m__AioQkll3BHte%ZXB}GQGJ4nDB?s<=NM!)r5qO(sz9$$ zWksUS8&%B+Va9@*`Ceb3c1h*@jCAk0i|`$Cg;DW*xf7|D8}aNX?1KBwRKt>sk81KI}kwGaY zt>iI`8|ydxTov^)V)Qk`+CVf@#}`X%xzGy5jhtu&kC_{-U{Z4Ac=$3z88O#SFnj2E zb+t#l`rv6EU&4k_Sa>A=3j(0F6gEoI_maevjQ;6zpR~V&tRh7YcRH$OoL=QV!!eeZnNApD;=ER6H?u zqG#@jk(3tF&YOLqnEMkpRa!5@sW2Xg6o-O%98yNuje8tY9J1&*q>MZvx(q)dQXDG6 zaioZ4ngzAtdzU66^Z_4Z_fpibK>56CKlPxF;|CH|QT<^Tsmm#z zZc5Ctv#C}wp2v>K6%Q^YqFB4breQO~_lGT@h#g`JE=rGB)iny(Y6|Dxr^76|t;1>L zeJgvsM#YjTcnR1?~4 z9=8;$Dy{D?g{pB}609m@9$$w`HU9C)$jmGo8CbQ{Uq-z)uXjY27r)?_jf~JsVMrx@ zgf77w2AIaeL@2$%V0o*7Cq`2-S!t5-z6{H?O~RQGD!&vtbOTIeY%^XuKIC^sogDHz zbhIa}$tL@W5g!~TI@VT4=Lnspko0VCS!$8Du%NK0urNDU&Y;V&AQ_gzhfOM;=$kw- zI~#eEHzl)Qb{4KhnZr3p36PWPojN6Za&gwA$(W+Y()pRgv37pua9%t=bNCWoJs-Ec z!hU9|g)^gY%9NtqoScaeojoaYSmp>r=*Wq=Ik{6N`zA`I>Wz>QxrO<;Q;K|f`h>rs zXl}v8tZZL)j;`qB5JjhYrxq4x75R#by>eOp%;ACZg_*-MM;X$yvb+Ta*#-G|xrN@$ zQJKRlYY^Nor%)KM9^R>np2La@b0$v7DxB!0rTk4X`QC!;sl|CkKA6oWMp)P;D|?c+ zFt@-rsTfRFLyGnPGl$c515)EaZRYTLzZqSzw_sw?#O%qF^Soj^0N?;Amm2~gNBk>r zODnT0>gQy8C*~LD7w1e2$0&G)i_HQ!!s)}JRpZRE>8X+T1n`ccT$`Q|L6ShEM@6Lh zym))an~O{M`F$a5Sh#kA)wKocO4IoZAjoA|yyxA%rXyaHN{iI|d{3 zgjz8+jHFde?_lr`NKp<%khp>(O9GugDdb9kt-F+TZN!H{%DW7YL zGG!pWHgEiX&cB>%9nKj!YD8L!>C#4y7?w6Nb!6HIlSaO@)YK6pKuaGzYS=Iin%iND zE1>jQ2PF!xAY9PZ6{>8otvDBjnA`Ip4Gac|;z^yRTMb-9?2;kgj)d2zoX!;1glA#0hJzfXH(Y!5SPI%y9ONR&>(B?g?&2U9P9A-o*H2;?h!f|VgMMcNH$IBI zNl+*sm}{xP!g+8wl>@TZeu*I*xp46w0PY)!bphvOm&2g{NVt9^DSW$@j<7NPv3?8= za%%lG^Nl_kyiH;lh?7$~D19$E;T-I@8@K}!8!jEAAn#u>${R2M?Jf>-;pF`WVP0VV z%Yt)C2jM;f<`)A=TKM`#^>-66rwwA5S^h%W4Z@uR%(GE&6#Tlx2#L;iej0(_0k?Iq zK)G=-)1lVO*Ma%m5ohKvMcL_0Axl4-@=P4XI~=&rB{ovLo$&Sdneq#86=%vzg}jLp z6Di(Z2wVwVw){dlQa@rbFdHN;QoMIcOtg640&cVXf;dvVF9P$C#D$BOx=V5L``bwI zCLpj!47l5Y>j&IUi8b24kn%_RyzL~2MlnAJj+^{ zL?4Hvi^R}9yEduH3R^^@=BzLT=S@oWT34(h9A)h?;BJ*zvP(GJ!@%r~f}?o9lo)u~ zg_Cy@3bl_4He955X8?0~47eMB*&YM#O<-JU(c?V{7+(||rFVwJ2#MkCw+gsFM3G1N z@f0v0#(?`4nEv!&f(vIqDlemfX^=RomrnUX>9|#5;AO|SI{NHgr(mBLc((($S7O`Y zJ{;~0d?25RgIpxsdSEukfcqF2_b?}UV(lObp?0GHm^l(>*v0boKH*6HWx(7aaiYGZ zZWHUSnevi=djOa}sW@*aj`~B*z`QDPM!al4Qy$sx0AYsXfQy7n1|~HW7m^MtFFC+0 zmAFXhxCoeyD$bUUwvcx{FgHiRB?ET{Fi%KaxO5P17cd`$;zH6v{gco#s@3JqVm*!+E8CI;WT~@!N34Uh5hXg#Ila zgbg7$T5u6lN9W}E3Z@j~6&92f`p(UsIHqq|VM%t`%-reY(?+MJ_H_s^I5&5?@7$@= z%W`tFX5^Pm$(@-yWxNw|dP7a1a*2OR<-EG`x>e%~bINj7)s*8y@#$FYp}gJ?;W@c^ zz8O=_ol=lBrtgya<@1-;1wyEWB{Q?9pBqA)IwhybSD0JUH-#+vC628)mTO}9x9l+& z&cJ8V^%vGxE@`O7XW0#P7v}iu7YAyWURdL=Sy)-)FRNKNX!#O+@PcWth5ow1DQBl- z*DkH}UpTJ;-}0YLs$3|LLn|ulE|dyiSdQ6D@dZwq_^EPe?Yt^&j5e-|t1q>(-S9-e zwvpB}7T3bc`E|ARwF?3%gQgEonYt9_sJw{w($213vJ^XV*J(3?ho&|AD8IGf_GTY7 zcv`cM`c=44;&AC9E-B(dbp}K#a=1{B7#C`Yw8p|?FSuOIK6;vH!4K!`q*3?~leCZz>u)5%D}y=p}L#*9SP_wXQhV036R9ra|nZ5x_k- zlC^8D37*@})0CAEoOCSXFD&j!1ZbbqDG|rpIFeb{@8FBqXtHPz(@uzvAF@zY$DxLf z&u~Po(6I}%M$oZj=B&*Ss##4Ld?#4%X{K(hw*GKnU~odyRFQY5MP=6lv}3%FlE zX15Fet;*Gs6kP6Ef4JeD;4WeOUCp`2h*by(&5*Lv3zR(hJCO0b{hP=WDpO|ZA=Q$3 z>1B~SOK>l8tPVa~j(rg&$J+i+w+2}&)Ec4&QC%{vA<6++LzE4&hOKNwvqsNo)^I8s zUk3A%n~IWKij#sxgVw(oXcu&$3=}7U)|@v8YG|C}O+})_SgK-Ksgm)B0FCE*Br<*? z?w`kzjCJ&}4*>ft1^t^SS=%paV#s=GG5?ZP4c9PPR97|sFUX1K7378Hm|t4w~zAjGItS#^GF#E6}kjX(r#Tea;hnAtVJm;xwZv+{cl2 z!&#((hO44tQKwu~EFXN=<4_vKXsP)D3=tc}pCdINainT$M8%-gh>CGssY!O(QiDfX zID41Qfr;s9_9%{IZq$VR@MMUEO%(r=z-+JueQ`}QJZrbdRcX^(lGblaykQ$fLJ#nn zRj#T8sZ8)yWO(C@W9wfJtOyo*g6$hS1Pc?IvpkTcHD~eTcKwSDX~DdN#;iD;(S&zx zEcOIJzQd#8Cb*+7j1KO*oSOH)%PGjrlF-Z14**X2UT&`xXUfcwoq2o5uL&JYh`HcY!gx2lEpeVX%BM zX4}T4o`WfkD?A5J(@nONO_t|rT;^#kiW@zZOtvDSB|k3M0r|->l?7jrMk_PSNBtII zz7_EO)->e*con}+Ov+749NHEtYqNsi-hTMGoQtbw23PchAx8q+X9ool6)IZbCMDV{q^g_^9ns*C(eF@1SQ~ZCvN`obz&((x^PHOV7v6Z4YCO0 znTET#eh}AE9Ctx!*_<5-ywgV=S6W+d%;{^2TL0p@_>6EAnOBe0`70dp){w_9&3kLNTi2@L-+0HOx1xC zk*ZE1&1y;TotfxzqMV#PE3vm%i?PQEgYUY4JLV@ttIcfN@i>de7d-qEJ6$oDpwY4R z2#$8z364%YUr4-hfe=xqOaL=^hD?x7p zH$LYAQg}4+{OtxLHF41Prrb}^>g0Jbu-sFO2B!2cO}S`;x+L@~X62b_?Q=`KOg4T@;lo};1Z%sF*B?*mHOP& z>csQ@C&Jj}xEEu9YWRMQBU!r)=iji8x^p6w?!^cJDs$7NU%6{;88+;*4I8Km(`-nx zMiuuq_EAX?88sNb6qqKSMZU%gFAja+ z#%XbllRTq~Jk*i({A?ZB|G1XN*Gu#?=6OU{2p!ot>c}QgM^>0@DVq%Agk^D!MV`@9 z$z&@$|LKnGe^5oygYQCp|E|}JP71USdQr|A{*5}+r7_nN%u1Nkvd`YX+)O20nMa%9 z;Q?7)Tri6|H*I0%gI!Pz+ckTsGHW0=`aHoph>R2Aae6pcK#&`KA;Y+qg19QzbZY~N z7I2Hp(ok`UkJHkvjhCbunq9g-O zuh1m1QbKv8geQ(s9QU(LlW`W0Q|iHq;&>x`RIyq$YI6O5>sqb*G3;j@iT*_E_HeSU zoTj4QIrSybI&RGMY~X$c{20w(S_+dU?J~AuoSvkuU7e&gWTFpj^e5V998Ts*%98ShbftdaAsl_%{*qdRu#N^YG#xiFYN)Ugd0%~;cDk3YUu{B|36_=)_T zng8dt@ku{XM=EylF_%NTje9BldS2;QO1oaOP#A0u%v@$Z!!@1
  • GL&kj-6Q{ba< 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 MDfl_b?6-CJKNK_TasU7T literal 0 HcmV?d00001 diff --git a/lib/extern.lib b/lib/extern.lib new file mode 100644 index 0000000000000000000000000000000000000000..af8b30fa28962cd95d647c9f5648c04c40f20379 GIT binary patch literal 5688084 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 YcQdRoU6! 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 Jccxm1)FV;HU|M+x4c$9u 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%0AVt?IhaNCavr?J}Z*uAhZQOak#}%n%Tg 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

    gBM7G6qAW0d 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%0AXZ2Z9x+x206k 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

    2uGeyngC2^`7fJ+x4ERU+2zM^ML&}r0-trvkk!R z^I1I?zp(C);%x-2HilH|PjWMyK-LYP4tW`lpdYt~B1jAMNZ>m?O`52F8A7VB7OU+* z+xeygvGCN!$T_EEaVx+&&b%K>24@0T$63`6n)e}tzu2i`EU#tMI>h1_P2fJb69r=( za{#U5?cs%!S)g*Sj?ro^f4Olo@O?(;bPz0#RqEL>s#jIEGi&5VYC+erd*P($wwM{C z)Te8tK8}vr;VK>LV|qrf>A08~B?DTcQF&uj25$mbpKUKUsoW5#Sge?W>IgpH{oSyt z-6Qr`8=05_tF23_`YVx<2vwh7&W4v+00q{8&x=EcR!S+&Ps=@Zj6vNebiL&UmYHj| zLwyV;t-WM3NFzjTZ-9z^w0SJ1y#t5xLCYht05vRLnhKY0`SlSVblDKdGU)3)>+9IM z96|ES4AcVdz}@8&mm8wcr#@22gq#_m0b0k~l2&T3%=~}~L!S|Arkv(+jiXn4xtWw; z`pl~FwAPnC2khq1XzDSvdf=*~HsS1m>eoJF#pka+Rs+tB6@TqBR{Qy?k6D0sW4Bv# zbMR(FcP7OI@EiWGFSYW^!=$E0$l3dg;piqjM;J^-w+_#NxXl{v+4|e@W_!0BSX!3x z!U7K?20ATRZeFSGv#*cOYn;=*8^PPnlQ9$wFoA4Wf4wqy=9kgrH^{Gg9Y!~Y2Lo%c zd3;=dd$-yC-}64Bn(uvjTHJkpx4GtzFaDZ41F>FVoPGc2&1i|w5t8NB&d#s0f_r}< zMy%25>FYxD=00}6WrY~6Hy@6-o3D;p>1Y>0?T1%wy|7@Bsc(r7FT!j$i+f`!O`JdE zoSO4+HTumg;mE@w?TPor(dO${{DHhbjaQ&(PY-wU+&9<*FnV6$A7S30i^U&yDb(BL$KhYA;%5L%EaT&&WI8C# zZ~1hbHxYzc9b?yBk5{{=#RCMaf~UMIOr(1~%{p@P%(CXjVfeLCtpweP^H_3KI*efz zBWY+3x|ncSAO2YEtgGjF)=GM`h!8gqc}wciV)w+ZukJtLdDdQz&kM?3K+gDPPjW5A z?IPW`7VHp{y3oboR{^5iB~w{Fed|II2)ReGy!-MNYv=0gas~;{oiVeREo|bW)P=D$|MhaQ75@apXdlCv zHA`uJ!#GeJWqT^4Q?DM0NvT(lvJIqP_l#*{kB%ifMK2WoZL1j+ifh|1YFSt&b9ghm zeklz0mW*HuS&6PXRPh@fHE=demOiYH3J&_3|ud zAK+5@gvtT%x{4zD)bO3G&-c-W*sBj+@X-Bef`^s|O=!YE{`JfA63*QCh?=9FJ>Q{c z(-d4^n4ppgijPkC@1RwFa@B+j%}q`_?MBgl+H|>GjyzD_3m`gT|et8%~e3wELI)yJE^iC zq(4OtJqjkM&gF0Dtvca5$-bLW(<0P`Sn0DmL8CgV8#FP}bb_~)P2FAE#+Te<)UK;g zIODfo5!E?z%i>W!lBq4DjyYq_Xn#-;RO+}oU-6vI-=?Y!u_oEC%Ju7h>e62Q=xo}j z4`plgfULA4lAC*B?|Y?_UVZLg+M&lSOgr?xT$8^Z*TlHt4DW(>%n=a9 zT9g)!SGYZ2%+K3R_V~zQI6{f(Ri9~yQnLOwYK*ZSHxDRi!yA(-C&b6z4v*pi;H>Uo zE#Ahc0hZgYnKz=%b2xy@XiDD(nPem1m7cEgI%@ ze+I?|?G%qR)WJPOo(7p-HY)&nJC3}MHj%$LV~=SbFYnL+n!^_R#K$wnl%`llV;kXe zWIB1-tMn;CzAU{obl(t8rvy#==aND@Vo~dF^TW^Q$C)!}2BAo`oBc4cd>>`l1~HwRPy%SmpP6{(1N%ZfZ@0^br^}BYchLW<#df#c%IP;+Wz3Rq zhBvOwPcEq`ERWoHxn6R({VNyWGDCl5jT}Vb_#1lfKotGsG&B*U4@;wUw7Kt4%*V+_ za_SDU`r+C+qxxrNy!>Nzx12pd^3O3j+%DFrds-@T1qCJO2C75s&X(WCn?ExqIy(-{ zS6d#?<$Y-;Okx6=<4Gw@_18sZkk#&PV;`g}TfrqU+Zw^tzIg@@QXSLEn~-*TVoY@ z?L#ah`VtZQd+49PJ_aRTfw{ScN(DMEM9WKPme!6z;X@SJesO5<|LGSpxy5EP>El>? z>4MvX`>%QrtFZ7rD(VZv#>m91ShSOKDHCfJk?NG145A6Ff;H}qR@}W1yRR#>nzg59$!o2i|jq}l_ zq0J8dE4#nAAssToH^X0FSuY&|%+)N&B9c9Uo;!ETQ_$fdcDhf(TWuFuSf{ucAXNs@ z&FP4PhPbFRhSnd5-j!?j;)P`at$NvaeG9i!$gPjg7lvebr+n%iU# z&cpo#8U35zm>G(@zpTB&SUlPb;JdX)3%|rs{mnI<*3Y}oPB1q@dXi<;6PV-88ZpD_ z95Z`mTFuGKH9k+Q0c-Dz#1h;*-Xj;y z7rPze%;VDP1l$Lf0}Nuzc)7b1^8mM8>l66JEZ1iHbrGi$h-py7;-|ZMB!|+qaks$o z6c`oAn}-VCe+kwbbbXd6hfm!H|F5r(Z0~p9NFnAiP(6uwjWwIvcNyR_-nTTAN|7AJHY>r~HG$v3o#zFARkV zVUAYA`&S$eUKrBsorfULBn05Rh-EQDRRf$oz_Z=v`gvq7f>O`QwE*rDJ<2geW)MYc&AhWZC11zi0I<0A0gU_&7UaF{>nU? z>Jt=Pef2IM@c_^IO?zzDi$9i^MB(g~YxBUT&vAevt?KIjKKH^Zkm{j;ywTo$C@ft4 zvw-pYQeIDh)H?Nr>m2wwqpIRU3>;A#-FN4pzdr)!NXkbDR};l)g4CT0@zu zf8wmjA{{rIb=b2+%rIEoC?!Y%%clGML31 zVf~UAS|qwpuo>Z?gs7pjbpN9szLh71Q=4G1N};El9i-fD zT1x}XghT`3372K<*(PIEwhNql5_P+Y8fBjfaL^XqiEggi8!iGI)kHABYdP3_jy z@0N&|ncWnXr@N1{{F{45K4E#A@~bp6el?7b>H5QFu|;B)W0n0HA^!Wlb+*TMKXn8l zF4k9@)kB{Mzs3=P-njU1KF%IYwpVLXrfj@#5Q)Vtqx}grd>+;Yh9|K5A9$A>SjmWD z+Vz%WGcn63+Z-P91)JyHva&aZYmQn3QFD2zG96;WZ3O& zPv#-Ek9$RA{re>)2i>Akri$D#|f0=ft9;9X<4h9gO#ALo`ahr=*6ajDzk zFM$sJ0Up<#Td(O7R-7R`NHD_2E3R5wT%%}nQUpFl12iz#(b-{Qh=ao+Um+MQ?^HZ=FP10~wj{C6-@%GwV=s zNu3NYWY?V4uu+Z2M|d}$N}XE9kA!}Cvpx8Z4>28U{k-7i6U=igqa!kJlKYSA1DiQB zzUgji#>x1fU}=6s(K%c{eqK24!`$9fXAiG$2#(86Z_HK+S7YWRt;Z|lxRmitH)>u! zQaTr84VRz3ptp0aZ#SEQ_q!QE(9d?(t0?or3KFaAx7=9)%;&Z>r|V%X>*TzYxL=27wCId*!7w(4XEuN z!TnYNRz(Y|NCVw`MMTNNr@)-9&|C#$RA5rQF)VcZEH8^!LLjJV4#*LU>C@9A&i$GF zk``+KYHt*&q9_XDHL`=t(W(6fM!uk;}voi{T-cUMbn@&|ewC(BwymQl&! zHS#7@!b0#O@gbrZvDt`bw!1Yt0cA}r?%kR_+^wH;)e2@0L}$GD-(Q!DFIP|7!Obj` zJ~L0Uyr@D28eq4X_%aPD-Wp^Q$vi#+)zTEgVp11MTAoaf!4J8pnxN55?4t~-vG1To>1u5Og^_Aqlw+jAia z!qO`E$>niY%JP(9wwru?BpZ*jcs6<)+ku~TU`k@&3qpamtGjR>G9bo_q0M|o90tIT z(O8)Xb-i9LJJt4<9?AQJfEP4}@cvSsNvjCtF*RV47tUt0E4OpgO}e@=gjJn%;jvKN z*j%2v>~J<=lXJ1JKsa~p{8w8f{=(E?&htf4Wa%stzu~#XwGi*Nt52UG*ZIkccK1FP zfnkR5x?f`ok_%fv^7U~+ZM|Y6_7|g_D)A$BEaUCa2c%#Y6)a{_ zm>Q$9bB|y_D_4R$()NfV&}YfLS8dI+jq+(sX7ZPL)`Zzdg4%4$xQ^H2_Ej1wywybj zr(-U)Lt*hK5g!0iVV9uneH-49YR$X(*Fn8yunyI^7oBH~rL-`WljLDi@uM^|V}>d> zR+q`?H;cVZA?AV;f;$+Njh1s!a6fQxd3M@0y7-ggc4EpD=B+eO%m3z!M7a?xNIAkZ z1>2%rN0HkT+~>zD&rf27%dN$*S3fB?9eb!d&mfU)X7)~mEhVdT$U7(R0XlA+2fN&g zrmnP8g%BS%7t84Edh>S2VRll0m-|E=63E7O&@sp4wCTWmk&q+~Z8t4}ImHm9e9K4g?6rH$`* z7!8y^N%_x0P_=7bY_5Ivbj5S9z5D#Ft|O2In(dqyO7@dxaN{NkuDqK0>UtJQMH68G z0(YAo$I>mGMAI)%?LM}9)v1Ps=RC>donKfBV$?1KrakOF8jEu_C{Di1g0sqw*(v3q zO<=o52c4yXJ+OUyxcj`_JRlqgVW9S5u7)W~@ayO0a^1bSt^-pVZ5Lk(9H?D|2wD*n zTA;{Q`Iy7FWD)W86GkRcmgf&qVw%l^(7W(NS$c{Hq3YN(`|FP(x#hLneAqXi%spV1fa^7 z({71Yneh%Fbxt~h^lv}Hew~Vq~ZP?E87Isd+19a@Q2dgm8Ovgk0 zB7x*M3*}PKyKS#uu^I!#IQ@BA0rqzM(xvY>V$=|}5g7UYqWUXr-~-N`pEvbu(z&&$46Y&mL^C-%;GXfx)K>z06M2;g!_=+jKc@Umf1l8SYA{I zJO+3=ePJEh&Q^p;*mz1~mzi!hUtA8KBp!!68fG5nIO}^ovDZ7I={5#Y6o>U7G<2!6=f2 z63Qv};W?)`HeU&7$M<#b3^@Ff*LFsM_4vlh&VZ=CGjeZTAfi>(8H0~Y?jZNq+-w&c z=BWdjR_?sZka59vp5i$2P?;#^`LjMI8pHLw(b4|BIX6-}Eob^R#@@7wnl&u?xgSA9 z(1wf`PYVp!CU=^AqBZ6^I>I6tyKCYBcxfPxp0eAmhP+vDe)cdo49%vx0i z&aSOnXm8pL0owurGXR&kSf8&xpp5vIwQReXYab!alpuRH7rwDZ`)@YcUb|My0NJ%N z2^?h-J_fK&1*LKQOu9>~)%Gv*#lu4EI5#u)NqLvzo74m$~ySQ5to+G9N*ziyLozl$a$vD_>Y6OU6JfV*1;pto@#5*Ioco}3xS&qYALepqF7 zlHeg9_3_+l?Mx!c4f``X2;|SZpok;&?$c0e8d{@H-g1l-F#&d|G@YAq4Il;#`+o z+yvm))zjzFE;&@Cyc~Wg$fXRGqeu<|5E7!%J_o9u=>7XDkUUyt6w)eEqVvKj4kbxc zi;YUoQeuRBC;r3Y5R*6mHvl@86jXLa>)2Q`1AxgkKVk3yQ=s&A%C&X3-SeEV`ylCF z-4=_Za(n=QdQ|5~dkMknFOqM3Uf|BPW-3nz{K_UgD{bv!o!IGAq`jEe2bKT=C~wzH1fR^otF?D;&LM#^Zfv(dSGn98xv z!Xc9E2qVp{t$~LWnDkP+QiPhFVg!3f!Nbf(d1NTXKIObz1DZVf;vq3JHRV+iI z)%7&B%gXQ_`Bx=&L3eiP&)uh52YEeR9SH^rGFR4or0W=Ssqf#{hVJ47u@v`SA4ch8 z7n&otGPwTF8$FQ*vZ%e<3*RwZ{krd&6xoWLNcY%9_DBfodgS+2UV+O8cO4|z;I|&j z;^Z3_*KzsKSPHOZ54o>Fp6gIK=CyA6<;iv~E=?A?-?F%_+s!AmpQKW%X-5n%XfttKKD-rg%pHcPuaBm_ zhBqIY^u&fdrRkRAlDnSvf@QkdDfxobf8CLhNNn-l&qJYO&-cOh#?#BIu% ztj*=a_4AH|qW3oKY`?i0jnw7C&BK=m3TXr{B9m4Mc`8yaquU~7tzo7LN^}>M4my+U z(M@OBdqP(EZ=!{~VI|52u&ObA5g+~QD)sDq-t6+B<%nq<| zma|mS7+OL{c?N=DC*SE!G4=?8+ENF;DtC7LmpS6rJy8d^|3nK(mxGB(4uhRxbE1a4 z$V81nDfp4g!M`y-388)xS;L$>3+26psdU%)ZnHpj!;?edkV?Ui@<_hki}114DWT2( zuvmxS%r0;fuF@OYhKBbBcd0Fy19zg4=OQVwBFwei5P9L)^U)Tq=^c8ElGfD0$!5AE z-I8?_h&xOrkZWjX$3UeZW+$|vNYA+FDe9Yl}ILVa9qzjh4ZfKggJKT1S@ z_UNUE9S3&xOsIxr#w|A->m;y6&uQD{4I&s|WB=u8H zN9PARCy5(QW~}AsWzGc9g6p-6LiUD_k5_nYl-EvxZr+}k0fg+m+l)wE^@)@l54rOo zfd#V%sq;-D6?W7JM2T{p;j93!*Mm14`Tmg09(%&ggB7o{aBcIp}o(qtS9 z#X-y)#EXM8fqNl0j#B+l2ha}09SLp=J6rD6HJnKn+g1~l)+zG)jt4T1ebwV>yI7HH z_V97D?_i~#U0()ojpY(;$dUu+6E_vVs|DSG-Yeh&>uSXngTFLLsZZxnLWWGFXh^HW z3%234bMD!NQxQ`0e9I(_>=@MR{DUhzLP}wn3~2R0gn-?yo09-`%vUI~GcQ=3kFk1L z$CVoSs`cwJWRK;M5foT;X{4x-(YjX8QH1K4;oNv9cM?AZ)`ig8OS&;CxDJ#^XIAMb zbpD;Bi*~A-(s9dn=op0QxWMQV)(BDEAi%6wZQ(BX_AVsC0+nwRSS&yljevYYkr?iu z%VpGk=<7W@)^e}w)dKE9UMXo>+PYE+(~hCMkDqe=E{)It?Le$8z9ozvrjF`1lc%eI zu?gCN*xrT?0_-xC2~-EVOxCd`qx=h5nGM_A2c7ZfkaABQ#NgI?et5`^SvrN$@cC); z)dnY5UWVH?bQgO36A7uV;gRsr@$92+EizYedFM??Kcf1**N~;Bv;Mu+UT!KSm|oLrytnn) zLWeun)OYn3I>))Y%P{e#r_AoJ+vVX?m1iF&eO6!W!D4eS(~A`epo zM8+{zI6;?15+OEsI1N~Zh0`gwwH3a+sZ)hWB6D4@*jSym4$($}hfUs}et0CT%#eKl zIG7#s%MpY}~?34`<`Xn^L}$)JUKI>DdX+y(Skrq;s2HT7Mr| zwwzB29~m5I+~*kE-9Nn8f^)CW2_4eU5o`B9z0`tpuepT|>D;cD%P;@*+yv)da|<2P zxpm+W`*t`WL4VLdf%@;C{=9eK?3kJ{sfW3R4smYs)I;3P7vFM`Vb0;%#?MG_@ldL4 zXDlApF?y1{oUekO)k{d=+8%mfARGre;wL9c)|j z0w$|)4QyQr(gKhn=xJGB1v4mL(GTkPLhco}aRwPK#a&<$%vDw!bN znYT5orKt+tlspL1d}*x=igE^BhsZ#&P@PNf0rRm}8e2Jeo`zyQtuspb10;TSeK0o5 zUn(Q)P)cacqIff;YH~*Vl2o<0U8 zd!G!ecqmptsZ5mDhBH%M!l=@)C-|4=<+D}C^N4vZT#L1AzPU-S9Nz}3oxY4s3^D5i z6h<0x9LYE(Bw*s9<7x&bS3q{jhxwEOm+Tgq)sf1DFT`W+^S9mV4wDV$HQwv#)RZ*{ zi2Pr+gBNnKa0Jw1%nQULFUFX^N);gx@jGf9iwx5)`=x-H#lDB5NmenopmVntW zsDMcDV!(BOZL{gtklGJ!W7Mvw(NCDta@tXN_?s!IX#7@>=JR9Yu_{p~_P&_k)m1_L zT|togx6XG5jx?7i|YjP7q}ZxY8G`uiT_eJ5E6MOkd$-l2DH zmt)c+^#-)rT>5~MZ=xGaBI>)Lj5|Un7*?N77^~y$1hcPLH<2*VrG4JmFi+a5!E?->_o(TUhRMcq*1^w9Sy@rf zS0murN)ypJ#eGu_LbL-p+MR=y=_3l6WNMA~AqQTWtMu;UsOlzO1OG=xX>Ubs$gZ;{ zeapMhY%T3T6RxuQP0-4kM7P=WFd8})8@~fXdkrJHt`&owZ@8wqomUN|by6UeB~nn8 zZv!gvY>l(9KUe0^=+|D2fV(n&-6u7(WAzUI&`9lXsSn$=+eVUb*FR)2^6p`7$y+d$ zZ)w4%3)P-}zC&dMuV73On>*v1_U_%DmPggGehq)m_M933<(V}AQ%tS-<)ACLUGQ&; zRF=%Ub?n=>Js~|r1DlbeLbRG3Did`d-nwSHM@~Fj^0xmQ(%2q2yQkHZc4WQHBW+G+ zrlx(m1SUSOh@)%xwkVShpR^ZNHi1b`OV{vX8WAC+8cOE~N)fg&ts?xMQ*6f6rQOXY zWqeVyXRrmA;_6&2GnL?Uns!zb2@s`~sp09GM2E~MlZvOe3|yF6xkLK3owF=Sg^l@T zz)CaAfPT-Ms?uC;cBKy0d6qiuIb+NL<>*6qFC}q63RId|3vj>LR3*oBPhPZb*V*cg?F48w>jr0ruM*6?>3&G{dUa!ng_|?cepe ztjm_x(4bYY=@;WA6oBF*yDPq{Wd!< zU#F97!4&4zg4=T{Jz{CyjVMR!WV!JY_8o;i&5o1rRUOGIWt$7=f6tBM+tNOz zVRDhwg;;L)Ah+~gjY;f<(N8P-w6xHh@8~f`P>`h`E;r1@l?RCL$5xteK;1ptid<{v znzUDEnn0#s-JWL~xQe?dWtlmu*6+j8o}WV5y@py=OF!IB4{qPfY4!Ojz!Xnrf=$>e z=6-yrnQaO5AHd)Kiqc@+YhLAL&4)A~s`GEab}fDmyoUcf`N)KJ6>+pywFz0BS&3Ve zB~0?rB=Su%o>o@nRW4RW`=E`zlF0sd7DaOjwA;bcA2)7B{xXN3#3i2AvH@atIBqiLWRRYGArY z-7fKKw+q$@Jl-z;Jlaw)wLEG7F~NnoNK!l2ax0MeoX1Uw-l!blqiL) zd$;MeCOAh^Fg;h{U4M#);;`R$EsTeC!)J2Pdd!5ciG63gSxZUZ@`nRwgIb5wT)3l- zIMFaw=*#D)$7kxW5?i_>aHg{7ptiuj;@!Xb^E#V_TFsZ}KoU7i`V7gtT%81gL{G#6 zkukasW}Mv#1gtNV3~7T^tJr$XY`geC@t()^;@i88Cm_X}eWIZ|50njW+J0kI&z6~5 zSbiZr93gBSa6(^9#ANxaEm8wS&_b^4a~ziDKHI{)aMCx+O%{-Mn;EG^pH@$mFQSL1 zf907fpbjD_kbQ0jaFSl!p33ULdt4xp`VV#iDBPj0v!^=sIjRbrqra8{?nDw*zo7r6 z2Dt_9Jg`9S^@)A2KX|Wu+-tyOvBZc+QFZek%YRpwq37xfSe-;Mc(0{*i&!eh;4hc0 z&RirUrg^^FZb>SirF1*O>o%0VvU0Z#&60%)MlO^+E>06rxy7z@Q7d*gGGIHC0N8~v zNuCIAOwO%v5jg+ew!k^UCdjTAZV%iOcZE*3<`Lt*d(Ff=>DxU(drtW}pWnU_S0TT>nD0>|BQeo~uoU zHc>c}a$x>u4WA(7AEZ)kLGU3a`^`|rn} zv@hP?9_NyXae4U5A2Zh<&_-~*diYZ6O=h;rQrL?r{Y`Qh`=2rCfnOCO1D%iL3})#s ze@0CyDLWk?9Q`4HAAlj=?)BL9Ln7B=zN_ zV0uB)G$veWms-EJf^O>-@h~=7cd^+?;l*|%Aom%k0XRjhEqxh++j=EZhCd>O6|i}# zU@OfxWMl&KjjkFzyq~1S$$yB2aS;(ZpN-ipS#1kpUe6ke+G<)9)dd|tBWT|7>Qx5H zX5BJhdW^u;xfKFb`%r1GjP9F{KCjj}!YFHXye3JF`C9g{AZpkNZzv{Uxgg3t?YNJR zOU0(-7g~tFw|3NDz9RWy^05FjBWB;YzuCKED{Wa2C#)TLN(p%JUCw$-ZDw$?6gtyWvL7MF@! z)wWu-i>=jKt+b+_wTo8%zxO@o+;=WvFd&N)n6ShxR$l5f#?hN2nO=3Qh*8wU zNvgce`nw6OqDLqMM_pgEqX%_s6g{~C?%;XBQ*k;sO?7oW^`O&MNl~8+fL4{xA+<$O zKrKbbbcrDuDeIx2YN{|*w`NT|<>No*kTEkwC*ipFUO55HQ*F{vw;w%C%qsWvbl@Bv zFaLQ@DN;b>MXv}F;lMaG>()u7%3B~jb01Q`Z9YgU4L85ajV_h*&>t%0Q6F2Vp!yid z{OV%>11ns@-~M3VhZBlFY0`UvT-*qV%to(4a3+uft6d|`dxB|tEB7>Q#JJxXnz-E$qg1ti3o+JQ-7dTK zX7pva36A^Ezlnp~;9FJSnru%rRg1AdUFhLEX~&1|Sv+Do&Yy*}#e_*RMF$S@u*USV z9c?QQ$$kBF6@X4d0(H7AE%`01y893+nwKI)EHaAW71tgIVU%bGIB{A#dF zCm`5=^UFtBiuwWT!4i?-a&%h&1Gagh~M~~3DQTJQ& zI3>ls=}1Pp&6%qDWH#ekkI~7Ft11+N&d1|g&dS!!iGgIMO6D=EJ=JFP%`VYU>C7B~W?j)5@9E0Ff@|%G z$Ac?*Q+Ru$=;x(#C(h{+S(f*QQT(d6+|Fa#`c$&M=&AF3If0QpbmG|o|vj$QDib@ z`!TzZ6N=Gqw{@>P%dKc9tL4$gb{{NxYO0s#{#3{;mFz*I*8-M{QWk5r)cws(DB^y) zTeIOpW%v5i7AY1$`DQ9^Z;;Ja(b2o$R|Z`* z-XZw}5Z9o&`%ms0uttn-0`f#GO5xa3?=V1yPaKdd9k}c%Js^g_k2VcUZnFL=1V>|Q ze>cuMbyEZvl++EzWAv)hMa^Wk2NQTSjkmnd>N?T;Lc9s8jb@@@F&r0zx@tQ1Oy)ei z5>8=$L7p=06ix03Up3~{U~ye=MpVL3eTj~JqBns`%tcFTnO(^A<{de>Rt-v=I`9g? z3LbF~e`8~Fm1rFLQ}D`v-i;wp&hzbhYYswoTV1pu&mgI-UG&CWf$Z!J#kHBHjoO5reYoXw%wR0=v31IP9#SU9l~xMobFMVfLC;F$OHKz)GfU- zNG?&Ei^fWwNtWyS+~L^{IlcSCnmUx zhVDL*ki{ZS%#1iIc%jmIeiCu5&`c0ws*(_iqP_xh#WyO zR-*pMhre3muc~T76IF)S;M7y)C0zBK;MWD1=$XF5vf zW^{*p<7i4;x-Jsp-X2Lu`f(SY#rx}c#_NI+;u8ooiW!$)fdt6&u|2(LiLXbeMa=Jd zf)I@YK?4_;rd|34*s4^NH!OIH@|ve!nXFDGd(4isHoZg@;L7A8bR4WXFB_myxKq=D z7jJGN77GNzKohHK+RP>btr%#qpabJnP*$8sGU+Ux{eaHrzrx5T~O%N39~Dc3g|iL67n<=5UJS2 zP|lRcZ(oF)OOlbVJxFmind1>HE2`^I!J8mHV3G%76^Ij4{eIj^*%=mom5UkNYOK|2 z#~i1Kdwy>!M+xq)PvyH+baXKzNo|?4NQ<|x)KIw(HpGGS5%qdi3{^-DC2Z>o4B%Mf zwgz-Js}q^tXunsdlOZ+HzJX}kAJQF*V@CKZMxG;epUDfN@vH*9WRRd;^Y=DF(@b!LH%0OI{6GTZ3>x{u0_$ zV<6%hEhbKc+7rj?o9N;J%4jaNKfP7xLCfGBHs$V>K%NVo+8U&j-zujz%)#O|BidWD zGTGMPRmc@A(eHD!9)sE%Rwji!Us>&mR3;nkq50DukD+E;Lql3#j!6Z*HtDvx4Io5p zO*EZ>w>^GYJRsL-wN-PRytx&}+<+-3n}3y%ot3DZ?U>J=>yMTDb# zT}HQA<*v09fW=7+G~C|v+Jx|BSh?){(hG}p&`!qDSBb94Y4hDiWIWMY)ux=32%7dp z!zl%bhO9l_oruxG?98fe%!A4J_iTzG84a93(YqLazbR!Pg{o80bpbDj8*^CD8^uJP zpNFd*ENaqeSX`|cyr~L)4bAGUiYDY_0t$UUCRyV&%yt_j^YD^d`&IFdShQF68>_J& z)|nGTy@{yiJ-3dGBAgr2ixZvLN#@0lSgspDMis|vy38L4F*&eRi41PT6faplJO+mt z8DtPi?mc`{^kN=^_^22d2CQhH*-y8{Q>HKNzP_M;&Ak~fEmkILsGs8POljrjN{tu# zO0Ag)Fryf2V?_lHJ9hk9U%@_zFRTW5?8UDuqOBKWnekA~iJx~2%P;vu6=wAeu)*C|ue3*W>=bgxWgyb~Yp zUe^%|4;s*g#>|xK$WkJLdkX?64jS@R7gbb1doDzwfLl4vqs4YX2INhan)d7yngV@0 z940ELYNIRwAMLP!s!eh%!np%pxe@{cGCmOg8J_^Oj={%^po|X@-Y+W52=Z7&Z@K&A zd-&j+k>Ku|@8Ry5?=ee4Sv3=<)%RjP&o+6hdLlV*gE2tm)p^)aM5F6AHM$nNMAbeb z&znT6#Z96Dtz9KbLv%s*o1<&i1o%zVX-IyrL!Ci6xovg{TdOb!xVoW%7bZlo1Y9m2 zk8~wdkyuo2604ln5yiE*k+hh*sl|~TF}#9~WU#9VyH#t$=?s>g;tjB5$0TMg-N(%2 z8ceOw+hN^pMO7_#TO!y9gk&u5(1qk^V zgS)zo)-p8ob>RRIdo~hwpUkwP%E>yM0J?MUcF1N`%yq{JJq-mlFFYLmVrInSD2qp%iJ*bkgGCYErnZ8U{Bq?y=@ceK^WN8&R zo71$}1GNBF(8V+TnH1I1G1?|OkO|k;wnZ8{()2n3y#RZhmtnOGt=P?k*%#b}9^^uNfXC#_RMK?tH z;_D+l@xC>9(ZbP->0*u@3m3yYm75!;NaB(;5~q_IazKgB4UtZ>?K2Z;M9m#W*Fr5h zb)y=YyqYyL#aAPss=3tyOAZtRmD2`z9eKD832HU1b@o(5%gYhu;Azl!8uH@d_AaN9 zmozv2NR4>26N$9epyf>>!E>jHA{Hjr>(bM;++)0EEKBR={lp+w_k_dcZR*_;Z~v=h zBIPI3yF|JPXUq6WN~E#i5G|;W&b{&84u0WSjyx@Pr?7vGOn32>Iv{QW)hnBoar9GA z6n$gN0q%(71-ClH+(lgn17^01}jHET=ZP-Y0)B1o_VG#0r&e zjKS;~+Jd;yJwUHz@h+bvU~%5_E}E|`i8b9pqI|O@d**f$kL67>^(_5Dq$Yrc>r@RU(%5_HHiNB6*13E#oCUN6b6GOE zuF5q#+u+E30nvb+Ln+q|t4)euZElA}-F9qiL5{?F@NV9rFfJH zJH(?{Xpn42fGz=r$0jVO{Mev*7ooOxs$<+#go|Iwk+XMlkgG=nO->#W2d9A803s+B z0LeS_V!c%aFAQ5S=yi()g`fgSFDtASTKY*Uk%&Ulk;|eq`pF}dYA^!P7*6%}H%8ZB zk|680%*^!MIh2Y6U4I;!&3?XYY!`M7Ym`C})or2WyDQ;yO}1OxFwDW*)GoZun8 zDT)1Sb_Tm2-aAq}y>n_NcD{Oek8MW73Yv+>1hf>~&zo%2tm=rSXz@k?ZzQqgc}2B& z35nN$@j2X6mq%q`!B{>MtXMKWQbkbTV`g7^9PgtkdCHpX@ov18Y_6{3jEig$!#O6j z3k~Ps_n>mE&SEK}*p^3$Mp=gUf%RccFYT>Fo~o|nHTtn=-;yj!v+o`yfW-?~pt0Z* zTV#CUh;j+XDkSVo#3?tl=?G&O>jYU}0hm@t+}L(RA@0jWNs6giM>WB#*F#tpFXy7| zuktDOEymm#G=~HSfY;a4mOWjN>wp9rD7qI%g~La|QNas0bw8{QZ!S}t&B^Ig?u;NR zr^;z^i&q}yaG@*D@(Yu?lxgD9+q6b%kNC5{YZQatn zq~LePGLghUBrVsAqY4+hnme&pU=44-_su@^VgXDsRnf0(M6p^`k%|#LwJh3!o!i3a zXFTJ=La%tFD|?a7l_>xyq$#YGfeyLu?#kh1 zV}Jf|?B^}#^R7KlMW7TwnYEQ*6@TEZigt9M032g7IvZ#hnZinBW^{V2=b;h{FK(U)V!%~}dgPmdl^f~< z1q3rV{Lpn)2`oIs*3($GOFHX3B_))bn@Y^gY-KtRg)KnX#w72=@!$~^J672vT46@S zCz!HW>)=}$;2p6E64B({*IXd!^A_aiC1xPmNt!)vt$Ep$EwDr0e+2Q_7Qxs0Kg ztiw=jUAtDInAuVVT~J$P$S0DJl)gkdi6is+6R{TR^Y^V$=T&GOB{dwdx^8;!i0XVu z;{uN}?|n+3?DPSwPA2nDx9U1Rt^{~>mkJWv7Od7PaWI3~|bqqL9O+{uOv^DR$Mgu5oKulGK_uU@QYJgSYLOj|#dJyZX{m~z!= zRkUZ_?uwxCt(BcbyCu#x75lo(ma7{5371{E2n&yqEg2ms23=8%vF&1LwByQ;9j$yN zlANBTwN4Oe%j>c$KUf|Pb6%&Nv*8L1MzBIkFVo#}`SBvTz!)AFejYl8=Sva;@_7f%>Yj;xOC!(j>7 zLm+Pzz*%loQ3g*3@DVhw^C%S59HHiffqh;>d8y`3f+ViD4}amk_<5j z_4nL;SW4X1fHXit?hrNEN2l8d%~F_?8cCF&E*feMwf`dl?Df|a!|#@hURjj>nYGyv0$`bE;I(WV!%A29Ozir z*%(G!`CjM9&E_ebYLBc-FVtwquRMIBb86~n(eJ7#7EPFEI=hdB<(x!{=34xtjY<-A zQ~~9YK<@OBIYKZ`q%EZ^W_cjEY(oqMbRA%%b316VW06DVey8_5eoYlelE^mbz);Tx z6zs7!Dru!S7LuEn9ocf4R60%Pv6Od?to2Xh9P?yX*RX3uRP>e8y84sYyJKIhj`sme zL}g2Y$$7X{wWr{AY+d1w5jGZyxpT@19wQe-4c;bkteR8pGLs_<~cw3a721xBxm8oWi% zX9Q{U2q*txAR#VR2=s=>zxHNChPgoZ4tM-N7kK6%-;+oy-kk zG^NY$eQ1xIuU^gxSQQz=8Rk)ph$&d;F$_kh?=nhq26sLKM0m~dY8!C5%kUT=dh^r% zmEl%5D5#1B`5hNI`0a5l!<*yU$P!kUZl+F+u+9~{y!~ZF(^~1XBPnb!NYi@}vB!Z6 zsQsX(<~da~VT^i^r_r#RD5#gMrv5MxO<)&Ow6iPHi}FuH8obp(H-a3{QdTW4EfrNG z0sH&bL@-T=#r$}GQofiPEFymj*Zv`L==~|A(C*d9nk>%SOXHPiq#MUzQb%6g!A*Br z;zVhzV3G~ThQ8RalaVKHvLhQCP-(;%WTZn2X78sh`gEfO4&ey^xlw0K9rFoT=B{?)?Q@S#; zgbrgbEpu|a?nw)qf?S;gWLo>zOgR?Ghc_odm^p{$!d+D+Bf|27Ls?a>BFHriz^rU= zWnI}2$Qenbqmk$UhQ@S@7YZ&<%t55jc1F0OzU+}NB}z(i|BIIu7QK94XKBaW(zyy( z9-UWSS~jQ4{2wbT@0?o_wf=V~5&Ub?nxpT$(Ir2z;}7! znLZ~6U*YjzlFj@9oU2?#cgihQBKTM7T~Si%A*W2Kl7lbzqIb@*jF~?xN(9{UPtP9} zC9~(-6|->B9Dh6J&b0w8Tr39{)ACU&g{MP@u zobc9vJ-=6!=jc}+V}OP4;((g}Q2gd-AiSP zmFc>v+~)kXd1?kr`egqxVI;x(t6;NBd_M{{x5W3OU|l7?9|bLqQ;Rg~zBCH|M&l%>uI zr9wr?+%8r6NC0#-^@PUM7ZNbNse`oH_RuPrDw1|Ln_a?Y2N(&P+a-+GZw^eNyA)jg zm$2MSnfpHnrkrzsB}}z(UcV+xPg9TPqf=F&wss=G5` z+$&BN(HMwIFYzOo_{Q{?(~Y&jWJ1)-4ZG`8zHSjroMMAQ9FzALVAz5|ekX98kb{`U zP7QCBgljtDu9W8L>$O6<2S9W6l!FyJeH?#U7)&bm)A2lr)72&In9DW2>HUEwf(Q}L zAWkx-w{p@$Oy;T6WfC~Gh2uA^^YV3uc0`7fbYM< z$x2uvG|=0PJ<+q09czssXeTYT$K?)rfsv(gBW#{fCKrXC?4g@@!*7^bDU@aPheoM$~UhR?C;({=Whloh~vU>Od4NT8wi#qBuHjoZ*Ydd zA*ys5MUbf8#9$t&(aRS&2Mbec5!2!&SD@z#9|XizMctV|?{Q*jaPs10z98Sk5mm9^ zg3_JI^ao1A&eQHd&>F0S3l?Qoc|jrQ!m6D>KjV1okA7+(E~eIM1|#wEW?e7}-TYKE z5Eku2|0u6K91X6%2hi}~^jtc2*1HuL2yhQB>}ge9i-PRwm5GxHnU3H>ke;+B{%q@b z8Q&nta_WmQGZ9LQINZ(`9+P!aJ|Iv1&F~KN24e#IG^VsDHp*_m?Ui_Eg>F!=WQF%c z_V#vpy5WpRbcWD5Qwy@ZJ6#quFf1n2(_dMa@`8a_f7TOcwXJFNq@$hr0I55W2M*ba zmtExnU7PI41Eum{9?%#%fu1mGt9gLU$EW(k*7nEO(82_NXa`QA#AswaZF%sNCqdNS z1Y!JhrWAyZxm<4*B#w^w=3Ay|e2OheP}VOSA|$fw;VHN;I?#&)13lf*UVbXk@8=93 zFzioZv>eIsEvNZ`gHW*^TC7DWf$LNAlq`7sBu7)RZd@1Q4dFW!X{h1};Z{F}gWEk3 zU70c*)(+)m2Rabw2~ZtJRgVP4LoVJ^a5PJ26w8T{HPAF3dWu_c3G&_IP}n?6L(EBjJFJ7W_4mUb!H$g{~9}CxofQYCx6FI zFlKRlO>0#ykHGScz0^PP8#X3X&!XYlwBA1D@&YW~;|!y6Z$TlJ;t9=X3EZH98Hd4k zD=<$;T!DtO)-Y{n1OU6syk#JiC zOhV%Jz<(>eRyd-dp9jp#61S&@)59@gf?*twFBva?uZ7!EVE!y|A^dmq_s5{W1I%p` zVSy>a*TU)kegw=R`!dYa-}B%+ADFvcak{+cfO*FiXT{68kT-skVGQ9*rVw8@{f+^B zJ23A^oSqLXd7lC9pvi{u6@1C~$$J5q(0&5vB`=GJoe9kK`wQHG_;J&30qB<J|# zOGfwC(vQ+}6bZ2zmM6;FB1NWT9Sz(85=-eDp5QERlnJyNAeC4C|%y5V&!^c3ozew z#aZDc{zoK6F?+@HcHmx+Sg&{{d9UOt?=|4w%axZNLM~N|uVbjb2 zPXq3lLlu|!4NoWu=i*3S6L6oBSgMD-aF+pdZvc+`eOh9Kuioh6`+3+m?tET;@u5L^4uY{pFhH{1)ZO`nemJK^+&)#f<^(Gr$ZNrO@DBaEgrXv7H@!SKt2_hQ-OcN z6vN?4iBU8I{ZMpWPgqpdu&iNGV?%3W)ykU13#LXITWccibuA~AV#VN87x#vhbuCpZ zm$yV}>#E!8Bg^XA>z1A5hHS}V7kqDgS)wBqO>H=-u{Kh>p)cBtQz>wa9$p+lcx~Mx zoItm7Swr=LslDleSbr*$L(OIrowG0w&X3&K+FsMLG6%bSS#48QV_oaiVyd^^!S`-_ z2aOQ-(rOl*-iF~|`gC0K#HTN1Q>WL))9Y|{(dm71x}$H+49ugbLCwtKx<>r; zj%=c*^LSGH^q@CiwwGiJjD-_JNR83PB;z>aiYfGE}gKw?n9!zL62SO$^5(Nkx|=gC^s3~YpAdpLr(%m*;v9x@$cGc zt=nrT5)C02m|ZYZ#JHh>q6^>8esKssKgl$fLYY#)1+DSD&MiC+IVE!DX+wWHe-SyZrK@mD7s0R*xH6vZMSl*6W9GG~T2K)xtgaPR7SDuEn>|pblCu(;V^di2Lmn zZzAG`tiWm^r5do%px(L&=``4cjx%8sdfRmTFhIwxEY3&Ac88Kf?{KJh4TzMb46sO~ zETx2DQ~XR#^FH>9#sxz2qhJ#$GYdA63O3FE8KC)RSe&MLyHxG{x}s2KueB4}So8cm4Qb|i{hfMv$t&H-ehE?(pW9R8WvGsC)CL8kzVL@S3) zBwCfJ(l8?7au%#b!ix5_p|#^=Obk7X&~It`@WNkY)(Rv&+3^tMNz6P5}cUx))RVZHulW&FMR-ONAsGgE) z`uHOZMCRI1v%MBa?vOR{(4(k;U*29XN^(6Vma)B_^NAJ_T9KxZ6>?oig`$vqWy@ik zY}i8eUO+)cE9M`nO*Y@_!!6W@hR5I ziVunfY8eZS6Y&)BLA9!gj|6NVSA2YfeesQt64xxxS>rh^D#po7vAvE{e|z0d2sgIZ z?GQh&(a%u*sI6_UwLFU4GPLnh{$~W`H_~4a$Z57Xbc+=e80Nu@#AP z0WCCW%8Y=bdqp!rg~l8_MHV<6wmXMH>BawZi}fQu#d;j13m>Q-D2n=Vu=TL7rFeb| zUlDtvs6R9T1Tj5Fzmzs);`olH_Hu-+IyKEhi>UrbtBy9DTlFH@Aj?*L92#~>8LAou zC|dO**w7)^vSQShB}Ma_il|jD3U1X!uVCU(ThY+Im(QP&*?TAqzq5ZY+eY0lh<<-) z;+DFiq3UsG?D~VV=jAdOfuz)^p#?+L)D75k%c7#UCPK{U?O~1~khfF;0g0o8`zYmJ zM9~NGma3fY&aQ@0YeOxvHjw#VHG&uJ%Cv7?PU9S82U$4QTjQL1N=>wioK{2607fGe zma%KS8t1H1Z7B6Ng(DiKJ3=l+%j_R!fwZ@y7vjHYN2#A6a_Dzp6FHR1f}s7}q`eNC z=vmlWo}iZZN-*X0CvsD8j7-7uZN4dYBP1ExD6*}H`X&o5A4-_z^~7aCR*fUrspHwJQ}Lez+Fp+Q-iBBF3N z_&>}1AE%BK9$m*PG#yn~)i3$2k^n%5(Zfu&vDF=YVc*#Bx z$gA;nO0-M%(^`)OFRib0^@Cz0AFVeqw^26ecf2F{$E4VTeXX z{VI2==D&?^p)mu`^Vn8`=lN`#hv%o+7RFPg@M6;ji?8`JTnjn>wXu!-YG)h8(`vR+ zxmm?F%0o1wD>NwXs5exIufKT;&fY#m*p+-ZlWpX~S!^R8Vr*O49WPGDQi=XdaeHI& z`e?d%T>?vGIv0!`J3VcPQ&WoROg)+dEavNnXN?`(%Ex~#D4w1kO9x%U(rL%1#Pn;i zd5VLOHg;?cHfvxLN^BhnGzE<5%<1VFGmB@?>Ujv6S)AxAo;p1}b*ypPlrxHrR=G;h zoP{jrv(Oe4A8i~x7Wz94#q2ZqiW=z`Y*VONm2_u7RW_4cMt3IRtQOJ-2eZc3)nSRy zhHyiBqy3;5J}rissqM5v_$E!7nn2s-54Mj=9+`3>RgDx|Afky5z31X_)>< z^D=%#CV7QzijLsnke=NOn$nYk_L?T$78vEB`X#VXit?IJDpR`g?-#V5bkPs5xnRvJ zO&{(5%tfzW9sla-MH^0vPFq`e&+lvJTz6f(t@pK;#@+S6hMsq?xNye>i+;HFc=|gZh%ZoK^7m5D7UUUL1Me|~?-6%F!KAa){{z-% zx?ei^`Tl>!j>`UWUEyC}e*4b)g>&kDzI^h6KmYj$wO?1iivH$TH|}?S!3Vz^|H_${ zervyTzI*q>LqGh{_`i=o?w(73HK%sM4)tICu9Zgel15IaMQx}fBf;}l|@&6?a)8oe%7T2-5-0p;k59i>v|XdeDl5c)&07@ z@P(m^*5AE)@P?-g`W{;R_rZDNU#@@r`{)1gm&RWn7=O^q=iPSpPtPtp_l|=feEH=5 z_5V4c>sMPII`#e)PhjBm-ioJ|ee}R9bu(Z3P0?*T`xjnUG5M=MKH|^oFKKK3?5(f# z{Zz?Oc_vJC%B)1^6!hb6`{~ZNf}7?%aKFe@EHLYwQ@|*FKD~$MfC}zs56$T53v*@fXc}+bM_Y zAxr1=H-7W!@eVl?8AH8dN|k4R^x#KAdwY8A%a~*Eq_pTbdeX#+4mmUsC~bbK#J=rUx^ogap9c^;8s{rQCEs z1TF<3T5m+@9)7c}-;NRKekfy9x>I@`;?Rd(Lo3i(nt7p1Y?w6RCW$`_*Kjp6^FB`kNv!qV~fKnjIqaIu|v+(Jmf&doV1wAazN%> zN594RP&f=@IzQ>5DCLqe)ud2wQy7JbDT0Z~I4IwAP^e88M#(`%okKYwluIddP?k!{ zXw&zzBxRgQd0J8qGASpC02_y!lnW*0Fq87Cq>MKyhs#9U)1DKUqbT$NM>z#ME+Zj_Y0P0Al6rNE>dLKQ2_7?X0UqzK*FuCS`-9kY6IIzTlwT?V$X|L3!Un8B5I+Oc5j(7_)4v z-llq6dOM#v9$hW5frIujS053h`u9sYd z(YfX^7xnkZto=&K+ZNYPBo|?HuKA!8gjAFK_7DHM-Qs#zauG&xiM5&32QCOrW;z~h zRJg_v8HO<6vaOgr5tM?^$#{nFZR?$cYFu%NMQ8@Ul-B*CTE*%upEr7XwZ-*m=@(&i zu9KJx&57xQWxGdm5k}`C-9&ySz0R8S;e8g@+meegI#;E}RX^|&g08|x# zY=l7(qX~+QbH04tQj4osauG)NtBSd(f*`Kzjqf~Vaor@j2%~c$%HS8}DB==EY50=l zB8<*e1BzEF?@fat7{UliHIhP9$g!ymeDXY zt*Tz(H&07vjkn`~Tn;a86{FklaD?-J#k&^1WMtUB(bW`Y@F=!NEGIB-NV-U{;YNu} z(&4gkqE|-hhs&o5S7oGbq^xEv4s(JZ+09Ckyge5gZnyj#R_YBuP-Y4apVdmm;qz)K zIdb;pxR)FEN44`|Pjv&>-@F(nJ*}j3x9zWJ=%NKa7oYEWT8dX!d9lc9j&7q6Z?^cg zQogJue6IiUKDo=F&OA^)A8l0)JBKbqrYafrCvF17LG9iysC{MKO2@eymG$B(Wk`_i zge8Zh(w%-rI6^1PWmAdFh6t`M!f7KhL|`HwuE0@*k($B5MRa`MVjNwC7klNP#k;%3 zpJ}dDxdt%v{qX8ptDK1nTa!8RdP)<6n}vp1`%`S`B1T+)X=2Ps8h$CTA}a5|aD}A# zuOf8#-c!|~iK0jyz8FWu4zqklaMay;97xuc?Tg{4iD{L?2)Brb}LTpDYZ6X&~A%}pys3VfXM=pu`FH{}O9=Fz*NvJhq=+})Z=1S3NY(6o{F z*z}&C9vD?#ho`A1tD1JZBS??kylWq7fY27J5^u%-$oqmS=g27E9YOX$nHggE_1Va4 zWi5IBS2VCkfyy7lj{%>|Hd0}B#dfEe(V}>F1lbiDUV~#+b~4Kjo7?X7ZZt5tdhDJk zU8#{bE>5j>Ll$mAnw#0sALm1&!{IsAVN5_o<_@dAvY3XMcbPGPaephORnRfPWmfHa zUz|JkC8+EzGG;PJ#hP%Wq;{URKjk)!fh+CduX^K7qA+&{S2wXmNdWeYkSA{LIHM1pto* ze3$Uw23qbX96ALt(Z_#l6t<>vjw!bST30PyTvLM>U$hK}YWy};&Nczn%fd^SEvl`r zsSm3KgO#(@$gXlWkL{rA?8M)L?vXe@dA|qd!vJ}wL*Bu7#W;X38Qotio=MD=zrk)BUyNeFOZz1ZI6PEHGp7^^*6SVsXw2;k@LX3%C8J7{=%ECF7^xi@^L{ z;=JUof{aO1@n#WUGJfgtd0=jrI4^lMknuBMCLGD)a>Aj<-z;F3y5g+(Bj*GjmrC3o z_;1CZj=KSvhXZgw0RIalZ<^4L-X&V{bp2ijrhpcSz!czX;VgggqRyBC%wHvLoQBio z#j#N2Gx(D6lJ{k}-2lwIqZ!6)H7tL1d6xillf-$+Lr{%}fq7lxyyEX#;QkHF7il>O zObB1gUn{(Xy8)Pmv|I$n3wIve76J3H#OeC!;dlj@k6dwD zbH!Qm&Vh_~f$61XCNO^a{wiR;FLAoRmOOe3`>e#UKs-49Y^xiIPVac12kuW2OY!Gc z?~=T?^OW}#<%J+`}(@9G-V7&4@ z;rf6XJC9+WI4Wk7B}O3K!*MSh7XtUb#OnEPP_gpbxye}4QA*1?V04@nFXZoXiD4if zZt+L{t|xg51WK2u`@0;N9#@>@Zw17B7MKSlZnTHLS@nB^1zXP z7Xx=^fWMUgwgdBl#8EoB`AhN+IvMedFBz|Jd;@N$0P`P-qk70o-p!Th1L8}@OCI_A zXJ96U3FVJFI*h&M_>%FHwWVuQ^jCoSkHk^^=O&MEHMNEj!Iz8|j`X_;m{%muOTRI|t*;|VmT~i! z;$dSRxC4RvOddE|WOz*;xV?e9H4ohWz}=e%?qJ}a%>%b5aDT}Y_jVq*sgUjoCyD|^lILP}(9=Jl_?#Kg2 z<^1kEaFc<1AP*en(_iF)qj>qfC(b$pmHd4hxPp3EV5t0YKCrDNB|4?Y0l>_bxRAiP zo<&*-%yJ#)dKT#^z?>O?qk5X&o&Duv_Az}%9H%L&Ipz-a08_Xa78o!6C>#d^Gbb09qu-IhEdi!i;{5bm56s0n&Y>UGFINEb#Q+@X zcLOl@OPp6YD4w4M=Cxd0PB>`D_)lPtY=8yEFC51MbCQm8gkvIP)C03x;zr@WRbN^8 znZmIVm}@1@D;$Ko1DL0BaXI0b0o)&eDOv&xj9)nR1!k&_bA*G+?{UD)mpH0ly~42y zn6$*1;mFbN81P>V%=aYDPrv(sc~ZwY^cw?t&ja(a#F_rOl(%<*DO?H$7!#MHAI0Cn zz*I||pMJ}LIbFv&^rQUT1`v{BVEgH7IID5!={JaH=uzjXU4@|Ufeb88N2@`W5~qyb z1o~tHjgRpSwhcAzd=nON1TLMo(^Q{tSLc@xKIU|aLt;-j4rLcARJo#I}zq{6# z@GqV0T3-T>aDL=*^druhB%8$Lo-?@>u_}(5WWdlf;>RE{ur|5bO-^skC z@~dpC##2;09k7Y&bgfC-1l!B_PBuP^=k;tGMih38C<-YXacz3x$DMyZLICV72-RL9 z|IjNIk$;xJCZY>VH)Q^ys2O(tnI0JU8zELN_#-@0e-wLVm3eBtL{idRjYwWwvIUj? zk|50;imxp|^DXmtk*#XdP6^+W#qJA@M9nk(OzsyISf#SusarnB{flf*Gg6{P zK&ze)+b>x?jV-u+dS|G~tOu#zVrcpJd{GbXLOm$!yR}8DRMep!9Brujai~t6NBgZ% zrubWq^+Jz*kE*_cLa# zbX(v|w>)A}H76X697$W7#_=!Wn2yF4S229d5xfTi$DSa9SLYeQQ*t8s1jzU_(<)$l zpQCFbp42;?Y&760DxNmjM8(q$o2X>^VH4SOqe-Kvr>{6dd)U$6#i|?x0mJBMeOwt? zUXqb-UJbFXyVJ_AM>s_U+G@R^97;!oi=%waD9WiKjh(fhwH$pX! zE+IK!=$WCC=3Oo0FeWILL;tm-sDVQSi~84gEeTy-l6}(Fwa6J79GVlRD#-XXr&KeZ zH?nOQY1Wbxy0UFJxSkB=tk}Sv&EN1GZFoBW4?903ury(2H+SRD=-gAm72qCrbj+)4 z+L3X+t?OUg>oyYW_PWjD=Th-=3H@xXyIe*quF~0BckPzC9oy?}AeZfR*V50>W7L>( zo42*@mhE+S5Rp;0n9ky=imi>811bh;TkG!MUboGJ-fuz+SrR5q*204isV|QUNQMdv z9&BE*wQgfGyKZ`9!q&$7yNQSYZ{C)fvbAn6+>vp);9frC{TC13HnncAOD-6X*nYDE z3BYi$1#(OvjuI!w_|4alHuW<${g5v9Ffz04es10d7jflBX5!G|!A;u+H=ehbk=bk0 z<9oa{Mi4f=@}Dh5EZ|BKFn;qBNLCjibj8MGNzTE&HUuY8&C=Ps3p^7QcDh z_|4Ldbzb z%V%8hAWbqb8)ZUv+1j{~2?*SQLzoeLY^|tInzvqNf|-@BUGZYgPHGkz)JK}hFTJ(L z(0E4-ogh)7${2bEsk;BrXeLrv>Sy2z5vtkWDiobN<+0Y%&?SSY|7jF57TSwbyRGRp zF+11?S25_`YTBqjza8Jn22Jh@*I&W*JEpyY=Orxfb=bbnG#V*9#x|egE6Ozw_P2{F7*u(@+8a7JzLgO6RzRtXt z!uEZpT?gB5nD$NBe!#TbV0(dS55V>k+n#{!w`_Y6Ho@@u!&Gsz$QYu5H=CY8rZ09DKwVCCbVA-+apZtg^fzkWFrfk z=+~j7(qI}FP41AtJ2yQz&Ph6yN$6H+PKp~4TZgWp0kD8m78?v_UVfXj*g+eCcJ+p7_$sP(F?yztk(G+(R=v^!}O#5>yar z{)%4N7vnnx->LM)wM*=;$Abc^?yDgzSUe43(fk`%;w!G|nF+Xc#Z?eL$tHeU<{?1GODSj}OWVB4!SR?LQ}jw)?`#DM~lC_5tOWBa{lj?^IzfBZxP&USX(N2d$FwqHX67W8uMV=n{8p( z_F>y%*l3cckgo)#kxwCCtTmBsXTfz}wspfciEaI`O=jC5Z2PfoBW(M#?Go4yU>lVm zkp^EjZ8yMnAiJs%=bIW$SJ%fX=aT^vd88P&HS9+|^^{%qcIKj5@mhSTJ=;C=D^uR> z5LC#e`rB+Hy}!dY%2D5C8-?H&wo#q6m2HQbwqnyp&7W|kGA?Y#nYI$sR$CQg?zaE-E5=K z+`~2s%|mRX&}?HHh2}xF;o)m&W<}`vG;l)CXV^x1{+w;3=d)}hJ%7PA((`$?;o)nJ zHhuU#aKeW_u#J59BiqP_SJ*~AyvjE6;dQp*v0G-2slh)XCpTyPm1(4bTh96myHZ-b z#kOKRcd(6e7QIywS2@1THcE?~Y%9U@9kx+gP`^sFDF4GYadPW|Vw`!=+MQhA98Y!8 z+1Y)ucylV*MRy-Ey%8rqr#6_R+IUBHO>_5#bRw2E8k0CoiOzP*#20}Vc} zu?!B1D$XQ}Nm6k-o*IC>=42{koVNIkV!=s>6mv@yp8#Iml}h#&8^y`K;(p+Zjag%j zRnY{?gNAM#G3jHnZ`LfJ7v`$8eBH?gDJb>8<&Hu_c+nLFz0+uoXIkUwbRyZ;(AS^M z7|W8;PEs!|h(=xCKq8gw>&2nGMr$nI7Z=a6T4P}j>++>18@OLFrQ|_0%Pq#yUwsgX zxOW=Lg->v4r9AL6wkZ_daoE}&O~pHxcdSLcT30moX*m30L$aRLT#R4pe*sXHcbHkk zLnuI5URS^d;fmuWmPU&HR+CG2O;$(K@o>X(FC9?`*pQCD*O;07M8#j%G zCZw@blLpSIx%XSLDDQZCOV{ad`d=`+Y4ImUkrr<_@a!KR6yW#RmE!Fm8jj*k6h?|Y zRvXLA<$+~hF-eg`h6Mjx6USur_zycVm@A+nVqqIGTH#X-xLf#y-V{DdZljUz6p0@uQvgM}^J=$dd-<1)?}UfDwh zoTN_CWEs=+zW}(!j!=aXQC9^7(~$6EOqGw<Dq`pu~-7R}>@tBqSEnI!?FJ?d5@*v(AKRB5B?VacR=}VQfr=Ne@Umv`x zEPcm~SHFJPDe+AgeW`xcth1k6^VwZv-aLGly2Ca1|F+K7^7hyN{f@fJb>p#T&8(j? zEv)dPuf6o3pPu~YFVz3y(=WYc(;I(0LH*CY!?q@~__A*x(bHzb3l&m37xl zy6DHH=U@Nz*2C_)@R;r+!{w8vR3HC9$4sS{*Im0EtM0k%$Wt!8JoirB+`D#j-8Vk9 zZPIUEt~*iT?)%${zkKl6vHPk2>Q~*-tN!QyDtGn!?+33vx2e74JIcS?+xq{0;{|(t z>WrrjS)KabSKoQ=f=}JlFfilK>h50ktK1*F%J7Qlf`sMYvZ>!spy?@lB-SVEj-iv?S^Um?T3!8U7T71b9 z=VdSd-cv7U_Bv*dBOjl5Ti4DvcK+$92^W2B%C~R7{OsRc`>eYA_p$B8&tJLYrMGhL z23B_mE8P3d%G$_~9jY{A1;%dz@S|ao*TV zCLY)_=JeYhz3G5~1)E>H^P`Kmt@)^M<-bq3a@T@}s~*|@#ShM0a`dRXCj4&E!+*Q) zz|FhV-Nx5n+FbDJbJGWM^-=n6KJ*>qSDPQbK1iQz{kcP9*4|kfggd4+bI3PN`{{AH z`Y3&6RcZWRyF>XbC`R@BDLuDg`k!ia`yIICV%>pz&&t(!2Ts!=0wYdAqW=Y<*?1E7 z;;qF^G?A}ksA&;*`;yBQXZ*E9`qfFJv1yAy#KbpYsPCZK{z8Xe)czENHsVQ|9lH5> zjJI=jrU^{_9^oQ~9D36cB!?zGbva&lD4$M9d{3#o_F1Psduwv&?%HtGP+O zQ|g>@=#`5eKl?i5&_qPgz1aI{awvW#JLK%om>PQG`_cG|pjvLY=uMTS58czfze5i7 zM+!nm;z``@_iNMpk|4~%jQIhcl-nL0Rr88dpFbLr1!E@RB~cv5Zk!Z)v7 zS?Z8e&KRZ7QIEZQsxzKx+E5QyxkC=MTtRoH&&dNbmoYQ&B;$V9`8>D;-E}^nF)Ghf zeK^md^8&{B`*mU-el2wPb)v(slNduWNo~Pf|87ABr;=~)1EAVMxUzUs*}3|~_)qN^ zk*1Z5q1;HArHj8cc(TK@C9|)gFddR|xJkJ{QbZ_77n8ue^tiz! zDLFrJP=4p2&{UW(ii;Mpk|{J4CE~ygIw)5;D7Q&Ufhp%vNttX?ej_RSo0R`?$k|tA zA`>&;L7}Cl!YG}umXv)=uG=N$V3YE=jVlpCfpLk|S8W)f8ZAE6{i=0PE^tsDlazAP z_tCPj9&b{@l5&DcIad{Elk&KOQee(Lsjyc&C|L*PRtM#E2W2KzTWpl%CP_KT)aPPJ zIoYHaAXG==4Nx4o^3{VoGM}Q77kNxqu4I|RxRR_gfg<(qGpE{as zR48USD2pAGbq>nqk}}nl{A)>>V^XHm-~r}DlX9A*EHEioNy>DS@_?j_H7T!3%0VV& z91W`2Q2aaxTS)%5erDS+B7V9Ylv^E?XB?D2Ny^ct@7&3jz6;66Q@2~AoaLaLBPml% zIlq^b*(Rly26-^^Ov=TQGS{U1MpBM6DHCbf2UBEHY9!@Ald?flM2`9s&>`lrKW?{S zM7W-nlnJJscN~~;swpxtCpjoF2W5+-%rv=fc3_@zP)1R6%|_+k<0U0*%2_2T$C{Lk zgX>BMd?Tm{A~ z+v&-RAiW^8O#0H2{K?;>6+hpUTt_e$(SHsKWtdSWQI4QtI?R41CM+ojn3PUQ z8E;Z9l9WSC$}ON!6jhp(LK@s_lrB)t2c^u!JR~s|Wg3S2RFzqji$NjD7UfM)4$&yf zFadC+M!6l7SsG;`CIF}pZpq1jLj5F*@+(j%jxEYOObIk;lxsjaMWg%&l&D6D9Ecks zG|GdZoUKugq)7spg=TETCFLlSa*d?yWm2A$lo=-FT}hd5QmSZb0cM&>*(51rOv;0j zGSQ^`O;QdsDU&FYVfJRqEZeEu^`I7nrm-s)Rs7}3o5Z{g5f(`<#u#?4#msdao>ar! zH*nPqF?)bNMjyB+-5Em!;~FVPQ0#IV;93w;a(2A(kDJAeB5`e(au`DdV~3O@D0VqZ z;Hrm0%o-8bzBH`@!x$|TOF`AS#2gW!DLn`u$Q4VT7D#J>{Iva^~T=55B@EeG1S}l0JkHa%NJ~DUGhr8K4$~P#y5RjesaQ zXG%GQ(Yem_;krO_5k}{VFc+nuGwk1!T!hiN&SI`Hc#^q#%uC0sP+=>e4A)t3(Yd0a z6of?Rap%VyZ~xokdPQ;(M(65aF3L${+OD2}s8BNAmt2I=xniIcgk(p@*nC&x=PjtB+KFgn*-Pzpk0i3R4ln^*kY;wqgksD#nEAR1f+!r3@$)56Cru4c(a z7@ez!xn@bOmw$3GikFIwHIj=kI#(}qp{vT~z>>?hT3k0sF2d+seV`PCWD{tdw5jwq zi|ZN5MHrnc$z0SwAQM{?ud%pBA;rlMM(64WMa+Ja`!R{zK~UkEA-M>nbDhmxO z_^NH47FVO>B8<+J0;M2SNGvcXjkyyZDZhFo7h!a+G$;ijs(Z<_H#~iV#kE;-5k}|A zfKm{ej3=2-|7G)MEw1Y&7h!a+EGSl~JUDrstt>w!xd@|kp%8*g#r*Ft?fkao*AB@= z7{w({EML!Dq@juf%Qo?7kYNY|F55ZIgP@4K5rXa2IcqB{u45$^VRXMXFc)b^T-O`l zdCKCdmt2I=xjw~QdrB_+z$jfKl8Z1p*EyhwHifYD11~MGxYkQ9!suM*GM9U7d|7f4 z23)q-IFGpw!jr;v?v$fYc`FTXm0X0;{W_nyRBW6#dV00R^@!vmjL!9G=AxEJ`C!>z zkX(e(xi&J_p_1#YNgv*4as5Sd5k?Q!1UF85TvSaJ~tT((rch`El%lVanT z)s62FLYUhm7h!b2E(XPljeqa61nMZR7bF*9bgoO7Ya*Vb@D)aJeJHsIqjPNm#me)^ z-*4}*{F*XTNFj{Qg(}I$wfNpYzG`tTmt2Gamn}Ain2S`Q*tl@@{pc_%4L>Eh2&4OT zDRZej|LW+^U1o9JAh`&mbD_C{hI`W!UtyGA4@oY<=v)wO3zwefUz1#f(ZlsQ<~jyX z3RlY?rj=P5P9!o6VRXMP2gOQdy)4g{T!hiNu3)Y)Ovi(b3fCEui!eGD8Uy&{o_jBl zT!hiX^#$fq>DB)A?Y9s@n42UQVRXN)WGV zSsqWt4u&u~*Ox%?ij4)5i!k7_<=!td*K9l~mA|(0?++0|n01niFuGq?gJPw!9vjz7 zF2d+s*D#lRZ2U}e5k}|w3Uj%~#)p!NFgn+@%;lapDvpCA3}L`!i;e3*DF~s_5;fZ? zZ=Fa8Vdy4GGKA6nx*ilOHuSQ5rsN`w&h=I1axcsMl8Z1p*A2|2VneT^J|npZBecFw zQa~U%w)-7!1O>e~N({~10ggzdKbwljqCGuEWh4^s?ayq8tm#R1M0+Bg@t$}l9uA*U zwYs@#b@)_VtzItwG|)d^xJ0;$Vz8_GzP`06?@d`rA1nn?`g zgRd;jQBY;39I`DRdARTn$}sIsO!MYPwciA}1c8?O>5z^x@|X9uX5#%}-|b0=uhq4{ zFD{|9L=kI_$5U0Eohj@?4EyZAf|vHFp(L$NVH;#Dn$AeJnq)6Fh;{}@SzT3ar3mS; zyifACpqkj=$4$E1xw(KZ@57GLOe)!fEvc~4-qN_Q4kU%tw=>oz(sI}5@Ohh~v2}6m zbB)E3Jpz4({#JPtB@oG$P4~z9I_n1Gv1|srOoJkU(oaNPTR$4bxa5!LEg{k*Vqj4; z6YZ%>rBJo_q&>x$nZ=OG{m781e7Q=brr6+`N%Y3+24nI5Jj2MfO^J_UR9iMEr+bj2=9?9R<((_#NDm$n#Lm5TP~?kEoCR)rUvVNram z+A3zNykO<#oQxH$kxSmHEb(Wf7(@kbfxD!~JM6^!`YLG>gdH{C%3TlR`sv=FCGfFilnU0lnmL+AIrJ5$u4{*|DmUiK=Dw$Gl zBcTUL#aFhu)SM#f5OYK?;~Z4gPh~jlvlEl!r@bK)@1^WoRlTCh+^xy6UJfdStT`3` zxI|ITM5E=e6tyL$TBJapTsa{iPSO7Rdnft>=yohaYfh!sv1L^i%F0N+KgyQf@&h6z z$v3-?$W+jwR5YW_)$P>WhVf72GGf@!AMf<#T2(<9GpkaAoFk^DC)pSG@K$AKO(~h3 zMSQYKYEv)r9mgOV?UrOR!`%aO$1faZgi?5_+AHwGSt^>Mt+i{y&16AsFLwyHqA(#B zlZ%Le(&j2vE=ueAQ2u1y$=yJeF1cAfU>tZVix670c($($}l9$=J6}I}> zIS`S7BlWt5O8d%4orgn7b+)Su^_eX%sjd|o(*`k4M^hsP>dl!{m=2jxaQlEaj9CnH zzY$LxBC+mxY+WRlOs-4B!xfljiPQ`ZE=omv<05~g%0Y{FcXR$qP4k&U&|$vw2|Cn$ zxEzUO`_?D=I=ixcG0gA4XII>`5{G_{LALIl`+!@=xD9J{M5Nw*AgiH1)(*2HLOxFE zxzT7JF@6l4bBFF9ul#9qkO^|K%g5|PY3V2K#r#j)htjf7-U}*^pKMah{ltAJrAqIU z4a6rOO`m**{V(LEPrhJ(@<~mt>L;6-X2SAtc#rrrSZ;8FJL1C$Td*|0fCh6@hhGa0&(ZmG{&lcNKT!we)$1b`>P#j2x{^Wt zI2$gYBPTL;Cfd;xhtL49rhsdA&MYcQq8CaN=BC$!$3K3h=TdwqHc-7%Ur-d#go zlsC>U?&Iv`<;L#EEZeU3$J_nNRs3U@ZdX0GzHzPnoK=jLxFeKdS0n#ASo1l5HoIr} z)!mv$`LWnN@vHAO(SAU?z}#34u8oJ8Y$Fk9S1>0rg2jop#w9Y$rZry~b~S8C70fOg zEKP+G@ax`VBEq-D%keD;t_k;SA$6giFiluqE$RPb?>oSws@8V*FkuK72_=dM$^bz? zB&5=HdP`<91A!n%AckZ@0%;@@iWN>kjbo0zV?nWZu^nt6Dxe66dPG6R4uZc}jup*) zzqQtGnF$%&eg6AAcO|pun{U1Ew|d!YmxXa|T+HndW9?SlVNo(Jg5~iN8e^?iS*2Ym zV7e+?r6|G;2Uyp@70}`kuD8=GhuInpJ7i+nOwr={3A23Ut4#3>>#yP{mQ}TETB%*J zeVv>L1=2|klJT0gC!um!OESkhU5-%D5%7uYhL#*l9?LiK%yPK``8Kz&z-k$*DD6J0 zyTB1F2teJz>zP%o)9Uy73w#c{i(&PzY*t`}R!@OF-{$gpaodUd7H7rZ?y)-T0sQBC zta0D$tRf4nUQeOZ_U4VD zwgOK8$#4d!ch3w<_R$7J_ok!|+!X$2Ip25rHDf&fZF^Ga*QJI@vH1>Ihc9q+rv zORg3DIA?*~>B$e+xIWvd_@K&p3krh1pbhzn)VGUWut1l1R6&Q`Q|R${aR-t5j%?K$ zqF&&zIelI?(#fK3$rCTmW}vCL9rZv{Gil+z{d=;lVs1?5hENa#-3zegz_nNrZmdcTGS-g_$A6!-97KFy5!jJD)nJc=%1xjX78!74 zq#WNPqeQ$D0jcr-eQ5O4i#vD`H4mMt(-A;&LXH3tspu4;CV>}02d|x0qjf}>9I+#U zMAQ<%N1;Wwm60|ySTisCM4@mLt{2FIPxkwszorszWu=w0+W*P|D3 z>@BE8vi?N~pUAh03#C=+W!JuOjno_Pxf>5}REft~df>OYSLn?4IC{S0HT97f{1P}G zuA3=vpeGV`0Jm3QDXP|9vEh=vFA}u(C2+sCx2Jjf8m6S9@R8pmMZd{edu3X+Pid3R zgioJ#cbUh-bpwtzCDpokxD)^e#lvatZ6_ON;xnopj$W{evLEBN`TRb2z*iKoO>=lB z4k-x~IZBFMQ%}vBkeN9oj=yi3YpQKpaB7LuWuNXT@wKh{Mv`tM_AnHFf1pxP>^QysBZA zNZ+hQRpG_qhLX8RD=u``R#eT)sGB=qnkY@~Z5TpNwfB`ykuGn+CSl?`P*v7Y*H~8( zF^`x!(j3G+oHbQvVa|=<_zj_mFZL-cj($C3zM=Iz?+olVxQ`Oi{9+3B);5*Qq5TlC z$#s`X(u)1Ju|Z+~*1%CyTD`p(Sl+1qg8674%BJipxO>!^)^b7hkv!|Ur=eXioEd>< z^j|A*T)8FEJ$eECZn2e@JZxamqg+1*pEPMWj`Vn>iM=c*jp!9>jD@aO66ASPQuc96db5buU1IqjpXX5nzsj?#8xBf*^a!{Zt?3>29j7ZY*mE zhij!7RppUN$s4YkR~eCPxO=!PG8Oly*GckL08NE6t_{r{`R#>`>yI1r(8LQmdo}$2 zWZ%DorP(?2Kb;;*ow1;z^n*qJ*u8b+%$0qne%bZlqAyt-aroc%itP=E6Lrn2x|~qV zGgI3^Q=?KJS&#p!O6q&mhl20}4=|EWYlk|=&g@XfsJFvku?;mWa!0S1;$=EaXw+9I zdV~gDpTLyIXx7ANb_flBg`&1oPlk`tK;1vN9>;!$CywR%beJpI%Ua~embi)@?Nc8$ zPpZz^uCk67b(KHIjo0KJOWl%LC9C&3_7iv zPREKX5f#^j5ic{^;Q1dJ>@|z7PTU4Ch-WZHpGw~tU zkv-}{mIE_v1cPDBiEqyf{Q_Xt#>J`eBYQsqbJNJq?R^Z)C`ve-K3vt_{qS1|%n73y ztQ}5GFU7A6nET@5RC{*-_cburoN{D)6sb?;i(#oxt#rJGOTraMyNXZyAiN24-*ux28{rntzlIA21aHr>|FP{>=hz1u%Q# z;`H`@17^S&9&ShWX25#_FqaA3k>d9hFmH8YF9dtv0^`Vx7p^{jrNEpQ7pJDT8fI1j zgV(h&*A>Tj?TzwpA}})quA}rifNKKgskk_O{Qd*Xw{dZ5{9b^)-gv_Q4SdKY^6gsrClK-lf3YXJs%p(T``Z2HshA zyz>Pgaw+(zIMv>Oqp?*o0?!IDnDmMcr>1v5^v9fz{Wb6*N2eL_>`^}Nm?=rs{~%Py z`CJaaMZml(aJ}%G*^AQ;oplD@<%JJ9Dz|w3(4){_1&o^-Je)qgYC5Q&d=8j>0;g}k zYQE60(Q7tYQeC|Cu7me@;Jy)96ptof)NoILzSkUV*oF@|Jx&dGH4<0=%)t_l>x(Zn zT-9Da^!J{LH6wh;>D!TNkHT@5GKg~MD4#vR%@9~bBW^yEz0w5jl>--PZ%^~qTZ#}> zyYt%Fle%Q;-XTdi3~kaj;C>cZYUga-M)USk!lmQWb1q4$i-#k7*}%;a*dy6%NWdP2 zdrbm3CvfY4`%Pe}oyUtG;WEpRfB29)67Ei5zUTx;=^a>(_pstat_wc#!X?}+U@l4k zw+fieo#3c@+yhLnFa$UwKJmgOTm~?6JHdSd+%jOwD~eB z?Q!kaNe9Br5@4#4oB_YBQtbJ{anSD*7)B&qoOM?US6Uz= z_;)-UrEg#YxE{crm;jFY(-8^aQh{?NfU^TPEe2kZtB1aPMUcXa|dOmU>03E+kU*NrA88W%5L2$zun zZZdGw6TnRc?(!I1{PO)c1{Yhtm|{zPYH`rGcNp)yaaJiB#8T; z1aKn}?n!kxXk5JXPK19j0o(-OS`xsKy%!R|d4M|{gNrR+s`rk195gOoI%r-pEe02B zkK(r`1{Ygj2={&hIO-3MTZn_k#fu-EW(5<#k-cRJ;+{+ZNBztHB!HuO%HMYhLAZG7 zp#Ei6gN)$c@o;4C`UG(Kz`Y)Wi!HYkfg8}s!;_Ek!W{z72?^lLz@3o*ZZL3XCxD|% zF{={5k-euAz?p&DlK_tT-NOmsCIL4zf`i7z%Rd?y<|KgY3EY(l;OM+_bpp6(lImv9M$I$3E++b&X)jg0C3Y1z>&SW1aM^UtORgW|E^8|*9W*&3E)zIdoTeU z)q`~j;3&PXB!Hv%y_Eot?0ud9t~YSsB#1LE0$AhX)l=#>=xyj)7Y|4Ec}M~{x|}gA z0UX&YNB~FYQH2TM$X-PPII4eD3E;@yiUe@S19xEpII_1o0UX&|lK_tFJ(mEE(z_u6 z9NF8G0InZ!A0&Vyd*3I3qxAli0FKVP`!2>oa00FLZsCV-=PPHqA?%IB#G z;3!{e62Q?qNPPl0O2<_R;D!NrT>?0=_iO?*|^Hyum>NBP%x2@V<; zuO3i&9Gd`+!p%wmNBMGk0yrCRvtn?u^JmJxn__UW=RFke#sqM=z->wZNA`Y605=x6 zwghlA-^g2vgT}=x4=T6f4sq(4P8x7CfvXW%nm00gnz#Q_P;|b(9GH6q&cJcvy1i? zF%x$-mK05M`hq3CqF~7kpVL)R6mmIyZl7yv5xWDkv>Go6rq=`GHp}qDk`mjZCD}7- z!Zog1dQ7_f)ELc-aOr~L((0ygY<`v2*4E)QjbXfZm|jsE_YO}5vk3Rb)ip4T_Lj~B zZ^wKF#dn_cfBAMy_8!%eYTVxWr*F#4%E-&eq#HBmx6ul`RKA*yq2`0;qT(4$&Uq=+ z>iVwycG9HT4wKynxft$YA z$ZzG&bH<*Zgc~_C+p7nipEPOXqW(H{^vCGCqt4yeyjwcZGj+!LiqyWYH>0z6MbCY+ zxHYh69~oSB?p|q=>oAE;J)WliYCqk17B#)>I&9DcJZwF*%|BWr`IoKSeU1xpXp2}x zVA1*{V^cDZVCoa=quWAUj&2s;P07ta;tti;)4T3(MhMND+M3^JJMd)GG+%0K+J{iu zno{Hx%A`rIeN9O#cSgGBtZ&|&6y0^e|A)hk&OX@uYSMwDlyGMsq@d?Zn)DqoN2e#x zH_T6pb|LL6JmybPzHE%n{se^~a*3El8Y0U@lvnp?V2?=d^gX~*7p${|LhBaoh2%|5 zj=mfXd{^FbG+CcnGUtrwr?WSr2a^UOk4uD7LeYH%iHbH&It*ze!}UcPHZTd5Z9fEQE4j-qi%v^VZndXG^LONIX4%KG znIWhGzKTy8yW@8&lLq5h2CF9aIKpd87t_Y36t9Mdq-|f(uUnc9ZE}-IX%l6yT+vyW zx-ys}m%t97Ob8vzN~{De{;lhhAKo+lniJWuEf3YTauxeA{&w&BagOp4-oGnWDfS>7QJn>VBgQKK3d zH)jtXA!k!z_ey4);>B}&h@zVaiPs$qq;V|Yosc@HJO4}beK%tKNAvwAaH-B}GWq{{ zzEAq!nD5`F_Hw06iEjTkwRciFZx$WZ`@MfK|EXTy^1mSeEuH26l#Y5EjCL*KbTbKc z@JfoBHUu;C(4Qk)JaiFG)GS;T3+!#kYukT&3B zl4jueZzfgZxSmOL+VmomR^rHgJL;?t#qCnIfY-jWrl(%C0}dXwXNxCj} z&PG~3J)arDL83)cuC0c2dCz-z5cl;aK zKuvxB=lE#H!%_IXm}QL(5@mRrq#4j-2Se(pc~?w>Dm`dmVt2uG&=toS#j{p^A33qL zkmvo%^-X=E?qsCZ_%h8>quY>~y)^M>Be@d&w-Ba@Jx0W9(rEm?1|MCde~hUV`bg*g zfk=PNGQXo5(_wsfwu|pc_{|5{3`o3+X|lVsn4jEP%vZyze$Ldp!#S%uW2MQGlEr2g z1}(g+S-b(iOxk*JxRWfd>MWvh>IKhY%)FDMJ;lWPSh;7?&f(RrE4jmbAIie-t0aQ* zolj@8A@S*~7g9{ZIx7KsKJJJWel@J>N?^WGeU?ufVO^%b36e=tGkpYp$27*yGCixa zxWzkZMK9(`j{eyEx#8|E5lbb-zHQOr);Wjg_bO&}9_NL9qDO7`FsXS%(v%{mYJM>} zx>1w&{EP<=C`PwwyQ+>_3oITbTPIVoCr>b?)W zVw{Gi2yS!-Qrt5AFiwOQM+3>x?kzo{fs{@5WH6*ncGj1#+|ra4b*Hr0lW;_B@6!@W zj=s?5PHHJmq3#gVc>IXI&{CYNYN9sQiME82Ahp<&Tc#wp ztpw5~_@qhYI9|qd3lv>Fq$`<@mJ>LRxzVFGMRzNt zRZMr6qPri`Eljso(b4h~594`7_ada*7><^sc(}AUbO+PDt?2eZx|``fR&=`p4or0CKiJ;`*V6kR5ybxcP~9^Bq! zNIYDJqVqy}79W!oRCLoI(Go8nvR8CxLfXi5^AsJO7ro4Mjf!pwq%BN$zM`WrdALzU zN99e6hbHM-MMveco#}2@bd;YvneHJ)N9liy>7G_}6yIG;M~jm@y=0$<`-Y+;%x-*4 z(g%v}6G-nf-2p{M{q%=S_k*INMKx~Ehy_6&MlvMgo1|1lmj>x`rW>H>%#dh_)Fcg8 zbf-Y#_Hq>6ct~F|oJG+&AyIrxQh}liLE_vQif$I9ZyByk(N!wAIz<~61 zxC<5CC6In%xGNRib&x0@OwuiiZVe@Vw=Nf2K)!IBsPU ztxrWv-^zBHe|euG`H@ujeVH2P!9xu4L) zx#ir0EsfRtsiT~4oIjp<(v;G*m)3^)0Dct0!M&?Q)o>DQQBjYx?o}q9zx!CG|Yv3sa%TMy7-J-Nq z-4!SHyK=U)%s$i-*wYf&wQ_ePeF}?9ThpPO-8@#Ck(iZR07!KKhihB24@J8bVSx_@ zOl_ewT$O1}>K~c{`<&oWs{`H@x{zs5kDEln^=&CCI@_)KHKD? zf=606(^qR?Gh)|`gq6cN`SViAQn8LB4Q9py*Mey_0VNFG>H8ZIuq;KxxHVZ<6IhaS{Y*mB<`CDiH8 z9=r|d1{MZ&xO~a1HL#C$i>>li1=rpXs|7PRqHYK;`Fof6y}8}@-Rw6zTi0};Yhu=i zr~|!@MIZ%7%Jek$6z{c68iXV7UWY^C-Rl@dM^%ISS`=T8B9%a*=D_EmG}|#rRrviH z)5Vki`D)%>hJjpA^ND+mFG}1+s<>01M1Ow z4--faksE4jTE=ob+6_%Vx*c8sw6%qLWv`F7zOuZJxOEt#AZVqOOC>_*WM(f8)L@7O)hF2=tb_Q zuhzi*hym&ck6hGs5Sq4n-ifmiIRXPKMv-45QquBpFDv3ylN_4~DKB5x z7x6Xh55@PS%lU@=Iq^NImo)4@Hoj+1=J`{%xM5Z@&pmNGPs7Av;66$%n>f6QVTkTP zISThrsB;E+gr@<^D0lq(TjQ8R`e?b=u)jXOCymR7{YCLTdojFM5g%-{MLDv+j5#avsyT+zf%bgaVOAUAbx;R{I_6`zpy>x{( zpY}J$q0P`F@hkZ2>)8&}q^_uE$Dn=kKB{eDQl~X;Kx{avD?UY3G-2HVjHXMw6~5@w zXi|W}Uxi>zthTfMY?YjQ6ghbDSsQBzTk(??QB&HQZjFf-t4h=uy2*_}pE{ZWcJGKh zU(zvoq~xjJt)eMn@VJ$tEMmTYa8gX6rmmn%shX4@21b+e%Q*iM`f3eaf++E+BTM-u za>|JhuN2Y8UZl6NjM-qL8#BYkEWnRe@{nm{VlnOP!+jGVwe>v~ zho)^ot2wQG>!Vem{YyIGR>$Z5NZiStaL2{x(kx@Y6o;D~oqovPGX2n`H&R!00XOOy z-x?gh;iDvDaq@g=YFjUyDXpZ{6_!W)>tju%uAnIy>PYkYE~1942WtK)a)!6K=!CKl zO1K{a!(7C;vn}#^5;Adap`*(n+bJW)0h!)qrsG)T_p8KCl zd>+>UN?c!*B~6E3rHkjFcJcfKX3`LDx;ES>;>nT{4Sa&wh4@TQiNaor!d^`jBFpzv zhP1C!^}3L0T}zuodl2$52>E0=WLyHm19Gn?X+qzFPUoG0>FvVbMd9z#grB8XFD6;_(>pP{bt?ZF%fH6(uMzxfF#kH9fA!^GDg3J|`_jybSeA(@QM`YPoQawf zN*-4}>DYfa02)8W)&hhj^lMDJpQd^Ybl?I0btnJ2g@0Ygzb@xr7xS-X_O*X0=Ga`S zgTw=Eb=}WYA$DYkeF#CG6N%9EUp)7Z1&TrC+(*{OpT9qBh&QWe{TBswM3*d_K^EeE zcTu&*NlQad=X68E= zM_O3p1WJ&i3O(=x1yE%tKX zbo{1;ev>o`(jg|zffNDDB+;_$9gN!usTd!e^W(_5mqD7zbhOCIbq_$IWnGi>xT2$T z^b)4qspx1?bS~3me;*x+RLP6;dtJU9ITug|v|A9#wRkAVrvNyQ2FJ5-+XaAf3g0O_)&d&_+SxzLOy> zW4=zsmtGFeeb0h)0rUN*;=4xieGt+m%=Zb!_iaeL1nG6(S1{ji6yLs>5OUv>AW=!+ zO~jCRtcoDoUVBpw=_t?(B0JfwSB ztmu9;9xHmaEXSon;;|}Fbh8v)6(k<+a!8w49z-GWaBqaf!@U<0xA!O{9_~&>_pYM* zFQm0BF26#$kl7oOEa&|xkp9hlb0Klx>5zE2RYH26`PM7Gmn*(&AiczV?^k?ZQ+)SA zdX@R^Q+)e(#{=|CHx$yFOd17=hg$&YEEd0dNVhWSY(;mgqI(I_yNtUX(tAvL8xptj zEhKK`*dB5^hC*7+?D-&l%otN3aYhX!&bSH^t?8q`f^-{`zJSE@`5Q<)pHIT-jfYto z4T;tUO;RqTA|_3Ow3tbDNar%i2dSA!AxJGungQujCe49#HIu@SZe&t5q}5DnfW&*f z#gOh`u{sBmlleA7x}E9%1?euPy9yF#T(976hQzsdK;n#t72M;H9%kHikhtaNA#ujb zkT~NtMS2SoUn2Yf67{Yo=`%=AFzHK3bdky=eFy0UCjA15E>fAKE-84C8R5Ej8)U`tvac(M5{5$H}Dtkp;n`IG`Fo6=^?3|FRR59v$ zQ6|hkCF)wwe_-0Xk$yg-|M`jj=N|QEyT#>;mtf8ov%cI7Ddd$R719Oxq_IaFxXz5< z*D~EGMWW?gjyn|+$GH{XDT;K4f-6&SwTf=3qWdQ#9tJgJngXS<$0fM*fTDXwk#>u}Z{OyWZXYck_$AG%Ag_kBF!XN;z{O7SU@XGDbR&g$Rw%*+}=b;oAF7L9E#*uB&rP; zGsX-^oH0xBg~0BAp>NsI;(MH1zMBvBDqc+({ew-hsZMTneS!z?ST1qjPOmNmKG9!V z*vH6G6HZ6yem3@Nlj{=-UA@qtIU%9yz#dyW2!u(Z(;B)MV3I~c;->tlVty7?w{0RYj>Mxn=fg;VJb?30IYD( z8gyrf;$|$}xuno3x5rX{p}ixXdbE}J=x%oH?5<`9%ewxcDOsn#bF%s1h3Dj{k1 zPdO`EZ{FnEOUg~IJ@kcV8)@~41+F|*OAos;eG=1Oyo>+p%6_#q?PcF+XL?hx(`Ci( z$g%WjYWt9zQn7%98q^msrzRJ8u{N~^7`+~>f z_67Gdn<+R_-A}`x91islT$c`s_ZgER@jk-_sRVH{v84`P@n3)r&d9$c_%e4kjva0< zb1w7Tf#Xhms4~8Z&s+HX2Ok>a_u@nC^fP=u$A^mdAU?GCLKpa`Bq?Xj_|O9XP<&7$ z+Tbk>>3U^<{Or(?A9X>mDlcF&=(&=(@ru(J%;0VJydohmnzR7!-fdI&|82 z$nl{xk(0m428G{|BOLj^jgN`Fdz%)P_`R#|Fo|lyyG$B^<9HT(IW+lO4o&_}G*oIk zJk_O{Km_(skb)hC&o0c;^)h6ek zV?Kend%b$mpKIZ6jQnhqUEtVVo+Z(cUkvG9e?kj|o9`iWZnQn9#Pu{e!cBn#9V zcjPEea%dfW%Nr2fj=wSKbR4O3Gf8LSNX^{DR`Lx@s)wozla@f@mX|>?GTlXx zl9+TEq^?Z54w8vUw?d*@ws0a1X*ucHIK-u=@H?6Lu7}i}Nt+?{VA2jqM=@y^q~-XS zSkKKRD&5}Db>u))N>|2^j+~r}@^AT@YCAa-|5Cn_#c%n$y?^`PvOPH*;?086#NP8m zqc<-lx?jX3jfXGYlVOs)kmv>s6MGLn-EF~NQPGDYFk zv`mq1RiwKWiSkX3FO)G3#+3Y#J>_)BExi3VrSD7@ixH6eF)0($aZIB0(U579tdQvC zCp@KeC6T9eIrQ8Yg5u!KMjQ%_WO8y$_%HP+>nU~e$Ru-A6t_cd@C108Br~K6CQ-Zx zG06&PIX?U{OF7d`!|yPY$Uc5_=(M9JVL|H9ksrl%2(#P^QVo-|X*m)L7e&U!hix)4>mR2AGC~c~aOf-juUnA}DJrc1R?J!T~TSS`cOCy!1!Q4bM-+-*Cfi@kiHCJF; zcjgJW6YtA6H`X;Zl!Y}`M^~6L#*AbUsxVKcZ6_6DWX@Mx-xM*^E56Lwti8q@sSI@VNQioT{}ZfR3_Rh_w}Y6+u@?MTh# zO*J)3DRkA|qSETBa|R>LXC$Wn&ekWxNIW%#*8X%c`5oc_m=k>EjBj3yeZxIUCKB z7nL@gW}eL7D@JAI3|HVaTxPUV7_Ev_AuVT7y8*6>UR=g_RWc9Zih7n14=sU*S5aM8 zO3Z}9n_9Xw(txxzsL3>sV6D|mySkd|YO9y>lAju<9?5KTxD-{Xq5)0A9H~Q!l8eRp67F1GSik%}lQ=tv7A8uX{MqR5zZ%5vIw_{>elvY>IEiGG6 zQeM@#proRa5+wp7jjl_UvD(lY>L|4hEDr^*u68uvSJzyRZlkUNqbmk4j13G)WW1;l z9eataicjVs9k04>UP*O$5r*o?HKmOUSQD2k3r~_65Hp7m!aO28FT*@ql!s;iYYJ`yE?eW$~CH6msKld;7-^|rkEHDGXsmzfTz z$DyC4q_tJ(ePiUP#lE#5Pz>f1&mPqOHZWG!;SJ0Oq3jSEIW2<*~F2=v=$>%GW-!!pIuf%jk^%S!c z#kU4&Q+;`N$c+|Z#;5w|CwZeClww_y8RJqC+uB27#%O;>0jW9k_TBhP( zrK%&km{QV|m%)(cshUKqz?h*QKurd;2kM4;KugiO<@&2)wSzka@58@}6Z1GZd2UQp z!{u!LQe9nFhF8L3aAGq(oLMzAl|`EPEZo^hvpYIpz`0a?br?8|E~8o5z*bd5hUj-O z1*}ofU zmqE&Nx$fS0wABSTbUt#;8CG7W*(Kj zSFSthly^p-xN7r=QwNSfa~AHnkBN&;InD7*3D)z^P^!pv~<1=o6JWGuXFz^0^!|V;VM_xGgiIoSJyWf~>T`B(_AF(`r>(a@y-${Aw zxuweIxb6RlcsR7yF5%K=(&Vs%LvcIp_w|#o`o%i&RL7Cf@_B0KC>z3;uY_1($ z@y_8dez|y~b=bLc3O9Z~G0_|LpL_4=32|K^Un7d9UA;Evk6J{_2S!^H#E*4xMI zE1LJ#i|d+i+x^3>uZ?^6^*Lvrk&-`Z7?}=9r9{l>@^CGW4nzQMEvG1Ak?|zFTmG7MPR=w@ln!_hN|AR4@Hu3Y%A9vpV z{#R=~lgGMV-+#-pW6m@F@}B%#{ytnZx!|tW-s{_c%Y6A;=3h3^|Isy5ZW{Q+#^_W3 zPW^A{^JBhVcgAxM4}1R6z{ekcxqa8!b+?>&@503cUfs3kwUjR|Q^Id=XX1Omqz!y~ z%ZndaO0P@0XUy&=Qf@XBv<$qv#{>CaUH8w`&-WTN<=>0`QGENi_s%}yifuOyUbge8 zr>A*SAHVv(k>_UJk!f3TukDzs4LiLamk+467iOuci%Wn*{Sd+!YX{QmgcJ?H+s z_|46a^nCK3+~aQVllQ^?b7mCXaGZ10zN5dM|DTV(?f!M+k|jyUcuI2KT{ULa>Xz!? zjHy>9^&WrD&0GKdQS_4AQ(vw8Vd#ZxK6~kv6MQKZx#`_Lth|2u+_6hj3-_$w_uPUh z=S)B8Da+8yp3iygJ!$QAb5=>uS5rZrV30xAn&P6)Sf(e|G(k{eOJ(f65;|XZxtewKpwT*Jbf@pMJe8yX&g!92Z>u z`1WJgtoJAF9`NPu3x9h&RR8@~srTJEs%HJHhBIm}x^4ULS%v+2ZaMi8_YLn|zk1kN zjUO!BGAM8Pjn}RE&lv?H#@zE!@`Y7B_72E;@{6K{4=k>od)hITEl(Y`ty}P6#@5Pz z=3J0keBQ~Qm%TG&{~hBFP9HGgwWWuGw(}b{A71f#`MJjp2+s9v{O#(jPj3C>$(L8R ztyr*YV&z4T{CCd}lh<$f&)YXWe!(p#{Br#bt}(O9Y@6>L_MxfY5KriU8-H?7+9?$$5LA3FWM(|_*q?PWWr4!){zX#TFvMKj*}*P@%BJAK#JcYgUx z$G5`OZ)=xbLTj zdwz7&MI}pbxGr?nw~^PU_g!`EDQ7m1e#M>f);m{JR)3tf`2LF)8B%YWpZ;_1S7Tgn zp8wd!(|7GC?N)F4&r9=7BYV9#;*{YRk9qE{%(K^REPdwLQyzG3WXSwW$#-k-c{z8x z@3+m5Jo8n4@9#dkZ2#854VB+_TYcdEo!f_d2X21++EbfPd3tQi!{0qp+&%ljb9@8u zz3aCJu3mG;w(Cv(ZvAXoKl|CU>+T8fv^?U)KvIJ?sZeIF179-dg*ijlf0zy zLF@cMu7Pj;_sRDjyZ*Gs-p}`WA&ja2Xfcl z`oayR=R1f0a^{+^ZaZLk^2JGc=gdCip8BUBe{amEIc`h%jN+e48{gYBt+f8Q4Oje{ z{8pdU_Pbs-u01*Q?KPkOP(J+TEBpI%W?dwCX1z0g-l3+a3l3ENbmPe@UAH`P^aVFw zI`WS1QX0n2`p11+cO4$N@P&o-Z!Zn+cQ*PQV&kp*0@kP@^7eDY}?MvTH+3Nr8xes0PxPw`KO?^gH`QJ~D>OtJ4R^^SrEFNr;5#-Kkpe>{ zFq;)WS;&~%*eJ_JhLP9oxt4h3WG!L3NEwuMm_4|E z5-#?)w?nJys+}jNoxZqRjGgWbvj#`9=xW~aN~|54?idYTf$9F*@E5zs*umYjz#Q2Q zO=a|Uj*78!G{f94!peDm+l}JJ zePiq#!!XNmq`EP1#ar8A(?vCl$C>KJ;?;L&oGpS6c*X(A7f_#!-NDTaQj1(W99)C)SRcVYKlX6k}&F!@Pha zwZ<2Bz5Q6Mogq3q3m5f#X>g34p$tPuYUSbCzh0`f!*^FtXP8wuQa$|fy)$vMo7yLE z%rJ&ImyYgT{6nm{5>Isd88XTzy`Q-~w`p6hNbPu=DFaX^LIxuO` zLuE)}dpoBv4BhoXt;lop>()^*c1AOdoQL;3nRS;oe|R1usR*kaM{4t3&uFU>VQKn= zF$|;a6Eb4L%48V21CP?>yr6DuY@AVj5fF;buyXG=d;U-@hL?LT!^q`M?II^8EV?_|XjqM`r5~ ziFq-0#xV?vow*GADA-~3P?Lw_8Ah9j<6`VgV3;G@nHXbd0<%Lw6Q4UX3m-R{$_h!= z%odt)iUxy{a5Cl+@q2=Tc~FKZnrC7(R9Cr^?Ytu^6xJ7tMiMdnNzuqG^&-ElDKN+& zS<@^uy%ozh#$XqZvkxS(js$7|j_mnx!$C ztA(b!5}${J<|sw8MQDyzG#|&<`87skrY>6-LsyLEN})+tEWal-qZQ2vF+t8zG;@R| zThUx6G{Y3l2BA4d(R?N}Llq4@xG2Z4%J2Y0gRD@#$7?XW3Y;IKxh6*Qg3t_C!umyM zG8D~;)V0B7DjKWMj8ZhsLNij)&;yC&@)XT?LPJ^}!((YmE*#g4kI|eFqgfWC!6aRA z+|JQG6ouT^#b}<4(F~!fy>Q$PJs>DMuDK;f^QqAERZ@C14RXxM?eydr4LvYNuB*bj zRcHn%nooo#Rnd&Vs88+$MN=U(lA>9z(_}O*p<81ZYZ8t|gWT&!hCcfPQ?tX>U=cAH zc6cLxLfBC??+MNE3g$PV8KP*0_T)CripC=}$0?e#p&11juH1>RRtt=(c?}w>FskM! zXlNu>HN$Y~L$hgBGX)y5oT6A>3=KI|b2~I-S=DTZhAgX^U!Wn&s%AI_XR_Q=u^gb` zTBlhG4Ovz(cR)jyRn6ISH5%islP}Q8jse zczn1f-Cs!49^m;7h`gIw1`HKqmSX2YXvnFWkD%EC%_$5+cJg3pGioR0h*4r1Oqb|E zPDPWQ13!BDf;1+=WK-}tIt|US=$Q!>Lo=#VbsCyK(U_`YXtqR;0jnCC+xWGboJ?q@ zXf+g+G)>XauPiDWIG!$&E`;VNo#s7g2&Q7P(|8H0nhT+!vQRa9pvlr{vX9|2Fcotl zG&UV(4>W$ACJQIHbjGP+K~tjB?15&UPLthFk{WcH3!%Yjg2v7sXfD!evX0|VaB9MW z=1v{vJ!l@+X>$7WdF07T{b_-QoT~X08fq7+#)cDRs`jepCTOT#sG6Uk8LHDv2Y||4 z#XJH{j!x5aAYQ7W)69p)q0_t!&1h)GDslb^8gi;88z%=8XH~NR8j7>3Spy9+M5B2R z8naGwEKb3xebN1|yk9*JnkNms=Vxt)wUpPHhOda>eav*?u47FV3vB}xJGVhYmU}6h zZv;lwc+F%58{9EW1{(^}myl*MK1RbSIHE~N2S5DbF1})hAJP?Oo_2;Ih4dISKV zqZ)N~Eb!2W&etUf?-neE(Xp&CEWX-9tObI_Fglivv79*4)X(Ldox;}!@k6>5EHl0t zh7{5!XvlGmHtlw3jRvh9zBWkcufQ_nn_);H9Xo`5360hc)oHyQzBWks)4($0n_);H zg@qli(b}PysAWMlfu9Q#s}(G21q?$9X@{`GHCj6^`0DNOwG?8d4dr$ih7?jhG~~EO zYsU?(YKQ6uU(+M>a$$#INFl8icDP1s#{*xZfyNvoK5ffBAI#Te@I(3xENaUPLkj7X zboM1QT035NsCEYSpFEqdOAx*hEV9Eeq>yeCcDP1s#|K}d;S(IGgY*sB{t91{!4GMt zU@;6Sq#?s3iIiNUwUZC6(QrSGG->L&YxoI#jR-%aMzF{+43l0FcDP1srvUzZU7e=< z=f2j>&etx8HsmBaVuveyDEIKHA805(T%)x^BbL!niK7Xh{?l?6@HKq=kfLBY@y#%# zkiHXkRLz{>JP%dPE6|YR8f{nsX!Y%#uZt2oX9OMbS`d8ny+k2tbbTFP{U-DZu#)l3 zFr<*)5_Y&o8+s7FsvWACd^MF=!$)#E3_}X30UC0u<~gAuZ5KL7ug7STPG%nLpuY+e zg3f55fr`qDJIZl#6TnKsH(|KtS$aFlIRIuwz!(jLHsGUoHwqTR=&k`x1yEhp&l!0C zQ*uaXgMvjEeVmIJi{eb~%eD3YQdu7h7GdqW_XrkY^sJeTHAb*{k6k`nWqm7HgweD9!B}R&`tOBnkY$Fh8>=vi|ZtG8gS=&|SxmE{sF!suBgj79Sha{qL_b+^i@6)eK&S!Y6HH00q( z?$o#IpHW#)3f7tM(X&dSF&ab{CcV+GZ=1?$6D-2$S#x!)?|Kb-KxKI|;0Z?j0T)UG57VN!bEW+qn3v{e!7r%+Y zRW7fG1dA|wRyAYEL&f0_1`kkKKL{3K^sE}jLSmTP^uwNqR903N*Ahn0s)fdAn83ZI zo1gd*orE02vjmGUdR84{$zkRE_#aJf&~-_2gweC=p)ndf+1b;z1yRn|1YB8;BZ0FAo#HQqb|lQ215=L!~K^sGk4lGF9*7ei2sWY!CU zMHoFRqGQdRw{w@uGUmV&jxc&w6EteyJM*II81de-^S7!5;+0=IcX9lA_8 zhU)~2FnZQ9Xp9Ckj^wVYxU*Pgbrl7&3_f}mDiBzMaU?hJvVj`b6u}~lp7l>?jD|r( zfjhZp@E$d+TLgBE?6u5@xZ@x@rH3=4B^sI}aG19v+nY;B7i(h4} z5iG*!Sy5;-jWIhd0v_Lk;*bo z;9A1yS^t7YJqviasy0n!O%g1^=vkLCR#zO!eelSh$tr86U=c>oLPjGjG+^f5?h%=y zvg!njFnZSI&=?IEAep;w=m^bNd8J?xM$bY80?Wur(&ratpm5|IeNeCnqi0>oSltC{ z%e#I}kNu)x5k}9tim~L}SpU!icdB9S6)eK&StwM*Q0_OL`*LB4$})%{lrVbMHH>u> zj^w%=vl-o(oUTcNMHoHnT4-<&3{l|H)11XB>mPze7(MGcXp9CqtQ()5^QFqVRImu6 zXI;-&a#)vy2Wm?BLBS%7o^=Cb$?faBl@W9;a=JbiEW+qnH!@Zq9LaU-zd;kjUj>UW zde$mvjD{4Vz-26OqJqm|rBC8o!suByL8I2*>n0WUS6L3hB8;AOGh@klIBm?!dsNmu z!6J;Fbqiz3>3ZzGmJF43fnX6v&$^YdUmG!w`5k}9t7aBFJP1{zD zR#_*UN|yNBHT10epfwtfXTEr6;+MXsRaTB*5k}9tpRwe=_n#9Fgj80gU=c>odVsOy zupahpd0S5hvmVriH8A&)n^e|X!6J;F^$=spdHCA%Lzb(oErLZDJ?mjzSTonZ zyjNwl2^L}WtVbBDACBaa+v zR(Qe@M$dX48l#~rdBWAaeP@lznr>xEi7@;A^9^g?8vNVt?+~+jGna-8a0O93+JOs%B*j#@Ps3b zp7kO$YRVf3t58EY_(xi3l?EyR(b>ZyoL`y*ORd->u$j!3|Mq^DZQbQSlbwD1daxLif`Y9fl=mf6)eK& z!`jYRy#(uK>0U%fW_=@AgweBhFjiN=!WW#(N^|hvgweBJhlXEABdll9I}=sbSivF; zw^S-LPzX&#r^zU*T+ld{*O{Hb7!9;Vh2EV9MoEcn(UR;Lc+UraaY*@$aOnc}fVgC_ zlsK#J$;Z0k%LDd|T^ zNw}syvb1Dgb=}<3>XPy>J)>>~fM^VzBYt!aX9!Elbd7mSNwLlPTZEygs;MVsLv2}2y<};sEh}xBR~ab@FDVPx)BC=xAW-B=3QtGe@rI7NGAmwq zMDGt{KT7dl7;C1d$Z9QODV&j8#9rfN&CIq^Vw^mAF%)iz^C;m8FFS|vELoOxTLaz| zV0E(R(5Kj3R*HdTJbzf9EA6h5!jRp`a&1CK9=Tc%o6BY^&djpf>~v(rxc!I=BUO?!?a$=w9{FpW$L5Kb22NQvc#p=%C#2nDzMrjbv0FGIoZ}}l?`~8 z4BizZ7mb%fafUmESaR^ny0Fz3WW*x1%A>T4kX_;OP^7^+T?>+fU~y)zQ?t79CJ6o_ zHrWyqii%+4MARUWA=7Kwdobb?s30jngY_teI412bybr;Pw}DlMt=!~{+yGu@L_dg! zx5uG!6w}MWY9lO`J~_K{wOYiDR}C+*Eb;wBTsrU#FlJ^utCUJ!6XW^t(Bk=UYh(R& zO7ZEct|it7jYZT7-ef%C2(j@Ijh)&tPbcZKSy=&uw@J8`SheqzC_pEHCXhqzuYXK`uX(Mv)uWiotsQVE{OL9-Fkd8GV?`UY*{7&)v&g1bTjW4X`50;l|5c`@ z;#E_Ok9`FW__SE4kJ&;kn11Rwv86~%UONlEnAQk!2 z`fxdwxVF@%u(m|Sjw(ANmoQ4hAziz&wq&ugm)}EzipApVuPZILhDsaodL`u@B}EvR zU=tNsUtJIr>O>s;MJax~Ck4bBYcXD$7j9tP3so7L-Gv@mRBc{sLk)Ok4u4Ztdo<#~ zGM7Qv8>Tu$P$V^B$HA2pBF^aaB6z)-RgMD139W~U+Rt8bW2-G^307Vg^#?3r2y3dx zySeCvqH*Y=8{{(q%e=a}a%)vxW650Vr`gz#!efKKK(M#%#X@KV5D50Fq*z2rekTz0 z;rS)`NW8GqhZK9Rb@0s376K)ZK|+3r(4p?Fj$n}J$F@+MhvGco+7q3mzTPA zjg8trV51}-wMrM6Fy5<&DU)Ignbc`aPWQ6TOT;Bo^?TT?$;gSX1K^dr zv*c%5Dc+fi?W~d_yrU9tDP+x5F6+*$$eGBKpV`Pv{O%lNQQ@7GCF_scKmk~B-ho#W zH&o$VsH`%Kw>*~B)h$39$wlKWaV%NlruSO$30Ol8bm7WMHXCb5w^-s#XiG|(Y8O}4 zmRH~;2B%bULFt+8?8KP^>jUawKCB1DpVjIyiOq2JoOrW0n(@U+YW%rjdiL+YQr^U5 zVFz}pJQBrb0jn#!I5ugvnwUi(6HXOj6HOIi6HOIi6G;`#v=d7ekO`-Xu!*LMu!*LM zua9j62T%WTK#9R4!faeDK=%yyhk{V%f}uNnSj#^ZEx zf0=FS=`>9;(M7;^gJVLpcqcB25#y9xV#GL|V`9WOV|8LgYSfzi{2NzyN=oo@^Rh~; zU;J$=Nb$PAzcI9S!-M6|uU_fP;?J*S#SAo-KW(%9S=OIgE2H$%x>i+fMP1y5EoE4b z&^{|2L3BnsSo+cg)8X0|?v)Y!6Jp|vWExUut7LLKJI3iE8V`mApV%Dk za2cypb69Cf$Q;LM&Hcdz8C`+>K^xj=B)+Pn3psI`Hn7B2gLDBUM$rcH2Uly_7vmo{ zqm4{wD>&^#O#rVm|7TZcV#5Cm3~D3zSIvUj$MY|=tBr0#Gl=$aNtC1w=D|vj$!H4o7}4U{!XWwdCQ>h1zn<1h)6ACD$^R-Kk3Vu-XH-q#O!4 z{UN`VcBHlBVC2lgrnHt^&91bTTx^J-VP&~ofqWb8ezj_p6AFVKkI#vKMHFExPYtNh z>T?$q_}n&!Ro>FplE?S7wdB#Jww4LBt1ZP&V>Dz9c>)DCpC@Fs(_J8zJhs^_Olwgt zht=tG`W*%Skkv9FWXbFF4^b0)9a{2AHPLj0tS)bX*W<|d!;%Ab(wzam^Oz-%cFDr; zps)@b>dv@ILLD}%-|g}^3JbheCvLMw=CeH-$&|x~U8LyFS;`vAgbEyTX{O@HZ&3zuODTlb>G+1|ZMgkY%9VRzX54!@`peA_j$*se-6Sn{x= zFFYpTc@xp5odIj1$L@640%&g&fS}6YbLw)xeOwR|zU{9i54+karrZt`sNHKTK;=Xb zztXu|>ML+N3v31X)~WK|zuN3% z)s}5SY{{ejHPy5fSo1xhLQjFig)EuMlcH&O?Q1FTHAE1WJheET`Bty5(39`=7Lp-R zz1ru4)*R9z_AIvKMJly1a@s>)kGs%DhD81P1BP5)t1INQJN&E>Vn0K<+USc$jZy~@ zLU-t}`CX0xZWt5$7hCe!EtTzRsoQ4t_(HCL*I`G@8`#Fi2s8d41xDK(Q`%8YwaK@8 zY)-G&tr}sw8Mlu;83@aCOe~bzSzry?L(WivpZXqkQ{$L;z<{&Pl860`QI1PA?b~bh zI&8QDI!HZ^Fd%jgRg82m7X9go02j*s6MvKF-y7{Z?DyE&ks56g)}2j zwmP@x!{-Y6@*R|LWz*vrI;+C`2_bz~>-1RtzI+V7#1CtBKh~L` z(3u~!!Z^0g@S&{@OB#^cfxfQSe;H=z~f_CUM+8i3>J;I*o9Wx@2HhcGdkIW)?lar z)4hDVRRkuN(hlCOZ7kf=x(!Bu)^Xe6P(2C~abUEEFtJ;s{V!LStVRu^{L5~|J zN~mw?E*tG;Y{}x=P+PLF4>iur8r4buSVyoRkdMhF1Jmx*mMqnl%bIU1^!R92M7Fqh z2LWd}`~{9cegUTX>HvcFWB26SL$-X>SS2==TzQXcOO`k*XoRj>?Sv-y?0(Ee^5t_u zWCikG9#wMPHoHF`6MotXThZEWR+qzR^P_~U%JUAqLMWJV`Hqm=<^)w96BVy)UqQaD zAZVlhHl%3B7l!-=PCJ{Wil{1nx%nYXg}vx3Ea`4PO3jY%LQU$CtAzz2hr`FtB;@lS z6u8*R7}FpASOo??Iv>haOrxIp(QWuK+++BWw=q||?S8A@89*L*X!fl5Q(aO_vo2G6 zuI{&b^Bta$(?=Yof7RJ^<>v={Y_L@Pk8E>n&>Qp?xI;8bvh9sja}KN5?Qr8n7>zh) z>{Va^Yk?=|cKB)bu1*gWZEFMnx^k?REQ{p?nIf-T0@V(1?95 zoQ=`oq71OKWx0aL4*I>JV2IT^hoW_OtS(z&e#qe>>keJX=yo^9j1bShX)0p2(-&}t zyi`gRiaD(H6y*E87_LdJv&K3NzFwiNLD_}*u6$piowC5D+VNZME;Jsmp9;yQGo)WG z(AjbnIvhbCn;xm7B}@nXSmy~)e}QvVZH1P%S4S^du3Lo4cH7);djM-ZIFnSPRbcgb z3$gaY&H)zdOtB}7(E4bFmkPwn|ucgSJ$IQ?YH(Y|J3Oo*)uIUbyb(BvA7fKxRUv^r6GZjYDh zC>Bq&C8%sUAIBc@*dCzYskMqe6EV5nhb?Xy3u3(7H z!t7*Ftx;&o`F2E)mnzOHk8Du0QjzO+c~Ko$qs3{Ynr56R<@?+L8_nh>&B zo7YgKt{`ONOvh$J?FP@M*h6`^JcWUvm*$#S<OHBIyA7klUns*36e#?W$UOxE~Jv&LnO z8=IRoE_0k-Yc^vtJa+6@d}n1&7@JFkGkf?Ab%uchhgUuGo+Qno7mfTM_TB_MiehUY z?=c|^5JtWi<&9ngLW$Q4m3KMO;8YaS5Uf z3L+{hxFD!kMetq_L~zUhJ*TRxyQgQ8LH+Lkd!FxCPrCc`TW_5@b!zQxf?)l>%yfQ( z3%}LbmLy9kA8Y&H%oIbvU}XHtputSkV!K%X*D>MOW9!*o)3UHpfO;)HHf>}e?;YS? za5~E0NORkGvv4K?e%?e|4$eNwi^6#@eXD>+-mGc&W20c_nfk6p++lFeN?rucgX!xC zJcf3bz&y+Uy`-pEY^mTGzvo5eO^kK=8-SCTO*eIxa3sT;r z;GDGZf|a*AbexkMR)`(v8$@4)?)dLX*eHbZUp2(lmK-Kx7fN3T@OqV^kL(*5roJiQ z%_~J8*|#K2ee1z{HVl0)g{kilc*jf8N9FwioGb9Va1=_a-)L~+EWBX#+Zj6QfHPk5 zLbYdVS1Z8TEP0{&+XC?30q2%mARv^aF9)0zl2?+xXTWLPvvhp}z{!!klJu0GyLSdFFUU_LWV;Sc#2-Jzu-Nh2T6C zlxONAf4u_E9?2`If4mFM7ZzTy{z1*@J8)X`CF@GIFAbc@L3yTqPeO+dPOE;buEhQ^ z6r9UMPJ- zpvDKz_d$8~`i&ZhbqqENq4W(xTxW3Zm%Nh3mm+Y!C`DgWWb_+24Q}IX@jp#N`>z)Y zlSu_a2xVVa#4QHrouE8>dA|pz40Qm6lJwmG&bXjFyS{vIHU#CF?WHdAdR=ljW9-cK zV)E($|27QXDDa|(q1|JnU|;9h?OPAdE0Pzgyf;9{r{Me{dGz~t!R#Ym<>BZ@*eI05 z>kiJuFnII9*%$_IJ2*#6;WdU$KY~+Z1e+JKeiIPg2ArXi7pfdt;AMmJspOU9=jf4| zRv#OMP=2O-yN!fjuu%w=FSUdDBQKC)WtwrQF;4R1yEEf)@|LnY_;M5scIu7Ay_$90KWyCqmmcOe>DI82u>U700>H7kn0aGIQf!C{tGsr&jr35 zoC*_3TVQ*!x6}IIqy*)e^+Ec^f^#A$&#tc+oVZDxZOC>?`r3iBBPh?V?;~)23d*zF z7dshqFg6PI_H5VpG&uW$@=SdjpyOL`7EfVyC64zmf%CEC+4D8^b%vVr;M_P>=u_<= zNd5KzXRzdjs$XjEV6-^Uwg7zz8wI;xOntG4i&}*LAd8JcN%h+R zoOY5Is(z!OBMF>aEIhU^Nd5K)XRL)6Y&@WOWs2mGeH23Jn*rXUQuGz0;#Y#RVyV#8 z*w7bHzqEYlyA1aauu-tjZ>ImK9TiIs6R`_r-xWUmMmjbMq5PMDxHxbYN*# zzIxysyi4$^;K23;)W=}pcixTvg@uiRJzrB_1S+KFJ+Sd!!K;TuFn!c5w%v#SiF&`_ zm9z0oeKhai15VR5f=7Na_1SrC!TBf*-k0Fq@j&VN3c#uPV97k1_Zx!Kn+!#u`Znz| z$3Gf(7J&1r)uzpVU z^inW=0r|cR-U;v?dpSI1kl7E`sBJOyo;`3D!T3 zBBBa7rydu)YKFdmadIT^_n*+T=1&SQSE2Ns3qv2- zSM3?oHj+Z=Yaa%$1JaKG??K6>eiTaIo-p)LdA|ei$}JEOLY0?zb-_swgEtm-NtQ3%GP_OctiKO{F)dm&!!=QV8dnLIyk4o;1z?@kOpdmlJs=~XJRS5UeGZg zoc)qV>%U;-CHu;5)3lb@D1^#)DB`+-^N8fp{1HrF67X~2w0;o+0?i-6cwXR{;Cvx@ z6+-Y@0q?mTWx+fs^3&_W=meE`Xzln zaCV2G?@Mqhyh^!-ZZDMY_2BdjgEs;kJq+G@aQ2tN>wtW}1m~L9$hy$u2HDpYoT-u* z$}b7v<2ho@y@vyg2ZF1gG5Vl%u%*4V7;n za0W@9Dn}4~6Tw+riayHsU2sl@!E0KC`o%_puFr$nNBZt6(zIu=Q7DObt_b7vZl;Cg zB_etNIIATu7U#k8B|qQz2G*z8D1`De-3J&UIZVVZm_91U1n}}DH&i($fcFkKE%pd) zHA3hkyKj0^aEyJhd}-WC34<38Ue7RiWY5Gfc-Mhf5C)I*JrV|w^t~DekNomk7(5Sn zr^4V}1zvF&Ji2c3yoH@51gj6?T^A;=UKl)TfAoJItsz*xG~c!lgGcjd*D!c7;PnoJ zNBIs5gGc%@!r)y2o;M60F!WUcZ)+Gl%IB>x zc;uITVeqKD?}Wjlesm}d9<{&YVelG)cQOoK9q>GRv9p9=?YSD_+l9ev4PM_ccvK%t z!sI;=29Nsr<}i5VzwKf0s2#i>29NT6BP37!4@OWl8vhP}cU*F*{ji^DSt9@IBJpZt zI}gs)emXOrLo_RD!s`Q5AGMboz-ejcB?j`!fOj)ET}t86eAx?}36iJm3&@wsF$bKL zfxLin(ERZzIB!TEmeW+;pyfCK&gXVs&~khW&Z$y(RF0p)sk{#YLP_PQ4NluYUO+iW zUn)46l2=kWrh}7b=LIc?51hM8;ZeS8!PzN!C6(g@ofkQC6%KZ zICbqjM>(h;H3z4il9DRNBR9&6JeuJQaL(+)633tl%pJU3;rnNM1?h zC;(@*ofotm>%n=n6dtv!E#SN(c_o$O7&t!#@&d|{0DVyh@qR2e3MG}J6*x(DUeI#% z1}D7~9+hJlII|_Mq;mMc*$~JJC`V1`dl8(EC9kA%90%u&o#!Y=W$61AoC@zjK#0U< zt~|Y?r)}%25Q)Av@1ej*8ItDLCIrp8Yz- zUXC({@V)>x3aT6d_E9-*1gEd$m1N%#a3`$kBPgQ#s+q2lFX|BpRXkFV49f1E}JALT%%*na<9ny^4oS{h>(NADb(}Z8UcdVBeej>& zCuiP{->O4Cle6*JcMfjl>ZkSO=)75xT5e>EqG5aVM7N&mE^hWc6=K*Py2^MTUCBel ztl|lTj@>}}w7k>x(phTxR+=yQ{Mbhb^(XVP!k^5ei9h*>01wl_mweox{JQ`?r|wyp ze8!*rjR20*LEpDG`F9s*U7Q>3OC>(_CyB)Rk`JUIf=~0_jLt8D&7YmRDsS!~&3i#l zK5SaP^oTF@0P~ja(NoWlEu>*x8$3k+*RVZNkj_JGlvWi|Zwy#bT75`IFw{qB6Cusz z63>Nn2TRK!onYxHNWvf6ART86Ii19brl+3aqj7$K!pfC;{{*+MOSFE=p_cpDB7RWC zOlmmf2@gMIn#mHar-a@{kjBGKkJcR0i)`IZkR~wZsE_o4gEk;mvsQ;b*R5Y)@R_%V zPp_UpwZrZg?%Wy&M7lE4pGRjD^!@%k;!@z)3H5N6E{Se`S&Fc@bi{CWDi@YKdyYLz zcYTFtJ3tct>;@^D%a{R)zTfp|*^uZBM~`N4)ES4PVn7qFAoo1auArtVT(Q@s>AU@% z-2gOy=SXp&aSvzF;!s^2C^bMDvvG*0!yejoq@5)^0h7uGYx3@a8;EA}@!7)MGyW8j zZHmY*Mc6|AFr4m7iG7JC&2i(##ay3H5!zn#iNpkd;x}~SPdqLTr^SIC?oT`~&d!L# zMRDL-%sc7Iebu*|>Z&mHv{7#40L4Zx()U_wYPiw(=LR(XE=ck|`}8$PqOy#}tf!vl zrW)9oopnSG5S2wBrZzC>G?<-ie(Jr|q>IXrnBr|xE2u{;uW%S|T(N$#hH^HMl9F4(*JpniB@sKDR z1`I!i^rWL1i>meM^z{C3sJTYkHA~v%&s(6Rd?hVW(lRBjRMILb!G|~ayRzTM`MbK| z{XFW|6#RLSN^&ddJYtFw{CU)US?W58>0N2~(5A4{=BtHdRR#`{KiAGKaU3ITQN5H^Sm6p zpp#|vkmEcxBtMTIG^C0lo-QGdaobo&`3G2;B9 zq^i&$up5;$P)Rhhh}e6T^rDguE9pl_B9GdzSEOhKNnn!{=7vQhQJqm*3?wn(dmxQr z>>7n(M9kZrz=I)+^-Qsi6va@fr+#lnb(f+A@&-Z+cju$*PL##~C;Dhml={1q`({v- z`nHq%jftLFxSM)#0LLgDV&hAUrOqnTf=hkQJX>HpqrPXxQU5c~s1KTF)DO)w>Wh39 zI4ynSSUS*pr93Lzqg8>l0SP_)P4hmMY6JV6rN)rNq(!sBamErA))Ue^#?lowN@1A_ zo2jt*3iBy!wZa}z*wYH57n4LDyA}4H!ah;hzZ7;3QXyOQ8zfPV2%L*@RE8wVaWy0n zTT{h0Rk1fidJvmO>xupAEDgrKDtm1_q-reXLaNSE9;9!ud9=H*znZZpA&Dg#eIa%i zx=oa}6_S|h2kK{wXNYMr@6AZttTcQNRS}In9vn5U92PVxiYQE34GQ#11#f%H>aHwT zahli9GurSy#GsK#1d)QwHB&@!idbucY6f3sL8USi$SfkQDFU+~-fFpP%tcv&(7m*sDC}KlMG}T6FogvXwXuCQ&UrG_5 z`CnMXE*}qm9P=OF?n&F1gf{*F3!73~0>u>u;U?U|xUIg^yTtksrh|s0So5 z;L?@2qlG)K?d+X+z~A>xUA?2PkC+b%igK%_y4S>hEEIkJV?m(Up(t`^D(A zU%F8^H*mxXyazESh!4aCZab8hmLMK&I3zKAO@<_fG~5q!4r!%%qg`p<2y)AyIhx0H zzTOrGq$meO=?B>X=3OiMa5a?+cO^^}!xb%DM3F4x@WoOFsq+72qZj-WMtAuy8=dn{ z7)_TF))`OCxqF~mdyAtWV6wJ{`_M##OyEIUl2{d$;T|Ct2bPJ>-f*%5ibEpv<`qSz4P;H`O3Bw}sGrl5GXLVWbU z559`+W2|D|_BPDhEe3yd0!)Bcqg7Wo=7TJ^s;pBHd!saCqO^4EfObtcGonybV@jYE z>~6NPHKc{?5V|2l*KHoHA0)cz8=HIJ60^Ejauveip^}Nv1ALpY7J@c!~lEiz+SQHq8s0$ z=~}#9n&p46y34&_vJ5Wz3c6W>(bu?0T}4#L&$bYYd%>7`jPgj^$qe zVgf`I-OVwhFj5h~Q9Edq4S%rTLHCTp9`AiCl0fI$@~wzBM14n`Pyz>rF~Rs&(ETsu ziIyUC74IOGvazBtED>ihF)8>~9L64LB5~m8;vGi}k%wwJqu^gmObWggG%_Jg860Gq zeTK+s=!}AYF)=ClR&2u_X{e{jG&>EE)6f|O|6*cN@U3_hd!(VIg-r8=A#xfzqu^gm zObWggtFT8JHx4q*{f5YC=!}AYF)=ClR^(%kH05xRX_gowr=c?nXbwWafaXO4yjvg> z%$&suiQR1$aeRHc`@4Bb;s{@#Hu6}Hk9wa3YG%eQk!}gZv~X5Bl`6N3frWxg9@Wx6cD^C zkf%sn5t6`eQdnn&WhsoVZUyflg*~aT_Z0St!p=Yv)?b9Q4|&4_Xx!osXeCJE{*h%Y zDsALnUD_zR0lu>h{89P7gT=w;gENrds9Wi{^8m^b&KqFc7r(y(^MudnOi~ntsX^=?5fg}iF@FeolJC@%T6Zx++`=*!Cf^lnXh*% z_KGf^4a(|EvQ!^ChXz&Q9C{0>8@uUxtD7hx?xl;CfCdm5s396`abZet$0+xf-o}J^ z$?hjy-uNdXb1P@X(0wiF5QF$BcUFH(UY5at)_c~*wj!Xh(F#gj5F|npBLl5wr?8_g zqp@W;8{1!X2V7`2(n=HPsi~!Ks+~6B3aAcaLpd_YJ3D9f-X7~RDut#lP469Rf{pws zu>!PQSI7Cq+b4Q&8}r2FMlmiosJZ$afdj=f_NO^3nU{v-MKMrhD`^oVv4q+L$>GJ)W~x}H7Xt=?N8t>M;c5_whnXIJ zNT~(^%=KDRmJ3x1)7<(S#VL`61Ebk_ zZVe~;8-)YiCZc!dThE1Qk&p_zxC{Hb3vY>R+dDcp0wm_kv@MIIKy$=&9)16xmH!8Q zX&+$oPP>EN?n2uYZ*S>msO91vN#ka341EWVx6@ABo`dn*X~xUHZa%w$Cnh;W$l;;j zLQFn&Wi);?_a1t;=)#m(?9tq>E6n!jdyBh87S4=zOjT(5-6Hk9g)`m3WA)A+sE8=c zj)hd1;whZwDeN8FwhwiKnbDj!h|ZQpK|s1pU&vzB(or{o28JTUotla}x1l4Q?6jPdlFM(4B;FJjT#tI`QrYWh~w$p&P5>y^L0nl6e%P z8>{LS%)SE$@i23Voh>WtcZ^OG^Z~eLi`K6wjPlDDTE!hZ_`MqYJyQ6+OkuYBR6IO; z>KbD($>zZ%#a%efUD!L)>c#TLozD^aUOAkMPy|v0deySTb!yPZX-DzO1qQ2b z<5vFv^18)RE;(JTi*f#DNMdwPh9uUTqk{Fv(w;H(4e&;~esrKHYU4pM*C%RWzCeNN zwEaVPBB9H9aqE(76!&Z(@Jmi~#N9!Z1s_sk;Nut1_F~Z2m#@Srt{`LOTXc))oPxf5 zRX_}#izv=eXdT?s3K460aW1g-x|g>z5yNWYV; zU+BLdIpD)0{_G|FuYLA{g$lh)##$|3zhIKaLPk7V$@52ICPF^B_v*t=>$@JN5*K^Z zd@JO4HdJC(P`tzToy}tPoy~jx#m09wjttcmxj&CIQ_#0k<)Nk5GcM5i#TmzYBj&5^ zx-K8c#KYNXY3j7Hc!d(*{HW(Mx_qj`%t+lhl}xWcPd(%b{X};!_XN7WGgmxRm*SbN z=o2FlEBZt}Byp#Up5BTJBU%*-9zC-ayq^_ML-7UgdPw99+lvd|JJv_?TjTc%_Tg$Ehn?78UQP4qJIW zt7U0vqG|(IjeDF6N&Zf43p>?ZM$$Dnz1;87Qj|0bQcHF;JrYk~DXWoMQlic7$!en~ zpB5`jIt_el+PS8ro2vjZfxk__}`h>v-EJ;g^V8<1AhyT?)M zjMO9a{rL8<_>gaUv=Q;$qt8VYw!2oh-$mu*Im7gbtRVIavi%D2GaY+v4y)R z8G5+exNWBEgplpM7VNqbqUOC)VBl|^BjchM?DBA2H!5IpTAZL1^2Zx^ja9E)+%Gze z_3KV}TPut@)psXd=tJnP>y!tE(iZHO{337tF!cDN&^)vSbI)nHQT`~hEN>U-(PHvj zAja}>n$GxZh@vaCJio^qt^cCG2buHBo9`wsiloPIz@-3OqxW^|7=FLUT?#yJ?pK^f zFEf(u7`V#Hd)GQXOA;e2UCZsFw0P$Yul$KO-_jya#b@H=6i;G(pwaKG;j9FFWi!2})BH|51 zh+3_l*Rf3QjlyXCPt=L{ObXwpmh(r^)u8W=NbY$#nNx=wm`9^)vNw3784BqY z=8b_Q#z4BWoWi_3NIx)dDJ1ds_8v%Lnm7$fTuj~!FNiC^E|7Zi6<{|=Em`VCvDiFX zI`)TIx=l&+X%KZEk5&LlXjuxWH>X_zNob*UkkCS3RR}E`m2?Wya%>*04s_9K%A*aX zamCn zdm#xe?<$Etf)cj0g(S4lhns^~OIJujOLvN8Eqx#fEd!M_8j_g&7eXov?f6y%lBmlE zAnBZTGbC9@kc2lbDPA1%d=+V~^r?$SqgSiMB-jj6Axw?ZZiEzK5?pwi-v8VH0-lRw zxrimK`LVoyv~XQKI+w1mf^G~OmGp(LfVq%=0~iCMz6`kN*u0jbPL{CX4!4$jwTRPu zWXoui*)`i=P!C$6sEfa#k(BlpbR}tTUJO*a^1j!+v$24UDR=_rwdv~4ttb>`iB+#W z(Tcay5|Oi5u!~Y^-Z~=A$C}f8oK>1H?|ww4S?GEmS#%+BmMbPd33-V8T_@W>&f7&5 zt$BxtC23Z1-f55S@+T$4qA_&B5%-t*=mtx}IjR!J$OJkRr_EsxRM2(OB8yLAmepLt zr!o1|$T>w>SvX;(AaL^H=?UV@V!x%hR5_&=msm>|JO>LCTzR{Wkf}@9=P~&mVL{%m z;{?UzH^+&-^*rRfKZ|pt^sUsw^j#MTC?;T6HUZ|eFlYiL9LW3Pt!_lJ$h+?;O0G38 z|By#L&*w`*!zj)c^F;AhE-hmi;YmH`f!Q~I4A}VGI`v_H@>&()PkxkSvZk1pz%tIC zObr>+MiKT{D7=Y14*RH8?oB=r?@!(dZ9+GvU6Oo=Gr~!+wj}wm_2hkdg2YRbKeC>D zC{9T0lH^aUCm-<1lH`x`-i-GpAK#n&F0$uZ@h5){x>i`w2IUU&`xD}(voCcmiW9+F z^gMEeaMYl}f>_MCzT~w7(?Af5Myx10i>mPzoS|#St(4OQ%ElOXVvBK0lq(fUDW!O2 z+vg)b=Ykx?(QrQWh?rARq9uv$;#(aH!~0<@SXqP&jE36lTuf|1b;S4znqhw~W@rKN zL>lx{E-gnPQI|Bt)A~k}J@;HpWoFQNwBD(H3wFg)^>};WqR4L~LMISPXisSadL}ZV zoP!Jod2d#iX69C0u#3M+j>*3pImFZxM)Zueo`1xZ;Z_PHUz6coKYx;`HY=+V78f_9Df#X}Gt& ze}1_Iukz&Ot*93e)t?wiRTZ$*Og+=`U6Hl?jh9V4`&S23tSSdUItc9^%?s&OmgYk` zz|xzLidgyt(r%XM0_hEw=%EDKBhoIyp5EX0@SAl1VeAF$|HaZ??7wB{XY9XcsVCTC z9hC;D6DG4LZ6Kr$EYaGpElaelxQQitpIfZ5=n=PAWzkLk!>n(_LTXR2aQ8D0sB4YK+aJeT01@mQG?XUPz#~uJ2^cWiVlXhAm2Kj{OYAXg!$AQcs25 zs;~@&s)FC=lh=L1MTvA%PV8nP{w;0b!FjrZEIpUtuHkWPUSr8R~$f_e1+ z9>tTcL`dR2p?;9Wt2bL9-HI_LO1l#KuUJbstmX8L6VQyCI2u zPeKxwo`*#9vq!rgO>h9tqO?YkMB1AniL_lIiL|RBiL?(x5@~;dBw7TGIpR5#3**XJ zE?X2NQRfvQiQ4igsR1Ohie3mwEJelC#CLfyi||qR(I_pU_af zMP=ARE3}BRTHfqNTFmOAJrw1(#iO>F5#(NCqu@8I7rgGFEPXSxy%k#)wO!mDXSk_Q z7-bnmi*E`wjLJbZuOk-jKSPbwrmv^9c1!_TsPCYHVWovV4hO{Hus9r|gD?4W%nSlJ zLdNjVa2*!_FO4ie!!^*CN^F!;%p+MYU-CZnF;O(`aNOWa-6y9w9(`LB1&qrWjq~On zpr04}>{KN^`4Db{HDf0IMwgKk4q+_+vr{$lUQZyiyf5mD>p@U_tg<$u==usS?W&@f z?L}gBg@{7jFvK-YJ-())xA6pvbw1~ET4dD2jwIxedo{knEoR4Y0{&?++z`Y1D@!iC z#d|&KOg|!t@o-)N*2ayYWJYP3Y3Pq%~kgAd%XT08-%=>i$c zh?wNPX;~;uaqbzmkjVWM*~gy^q%GY2FvuJ)lw?^?thlR~zv!?)Mt+o$1!gf=1r&T1 zlTRg>KrNA3;x;-QLj5@Copj%hl_-&PnNe)%luCw^S{A)TMHZ!}g74NVanZ$3m{Gw8 zW1!P3sY2gxSfE#u1s0{##ZM*K55dYp!^TQvYQ2S(3``91^r~uIo>1tmG`g0>^iQ!U zi$@ye@UIztkxfg=9U*uJ*{``(DDL?yqk4?%%mS| ze`ZEx%c4_P>Rl6w&(Hf4J@kuz7xilRfdq{%PrI<4-YH0((*8`&9vw3vrg!}t?0H)9 zcFNmzhFs#kNhqE`Ct36x3)$iYT>P5m8N7S?F^ao7$h;kFunRW7Q**eNn}d0^MR)GY z@xYM<={9Z-G@Q}(4nEz0Z=*T3CM0?SMV;`uV9U>2HV5rcLQfntiY8JM(qwKT)NDi( z39>E=`mW+xJbFs>h*}>4TPAFSioGf2@>!9cn1W+h;+I zPCv+pyQ13{;6yZ&i_~)T<;wubM$!H~FTL1rO#QD>RF=4{gc%Wy!tIAK{P40!B*Z*T zGpA4}J_pfLCeiYz8J0h}Q?eq|gK4*I8PX2zX8RLJYFOG3)Hv3Ir^14Y+7Xkljff(N z1u7n3OS{#RC1C;9UukcE~4xBfc8TpM?mv229t-m^_b7OyTA-Fm<(0YG)VN2 z5-kPN2hi`)@DKPTZyzMO`yZtpgY+)P{tHqJr=Z`*qHB1Mb`AD*7^?$GV6+Gv$yjel z;_7N7q@~zA+IZ|Ma4dc4Ct|sU*ao&Nw{2EXCwQaNc=SFvj0f-L=ttlDn&aRSHl;Z* zA<^ZMX!tZ&26 z^Sg`&hjwJNA8vNeH-u44dRE*DH=29P2awD(-aw_H2A>ho6&?<;;^3hJde#Mf7j-qG zXZ`7Ig+cndlAm}M8t>J(jrVHAGvfp?9C&aMAb@%Th#-L9oXK+K6;;PG4{CXAqaJ}P z2i(-s1oJ4Zulf0NqyY8-;P;7`&Ffuq6PgxvxeCVIyALIKyHLL$CDHj7{RAo=?_|k} zvtwCB5M{I|2%>E5Us8td z^`x&!;M!tb3i0o}$*+40rzdPcT20)?*0b@ph~BX{Z7i1m#e<^p<49y7vy~{#lE*6@Q#F9M)(s_=hZYJ)^P&X4x_Cb)ul6|<6Wsge2~;eFkYi=T;eZPy_a8ZLt?mtaBiV-l10C=L<{3x97~I8k%E@ZA_ZNf{=vMOkf=JMv}TY*igu7hihhtp3R>Dn zFpmb8D3<0z5-IW_i4>1RTE+R&Be&Ho(ZXMNoW@7_k~_bVRNZ#UE%~yMtPZv$fosd~ zUTdlcFNkrrosxPfX^4_$LJ}kH97qN1!iA93i2D~m*P(B2uo6V?z~?&nIEO#iaoa!F ziN;qZ645);q9B64?CBhdFMSI8Mi$=UZrj^UpX<2)$3EBje^z3tf(s6sc*LUNuYdaV zU-o6-Yk5JJz?c48pX<2sZH@S90H5o`%FlJIzYQS1ELETDMB}>>+xAvjGbqX*}MQP^xlfDWO)jSfCxbZRtlDMs)MxFoZ&vkn6 zDD#het^>cjh2QbHP9%M<6HTA%h`}VA2NQfJI4!cUx7+H)%l=&F4R{FwhTB3#IG8WW z#haCt>D!_zE8E86mk$y#_T~PJD~!s8$!@(%^swUNjtjSe8%Ue=CI%Gnr;s_g5T*|R z%AkCwDx*!5#p6LD11{|B)^ngTQp86Z@oo_xS=c$?1Ipqaky);OScwopu3+4@)di2j zk(zD!D>0saXxTB78+H~pV*T{Wlc=$oBE;-j6a_{w{bdQy{HPM_hy@0k#C&@fB=Nlb8Az8sfTlX@BX9t%DCZvh z<0Cj8bH{}e=b%BsCL#UyNWBG3LB(){9l}c%^riss;$ghLoSH4}W!A(u6S&Ph0ebP`P&2yufme4p z7B`=9doWR7PIs|DrSHJfqQ!kp`Yz0^_sHg(zx-F|r@eaE5=ZRjgir?MU(%5LZ04VNekBX%m#??921BVIC z36KVJzBfX;hGWxI>_`<$w~4RgSZZA&?HWk*UV?|eysXKwZ>m_-61V!WkL)o{5^&RF zDLJ`>2PSm=DlDQ7CM0@@B1@>GMoMa}q<)aZ9gsngrtt_sx98OY)qbVfH^_8#wuC1Y zbT1Shp>ephCly2mlc+KFM;awOsj!WYv}WhV^*lE&b6ji#wc^U}R!HJW0W~gxErcYV z6zGt|ovn3{mcnq4X1y*nZgx3u`a6eK>OtaxzM_cIT0s)d{wu?+ z`tH`vgX?YF2BA^wL^}>*NUZ^vl-1slkc^_5p)e7GBN7QXOy)@X3Dim0CS#j|jXq_` z#zrqQ=3t}cmKPiSs3HAq6kRXP!bYFB+>VW=syW!`CgTEZ^hN<)pwm);zPHw~(Q21o zdR&fe1vYyBf*wKASV0eyHeuU>jjES!1Mk8{w2OC{*?bzE4{tk)P>{!X8MH7O7ARx zy}y~h5vLEQJ%#IIr;l3xO&eQZR(fat?QQ8%X&k7`==LFl;p=%IMe*HWdL3K5`PJ#N zy%v~FX+6xy{Z5s89!u22=s`@B77r;UXvvJc!p&om%44z0V~NV+7F!LG(e z7zN`f&cqB&vSD$kBYEz2<+;b$BJ$khERpA)U?~yOlPrw%ge1nB z36P#)EL&lQ6#zJpA3+Hj3_m{0ddQE@u~Z$>Jhs}#YnAE z)LuPEOaGRKgUve2m4_3cKUA=K*x(rL8wPWLA`Zs6F+v(gW27;Th$kzdUM zW*q795C!8{S)6Ldk)AhEFpgJ=Q@)=}B0b!sK=+p^7?(A4Uxk8kP9CSgpXlLu9iM61 z_3{`mk2U47mON66x?8oVeO!;!qTXhSTGTr%B|_TI61AuUEK!SkmnG`A2U!{k={=Sv zKsv-yHl+7ing!_tmKH$zkfkM%4zsip5`ESdrQHwdW0oF<^a)E(Ksv(GbC8a*v=h>& zEEPfejHP{$K4<9=q%T-H0_hk_$02>m()W;#vvda136?HG`idnQ2)|~@4e1+}Vj=yD zrRtErWhoxgcP!O|^gT<>Af05X4Wu7fN`!QZCF)&9Ye9C7KrOGd9{N|~-Ozons%_D; zngJ718zm(wsk@TWlys|-Mk;B7lCqUFOG$zDmNvSQ56o*r`)ZDUh9dmcoLy5a^gd)u zZ&>zsEZS((NSaXDAp^ykWh09o`_&S zFiz#LhxwEP-J2KJ_j_5Q9NuDya-e_WC$9P5VW~v*i2PCI@CoxNha)Ue89rr+ayZHo z!%_kyk+z;mdM(hSR!lNvP9N)Vu>o}Zm!sPNQsP5<#c9=DyIueR5@K) zqRL5Pi7KZZOH?`SS)$76z)~Wln^{VN)RCp`kovLI3sN#mX^_%c>JRB2w&hkx{TUky zsWnR@A@yZxETlFpC61YzlhJg_)XeD_O}yhrX+vrbi`N*8&zv4VWvVwmJ7;QkM$V+! z@sp?KPVr`pZBkyuHyt;1ig$WbM32jyl#w%H^r-0>p<|j%nLH^(?9@qPL&rGMjmw^H zW8>VynLZ{bGuzvA%BZnTrsR6HE>ov^r+afoWozR{z|gFWF>c$22ubn+!CbGqG$@{IapCJ#^4A1AS75Sw)BJg`$jugvM*#DVGF z9Aul=Ej=-jcg%T>*Cz%YJ%j_PoN7~~<=9U_Fcw;goJ8z|9W(~m?XXbzHux-M?;SS1 zWN-R}Q8^i7`;4YW8IGazY#OwM_EY2>%urzf8EQ8m(9p%o(4{uLWaz-mjF}lZUC_P5 zG1F&DudTG7hA>lPPiES)4>a>$W#$^2UNSQ+bBs4PC!~$&bsVV9*V+;@yq+QKERHpr zNifF>OUPooC9F*DD637Zms;!-woGC1fF5aLNJ?6hMlvZN+2tfbP| ztt4f^s_z7ACH^-`KXGj>>2k_r7)LJq&Zg2*0?NS}h%782|Jp4Hk})tfF`XB2p=?EgIgmP! zO^J*UhiV)}rUH zqog--QfdTkY)Z%obBgIImqwP>5UNQSB_`$VZ7Q{n_EQjoxkXq+6=$~yfC{8MNm<^_ zrk9#;z+~R3d8bZ&u*8+i;lzMdRFBTdBYNL@TOzBsuTHIAzQvXelT#TYFPjs;;ecRe z6E;)X44V&h!L500`?|71bJuBm`hety%2?2BDC{}R(=Q@JyfkM%3QxcU8Q$*+{#+@Qtu=QgbQ_S(T2d5iArHmJ$8 z3%>cMZ}R-!p?rF?EsH+t*mv@MaodMH^?63r+ug#wH(_M$hFD)*2^19+96B@q##xvvkm3Dq-(=zi$ z9eU{lqr8*vTXiufzRN}9yl8BC%YonidiH@~yE{MsM%C@5o!@<`{Y`VHoUFWN@SEr2 z>hEm5aPoKi2I$``H_}i3g~S#v7T4^kkj%?pO zF5VEm`H5{$9(?*jx6K32Cr#Mi^P`p58u~t3zh+C`l*Z#qJ2t2{`|63K4&VCpuP3`y zTX3|&z&dlTAKm(wD-Asc{?5e?qwoE;N{wxg|2%Q{PYoLwb|yXk_OQ)2<#jU7|J`ip z_Fryjm}I1XVBzP*Lq99Oe%R2*)=r+>?Ea&_|M1(=J&CnL9hdgK>zSdyeqQHDfA^@b zr!8Le!WFGPdg_VAtvOvWuU}bQd1LKe5{eHi%?hjv=*)}X`$imx?_3Zy)rFPz? z?<~Cg+r5WVd;HPw$Ng`fy?4vx`cbh-uh-n0^YGI2p8kY$&mVf{eE%}Vk8GH?fA6TZ zZ{2zzwV3!25BrkL#DJjOh01FE6CbA2+>y-QAnFz4!8$MWK$>%3YPW z`PE*p8}*Xft@Df5@AMqFlUPVAbfxa{7wx{Ys@*Xg%4T_3Gdb?WKL%ijN@Ta_m!UGwYdd)Az}vE1&6 zxAV6hd(kN0{uf&MPeoig(m1a+(>vj4$B(j4T-kEe2v6Pa$NsamTZfyH-#3mY*Dttg zUc_%-80Uewk-=yOO6<0m@$;;_I9*E4@KW^TQt%uAs@;CH<{cxi-*X&>4e{##oSNOlZztF(F@vkmg zJ$lp3$Pv#rxmc}wd&3SRKjYlU&o~&gc_`7iHE{uGWm)4kx>oRf+1_ql(ZTQH;F!L9H5s>PqFa8LU4bKX7sbe-|r zTEsqeDQ?S|#s_lxRQva(T?dEd4w{_N?zzr){(0qX{WmNe^=eYYv8054o;PAAk6d`` zlH04UhTmGAAYN(7V+xeKr2fZ(~-C{hJ)AgM;JR94v?@Kdo8~DgOb8}Zdf8dxmW^#wLGkfEg80C3-*q7zIK3p~J z)~8x|(wE&^9<1CXx9ZCE*;x-B>-P2w^LBoy)j6>F z_GKTgzHMDA&-z!d|8C}z0clI0IWgs}^L-EW`t!9D$p&wqKmMatr;na0jpu4|ZPuPI zR^3q=uk5);j&9s|^TD^KwV3l9~&z-?;6SzVFm? zb!qyN_P2byqWh2h(s)%`4;p;_);{ji@;$uM)BEPm4;=`_Q~sG;rAlr6sqDaf4f~B_ ze%x8@QU%U60{>!fD*tK$-@=GdL?^kZ< zmc5&*&1jeZ&DK8`7mfcjs{gOv6CbYGm)d&%y}u2=rEcW5*e_D{{CijR{9?n;wX&uy zZGCIDE3lk~-SeKWxbE5tA8#(rp1Ko%I()kStg8d{82L1>`r#Xk{&>3l;G2GZV$AK8 zwryVVeA{~}UKsK1&-cw*`RnPIjiompxJ=G&k~#LS!ZI%UBqBmf9G5Z5+oV~uyIigX z5}7e|Qj^JJ`9}l<(qwE7?j6s_AT4wS5aGJPxDYTDYfZ*xjLsdOkWK(ySVXv9QE`UQ z#EW}M36trk99VmVi(YFYRq^qyAyPUkhps&$T<>5{7oKz8c_YipnFUPz{$PZw9VEIn zS!wa^+aonxxY+biOoVHdJ+~^j4HZ4_Oi6q7UFG zjMR61C-sQ3rw~dnltsAcn$vKR+o6YE>Wpw5#-2*p>XwG{o%YbHMG-FguU}M}tcuZ} zly~T%E5!)cHW*BAL!^B4`vQ@x@S!Ldy}%aX+5uzgLK>WV9D1nK5w7akQ|Pt)V5U zFvqZGP3q(|PCfLZo?VZ}p@&}Di*S`}55?N`RCVYfOG?v2HEGvV-JyqG8Wet}`Z~XB zexb8m*EsalaOjC+PG{`-UdsOca9Ci!;2xp+#T_xf9F246p_ddRTnnV0xcrX}I`vRb zH~ZJj4UZkX&Y>rsISa5SdxGn!$sD7flAd^no?6UVfPH8^H#qdva_C85&L-?>1o`RY zwqKm(s%_Il<3@r*PaWp?u%}U``|#nDoO-Btn*Jd@bsT!?F=r_4u?_CD_K;IgeVd-S zM@D>5&!MM57$uv)p$Eej zeAtur*s@+Y42K1_=jO~Y+7J1snL`hax)H7?v8VP^cir^XPCYGcdZ-b;di&rQskgFX4^U(E(5JN3XsOZy>vZgS{p!<-?s$JQf%KPo5C zKW%M#$UkiydT6$da1Fwq{Ieka$VjK2_RO*Rxt&8#2j(<|F~qA@xCH}kpglL+^ia7v zIP}nr9O3Fpdu)HkEP|^7^>ni7p>eFELr)@e3_Yi==$hozL!+hHPf1UrLr)jxP>-e% zJ@W`AE7Kma{^49)G%`>a_T!A0KbPt2mBMi}4W{$P3raFAshdCwZmBt*ZQ?jS|vhNpI^AdjU%bZWJr`6=} zYK7>OX4??<(5L=pol=|c>#!%CIrmFF)qd=^)TyVxLr=Ox5B+RygzGKrX>2LK=Y=s& zJ#f9n9%^F)9C~Oph~V~2r5WF77cw`?CCYxQ;y}>a?ks%W$r;R?wb;{KaPflqq`o?*

    mBNYQ}1~28mm2`zJ@c0Mye=m_pH5p$S{Y0Mlc5*k4xkI zV%rI;9^s#n%%PS~dj9=r3KEeQC9*z@F-~daXylbNXkZ zO%Kh>Sq?pun9~`1YM~1@#~JgEW!*BFIo5T{B!`|U%posP@D}gB+ga~Z5o53SDGoi^ z%-Mn_6AkJ4tUZ3Ihp)Ruy-#C~G1g_||NeWnLr)HKHeyfhutD{0b)0&pGba&y^5HY1 z8{U=U(BoxJn@GG}N}N^iVhVzB^4eV3lgk`hb&#GHJ>KPBhn^YCDZ~IpePiA6MYlWk zU|5HL=3!4|Z=G}X+8GW#l%wz=)mPU~T*jDbsju0JLzYsQ<XN*&=UMrWt_GW}~82ERZ*&u0#e zRFvPU+Z$J%=g_l&IW%Ta@Lm71F>YAOwGc7(cDTTy=T7F($bhQX`rQ=ug0p|+F{hQ} zG=AylEq6NftGz znw(hV(6fX&^l3&FNJF#Nq22@iT*w@n#VD_u_ntYw#Gwbx4mL-?(e)r*T-OX20fBmS z=1}R%VY}kKN28WH^ekhJF~>c*qxs`jKZ`lV7Y1i}7#y0pBGh~uJg=3^G3LrDyP|4a z?GgR`F6Pj9K>dg2%9W0CVfaH{lq2=i+n$KSqLL)*y}^5!W3<&KT^b@0b1ZFj6?3e8 z@E%8AtC>UfK%x7bPk(aebuVHfTv&+kd|GW-)(uvUDA#?=F~(I|Bi-xB>we~xoY$H# z@_N9L*BVD&4~CH!wVcw*wa$^(T1Q?Fg^}0#F!FlXk=J@hUK^Ox27Br;KiAtm)LIv! z&2MDR3G8X?==-DpxRoR7>k-75Yiz2ojgGt?Wll5fDQr713WI21JKThr2-kk>Y1}xl zY{(cZN96SwbBwk@YpqR=ywG)_hprANhiMsOx63iX(w?7Sj2nOd{2NFfyfP=xg!GX{hO?D1_okXFX%6)=^ zqdSl-4un2)7s1H=oCER5#(0y;i|%AmNLNU2qrn2nbQQRQ)ffHWBnll>D*E>Z6zVDD z8H*la$mb4({@;@bhRsbJNEZh(#(^wxAoLvog=Wg0cO4uT4FMdC+~XZcnnVUDJzj|{ zP{>Y+G*QTB66vLoD`@E;^U8GH?+WJC`jXQ~rRpz{p$d6OA}bVfQX=aWa(!8m(?bdw zERhKcxl9(csI0Qf&&Fs;A_*RjO$c8LW`E zC9+H*wP;z1aIZo}NMyA_9+${yg?u8BIE6&e6oQbXkd_h=C4JTvtfXTkXM{?1Od@wH zkND3Lk}$(G113VBQ-!or=dU>1IE;fNkrqoT;GywcN7 zBBV!fZgn7YCDK4~wmCQ-IgqO=iM&kB6D2ZC>3LQnD;08HA{!M_H%92$ppYRF$x_Hd zi6kiG5sCCr$lDST9(&sr%wzwtaHPj*N=N9T^h}nBS+08>$PNeci32HLS!g!(jBp?` z9mrh{WV-{2tRgfIQ8xFM$a00Ok;qzwyeE+d6;kd>p=X>zT1X^bA%i5+O(6>;BK-V? zE0~|3v~YxDBigNF3IIA{cEx)qyJk9BZvmq@DO ztg>)2UB9}5wS+Aej%W#AIFK4w2inuxf!yvub~=#54&;mj=~g2!uc;1Xy#w((kRKdK zg=>W78p=QIB{EMTV^a2+;t-Nr3&dJ z5wAkBB$BNVpG2Y+@|Z+ADCBjC3{uGF5)tEAO*BrI$lS8OWZ{U`n|!?yZS>PI4rGA? zxlbZ3RPHZIq>Vy8bfij*56o+Z1KHw0PD-Se(pv2-MTtfh=|)uR4%F z9Z09zftqt2$aaa$QQr96!TH^R#MKd+Z&Rtf67ebIU5TtwNcp-V)%^9fX;@{VF?EA|nt12X#GH(nZTFmW$irfRS9>LZcX3Yj61 z{tDS3kxmMEOCt3Za!Df16;ijc$akPZ21%r`LY7P9VTBx$NTx!{G!c4kP{>UZ>8Fs1 z61h(y+axkZA!j6VtwQQG6`GS3GFBpwDddnu>MEpCGyD??B&?v2c0eeY$Rr?c8}g9k zG*qch0Eq`@xI&sY$Egij45We$`2q+nv&~d3TL?XODLwf>D457+KuC{?v}h^xm`EWI z3Xdo~`y?_^A-_tbwnFN)5~fDa4`im&d_NEhCUOV}wI364w-fEhL^=bZ#g&Q720~Mqi98R4x}k}j1VY)F zNX_Opd#4LJgY%4Kq{x*7j(1Bk9t zB>|yeBC~-|UM8{y2$kJLz6L@yXd=}+(me?)k_v=8Z*uMg5(gxgb5H2iyLl`0xVT8X zp8+&N1H!FvB+dwlBBVLxlkKu1)J;<{ubLd{O!wLlYCiO1iHbu*f;Iw^l8I2Nok}xK zw3lEZ1z{mc7l4pAOr&Ke!tp#w`EWFl2cV~-LKaJoiM#-W>cT|608-V4xD!QtHaV?; z(DZF0BZ1IBY9cxis(KUI0fgF^iF^g5j}58RS$u?vqkUMP1D?svW z$ag^QvLRP?!7uIDkd8new;@?Tp0y#XfxK!%b_03KhWrTRLmP5+SNznV4M_%a(uPa} z@{0{w2c+1BybYwR%j(0Qfm~%nYQo9a+K^NrwQb03AT4dkCLo<{$ooM0*pNSf46`Bi zlf{3kG3#^ykl8lQLLiH6$TL7F+^iYvu@5BDQX#)fq^&~gq=-~EDkNPZ4=7}xuV8aiTRuDmRYIAwU}>^$5h8`wqm~Z5HoZQ>uKKiaEC2cREsuFBd4) zlQI=^Y^h#yq!RD*Q>tS!6?1H1Y*sdMjW%gNRN2e zky177CG;?d04)Ou1%X)gyav?NL-j7cg(3D@sfRfPXa}Vpfmrptj##@M@!m3}a-|A; zm_vZp8VCh}SoIVEHT6)r#Je=ao+9-yhX8G-)FTk9p52JG>k;p`QmTmF!XD-jpd|vK zAP}pbH-Oq}S$qRU?0GU3b8NM|hf_7e-snx@&3sC=L*~vL0<`l|k3g)szlm6TDa6|& zl&S?LN@^|4AwXMCQzwEzta{!8YU-g{7GD?HA7!g@rylYLV z8uk@EmpKGzbAV6~h&A`OfkwEjdc=EZ#K!CPe5Jq~0<`#ke9#19)$w` zkBIowk&3**90IhhQjb8adiEpMu1CCYOsURGJA8IP2MOxk zl_5w)_ArMPER}i$V%765>oHm{^+EC87bSZcsi@U4hXCylsYf7IJqHnMwmQ-y-s`4R zo%;(t%ppLV350?`ta{!9YU-iZ8?VZ>Me1P=r#~+B2*j%AkVB97)`OB=IY8LM9M;ng z2nB&y^}G)>!qp4=C~V2U#Sa$m)8a%MEmJXv0PQ{?2{;PGs^-Ii(tbRMeiCLxA=o5DEgZ>iGnysfYThcvp?s(YFdc%ppKa z0zyF`Ry{|6M!5Q8Ul!Z$#ER?0d$~B#=E_veAwYWu2>DqcRy{|7nton%ayzc|$m0}_ zAyqt%%ppLlI+zaBf_+Y`nz~{m-qvaitIU#P4v_CQjb8adQK2Wt<_17 z`0fU<_Jh>J90IhuL;0Wy#H!~jM3{QWKi8@H%0MczhdHd^A*n|oRy|+a^pHJKO3x9g zhdHdL=`cQM0Jf-l&%Y3BmW%AUQ|W0n zT$GDBtY;$-3Ieg}`4*^smGb|w_b%{pRaN`&nI=uAC6E*X6etiNK)JQK^#+B^B$-^= zOfqenw1KwiG?_LDxiOjPMJ!g^D8n%-Ufx$5GpY6ee)@eUzjJ1vb)IMKwb$Nz?R_pe$7kx9*~ui0F`TTI655%f z&5fG30<>2k5&!E!vq7=Y$U)1cU{PraBaV)^>e&ZOj)(e|Xdy`O2t>c%ka`HC=Kd-q zIiA_rQq&TQk^8u05k_VG5fV3>|0r36QCY7s%Q>$j*Nc)8MrG|!!&)d=gi%?4O2gVD zS%eW@{TL+1qU!lS5WD&3p7p|J!lHd&@U0);`H1jLLco zk{nMlwzPB|a~%{I{+Yf(NC~5|-i9Q{W0W%QyK6A*HCT0$MHrR!4zo_dmX?lP&(5(} z+a!xHD(i2MSa~fz^7m(0tnWz{VN}-NnPuel>bJhQ$zr`ES%gtp?=s71mDim3_1{>m z*W$s&x(%3+pQ+I00-BbeYDdClw=V#27bTxQYynwIx=tX^iZ&XX*{sH~~X zDi9W^W;u_- z2f)gOcNwG10rHt;#HhyOcfM%lH8&zEgfMDeM>6YZaabF=`sL*ot4Xp5qq2@-R*qyX z-B$>tQLdO|5k_SdFw4Nb|Hl7dN@DDdNfu#LRw1(tA0GVDPMm%jtQ#eZFe+;%vy5mn zc*|7?5(aCxWD!PX9nCDGe;r)%7bq}T`z4DoD(e_#ohQAq_kuNL7VC(OLQEKyRm7~b zBDvR#BSZ{f{aqcWzoWD}C2&1x&W7a~M*GK$!{>aMfTarZ>m32I` zjJ8ow^*B6Wc;okyMHrPeOJPm_(8Ui~tRpZ|&_WoMbpo@D*!%70Z~3~#s+26ksH_v2 zWz?7V*m<9}SRu(GjLJHRSw`#qSnK1(7VC1!B8(vbYZpk8yn%Ak!qBc*gFKOR? z#A5wHvIwKHikUT4vhah&$ZJZE*e8t2I*nO04<~H>=4URnSf@!AVN}-X%%aiU$iYfA zN)}{Q^RWWuIgbM$PLSW;uIfO0QrOMrEDL zEN5@bk}Sfgtn--V?2WmSMHrQJKC_&?5tJ;#fMxT>1OuV5L4TS%gtprOYzCvHqBM@3vSsNETsKRvELL zy>Yi>5e6)qH_DlH7A!XpW;uJ~ZOI~x%DRYI&fYlVa#23QfMxT>5@s3Rs0|c- zhY(_^mn_1ld0osb!y9T(8IUZ(sH{tvH66;09IVtQC5tdBtBP5MH`Jc;J;@@B%JMPG z*&EME7Gc1$dBe}F`LGZP?c+UXH(C}R*)P087&WhIW;uJqCs~A1SvAaZ_QsH85k_Uz zGRxT;Uy>}ssH}j(Qv27hB#SU$*}PH5ta;KKmn>d;3n9ef9T2~SQS+*2mf;Pxr_7fu z!lyb)qn z3G6^Z%dcK=KOw}TOBP|&yp}V|*&DY=7GYG@3T8Qb<6+4njLK?dma{irl`O)jtd-1i z_D125C?8?KvU#J8S*PJJ650bdztThqv0NZogi-TqXO`iOza6!7m&Iz5EW)U)Rm_?R z<#fg`79+1sl0_JmwVGLmH->&YzQM}tBa%fJmDQoJ8h-TqKUl19NETthvU%fDW}N}k zkkFnVxEQxI4GSNUEW)UHUB)cK8-JMg$xm3UKS>s0RMr}19f^F5GdGJhV_0~HFe+;; zvkY&jW6If*MHsbQ>r56B+LIc+I>jhgon#S4&8w4HM!D3na=l~`MrEyMmh5s%BJ^)BH>#LAEnc))QsEUtOb++3zn|pMyv$Jy~*4-J4LVSNfkXc9asm&q%yU|xMBR^1z` zq0edif{_7yikd%c*WnK|kXjsW?djd<4#217O8n7ic$=@5iOc-~-)gFhMYeArFR#W2 z=KR&|rDdFF-B5HO9P`-#t$uuNudLh`s;<41$d$HZ(CGIQ)l%Sm9Aq-NDKcnRjl3Jl zpqlVR(xQ4#0g7n zO=_$vUD-PzK4VPnlHJ*aPpA8WalGy{wO+YBtc-3;hoLVeYE^B6^a=K~daBAe7uJ>1 zg1C{@;6p2L4wcuJ^ufzEc2RY0sJdN#dQ$e+Wxf6V4&c>RiRoj=oBAWw;aFFXuRhdf zRtb8M_)srC!iv5o!&3c9H-gbhnj>36J=;clyH*WF`@4OvUy5$4M#E~iLt86qeH9`c zl)2NawwexOSc5j36-;TP$=?$-eL{8VAEvLr`>d~hrhHHuwSkf~Qn-cV{ME~?k4__I z`P(ZXrA8TwMh=&%6^O-~BN>dMUSyg@24u-fDgiM?cuemD87|XKFPs{O>o=lP+ek7reN#zB(~!;0 zbdrjbn?O3f8QV{KGBu-Qgy;xKttlB~FI#e>N{3BpTj{_~O)ML{84j}h*14^E%$Dq! zjR+jcheV^OOpYJ__wzQ}P1adkttV5#mC!T^{h1qB*2>IgmNmm_Y*|y3CO2tT(@?nE zJsM#G?Qc^f+cuw=Je84ut4h-cvbJGd@rn3qc-~So6g8(s?3q9~hBJs*SRQr;(Oh4Y zisyZ*F};xypQ%O}*0N3@0H(@Lm=P@kLj%D`EW8q}+Np%p`P=DWbFc|BYSG`FfMkAZzeKB`0@EC) zF5HDH35XmtZ?&Cthykc-LDSGC!$;z*TbzTY%H;_MPH~BXRbG#v7K5G*GRe!iNdN@n z132T7MIg{J>Uz|L(Gbl6#4IE?JU%tVDG;9_0V$lRc1$R-Yjy0Kn6DccrDvti*A1Ax z-77uRO_kc?T#U-lPhD9&UpGv1oMD;evm35);u0@Mc>zTqjU%o;^w_>|F#^5>~C?b+Wn+)mYDIpzmD+=ksAom(u zlxT15iVQ}4t>xm%m0>3eW*wk-&~C&7zSbo}j16PD+$f|pMQXu0u=IdpF9tI*NMPF< zed*CsB{~F}a>@z2P=z2PVq~f+uxtar(UDTd%~Ya;htm$4u)#kf;&nY=R+TD+r){o) zMYiZ83Q&W~Y?z{?Si#-KeqBM1`y8KB;oR&S2S;Mz!LEpiyeTRfBb@4naEzqf`V9ZM zF;`Wt92)8m4s}Oltd=vNR4e!zj4k-LA~r|rqeB=hQowu#)d&LA5a2=qg*zIRJVned zO;O<(^Dm7=hk7?|^M!i5Vz^MwjkQr;8?B2*BDHv+(eWVnO?l1OPUbVBfGk=h;*7xc zynq}TQ!;=8x>ViR=&x=I^=^&yiwnlJk&&)w?{KVlXb|Iy91G||xgSHb&3Mo|o70mi zXDVAVPe#lnZAOSp65C>;%MmmXrANw0LlfWR9w~j1rt_%el+L5JF&miX7ivVZ9klmv zL?l?{7F`@Vi%n0u&LWFuwP_nq7&n6JI6gj$Yn01T1Z;BZFN%1CW^G z1gXNDscv}02~Zsf5;Z;Z4WwNq>m%9_MjMCMv_5B++szdtPT*NC$Kfrh1&qqCCM-pj!mlR ziF94Q0(Zx7BOwrt;wD^@7fipQr;oU4Gwc#0TzilkQR5)4J8lejIk^KJ(WSkK88r_* z()8A$cr;ZBf{ZAq(oRG#wx&xdt;CLQYYZa#Mt%Nxckd84PNRj2h)B2ojOkFy$%s2t z9hMYaYkY(+peOm50;Y@wIZBl-4kaUaL?8vS&K-_d`Eh3yr+N{(!cS1HPFHne zpeRkXM0zIa01Pk&k<=r$aU{(_TV9SK2st2_+Z2d1JQGXjfYr5fW>6jP$IWhWKZkD8 z$O)>jvD6>!>gmPJ2kUknQE`)Z$TV9(0 zAa2V`P#C|O!|1H7SHydx(MUgz*hqA*u)3D|8E`e>{(dopxPa09aq&|`8@^@)-idEb!cEE$T^+1!8v z8TT2H7qv}j5WR>Lr1Kr$jkInH!;xrvl~N0j40Z9rE*fviN$Ct1R7(|KNrnbHA2T5O zHfTCE=!i*WF}&uFZbHPytuPESpp9IZtl`sj-0f#oQ zWHO3Vt{JA$oB7gVS~6cjOhPzcNK69R%O)m0nDxmR+@1z&On0&Z+lH%2;VEhuUD_Of zY_*O0NN$_djT#3xhx>c!c33m6?Qf2(h-{2RaS|5sxhQFXfkfn1?1B+-jAxB*YJ~qf z>s>V1ypRb|YLwbmSn4KndgpRfTmg0C(&KeE_SEws z<8pTgE_c%$Gdk3VnXD)tE;Coxin9HqilCY;kk48sJ-j7zHSPl8Y>ykY%So_2x5XoV zPEU4K8h!i_mD-*|tl(fQ`@V7=f&6bidFaD~vN&mv_Ts7CE;=#q>>3)nyf@;jq-SVr zwr;J%Wr~PwYZZ`1dU`~|E5VtI?GCOSQj!5Kk5Q_yw2xG(Q0M0-Rg8L1-R)V*Bu<7W z3srPy#z*{Ayke34D!n-tIJqxnFf&4g$>L~i8z0d%m5h@f8fte^Kp|8i(e(;rIC3IT z8&wH7Z;FiYB@@vLlm{1h1m~v`6jE~GlAq!^)H0^ildh=gcuplYeUy$Uqq}p#vwoVz zny94Dl!qE6FRIF{vq>#w`sZIdJL7{}dI!5V;>-w_J`fMm;!8@=Y9_}hPikjoX(scq zjN%Y=LYop6lV_U-z&?3RDa1dn)5$f5K`Xg0$>E1VYnfUpNjLlrkJ-DgEkN0ykbzh} z<(p#WVNmMi)5D?G!KsHsZIV~j=;-8BD=3JoLrODO;=U8xJrX*hQzC@9Rr;BKS~A;r$B&U$0&N|w0{MOog)Nol3o@k(gcl++EgWX?Zirb8>uGEavnoh37= z3G)pjzPs#x=PAW8S&+D6+h(D-1eEFKRZ2FQIZojt3l{kxsjjnNIn-7bEQfZL1&ikO zlef^JC1#P=0_0_@DX!e~w-8fo%gk}AsVrCyHI)U+!FyS-lFpm5x=otmiELO-zQ~HV zFtt@=#Vd0N7g-S(9cqS$$aCmoS=s5($+F^6L$Nje!*!QBrBxgz#ZC?9aH&oj7Z5k% z!&%*DPbqBH)Dnl@ojsY_w5{%_gNvKM4mY{^8fA*187WTw&P;MBRc4Yy%g;=5X!e;& zF2OOa?@DN7u{m3IE(cF1KTeS1^sK2)&d;8l)SNRv)S#5F%J$HK{f>T0X;kCxdlp5^j1Onw%T7++jN6hMj~3d2Jtk+LMD`x8(p2BcgnN^^&MQdf-9=t+CwC=D;g_``NHQ}y3ry0MuWbq^ zJRFXju}&Am4wverY5PC>Hf@Uc|H&Eh%+EGcuFCQbFEu^7MbkUDamf9it%68%)7FN| zaMxB$q+;|y7qZO&R!nri$7{=7y%&`3Ca;~8#a&(-Je%9R$;EX3w*lPVwcQJ}WuX)! z)16_9ml9Q-Zq%lRQ^nXr)M2kGN~)Z6iZWMiX0|B&VnEE?@59)=s!$u=Gym3AY|Chhv_3ai5yx4M;Pb|?z$1}Fi~>GpS~ zFz3#(XJZC8C%6b{O0lxQ+tsUHaJfM~DNkmt!)}J+OcxEA{F#&qQySC`$*^yF@rHOrnAU9lHWGiSa7FQaI76niF_Zv!WnB`bzK3pOgd`^NTS zWMbH}$mX72ayhc(*t0oIx73m?IecpE#%6uPEZLmN5bYUeyu*~7Q8om723gOR z|MAthBx6ho(__`58(Am)TPYqHa~wr7!R^XZhUPSvASXLQPfC^DsN{hx^uB z*7jjL4bjo><|$LA|CCC)>~*;QD`C)~8V1DF;(7_jLS}c(!@@hC;_>k$ zpQvxYGo50I4X>Eyrapsg+_jo;>~`6i&o?`x^8U)r>^w%XD(zjvf+{@_roYW{F^ zXgCt>-&QrB-z*>LuBxnBV3Mns`Ia^ZLM<(LN1bKHM*O?`NL3lA{LZ<~4dIc9MQQOh zH`Mq8b@pPUU6`zh$4upm zYimM*V0Ck&uX<=GHiG}<9JY=%)KoVHmemJ+n>yiU{x3+Q)Qdya)gc_K!!f)XhhJ4` z99t9!)rb5w4a;y0|E`OdeV8g21{#|h8*8guaA<(vS!0lze9fU6f3T&64t2*mH`0Fy zn!J!N*w9=bs1A_I@Rn4-!j{JB>gI-}H2`$+TX7A=A-uq2S$%b&uEr;y53HI`F}13~ z);`Muf#6bqUE?yJt=%oGT~>`o8}y5JUf~r~hR*qcU}H;NLw&V;8y3kI9@>9b+JZo3 z^U}JO>d-Q3<#kOBNnNPA2JOXP-PG9JY`kp+!MXuN8Z>uSrzqGNbCFoywvULj>8knN@d#>V2>rho zFTSE;nI_iM`|1M0x|W*8YTv3b-cH4Z9*S1Y??MEK4&enkB2BOV>NRQA4ZdY{frd~W zq6fVhBMF!kV(`8lfNL9qwLt|9Lt|B?Rr9wbWo%_r;|n#{H2FhK%~tb@#s>$rGZdWQ)>C`z{O2Vo6+lPYJDw(#%q?0cDJapsd;IrrEV#XVbG;_EE$K&Yy1t> z4R!UX$;zrSQ@nU-OQ5O2k6txGuXdzZAtK8PykIlUz**I~q7VRG z<>?QXA)b}`eE|w<&ZY=8^v0lQq&s=OBTY;>XxNr=KpN#Dx2$miR639D?5Ctdh6zbx zX@H~D%HHvCrNeZCbGFNkZ0$0cXR64`F!fkvrdc6n?fhb9nmQVGxN4C`WjJnGm;q=s zWz28g=BW18>;yARmMzflhlt={zEgR7^#}f>XHR@LpXTa4O*H042z9+ffxq69G1qW zJ!%=67FOwciY7)f>&6x)`vg$pXn7M3ntRB96PVa zP2UQI_Nw0cugC@N{gDWs_$B0zT=3q^wmJeBfu2QVs&Zt zT>#8dN1Uba45;Y=MwdAH&aG7+7LGnDdjl{tPZ0S|Q*c{_5L;?jtAL3~oLXK>Ul_Pg z1M`N&(YKJTd{upCo``zGN=rI@>w&pf;?n7R1DL{-((C&+4$lSVX^BgxZw5X>d^UZE z7>k>IXW>{tVi<^xRbI<4*FkeC37j8pY(2Ie!4I7{E>yqfksVCv2l`WE8H$$xi1-haNPoqmD96(~4MUkn}R zE?~}|FL2cSo%H!3KWl-eZNf^6>Ss$IwU;jdGoK8@;=yX^Q*l+mJevVm3jWIyL;7fO z()R<%k6ol`4`QVyT^v6E%#n))&aK`k-}59!Af5Al6$dW^uJ%HKQvH%tzrcJ(;@t9` z12x~1m~{F62nU}beHRIos!z@Ld%!&Ah_mX0^4%{nner`K0)1F%Ntf?_V5VQ}gtPJ` z{@D^EkkZd$zENk$=-cAw0(YUrQoHgMrp`A=Uu~B9>VaF8tZ!s1UKtuTvei~16;9Hp zO)1spGOWaObO~^`C*gdBr9LOzGg;t%34QMY_w!4HDKsT>(|2W+z!+O6TqO?P0NgJm zmi**|L&(rx2j*lS5?E;bb;IF8v9=Z~E$MJq_%!W$thBh{$baAS5yD#B@_ovOxIzI5 zi<>?w@3Fu%N?f|~ZUW{r8T64~z6s1PGTaH}Pj=7~=F2=^smev}1H3uxMGthA)lw*i=|GT@Gaj=d7Y z3bC>5E1_vFFGbis3EclktXXg5zLMyOglY4T_!}_i$jIrzKJ@LL%YL@>Q9P{xrbfm2 zl5upt76hhU;>>)L^pXGifca<^xc>s?j$~X?InIN=p8@k%iAz_G31AB9LBJw$Ddm`o zV@w_@eonup?`#UR2bwN+Lds7N zHT7ilg@E1MdtFFbu9>lCU9TFDxfE@Fl^^uufEwkdN6*q4m%!Znf@>k z)R2WyLKb|pJ8>l0(9yZ>GX3SX_dP;O9t6L~nx`Fy?MGomo<^r8b({(zwF7IBcBPs6 z3Q`|n*&W#4!m0bQtzpK`OxdSCrLQdUj#cODOZQhi$Tr-CgBqRCXmqytL###k)3j2i zo`4jcbrhv~zWqkXHO1|(kCW+|DBEMw)pnUx-gQc8e*;z?+JRBpvyt+#0W=l*8rC9> z&QmUCnGdP!S!OHG+ZoC;GgEm|iZc#|Q5ef`#qJjX$kTA8Q`S-mQo`rwASLR-X5+gV zY&`9sVdJkHY!rSZ8&mw4$;K&}Y;zwt$fY%c{qOY*sG~|JGYxm^xwE1?< zhpv;0c$E^+9h%SU4w2-s2N0cYp~WFjTk)w$!2mP5KFh{ijcP9TMZBS@n}|0!AC~c^ z7AetBRv;zpws|U3<2&{cdW=JnCs)GX!cu!gr4owBL?slF$$u!NDf!C~Iyw>Z>U$>Yauec-;ClOXb}9CEaCOAZ)OARS;Cd@kDU+v66V~%Hb!F#M1ETuHI@ioHy+rFW7>Ft=9~C=Q2gwsAANhitU*z+ zQ}qV#Yf~y7N(A?h?k?Cx`Rd-$hYEJRNhy!+^G-aW`+5+BE#v`0(wU^LQHo}cA#M+P zi+AVVT>U^I{?h0}v4X{A1-m{;utsQ%zus3XKyL$+*nSty)iC_|^yBo$^cCKTC(VHI z5;PR-yjP5h1%-J9GwX8;3hN5-TZG?Y{FdOi6u*_QeL@fHhB7U&eP16;x)?cX@uS89 z`$A*E-JIoX)5n7QmSYcP*`AMHh~jur@K;Nz=>|}8vHRBh*bU}aOcczat5RCQ%)k?3 zSec5(kE{;9QBW9o8k^uRv1xk(#1-VOSkumJ=TC`WqcTe)X0|!6|IKB<|NLLY0}>V0i0N^>geDHhX9F(M4^yb6Y{)p3Spw^V-& znTB9fVFQ#EYGb1xglpa?Sknd**92kun!pnw9r@2}+d-D^!iF)>G9I`ZA*u?_l_7uJ z$o%T@z|B;W@xX23hk`ivZlWJOkdJDc0tE~=+M(6D7A3a7G&)hRi>^lO{LuMR3P!(- zR9^$vDK(TNwx*sedQ7wRi=(ZGUeS*Y%W*JxbWfd(|L zX$3QV_^C%5^P!E^qmB8{#_G|=e3gmeT6nI&I9CM;O<{K;@ZwnTrao;f@FEo>qz7)o z1)|^q{azSkwXWdJJKvcyGW~%-f#=m-2#=_^iYF6oFY0xr0toZpj{UE1lV}XxjfFIj_Q)2u6TRr1}d+5N`fn#>Q<0<&) z7jZQS^}P%Iatuj*Rc^&W>W)tq>{^F?lDFe`ta?I!?4kq0qZj>Ub8f}%*N&lxa4?o% zaH@~Ixbsy{{B3=abhmzh9De&&v_O(831r<{FB;sG2D17yk2=CIqRrOCGvL+jccGQGU8e`{nTWsW*QX?c_bk_crfU;Vpb3dg z3fS7w-SL@vGx>7L)gFo$bmBrj(YNo{<1e9Q?R;R$HGyN$x-R-l!AHLG9%3hY;Y6rV zAJ?}ZKog~d+xPGMP_C!oW0%w6cs}jKs55A<4#BesUGSk1T#+oMAtiR=&aDVi)8R)s zu9&g$In=HmFVZ#rs6?<(*AjvJiyn+Egpp^CHHrZPb{_{P?!32Ho)OUXTMwUg1@aSl zQ12aU5KvY&3(6MgTWc?RD^`JKkm-_Cd{%-k8+(ltJXkYEq46kVu#_?Is2)^?w)5T( zimDHK`?QG#vKc(cg*E~nHKPvQn+VQAF+%!uJueaP8rl%Sya-^&>(N|_Vi+bv@bRzo zz^pzEqn&r>?%a@pl{p9UVUv-=myI!y0?=6S<7@%qmi*m~$pB5j#sj;_TtkX#KGrU} zCQy((joVX%xtpf_6lj) zNabl4%2bgSMQRLdp7woguVLKllw#Q$1TZ1{7E(GNeF7;=Of5(Eqkvqb^&lmVjv}?4W!EG1IZoYy)U}+t7b%L}McN}~ z>K90fJl;Y|Xn7y03NBG0Tq#l~nW?kPR5?x&*1OacU`2w{vQRnd(AH)O3%D+l-XB1al=) z*E0hR@Kq$VzFIwSm*~&90&pMNpb$4;JhjAna6gODRE@)k zsE+&k8uU>Ls&*FbGn6m*S(oarp#v$GK2ZJI*V%r$10v44PC`m};Ve^Dj?{l(Ey67< z<7k6j=%{Z=vNTq<+Xp>0I|Utmp&S{)lBM7e+t4pYB}U zh!rK;G#7#t+K~zQl9WV19pfs|9~YH?nHQTt zv$2U4h-s`BbIpx3>s(iYO?xFaz9O1g)S(?^+9P&+ywf0dXeK(^Ef3719iOBW z)6ROiQ%XB)By2YAERj3NaOUVDxx<`Fxig23(3t^Qb3W~yFLz+y%+Wb=hgFxzoket{ zSne#Lo!Mfij*GKe9-*SrbboZE6!1<+?qEhgbF@kFxJ>zShb_;QI}G#69kx%CJDl;m zs3l}0v*<9qcNNX+H=}HYgJkU3Ear5K2_LS0kSM~C4(UB16ZUjSCz5Pt@K%7wYNY~M zJF+r5Mnwe)vZxbPp{R`xSrGy!bacr2m>Jwn83@Zd#zegcps3dlSv^8#C=|6MWRg2t z!bZ*vK0yj)E@N|8s45h7rz#XxC}h%Id#U&@k}^@H9b=*`kq59dgHOv^5aplQwhw^M ziH>Mih3H(gtF#PRtXkGKGkA~GB%ETBEhjM9!3kVnXbNWGA2p1Yh2|!ukM(m#g&fny z0_e#ddqUX!U7$Pu0u8d)h?e>ssT4l!kSbR{4lphl%na`5ATGvQy`?A7(4!ZO`6qV1 zJ#9;HqGXgt4*f{l_Lv*NkW*Fh^V(@+^{Ye6g>8KNwStK)v+V+%2eGlwk@X+GmnJ1R zqtWS!jQcPYdG*!aSAFl`3_}bt4Ayth>@)FU+A5RR%W$Gu@u;u^Pgjs-=@yJ++GAMr zv{~4SS#BIDF`J{A;YYC+X?J4#5l%gdt(bRy8swcU`z}(CBbBG!j#MSjzJ7!h&3W^* zpCYx8Q+tuRni&rx^)XI8X{KI6io9B+{S~QQoNB_%P0ScpBK32~^0d`vY7J6PvTVI6 z>o!w8W~$%B4I}jgGy1mbJmy=osN|{Bn;2{4)Jb2OdUJRN)QAbrIYE4`3EkcS; z1M>KiojJid#QQLG%SW6};%*V{4e{L~uX?vAA2*DoMEB>S;pEVbC4Vk%G$oejCYE{^ zH+$)Bk@uf=x9I<}mEsI|rrze&kN(u+!q}0xDuVOlzn1T&JKu1?L478jY*y#5op>>2 za_Mk&nKa={^g_LwE&)wV)OlZ<2{qHkeKcX#AWry!fW};LJl8nx6~}WE{-m3I6OFlj zo)vOl$-NS%2ROr?-sjOD=lxqfO8-r|ZT}(^+wUS!{}6W(=)CMdu_})+WV)X)hr8hk zpqVZ5U)GCqS`KF}(idU}MWYAbGCsi4S1T@9p(4`z{%I(5_WeybvIA?8_8_(*2w3M_ zOEcBN^vty|UAEqTV6YAQvB2s(QPZML?|LJ|42JJ zPSH5|5}o)D@=swt6biVuRoAnmsGEv`48H7j>5Owaj5O+0!NK@&2EvHimjH= ziVGAqMO!OIs*Llv?A*1*T9E!Zqqry1yQwEO5FRcb?%6id+f_W$6CREfx2|lfo@)eb z@LZNntd2U^7qI4OUTpu1Q)Iw(oT5(mMNW|^be}++U4NNV*rZ*W(&q40a7F0)3a2QC zuW^dP;Ws&jP1MH%SY zznEd)#wp5yt~BI{y6P?#uQP-sbs<|@I3Kcg1*Z(uT)cR%s>C0U4H@qVYm7w(Rz|~v zBmA~!AHUL<(d7!!Xvw6!O*z8g)hwdgzsx*{1TRLj^~rtu5%y83RQu?d6Mh|QC4AV_ zPgs=4c*`VSWtL@G48y1_-HJM!^`zat5Lj42URA9~#tpDi!VN3xQ@vjw85)ShqT41} z10#xB&VDnCs0Ox~2a({#$)mzX@~CPf5uETJWUYk%kg1=rY7I=HJce=P*pDbGZ6%-_ z>jnl&KmW|TfBgG3_xa8=ewS^y?7Ca?ufD=4 zkMEJ6mKNUo^EzXH`?}`)4z7CYJVQ_N{(UvezWdCj~TL{8&}>3u{}>z2n&Z zuOE1}JbdY?*S~P~y*JX?O+xY$Lw}1KHy7>6x5Rp$ zx#X$gudaXT-G^>mp}+9wAJi{d5cs+Ad*bP@Klk*8&4)$QL#H_db92!!Hcl>4V>;FBk_PPuHwx{!|3!ndc(d=J8wAbzTZ<{Z@^UlfOQ3L; z)q4DlxPEwZ}4|HvC3xa;7a!IsZ&F#4UZ3;&imx3~M+#8eNRa^z^fjgfF{ZfWVY9?uRb**w%g zcc7b3orT2y?lB4nIi5X+Li5-D-Z2`4ay)c;r7re&j?u&@$MZ6_)3H{(JnN6*f1mB| z8>1+h<2jkOSi4$RzLmq1Cc7S*MCEuou*D^JZBx&&A5YaoM=U+tpYD8eYKk5@wawv| zRZy-Ue)wTb8>k$1duXm?>AAAtt!JjC=%LbN(nGT}RnPPkJx4HR4Q;V@R9*K(sy!5C zEj?7OBU1Fxse6uRoz(OGfp$#slFM~eik>4=^w4t_Ii4D+=i3*3`i4|J6zeT}$Ug-s zdg$Mnb3A8YOIAeIzK2JUEqlcKW{ze|6kDp5`2UpS!5s^;6*BqT`0ykg$??#9o_g%t&#(VcDrR;T818)@ap?pPl5c(M zHM<^B7pJfudp|un#pY8PgGR$g?tbsHe@WF-oTBH{6g{UgW;<=M7JT%aKd0(BUC~26 zJS{~JwZI%tdOam6dd^7Eb0%ZxZC?wKI%jEchw!*PZct6-c<#WKdeMRPD_=P?MbFuc zp|^Zd3n+j3wVP7)%wdclTWUWKe&gXI&Q8&D4r7dZ|JI#l-?aNjw2gDKz?{dJQfz6t z?UC?@QuUmVBRL*A8={!`$^2X6c8q8n7cjQW+IQxqz&yeb)! zKCk&%ZuNPemNwho&$S3gay%5JDJIaeFh$Q|NHgiVkTG^W zi&+n8q?SO-iCQuHOuX4q$P5X!KUx-=m}NqMt%0EtotDL>my02xi~3?Q zBnJ(F$+E7n8ki*>17t`#QY3ncYTKcz^{qGrR3p}96iLJ$6{n4MBmpc$;|Q!o#w zNdA^0Im>7crk*Y-Il`1&DCB_-4jdp$Iwc^F~e(388g%rjX>dxd1KDOoKgr<#(hrDUopxlKxrHYG1fiOBsM zQ0ftiZQG*hV&^22H7F(Ln39L2q}-I`(XqSwQur|5PRpFtUf6@&y?IHB`2Gb{Zf)+N@mj(7|Tpk5|R>;JB_&>M%XvIY#7mL zZb*^*KuQXsIY*mod)weeP?h6ZDHWa?oBcgY_cM}}&n%K3g9-S5;P)(3@+?is70I_S z0jFxUFk3KDpc$nl2_W3k9Lka$gQ+x)oR;MGkkD9RNp3w_(=JgYS7G8DQY1l4lP^;w zCt*^&QIWg~NlcO4d7OB%%F64bWH6Sa%#z+CB`27YS0N$c9F~+cHP0`_9z7X#Hhyz7 zNXkg^1N2prO8zb-xh%22+j0qX<#6bokDvXzI7cJFLOLP9!WiYvnHNKnw9=ZAQOT@evJK7f{i!mh7HefPEb_t2y<|;_l+{O7RvCcn* zwwlHmC3hdBIi5<|VqNx$bx(>jDeP!nV4*{4KCEI)xmM~C5_|4`!g$WdmSV;J-@Wxs zG3&;Twi_(!xr`x!_O{d`Bz8U3II8Lqvp8avp=*;K#*jeULY*Cpkl6LqK&t8yXC;LG ziPXaw5@>HpJwjsFQ;VajSH)EbVwDxs7H??9is)y1hiZT%rZ?{1{JA;eJeSZLi$y6I zLjvsvNN5ofyPi5ot=gG=!jiROu1@G@ibd@(h6LJ@)A&ad61$#y9I))6+7aiBg#R*F z^(@6v%N{D1IKLp)^fQD#j3I&63JEPjV%M__QdN&Q7bf(Vq#nkQ zKzml|5fZzeCLC2;i@5ehtP^B7VT{sRg3L1d4tZ5vT_M&Au&8zzLjvuSQjd_>b8p5` zwG`qkl30&QJ&YlNw&+a$(S*dVrv(SB+M!k_u2c~IYhY3BFop!$%TkY!*!6^PG{-}6 zG8gM{@AW<{u1sP_JNqoW@f5#|A%WHn2`!f7D^fzzDYVgUPmw&MNW}X-8LBPEPmX7* z*wOBtbMqC37L2}UTbL=Dowb5l(#6_I;bj>2Mc$aFN)};MRx7h8SWm+$mOS~p2`nl< zVN}*iNOC;RtTD+VjLK?D!@5(l2&1yv)3AOgS%gtptC)2ZwzTw3ef|4{5KF-v@k6j9A{#!RGDNE1}xiqIXjp&4_gn`-1FZUhRA0nef6TjgTdZd#i!dr{t-`9`Oz$~2ay{}K z9K=Exux#E~2T6|SJZ!04KOg#^_bk>$l0_IbuTEwe-uROC?MEzDw`37UWvyox^%TlW zEQW;%$yyJw$_hi`R?FX!EW)U)4QW_UNfu$ivU#J6S#&jtEIjpzrN1VGSaQ!5zl2fq z>W0L+lB2eb`I1E#l@(#ube3boi;>p`$s&x(+6am0%Y;?i#wR6x2-?TarZ>HLqS~Ik$}xYG_ypqq6!S5m7X?Z3HEYFe>YEW;sWI z&5}hJVfBqt0)dp=rbz7Zxt}#tJf&sx?JtiR9L(z^i!g>g4ATbiBU%FOtE|T)i!fl> z-kdwgEP8jYy8IOkeDbrw*MWce@vm-d3@r%Yx72s3?@}Bn_jUM5Ogo*Ok%8gZw$4rc zLmR^Vc;76(NFMP4Ktx7Y$eqk^LeNK=V%?pwNOYig5O22Cs{H-<#ILV5vN0U*kMT|z zUm*6C(iaC?*^X6}t=mTMV2rP{+(%i~3L{b|LX+T;c_y#Cf_aUDT|R$o2=DK$DEF=G z!3Uwb@eW&l#%8%c(6E|SXM|K$w#K41p5NbITILH?*OF=VkytQ{!&`kJergL}F&vKg zS}SUeT=0a9095)ae3WBrCdO)iwT(iVfa0dUvw2nJN_-I6SB5f6o3e%btJ~Tm^z~;l zjq<4~btwcJUbO(9S~rT7>;yVweTki_1Re&6S zxljfJ)#&%Pso($HCJdk>cvMS#WRneapsE0e5{PEP2B#jS7-AK>tQ?>2Zm+;kX~^<( zxsQE?78)NW)9H26LwLh=Y(##H+b9ZJ4|;UFFj97Be|NViE<3~x+1X6Bu_7`sv^nAo zXRj)nn})g&nu6iM@TQ1U9u$@=TaaeO+?0);6BIRQ@A{(ItIZ$0N=WM{qMRI>qc zH!?yq``z9{MIe@j8U8>}M~odF#<$yzPcyqbo7d*YARvl@YVubvPkDq7hp7fhV<;Lq z+$u#KWj2!Qi#;xF$)4y`C@M`2UgsXoobzgm3RS4VbdPJojYj=t1R7OY)fvbdYnC?C zbE7cCa+SM!QJ<63n#qq@m}dGi3#{eOEWnCSCxK7tBM!ZfW41#-ae$`nD-QTWQ*Bn8 z(IV4mwi<(5ze!8xI(I@i^dBb}#WuLktoJM|w(30#uu|`nz?&|#x0N&nu-s_%DJOWE ze&qz0?&)mK#?M)rYWg}$yyfpK35w4r$MM;}*4h*4y1cWCzuD@mq;rItty}A&;ekj) zc(5Cvm#Ba&($gb$N~)^d=8h^#9cm4yJI}xr=D+Z4tg|ydxTSZndt-dC3#V!&RsXtW zDWR|O{`-`s?BA+1<^NWtq4@G|)Y2CITNQ@}gnysPng4H9nzDbdsJ7tWs&f9l!oZ?` ztGX$pIAEXBs*_ds>q06k!!;rWoc;A8=XjgVr6!)U*@|VJTp1^1blt{wIm$J|rSb5f?@XUhR&w^a|R$<+<;Q z1&_}ER33RF3u0Q27*%hafc>M@pGJ>k!L!KUx!_q4(-z$BxHLvPH3uhnc1^;GX}k2I zR&P?XNW(QeMCX;ggByo3oP^t8YG5<6a6b#TsQ{W~?^?M8-I83~EX#4_%GD^v1A| z!4?r2mHa2gv}ZYqaaCyo?xURyP-Zk$>_ltGo@uw!bg(@TXRIstykr1YjQc0$VK0VJ zPg#^AO)Y25wr4%5d4uAYNimfyCp+a(vz;v4p0!z*Mqe@ptE^@$iXH!$D!Wle?Pp3kPH9@g zq%_z~Nbb>ToGMy`;;Tur@pRh47@lM5q`9Wgx1idmRgJ{({7qM9Z#SL~>5Xmk8P8GC z;8EI+A=a-|_2MReD<00mtq(jsM2{QEN5=@nC!3|XF>8sLRMlDI>nyDdG&WS%_-ksR zqOPf`q-Gg@o2%v{X91`Q_!_JIH8sK7Y9G%zs^*(7>8hGP%+GsO&F9y2Rn2c*$-IT` zqX}8WeJ?O%7=BEe$r+HP+VEh~jlu&6f|ckOx*&W^Lq((yZQV zCa9!18Q?Wqw~(soxjCPsWp1q1w(c{OdGP5NH%H!)varqGi^GVr2%w`RPEi z7L)79t&1A))OvDbSOv=T6b<(tGI^O-H>Kcvjf`d(M=;& z4m~9s>54}Y=HzX0h&J}e;vCOd_iTgZ7Ey0 zpt5XX>B2>&HX)K_rKJlNEGRCnoWG!AJ|9{?qseolHhcEjy;1yQM!9@c+y1^FdcJrM z)+O>kBx#?Q8HITAJF+3Zsf7N0gqOY8zMq8iX@%ANgt)}ePbnVQ-h=;?{EPfA$12Et zns2xLX==iesvi0Oc(hN8udvjYjHCZ&`EVAv(}4R}7C0|(H)VmF2HdS#;LZf@&Ma{B zWdCzn;P6i|+RIts=>I12<^K;N$%~W!=HkfAEN~Y9SCs{hp8xO90!NRxe=!T(>A*dZ z1&$#5vcQp_rxjykTb%q-isOaFHV~3dIBEyJEO3>;)n|b#2ky!&aO9U;vcR1M+~Zl` zjtB0qS>UMY@dnGPid0z!4j{*Z0H~VUEtOS@%jyTnS zqre#d73-$&4Cvbp+#jUADcE=Na~SfsfLTog9hRwBEu5O~HNfB>`guv0@BP5+lQ_40 zsaoF!rg)Cfmkw76%<2rdaj5ABrs5o-kNUk^IsOxv+a%7d9M^&WBrt>L3VmjKN$Qtp z;J{X3z9|2H%*}rnL(QYW%s5}@%fpXlpVjWKhrAA$KS-QvpIRRtOcG9^i2@cCXX)FH zV@rVfp(9S!_iJF@bi`TuZiK$0F^TyBO=PgRm6zhs%fL*b2?`cB`=;YqvBWTt_9^Z< z#L07jTP(3uA5Q)9DIBN)W>%TdM&pju~H;VD7fzocu@q{C;5eUBc>I+dZi{u}afcVWq{bpVNHzGZMo< zY@G7_0p#}qx7jC9YCp2t-^n=qSzx~Bh_l)OwYSG521#C=^8FExyyb&Fzrdu+_i#BrCx>l7!>)58Hcg2uH)!e*$-(#3F2p^EU_FuYt)45KH{mwv)aR z96MfO7>JD%j`F<-xJ?=K5$;N0zL^E?ZeU)?0{3@d&aM;Ixs{jBLoWhmNaAv^?^KQt zLOuq}^m?H$-v#$s$Uh9su~dOrXk2j8*97@CVD6W=JQo~=Qcokkb&ZvlT&zy|2p0k7 z#tb+r??b@6Cvk4&CEQ6EG+Suk#F7p-0L+aUaMWIYDlx1O8!ktbUYTG>#QD}AfO|t? z&GI_nPFjXOf|V9G+-w|c1!hR%X#8}_mvFZO^Ybil$D{Hpr~7)AGCNT`e#wlOo ze<%wa>HBCFIBMq~&l2~EEO1ky?^CWg@g^BS@bx`>ogTPvNvzr5Y;VLM+?iN^49xE( zj^aK1BCmH^`Y2BB2j*QBC$D!}II=GE@6 z+mTuM2nL*JFa?29}fcaTrw`H9Dd*q08`e2 z1Qt;a<2t%kztpZS0%nG-p zx?p2#(7&>#;lk59gRM24?ST~+mn|+WJ>B7WI+XF7}?x49E~MO zgRSi~D^?~6TbgQ{{lP%%>BTgHypHvDtXnkCOe$H;g=^YIBGHjGBfSIhe!MOr9$ix# z8M!<*G`t3HaM;v480j3`G-vYw-Wh}2Kbs=abBZr0t{EEcjjY)a@9potfJ|94Fw`CI zkBrRi?v1XI7O#m$Muy_iu1IHO>u^8b4-%a_w4qPCP+Kz7b2<$x$6(5KZGv99DSm^! zUD2VDp^dTPIV;X7ZW)F@dOv`N0Fc|ja4-ISl^VjA9a_a_BG2a3`Pd45rAVF2vPx4%XJ8kw zY>6rJAw}3cetV_h(u9$&7UXF(GzuAYNV>3*r>(@6E?wZu+}M()JZ%lObSj&tt;e>S zQ{C7KSr1YHmi1#RxWh}u>&K+EH=kP9Dt3i~Tq_E~I& z?DI&qvFti*MIK*9ifqi|Z>9;^t=K1P^R(Nr6=k~%saY($$4otl)OwaZf~~+kjTDtC zk3VfHWc#q+!?OL@iuyf(6h-$u?M-Y&zHghUcab8$V!nmYE3D5oQ(mMx_-H;-mvgER zsXr6`8jZZ=a&zqVZdAG6Y+w#eUmhZ%iIS z^%25QpDisEj`bvQ#N*nO{XEq1a0ITlJ;6OM7#Zo2nPoO74T5tv8V2$(k}Dz`&Gw>- z16${DYib(mhD*0@<0d$?MWoM_?Xoq7HwvNEibe{D&pS6Th!4)q3x)Bv1M@)R;BY)P z?_4;LJ_Bfqxeruy%f?;2G8!=&I#nIM9N*fm$Gxlc&GcFL6ZP$d`r7=7g%b-Vet~a@ z@7f(dijTzicdo10ec9Uk^t{e>_&HQwyZ-vb=3ELR+RnYX<8`@|8mE&nZQXrz?luLz zx`=i)y22-x9LO+)V>^uu?wgGj9u*XsqE?XrF4yOTcieV_S}?@M8U_@X0yohMH_4;ehlGCH|F52+%KW4oTvmV#ug%5Q!BscX zv5NacV}Uojze?$GMkkkADRVm@c|3lLGSe6=%6AS@qRh7Py<71htGkQTze*b#B&_l! zSe;eAl$dlT5jhB9us=rL}!w1-K8U=+P&PVF!Eb}9E98yL6?q<<`Bar2>%;uW| z8GLgOtFwF~YUe&WbJ)v=kl^bh^lL1q;D|$2x8FzrdtK|VE51tZeYT>jjlPw$J_g!E z!OucU6n8FCqPVs~I)CHdY5-TUI;)T=4IssEblbRB)}hyCrcymuvRayE3M=Ozl~Mtj z8t3j*+tB|w>w^KWCw4?%VY_L_1MAlA$>r*(0Ii58P46SuB8L!_QYQU%BkpkMbIZb3 zTB;P}XU3vcY^zl*R2iaQ(p*;bOFvS=q)AlJ$62vbLD@K=0kkA1kk3FBAq&p)COeP1 zo@m*}nUJIx@*rccTJiZ^%0{$hI!RiK^{DO7zDtQldZZFlASpvTq=j(ik!gN7o^`eba29`x$d6EpN+{&=+)nQ7zI?1RyV;$?bWexf=T+tJ;zqZ1f~_e|8~ zCff74ReLq;=z9|FUQ43;y@2KWUIq6eXGq7q^g8w&XL{L1)Eo2O))>VXjyZ*|icZ9iV5jPV10gPJ z$9;NmKM(DC@BsgEP_l)X{V4+-E^=wjtcIooG?OdhZ@nDPsds==_Rj7xRf_>^we2nTQu5imein4QIO-){Ny|wsXlS<*AM3 z@^Ab%6%%NV)B8Nq-lXB1P89YOQnVjyE9%o$B(@jno{7SWgRec56niC-f^Q$(o5v?^ zBKXpCO>_;ch`(baQZ10pX4yuhe9Ra^s)=PEMvAVk6=~naRy5E%krLdeOxbUc`U7)+ zXC9?1aN^9B&L2+3TBI$&R!lA~K}t*&Cz+U?W8@d^?2CgS`0G-=@W=j5O+y^OFG(65UL@)uCp0e$a#Z9zE&(iHTc1%KS?<4vGQY+#qKmC1Su5q)vdW zh`+EW`tdf%sJG^66pO?aho2xN`ujLi0`~$^FEZ{ANFB>sXs8mh^N|t^>YGRM(MD`3 z$meNvE=j2(Z4g_5+l-VL>b_yhzGKRMgVcpsi?r9U6;{zLal!Q>CAcMYos4m43*7Bd ztx3Oo<-Yh$4gpb3vCfO(?w}ql8fz=W1c639Z3PV}eWF_%%69FJO$SYTl>&I` zv6FOa!sr?M^hPnXS9-3l%YF6F!alYKGl9|HVqdS%MF@!O{7}9Y>jVSW2>137+YEK6 zKngL-b|6xms)hr`Xbhco-QXzlkkH zPFYS>vz&G)S?YmV`r{2DbJ1b@7tV<0lPrI!i!k~t`ZmR+~jQ0OR*K2KZBIe{B@*+ z=I?zVtMGSZzsXUE7>?}%tF;d6y(W{X1a_aN{ z4|{I{9!0Ue5BD%(2pC9!sE8l|0Z|YV!Va35B$EZQ5)yX879$3}4}EHJZ9Iy_kejxRabJlR3ckWl@$KLUzp0#oQ1K19 z0zfm(=jp}GEG>L*Sp1e5EAXSekJ@eY;`w1()hWL9pu>HL{`N`7#=do|iXQYbhe520 zrg@dks~4afbpi-DVQ5|29LN{>+U__P(`ZG^mqL9F7SphF#*1m;*2T04tfxti&qJL% z7SqB(VI8g}H>_rO_~5K?T1*T7e{C@>94lWwUiZLaT9jN&Gv62x3#w`{EduLlmM)Td z$Z%A86dMKWah@ow&(+M0s>zBToJ~f#B>b2c(<)J=E?(36|J7pJlbo%=a6Z)<#nNhP zUw*i+&5FTMl`VPHs`|BW9kn^wy5VFXF>$Jbr7&_32?Hj*%Gh2*52JmynpiH}^I3 zy~p=){btovr>46jW4PGV1&G?9x$`kE$*o`|)Cq;OU2|zWT<14rv(?aHy&0Du&P(Pn z+ke?;7CUi&5T;o!S0#@J3mW-HajA_POUuCvFkNGJ`K}B!U7qigg3-8-3l}&IUHE7< zr>bg>*%q#=e!!I1>3h4t=Z>gD4pVxUp0pgeNv?U3;mMEO#pVdADW ziP5^Zi90q}HitJBMEg>rM0}JUPws*%{3!B9%X&V%@wjd{AG7UgLB)k96m_?)0VQS# zD?y1F!egM0xjvo^tPfnSRw0gll)s1c9FF%HLg95g4T zOJ-U+E5lKVgDkcH$E7%Eme-}}jnrU6hNg(2g?<7M79t@7#ZeFD1mWTr*OxGL{PN3L z{$%En%45wV&2U{OP)1t7I}!Ptk4Zi-|EnzWW?Sq27OcXodT2H)YK<0G?qZE(b@KC2 z0U%{HJyqgS&{Nib>;EZL3i@wd&i_A+bE^Ro53f#SiWa#iF*OKOAyaNplbK3WR1PS* zrV$UIPGxE`c!HVvaQWK!CDF%dO`-9N33A z^&X%uW{UDViz&)4U1z#9H>f#GrGYACO4k8~B~bqKF4htue?XY+JeReQHO|A1QfbUnX z1@?tK?$YU5rPB4ZB%pP%{-i`@Ah5_6SzhF8 zCVAwTZ+8B0b@Gl^B4-cF*}o~~>e2Hu3RXqs9jtX$FT1Hr)%RDG9;k@Ajb=!~bT=C7A)AHgEue$!K;ggQ~bne?y3X8QlW6;G~S z^`DMoi>jC3nmW4o+%;!89bNJcAJ{&#=avnR%@}##v+Z;DFF%^uA}{vw<=ZaIO&)O9 zT}An`cYPA^?5hiA{jzdNpQekZy#M0XE}dfEUC_$a`G&ni2P~Ykr}e6_uOH}e?%ILN z_Fb9s;V}2I+b6E~JhkDp=MVgRmv-oaE3eh%x81Yq@#;C}&p4Po^Z60mR&>;HI=}C~ zZz^o^ue!F~T5TMf+RK%>;H5=XCuE|~b*n~fJbl*NIe9AX- zuUh_}_B(!gdD@>9I&R^ltc{08Z|kZ5{<8n9Lmw}B>H|IBY0d7P^XM~W?PomJcU<4+ zep&P5ML)!j*fX~9hHo+=4$T{PZO_w2&U@$Fr>@iPzGVI2=h|G~V^?a&#nY?Or#`vy z+97RjDk=63^?mkJ#gwn!e0WUGb+L=-L(Cu(%qG$Axx}DoUz2NMmjLv^{ z`nYw$-jCWWx%kL|gvTew^t|Mp^^ZRL-b-KBo!PKJ6cug|8qf^RQ->7Y|xB>tWq)g}Ec*>%x1ineg+HnM1xP@#*}#GQV#9 z;P;bfKL7T-pVtPz>Ka|PX-L|OQ{U2F zIs5Y4?)djpJHGhonbcteydPvo5Bcu9=aSdx|8@SJdlsL%$oc2zI$!^<^B2EU*Y>k7 zyh9J&fBxJ3bKI{@Xu0p@b+hI@{L_=&+jk%N>f*dzpJkOyUQn(7e}1EH?TeAWM(Y1{ zc|E;>sp0j%&An@z{(s2le@1us_m>54G;^JbLN1AKpCfu71(? zywd5rORmn(x#qF2=Dcw*_nnNRuYTp#aa;dA>&15Oy|AY-Tx8#GK7RG5rFXqCx9{ao zwqO6ng=Lrg)n~@XH5(Tp0 zOnGLP^)8;ivZkqn7CD@ndq&Ze%HFZDD;|CF4^hWpet1W z&EI21*9^?-Do!WN-(sc98>fRNfeCuF`cES<1;RAZ%wJrk7^g#@b?@&UpJ!Zrdq@O< zFjgs=h&vtn_;(OJg#e*Es=4Jn`G62>Y;4xOV(BsAw<{n(y*O0nfN)g5?MGF~D`UD(@Pr?^oWk`J@r3hn{qQyt2 zqmK~M9(rvET7{m&Xh{&pDn&C3r=zEoTE6y9lW$~8DZ*H#=oNR2r&8+0w6=4Mw62j- zgt1D|%|WN5la%TjRsh3Du=ctn2xFC^MPj3tf6Tr3H$&<#DMc8o6kRN#RpLxxg{$`= zL#mxzksyp!iXMeEymwsg#uP)UKuQtDDn)DePDekSDctpnXN@6MDy0Zxm7>Sdoenqz zhd=s$e1jqNn3N)nRf=Y)hUNd9nro`%-BOA$Rw?RdoR01|Q#e|&@dG2R&a#stj4PytC|4BzS{L6-m%$5tQV(IQQuOGe({UDwAS}PIBV1mu_svp@FjlD! z;28D(&)SjbqI9XFQi?EEDSG74>7bTK;reyAo9bO(DI<)~Gzbm)N&E^dDdpDbpjxAF z%ZQQx(q-_)HrWjjM(DX8oHy|+P!D;#(a%3UX$x*J=%x5p>LHBawL=-V2h|h9dUVTw z*d_+mrRy05DGD(-1aB!gyYVY9Kb?uIdi9OXu7=y{dY+Sd2xGNs7nahk`r<1?V+^VH zq!eMSQfIRi^}rOSttmu8dRjk8DZ)U?^zF^A;5Z$FNCaV%tH}l-WyW+vOkgMlH(kS3`Q2$043f+19G^f=AT&H6`&XnccCk8Dy=ZE-MWWwQeukcyOjhaOK-?qZ{LLu?;FS`TXypd;-mYXq@BKhHsciu2QAs{UeWA36ej>|iAxG_*q zB4f;X_5|ojV$4FRCvy3@KLzT6yO?~Q%AORU$IF=2I8(XWb-Dk$Ks_lIJ=Au*0eVsy zqt9Ubtvu}>VNG)%mBtuz+er=3lg^lJurrMi_20)nD)pH9gyD?I#W@_u=;t2$C_O;W z2*%Ktaod6F`M^c52I|RR3~3`hcb#>^ju8QRG8xkvl|{X0k+Uy+44IStyr}mq#*D+6 z{P3KEPfg7X(38y=@@kSE_{ype&3c57582=iGq&|Q~Vb&wk z8qb(#=#1m~(d9wLrU{HOx6|mO+}0`R#IA10@9ks zm`I!{t+OuZ^Rx6H)BI;TW5|9KdMEb0L8fK$jUvQYePen+S~D2au%3$o^vnp*Gm|mx zai%;k%}m6gN0fPvRLmH??R1U&5)Fkg6i#U-{%cwc+ZA^c0yt+&&UA%I4#13*oEZvJ zX~Gmc>XD3|rk*0M{7e|CReaYvfb)dn2utHzdy1pyd4B+>2X%i4-Bo_vl4F!~LI9^K zfOAU#=lKB6hXI@)B`05{-a;Qn6zBW^PF?_~DuDB70Ozd$&Yl2HQ|iPy=oULma{8+L z#0Ow<1332taNZB#d>6opIK@Bp0g@A|QlBC@LlkF)Nvhb<$q~$dUXz$yCH1T1OjDd* z^1^7S;!Khp@`PeXS4S|-D?hoUW#+C z>B*$pot=ftl z7As7$VawaQI94$m4cok=~JP^dW5Bqv#M9+RB&73YBD3{sp6+6g@q6lbI4Bq~npGX&;b z#ThR-7bwoP;LuztOL6r5+6>M-44BkK8=N1(A-6X;GjKIT88A3sfD>ck6m$@CXan;u zII$K?3MM$`gOj21vzn$n7ETi^R#AQo%rtN)KL+P@a40_pr&}kHAA_?ToPNLzS84qV z90~@feT?`Rmch9Q9I6h3^DHZZYgL4QR3R9Jy{&YExkfJyjNlqWdxmj}hGpD!d ztN9m0(&>=V+ArVV^nh5+AdPQHHe)Q`?w`d{y>M=VW8YW5{X@)Y@k84ODXL}05JOAG zY@dSQm{Xq(uG3-GBd&7^eHWxi4`Ya-?Us53$E=5%uC)|mt%;=ib*HoV%B9m%ic)Zm z)Yr|sxrbO4A@pUCqSP5f3~iItBRJ;N%MfemA!~@M36g39cOpHEA%?b!91KBl%zEa6 zYtDB9aZiEz zz!BF?+A3CH2tOK9)N&a^46R1$5gfCgO2j%Hm*X6PvNv? z_N?HT^;99&>9`4Jntc5$W7Fm0svkeJHISmf7^do_9>Fo|nTL3%BLim_j=aJ@R*F>! z5}VMI&RAc^L8Zp(6gbon1jnrB5^$Z4VK|53_`w<0POKW?hxP-cs2^htF|-TG%@G90 ztY<#BRz2d%m(VL9MS2)R4DD;FM{vw~79iHBuMTGnn<%dSNUA?NXR0s85JRg1hl1dk z^;`5(s+OgKTccYX zA`u7!DU&s>14lfuKsg+JPyHYxt!ybp7;9SBvs7?vTqdOmW0hLLQo*gUMoJOJDz%cO zsGSB{<83KL7^~C`EEU`uN2C;CAZ4<~jVwjcWQ`l&`U(S}USH?-1&g>itZ4xR8|v0r z*sNQkAvH!y5ymQYGfOpRK299;w5p{PVXRWOfMfW^5(>JFCD zeZy*vkE9e~tWtMcq^#|$T|Y!35C&2vYup8n({TaLWQ~rsZ=c1?#yhD*OQ!@(uhLwMf`*~Lo~~sk?l!J^`s{qvuKVxJ0&qQJ0q#F zVg#m|;m*m<9+92tO+V&TliXRJ;aOQ3sn+V}Px&Xr$$zF#`m3TQ=D0J`M|j{;8J0xF zC;JoP^#A%7{*~aM?CjxL86z@s+yPO^9(PVg%5d+9oDpW7330qDKth~#TL9tnc}nqs zB(#aN#H{p<2nV9X)Ny<*m$;r%Y0PdZi5JwvsD6v6_IU~HOsX4>l`ql<2Dify8 zK;waPQP&}NJ3#boxxdBgRY51*BEMTYVH(VmE{n zN^ZD2J0oW}I+!F_r%afUH)lwQ}6Vts(!)1q`(4V%FQ1OEkvy(<7d$aZN z0M>A8g@t9Z={8B`dGO|9 zTwgZ;<49{iQyh}=cu1#7bI^FHJ+H{38scLR6H5uFS9qx^%_(!9sU+zYo~ae3v#KhK zXls<9kRBmJ4NhT3jY| z!?hb{tp`!%{R*aFYoR%nx+93%k-AcgD)Bm`cfOlmipS?0*8HgC^KY2zl)j=!zCtD zwW5XCmlDl~?2}+FN(1S5P(h;Ww3Nn{gr|(IK`g7aK*)bKRA-ag;s216e9EYUnYzkA4 zL)7GdCm^lt>Zz(MJ!XG2s_9s=AbR=}P5D@B^|%VCYWBFKjoLjfaZ3%KkcO1vIn#~q z(^%ioXQ1vlnibKglW6XY`o{5yMQtN(N=0UIMFsZbRCb{J@xcumDAKdV1coN9Qh&L=FDqsWn03=6pW^ZZGs;dOrKTI}W`1(YA3}ZGLTV5_ z1epXAC(D{!h$7|;5E(-a_M?fDdmNp}zI5GU_S3*xh_%eZ8pe`FcdXl#9DY!8=wU>a zSO;v2%aO4Ez^nrr8h~{SCvIDb>NB~g4yMECk>$W|M+D7D&VfbOY#9jkD05C#w-_=X zM%Nb-qBnm`pycQgEGdQJ*^=Qtq1;tDjox=zoF<5rpQ{8xaLLUM66fzAeC3D%G^euM z9jYPeR}#W9@jQ>)}+k!@9$+6wHEI=7Omt}7ENT< zW1f?ceXUwfWO`-MqzrakgRx<>V<{E4NJ}ns`yN*&g4+1FGzGJBVB_%{>n#QG8|nT# z<9=ab)tpN(=**~^GYyMcUH!+`|4OP|2f+pZ7wN|SkJ9b?KT4Ony#Ixrsr&t3q}%_0 zlJrILy`?olDy>LztZ|1r24w?JX3oeHP4##ZE{p=qcH%mN)$B>o z8l+ZEf>u9^`mNIjzala%0_ysP(g|nz)C&7&Rv6;=0-5 z=K72~q;$|(bx3sJ%-QDEAZ3c?vBh&{l!m^(GZ5BdAIqg!pgBb6Ryk$rtfHI<+ z*tZtRV(4SZuc!b^9#2r0)zZgu#U@vC^jbEm1NWAWLyuel(Hpg_ffLkaE}im{OhuIvu-yD}U8t}st&}Yt`zSMM_>mnA5pP(*Fwrni)2fDDW^#Y>- z1-a}v`8Nvua`}IhrrDN3k_<85JC>^}*>Rj~)(6kzF)1=<=)~t|YVs^| zc2YE&vv?9_JN|h*IV#PWR9$n(IgK$4=<_E_Pjfs9%o)%-<&fz&(D61RV@^gbIP24D z^P;yH&@IKXfw!o)InTpWC<7}Olob`yM9=LWkjPK<4Q%vITOcs>^C&v@SVnEKh9P(C z0~*T~<9U!g+?K#%Z0Q_qtvPE-$-cuayLtu*RpPG`L;Y}RwL1a>jc=k4>LOn?t zmzC(vN=i&hr|1y|dqigPh^&-UBxgK}-fu+Oh!N@O8E)FzfT1J%HIns_u?=i!;2uP! z9~mD?hluXmaC96B7VB|)seHj3gHY4Yu7gpQZQN6pd2dv!EQC#*Q5u^9reZbP9Q;Za z8n0K3k%!ROfbum44OYa)WZ-7U*&yLxRG-HquUp}GWTjP(U(~SD$K1oCK0UVFv?5mUJlGE ziL=_pC~p#QF97pLP@Gj?yB7G$0S*eG^ld_19x(debW|L}&Q^WJr@*&xPza^3JL2w_ z7zW~G=rhXk0{CwMcV&b?HDs5EfY~H*q0(&;scE}_`SDDl??OwuMmffTKkh6|dlm-; zdVP}fXZj8j@!R3}kHpY#4ozY$UrQn0C>%$D8`+5w8Z}XORIJ&YT?u?Tuu$}$# zN4Qgi;Y@Ghk_y^s;tW3=eUt@5L7x;)dPaImW_n(xXH-(!kS>Lpc}ax@-jNr?4UUcN z5+pu-ly{_ORQAZiWN%`AYGH=Az?*SFFyzRpIhDn;i!zF*mQN{Pa6x8rVe*1GQ)U-W z8;N&<@Wu(0C*y_1{ESf<>4`(S%&wR>t*pG#kDHlSkTi0XA2T~6Im?sj&Fd0F7Wf&* z(>N+MM{E4kl7>vk#~T+F6Do>lSK*4LsH%KIa#6*_m8E49<`m7jsCZ6M;hc+l%$to@ zt1ygRR8)R$%=s}%rDerM6Q))b&zgQdWo5$b(&_Y4a_{NIes_8C7Hy7`vBH~6SqnFPw%1AnbHnos9<(78zoe7{$^5J zL{lFwwka02qR;IJThYt%B7Y`Bh1e__&}cUJY*u#$&cZwaTRpEvlx6$ul8E{$v4=3W z1vh1rDpTdMfYr9aS>&<@s9`vwHB;V>1XLo%FfHpMBUr{c!bn zj(;|(Ok$s{pLe8o(vgzr0WPY0Ol-h`z+K5_mn%q2D-{HQErs7}|Y_YF-@ZG2V z-2+-r(NiG1nEhO-Qs$wFpi4UyXJMXxpwgL_h;uxSXnf=ipO-i30{bg9jU>^zzaY;-I`@LRay98g1XSnL5Y03`m|+rz7I+wBE9eXywS_*YVvo?dQ|Yl zY*V87-edhB-W3U5FeC~RgF zQK*3)FH*-L{Z@Ickg8!3fXX0W!&23+Q3{&x8d5f|Yy6?ePD_cQ`K}_4FYL*b8b|f| zu%Ryyu6z#__*E8}*E4?Wj2SZ&emUW5)5CmWD-xZlqiQ@yhTg(5-*UOGrP%A}>~x@H zHJQ7HE}>tQW%W<5z<<4PwabZ%TG2~MkrXyFoG28a|BK-uLY0z4mZ8FF^i%q{$fVo1 zgyQ43Z1(QMenUnp5gA}Hv3*w&D)NPhH+|mSGit)cZ{Nb5GknR1oA?%j zm)gX~2CWTy()qJ5b7xIzn8&vn%21cpb>UDvl(m*WQ&Y7Mh7-j{$*EcF9L&a;H?_Jh z49FF}<&>T;f2T?^?TFwZ!S|cYa9;H~$0OauqhwJ|+Lyo2k+~0Pduqd0P|EqcYnoJV z2={q+!3zN!8eaZDwQOH4W&4U;`f(F%d+;=sxb~W7aaK*_6-1zUPzHDT7OzDV>Ppxq za(NQWDO<{n6~3z|R=2V*bH{zx(QC70q{OWwo`cgY+XPoPgk7MV-OKR&}33Rb}Izlq{tpZU~@_YdW8gV zKNK;ovnc5;`0)W0MR(T(l=psC5JK~T94LKG}*VAyLx?8^=5R#yI{1T!jNoVYIihF zw4iY!a_JYsnd_gVZm2eGg7We=q?e(G4-$?CnwaeKGkd$4!sqjL=I-LNmO%Wh7kQCr)b8em_VC$YEZ@1QYL7?SPF z-d?8FjxMXo-%dVX2A|icKk@GOT}}R6leuGP+N{blOnl4AFbzYT9A~}zYqQHRiQ~(p z9r`5LUB;Pk&!T_Jwp8}>t><}g;4IkpCP{kHPPPLVTa#8M^kE#RNt>llD$>g4T^PTW zhEz8)wcUr|qOzrP!`@b#MM`_eP#>pZa+QKEGqN=%8c}kh@jg0A=-1~OeW0e!x2OzL z^DyThdz-!{e@62tlrEhB#@dyx~2Lp5n(%eF)=eTQT+w__@T z&M5~|KolTcs~jP%z1h2+JrC#j7H;=B zYDXdqhcR6WORX7xnDcOCC{G^Czou$JF_1hec|&;h`ta)6I~}Mh8V8pZqWkdO@;Xwi zy`Ij_)?ibete{_!OZ!k=Eexk#`sz2qfe)t7#DA@R?vdKLM^G_T^(E1{yNT&@)rKvu z4O>Pf$PpLXD15D)P*EGe1PuAm>vJ)wq_BB0B}ZWy#^J~D-?st1*^AMjjJYQ!aB7~7 z83jfYD5ALlynQ+c%ie0@SjQvx$Ka5CL zKZtrT>frED;q9O9c?lvIuvF%2bbCaSd%%ft_4??mQ_#^zqanM2ukmgl+N69-O;tFx)XebeSJ_s& z2Mmg@_bq3Qo25Sf1>iNw&Cs7kU+p24LK*D8eduzMFMkUcZNfC@#4-;~uW1RcHkPlR zH_jy5#~daFP`~2jU+5+LrDzo|7l(_#slSXV56+cLO~qMUY+nj014p!W3(iY%xU_%Z zoXETlIHxf6wxTG-RObDzs8isYUgmi~UBFbWqCNs87D-y5KcQ8zXzeLbg12AsdWY#+ z+QE}(X&_pQ0d*}Xm(~|l4O5k%<})=P#T2;3pakv)Py+W6D1nQ{c;jV#hd>F5qo9OD zRJblN8I<4^G}m#HKnY$MD51Gd@y@`i`Y_f!4wSIzKR{J*{=QUH0q!md9PKD0aLEzk zYuYX?S5d!!N@v+-sB*FJ)E<;rcq#`a>_-kEa4SHivBYXneK{|*1I%U2+omY=`?6NA zRn*I%MzF*-P*<|VXP~N>+6ihAQ{RHhV%$DZnM@r}6fQD_yN}(7{#kYuzBkv>B2r}H zo4AnH$y^0R|05PBP0NpO2CSB$qP1jBEf!~CgA7n&HJSW-5)PMEfO8IxX!d#fMGH-1 zaE!w-9!Hm^H=Y4^2pQm_8s(P&q5f0%NNeEpWQ{ZbZp3$x~jf>CZVqdAd_#uC2wm zB|--_#KAGX^TZe}Y08{ArIj&!UnV9iKO-YXzgN?{g_be}w_B#iRF=lzYkQ^Ba7#!4 zr<*}gg|IkbW^RF+w0OU*VUcp8#CaFKhAS3 z7&xkF{hHN_-rn@&{8yiQZv6+d*UvBC@yuo4-s&IUx8ljwtNzn*Y*F>{TT@5(o}2kx z?M7`#kI!$PxZd;BhSQ#}y8WehF56MG@RNvVUtKWkmz6K&tX;6R>bD79I>o-bpp~oh z#0d}HIeT{OZHFKFu58f*7e2OqX3s4f9-A?8-1D7Z8$DwF(fuEGYx&3G)#o4H^4zF1 zl9_hAI1^v!z69j$tr2I#?v0t|IGq^s>6iCC>>J*LM=sMByd&cm5<_QI$!moy8| zgVCkY{9t79%TMzFJs4?#>4-B~Joxs;7;pUaoD!f1V+b(R)l#10K5N-Muv{1oWLi{q z+S;&XfF4@BH@4kPIJen3fqJO>GPX#hZFeIB^w3>jr(+Y&WX-E?dHU2qJ#?$f&_i3R zwhqwKmN6&{hrw%WUNh?vkB88-*XeixXDWNIZIAtI#>{6)ByUQKwu6lhNb5Al(1Rg# zXY+r!j>eoI3q)tHrQSnQwUNoc;vhpmS)j6hY^Z zb}MJ5&QO}?1#p%HaBh*D)0EWq0L+g8oEUOM4tjpZ1aKBhPIIOC7Rhlc&Qp@pRB_&r zoKqC%bIH*Z=dS?HY1BLsA{C~ei-arAbrNH6wn$DZg*hrYZJ5*Bv@I6h@^d=G zlnalkxv%_((NYFdSB=0Jrj~=#RdLLE+JkG|x<>RiB=)h?!x+n>R%fzQFPy28X+tT| z-tj|oU=W~Qi7~{`hSIQrAUNjKJAi9!1VwtpSU~7`QV(N@p*8(X;3fmM z5HLM|)d^fy5JCF3jg}yv-b=seJfMKSf$Qpscs~KkbmZFR~u5JXc$KzjIh|X zl0#gzXG%eQ79IuqKm2HRasi&-E-mlJ>Em;Tc$GkW$6C**{7`nR z1?Q2U){af+S}7v>x-*3e6_r#v3m^KXmyYyL9PY}h;H+{3CH+l zyc2G9`a8n(YBGOR>_jyN`@F^p>-7H~U_-uc`QC;6%DyeXw+JTK^v?kM*%a*R_gxRW zZf?!wF}S?-^AsmqBmOVyo&!*508oE!{JK)hXi!mA*<6_@@ObYOVY(?di%HnB-#n{-Y zk~UL-MxG;3zZpw=P5|Tg-mSHB<*|%jyfxS?G+k`FQ8-5oXBdC&ONh-x_sB}Zc%G7hmw6NMKP#a>zo*MP zd}XTm~68h8fZbJWyR%KO1(R6eXUtDyLLURA}tIy#51pIK7wWF z6{Yced4BJQ(8c~G{?l|!(oq1*D;hRm#&`ni=Kl9z#<--oxNs^Aj#ny9{7sB`haUN} zAnl9IOTWM4=MCpAU$0y3WUX#fm03gJ>NZuEHJGoaXbHzymoad3y@xkJ2gNCO1JRhr z#l`m>9M7+UlE)oz(3_y+aHY0XE^_#L+y*2Pk!2*xR0xlI*AK@Y$4lPE8+Np4aZR>W zU$8gv76bAiaNX%v83Gm7z|ChKooMkQ3z&-~j*MmCjC3ytzXq75bh8kF)=&(bRo@6; zW=dQreWM}29GK4~uA%%j9f>6a927$7n~pd)F!u+=S@X96m@k9kjPgd}s{JouBJw#| zzMB`SypIC2MdCu`Z#dL^2TUB@R7Idg0YjgWF5$euT;B-pY~a=av&jbTQ(*qGfoqLQ z=|>fV5GsGSAubJ=of1b2Mn*ZTc8(o`d)zoEgt7~j<6>a0lekdn67D`=-mroD1ehZ> za8bBX8&5ZD5kjSVC*o3p`9|WXvp33X)Z2XUe*mUP-WQC6!}xA=u=0}GJiy!`aiPjf+1dz9r$V7G6mB7+Q-OJ1;;iMR+7f~KzpsI* z4~jF&aVl^fCkq+<9IPBaBeE}WXHO9*Oa_A1??1u63Yb1q8^(Qv=o^8#h#UtY5=XFf z$&db$7{XCtocQ8Eir|QMB%7e}+E4`|kUs}|!@WHeb^vBTF~j%?nqcYPiRgY8Yufub zD1>SsWdBbkhJiSR%HQX}{b14;EPvNT;VC*`uDo1mdkYOXSpIq-y684NMe#ov?j=Ok z0++ffq5B4CyT#TouG18VLC#&x^U7pk3Kf#^ZNydZI*`i&=mI{?gmcL;sf@z+R~ zZnN$N=7_|Fs*ft*T&TRur~-+`5zH>vgZ~0BDR&V{+`0&c^CF>JfcflhfeYoQS0Q@t zJ(_kH2Zd1SQnToHFLdIdV66|MyqgjC?7b+*YC?t1AL)A=nDg&rSV(dWZ=a8L-PZ$0AX z0Mq9chK20ce2Bgnm_s&jeP7kIS8z}W)gO#O-0#5TzQ(YS_Nzd2H86)7!OaJ*M;*p4 z927#Odq3iK)M?scDma4Gen$UHZu}`Qz6}iX>#q#lVnqK0OzB2}3&%ghUkn^|x32*+ z^>u*@mF{9hzYNT1TK{S6(QOU%maG<3y!QI z0`*rtKE_J`I4Fc_zc(W8N?@Y@&9IR68;9r|U>=sZQ2MCZZUtt=cA+nnU8W&=CooB$ z2%HoDf|Zy2ZwfG*BrcR6Bms9An4zCGtdF9{;uKF43WQMoDcSE4V0K7csPgtiy@l;S z|Mxko3%Oq6M)Z5YM1CP~p~_K;Xb&(?HiF9l?rUIre<}2Z%HJqN7Xb5cBe*Q!wgMBg zQ|Jp-AC&Hez+5A7q0*&x{xmRsz5;;|sz1m^Too{{OI)aQ3HLQHabJ_R(DUNih|31% zWr+*b-lhR}7?|Z$E5@FLL)fJ-vMBz?`>FL5u)z}rs=+had#uy1I(8a*8;zT^;fgNPx=9KKpYf8 z*_raU7nlh@GAyJYT#V@ZfNA-Yz=hIB^_vdN+D33wfIA3G{{Dvbtwi)nV7mM)aN+nD zth~2@Uk*%*UmC_yImQ9=hQx&`2l>6@0A2&cK_OJSM-aCSm=6vztigUf{Z~!96bFSc z9Kp(w?tqi&{2|2s1?{imkgjDtcb9JR~OfJrBVBZSHy>01U&^S>AtQr|U*&Iaa_ zMsU=RcRGqWDh>*v(tQANZvr#Bo?-lGaj^R3asZRAp`sB&>2o4(nZz&Ckt-4cvLat+RnU6S!|} z;HW)l^!mOj1gnp1#5)6U?x6M?8GsA4GmR@VZQ$AiS78H3_N%plBR{y`2Cf}&&)C34 z0Qa^H+^N9*+Xjx>%|07An*aQ46Ze}99Hsl04IHK0B%*PDp>`c^14sQ|qzxS9?{piu z&cJoBfus4r1vYS04v!67bKuf!;OM$D*9MN#9d8477I0H-;3$8KZQ!UrYHZ-n0B)rX z9Q8vF+rUw~e8UEg>h~iXII7=YZQ#hxzuUl(|7k57_j?*wo7%up{?4$0YXw|K8@M*W z^|Xn*zy^-Sg=`x*D(^@eIO^|b*uasU=i0zg|2)qIj>d)SY~V=W12%A^?-d(3nn!$O z6ZgFh9M!MZs&W6L{-uo#9Mx|J8#rp0oowK!9rd<>YYkj~8#uCaicQ=^8#u~er41aF z_c9we>QAq+fur)?Xah&>=zbeG>NnQfz>)vGYy(H*`Bob^n!jwffur*NU<20{xT7|4 zts@)vd#aDFHgGgwJKqM5^bNLwqw*%&z>#0&*}z2sH`OMt+y;*NjU_g4RF0c$;K=_T zuz{m=AF_d?cD~LAj`VG{fur$qmkk`Xw_j}F$nRZIjr$*!<4hYk8fW_2z)?Ad+rW{( zjIoKEX#+=go^KO(jZNI0HgHtl$8F+Xwt=Je_LfcDCpK}rZQ!UK{bmyv-nwzWqWRDn zHgIIWvuxnVF1>8xhT6mpw}B(S8fybb`McN#j_h)&4IGVwSJ=SOIC!%STxa0!uz{oN zsF!Wv$X{N!fusIqn++VA4_fEsK39%29C<{j13&wdA$uB)$jW@aXW3`sQvD@iEGlfaepCw(Kc{o zm+m%k{cPaKeu*}5xi)c=ZQ!V#m)gWFwt*wNth9ln^4?<;_qa{mD>iUczwg+<(fZIA zHgUh(z|p!?badnXM|L^i29C-x%m$9?H_HZ&#-l=;xGEbs8jpN7a8!;*ZQ#f*uiC(o zzJJ-kQT={t14s4thYcL{&u!_UYEuYyzk>4D!zONs4IIr6GHl?e-yLZKN9z$&ZQ#hS zif!U9wSlASZl4VtUFY3x14sURpA8(9cdZQ^`NTv;3OW?-Zz>&TgHgM!u8q10Fxnc>UmK=KOno50JB`;8Y;)_z&!4c^D9Re=-U9yE{SWX96thc z)QSrz2etF?jt=b%9298YZS=c_KT|n8z)Y05hRQJ)m}UOBAmvyE%sPo{s2pzqv(1VN zT8=M)*)MSom80ER4y_*!3JsMb4VVf3xFF>y1Lg*aYp5J|0`sU97f=rJtLK5)C~*z> z)mOm$C2^U$}tm|`Bq%eax4MndWmbO9FGCBMdBJN z$LGNO?2q#+M_-hqX$+p@#zCQ>a(IBrwc-NGLF2-BU?w+$<8}_ra*4B+gR{aX^2^&L zM&}ysP3MSqc()B4jc@k_;BsU+41I)qIvCFHi+{IaBC){_M=!O<;ER7Lp7f0Ll+5(J zOwXvKv>{yzGxL%P3%nyQh#MRm+a*YR`Y7*6H?g~{H;{M5n>Z-F=Cf?&vzRrn<4 z?4pd~spV737hI5;T$sFI&Xn23(?%A}DwjbOwmC$Z_c}MZwAyS54OzV6AjNZX@dhG~%eZ*ML0!evNXj=;Qx(s& zds*W#v$X|(XGp;n83Bd6ATaQYgeeLr(q>*tArV4ua!a!XoThBVjPB;U6a#eQlO zGlP?&OCV8g-9cT+IqyxeOqp_iIAGs3y6P};e(!PQd~SqvL)6e&dJUn*+W1mXah1+Z z$iB<>E_uAk{j9~9iMrn{-q~z{!>-{oB7`3{4eSO zEb^scqt-^TU4ccGY++-7r2*EC-VVUhAY=#I4pyUC7-f`jRKYy`t4xJKWK5@ z1~!ZOFuDK|eIxoxqZ?Qxx`BFh1G17z!bj^}AG(2Nn(lliHxnCcs$TA5b`hhO8-%2U zpG{ZP3PruFC`v})=*E?x+=`l|sM{3vDk#yxyah^hFrR}G9n80&rsIg#epNhEGi|Jc zc{tG1^L(Gs_%hlzbm-B_*v3s=6OZN^u3N0ow`tP&i5tRrCmm6|3sB^0&LaBm|E~4| z+4~*xhC3=xDTz{@J90&tB1ij#vqJX-h23~O6`iIOD+?y}b)#aFgNdyP6f3EpiNv+( ztLdCm5VR{{_oes~a$i}V2vf%VJsL()K3(GH(=>k;o_8TA;d!~Bgy)R~B`jF1c$X;N zG5Fwvfj;P0k9IBlKNU+hSy?&T1A*0_TTtRCiI9%!d!IH{&OfqjYvm=_^4Hg#wxEvK zoJhT#CU=`&wxuf0mlA<}sd2_Q*rp~Y+_#}VC9I|(f(E}0;TnEm!{vf-gX8n?kW+*0 zuRY;4iQzT5;Wfj<24_W7IRRq4l#Q>G1WoTQ=lr5cRPPI~^&X~-ZPHQ;_H2dhnv#MU87BDYS#f}D5!n`6-&+2*3rR*XHC8t^QP!+BxKzRwCbBD|x zq_vXv^<~QC+O36pjkDKAWq>jzvPW&i$ezd)P5M@x+)Tk{o80{!(q48m!d)A>a=k`; zWcy|HRm}>?AQLy1$Wo)oZAR;rCJJ1LXmW@jxEx(UiL&(xTDCJn8C*}n=RJa?`)+~z zx~{o;GL%L>zg})Jj)-73K3Apb1yveg&&Jctq%`B}=sKzP%GXJqR&u&ZG^*i5Q_KZ5 zwFV?>ZViTS!SOKVfRv_;!Ok9m^jpEIJ3>Kne3( zTc%%LDo2NInWqG{%yUDu%-R~2(GzZ;7bE9n=V-cYWh)-xKE*HRW-A_6=F`pOql%0c zW;|>%qs*PrYmjr6b82)gCM=c>>cx|mgDA3aae2(83Pb2#=Uz0x{IAZ&}5t}^ywa6$fvbCoJjY(YLJ>Ygcn=FaW zDfvV1VlXa5E+r?c_3q9o`BP^{5c@H(b(ZX}BA4FASa`+}fyLEsPRU<7yZ)OdH*dbj6@ zD}xfPzG}DXBSqgKE(y3VrAuj=Qi{=whKK98z7s%+E_4j23g%5$RGFeKSJYBa!gJpO z^%YBe3`z|s)%zmMMwJ$+ew_x}D|mp5whqlAo4UEAO)E!XcsJP%_LReRNtnrQF{1Ri zhz+U~w)HvcbHWN`GYDdfbC7p2RGtq?43*?`!YX;7gjEU^brC3G0lLGtlPy5@$>90G z5>P^m=uyO&e>kVUN?$z?*{^<`-KiRIpZ9Qe-H+9Wn_W^;-*p)n+FBYx_x4#!%N=`r ztfkeZy`9%mN3ys5TB^srZP%Vo|034XLo9onuBB%&u*h1H*zG(}J* zT@f}I=+gzlbEpR^<92o#DB)MvfJ$d8kRoA)dqAZy?*YYo7SvppT??w5DY^u$WU3BS z6;sp%FJbCUQ1h622h@C~-Un5|6k4`pBYyE0I_SS1-bLj!6D_@0o^N7!-foIPUyzoQ zhvvh-P!ZLK>m!%$48vCmNBb5=t*G@z!1DxFk6nXUUsc45EWhcRs3EPZ+ArN&+2)!Y z$Bf9{qt(kK{VSUx%+RTr*MATEDhoJpw<$yjTat`{B|J1GD-RYOeF=1~|#Ei&s z;I&STA~<>&oA79YqhqoOZ%6QtY{NV383JE9HY-Oii$OJWm+NO2+OODGb@15KRfX52 zcHQ#~M5WvcoArYRp4t^T(e{w1stR`7tzVXhq_$_k@yo+{+MYwm#Y_-d0iXB0gx|-W zpU7o9prY1`;mgmiw?Ln-YX7m?2ZoK=GtS7%G1!%ASldJQ4`rgqBFi@Y8Vbxdc@V#k zQP){w_!e!C{CXeSGc}>GJxdL3Gi>|InLNFawk3VLrM~dJ15H`=(S25t_uWMK-VFV( zq>0E~ebp|#i-@A$ZCQ^$>+1_Al{j>6_;{KU&=ph}j2f*`$3CB_L7>D0KLb=gciq*X z#KiSxP-B?4P4V`DTE()zgSreWt1j&*s3I6XT5E%tMa=5~O2nQIO2m3p>}VA`LB&$u zgzRz^>r=7!sMx1Ljptm^uq|@$KWcgOhuq!C0bmN!%653QtiiEQ4u$1d*= zSRpa0^@l>ZrLy1(W-f-c8q+aT!^Km>YUp9}#?WnX`>4M_eE$V2aWr|30LC@E0FaRsupA=HQ)!b zo*_v)+)WUg`V7Y`$Zqut%a%QUoHcPmqL7w0E5HJ3)WXKvyJn~tDv=h!Zw?qZ7W zLG5Q8-GdUizM$^qSh~})hN)qo4lpiJ;ZhZjmg^p59No{IiU#b`Mk^fMzY_YUgL;T@ z^k9_0l`32%s7E<=0jMXKS_G<)^(|Gn8il(K)YFW+5!5f7zf}r%H>l@0b`7YtO#Kto zLB`Po?xMWUE8IFz>ljxDO5iqu61cZPiTu(1pH~@2OOf<=p-cNr;dX)&xNkwNXWaLo z1a3blq3>6PquohfXIwofT0?hfO>q{umY{^bHlQ{$j^0834TnpkH+clE3#hj^_8d_E zVyYLYShinZg&PR!eU2Rl>O-bzF?2HHQWY)()W;l~3+fZ53P4R^94(cKbm>tyk-uV4 zI~X?y)KMHRtrBN}qq}kfw+PgijH9O?>v6cW8k_}=?(zwLp(V$!8Fw3~KXACTyKxpc zdVo;i{t4<^#yti~;GR*qb)ZDLb)a@L?hR0X;&5qi<1F;OPZY;)1GSf_PeC2Q;o`fk z0{1O`3w_^%`jK(e*8XA~)v~}*K7Qs{D&awfwII8bNfaA^Z^7Pw)c1kMAB-c@sHDWDE>{xTFUSK$gkIT<$| z)bEU=S{C~FxqgnNMRi@$j>7d)xHwSfF>U~;9*i5Na2`;?E_8SMe8!Cc70I|< zg)2}vxr=WzLsc%VS z+%8Z~#(l4FKY4c-0z?w7+0@wVTcj_LO!3yxK=nfV_Y;SQNJBP3I8K+7=gp3 zb;miJalJqZTpTEoF4-;%hf5oZb1TMqKnWbZlp@k4U33G-rRCs!3gZeu3EX&4Lf>Ri zqj0#iBAi%W=jM#N4V1v$ z1xloQAE=2qT-rZyZqK;KKndK_poCps07ZFpX)oh^2IDq>61cZOP2<@2aGt@`M>w}* z+^3)f?n_W2-CdxHak#WSIG@Qly5S^n2SJH;`8%jtIB-)CXX;a3S{QCZ30!kf0!KHd zN*UJ{R7b|0p>UlQt~;o5#`Oes7USX+ZU88ezoDS280QAngmEbfHv$yZ1Zox3WlZIR zax-qc!c7LXh+~UDUCC4lDC*T+TA9Ml2ep)A7lOKqsU@J!W8BpWR|`t?&o_X&hHdCmf6z)Dyq8WGgO5Pn$hc2H ziT?RZh1*3GS|4f^)Gdtr5mZ~w-$8}@9h6A-D5zD8bK*8HjiWBDIVe%Ttw4!#v;}o1 zz#=ia?2UOF;dTaiyR{e_Ew*3l(k&s7Dxg6)4f4)+*c$3U@20#~F7gDAAwZr*QuO zCFyJAVR-+PX{o0+i@?cPZQ+ zP(t62pk89!0Z^jf{axXXf)f3Zvl+GrU|cvT(eJhbCF-{=C{d1fpz0Xc5tQh6&sMme zphUW{pf)nDKPb`f4plfeD3Pug6y5xGX~RK@em6(q@<9oG<3Md;Tp=jY?-nUs2`Hhj z6x2J6s{|$b-Afg2iNak4iuyp8b}cB;@7|zrw}KMs-U(_e<5q(b{q8>$?om*}E>D5l z#<=G}iGKHGgl&If!3fB=7_4$|$gA)C24~2^bCGyuF6g`6A z(uRQQ#QyA7I4>ySr^7*g&$w(*F^tPsxN)FF{t7|;z_{t4Iy0_B;YvXXeU+g0Gj0JW z(cfR8a94p6`MVa>0miKa)tmL*s&IEI+-gvV822EkK8$-*;hs{s=RwgJ=hD`JqN@Uz zwqD^jffD1)+n|mx?tM^VocUPcz5pf0nQuVVGj2C1G0yy`a0ft%@*W1&1bwed`wNtq zpE{fC^%f3F;97!e%D6V5=wTSFM<`rJP~y6$3#f3$odb%lXa~C zU8`^_L7mRHTR^2V?oNeU4XQoIJ_xEKQ;&e6D>9e%l)^m^Du!d%fjXP1I#8L6+oW)B zgA#uAJ}8=-xU_Ac`ZDe_h5JU~c7r;XaX)~HXWRjWI}EB9$NmMX4^vHA;PEELg@Y39 zvL&d#9NPv|f2K|cHGy#*6|M^?;Rok{8pOC>poTK8ufh!>9>*qtx{#@4P;?!O9$4YB zL3ucK6sTmT#)7(lafJ#uohTlEi$SF_ZVspsjH^_*1)zjqEdn*1an+#cY8dMg3b#_> zZUL3axH~|NX54Cpdr;vX0Y!5=m-Zy6F^qd&;nsl?_NxPx$GA5@jb+^13im!yT#jv^ z3K;h(sBw(jsc^eN(KE3w?FUd3nED0OB*q<9xW9;EeNFJayF$h_1C_(LmY_uawgDyT z?Q~F68P@?6trwsNR=9IO3H$W|MRQb_76)o1;|3~R0x02E$)IL3E*(@BiUoT^KmidD7R6q$ zA@*)!>@k`cdyOS_>@Bv~jlGwsu_e6coLgq@4j44%`}^aa&xhT!&pgkq=a#v1XNUkR zf_O1twI<#G$r~zp@nH2O-Z-!t6K|5_&62!tz_Ji;Ay{pQw@mVWl)N=y^(Wp&u>6U) zP4aeu#roa-U=1YRVX*2E@1*3N1&j5&7s0~0yPfG8SoMi_Tk;-*#mesmSi_0;Cs+-L z_m||Qa}ed10jzl9Ie>+0KX#@ZV6pnm0~V_{XRyW)uLxM4#49OzPVg!SS)?MU`-%ibFjRL*GBR>fW_*!D_E0>7YJ4(;)P0H1Xyg|6ayAstJs<1!15v9 zP|1r2i-k81teM1{2v!Z^O_#iRVD*DF87I>cu;vhN1z7kPlWC$!iW4UYo)ACVAZ?FI@6s!1{rB10-*RE_wc7{X)D>k{2j>QIgjmtUbgVB6*`FZ?fdg0&73<=1JaC$y+OV zTfjOhs|6NbquZI>CC^9lT1j39u+9^&o8IsbxxixO=L{CE zNxk;w1B(JIDwUxXsU_B*Xpyc(Iyg11l4wl?7&7ND&p6G9%m}5#! zM@z;;cYAoy=T+rhiP;mp?Gqa~bV_9JqFe;G0Mysu_}kMn_0hJ84ea3s73mWi z+CR(=yQDKDxx?HacKO3I@gDYx(Ga99J8vt_!)zbV+a`EeJ&B*}Ya3>6#h>!Mhb(x4 zca2&1P6gVKZELEu%ZSO>EcBtC8y`JmZ`v6Hmf;c1e|o33f5sE={vc<=4SPsWKCqZmK61z&SZvE4w-Qk~z%z`V z;z305q+%tpPl2A~w8zJ}wP!Nlr1hE1QjnxcG_v9SUVMzf$>akT^St(8;e9hFQxI6X zq&xAXhe68agQ||Bc4>u54@Sx7QsMbi`CO|0`AU4qhvhPi-wKz{rPhb1$KVOYM~>M# z;R9n{t_}#i6u<28*E8|U7JofrzieH}2UC0mIhrz48#2SJM$&36txjOE>@NiiZ#l9D zl+z{0+6(WlysOJzxK7dE2S8GRnGCQ~v?gT zQ7MmHCpNo~JKhsxrkJM{0gHKBHLwDyi$(upRn`P7R%IRJ z+0|g-{d*_V2C&jow?8F>Nv%d-sri!TOnW6 zdY@E1n7Sq2Hub(7#<%j&8#!FyskmnJNc>Cad4@Yd?C?$RE;sZlZjfA-{VFmGK48UA z2HQxhGgvzB#22#ADXT6W;@P<%=yXx)Lg6CF5|Cd}~Ro(gv4U3Xh|<{Z&==p4~? z>V$l`jy)Dq!yXCT4%W|9RmzYIFGLY}wDPPpRLgJ(6RQQkKdD;O*<1Xh3T+ob5b6XD zU*+@6ki4AGjakjD_GWWTkLo1vlk96BbVl$R3hZNUF@$=aBzQRl(GD{3D1Ie2dp6N~ zpYr}o{4EA+b{ZZVWpDe?_3VkUCt)H81#0@|w-sWK^D-!be4_)s?*(rDnC8(G4&N`p z=7E*L(#9`*MAFVQ53uc2YsC>)C^@y%jiI0CFYv}E)osp|@s>}sri+96e+&SKT%Qu68eA6qR}QKzc;yT{Ximk#>nwNL>ul6#)>#4+9;>~X()t!GR*y@;V)eKm zto2j{xG7Yt$Lp!r98uGAvU>CS-M0Qe# zJoY*t*7o^za60x~`88~nt{MBx(mpJToF?%Zy#6;KR`vt0EmhI4j?+o@X33<6-65H# zq=rH4E1Z3WurJ(5V*=NE%{vO{HJsYYv{5nXx(k*v>@Oxz_2K0j8`^Nj$chn*hj~{Z zSj?v^U@@PX3f5vO#@S#Mpdk=9IOin`hj;F0Q6KFu?xoq!emDBr|Fov+gmq7)rt%qU z$^lBjsy1?_r8dTWk=nqmo_2I`!|R~?7pjAc|6B(yty5|)I756C2F>NIxDJO!g>0kH zsp5w`GR3-(7mIWH;j>#;dOZidAB4Y^4BuUOM%S-6V^H`H1}1u6*Yzp-p8bNZXTL0` zj3H4VqDqb5S0%ywnbxUi7H<}L15GL!I`@f_aaOJ$gz+sU*I~AW*JZa7PrwyKBY4A4 z_7=`~;&NgJx}>nhAMlEx?6$7S@X818Gl>g2L!1y-?F*Lbqc2&COl)FHDS(yJ9EqN= zfXZH;ZIgI}UOw&pEMY7v0Jop$!>EbP9)+2Cf0BW(RKfF9a(Rud0xGSY%Fw!VA`tt4 z;Z&`7NzM9zs$j7`056}}oBiCF(} z1*}J;cmvjOvT&PXu0)AvPQ!v>xIy(nP*cCCc=Apcr6+yBqt3W4BU0* z6B3*_vk6IAuntoxRKT-frSJm4_(v|O`SvrTZx?|?($uiOCc4&MMu3ZY>W2X(7 zXWptrCcIvqtalii=v+;lFbo{Y2nD%_MBSfdeE^lb64%QLQG6(Ap z7IU!SU@-^7izDV%bEJh6ZHBFp*3V!uw>k|L>*yYX#oVf_bgRnJt?FrRg~gZ%{XnXn z+J!W`)q#I@tN(O<+c?!(Q^^!&P3fV8k{aTLYW<{!o$*VZ(dJ6a9BNFeRr@J3+FUe; z+5>4|Z9VKu&7saw@;-XqTj8S(U7bRG3%-)}hW)W&rZt50$t^yO!wjD|!3(YbX*2|{ zfK@#jGKK#;_{kv(lE_9iSUZC-p(xqU z?}H$P`P@GCMQbZ^EW`i&VS>9`$*~s_C*xftYKXAF_$7z90jauaYC{~m82d6q+;hlx z6>{-E!D78!ZpdkM!kodvXCj?UmEdz2S@=Ze2(oltWCP`1 zuvp`v*@!YwrndIE?;|}MuD_0iFr7@e>c=K-xDvaQO0ou6sZQMBQg{)ZH!fS#MTveX zDch)>z@v+je{xl7EOH*EEgprz8@#of$npD1!Tr;4Y@?P{A@d+`-mTjz%SgGy9Ft?8 zB_7l*Bqh?t2fXB$w;s~ri_t$e)Bo74>g&&RxxtWVHvEkTi_NdFIN1P)O=t&I3*Ine zReuXCUiFycM7S{Hxi-$wuYaV<)fxIbO8-Y^=>O?p_GwE1kl4>z0vMlaC4I{9m4n*x z23ZYXZ1}oL$y0_exKd!RcGmu(gm~RVm^SBc#fd{Ke%jbO1J6V|NdR-UZ#+RN(h zT&j0GL?N;NxRB`M2*p#p@~-#+j_I;_?S@OWywKPkQ~ECmA_unG@+W44wM;ApHi4}q z6WRbQmNjjub0A<*)NcQ)Y}jbo$o@ah1}rt{|F?;D3;UmIgZ>uvT%PL5$|N=a~1U6H@}ou^ssrz)bm^@S>neIoy_WQNzc=Y+^v{TBy|)jzIk zFh|99@|co_iDaH2ZrHJZ9b=u!kNoSH?Ce$E!U=JE(0~80V^)fS)n2M^U9xGYWcF%o zmU6hs2sh5*hH;Yj8z>a~mm{XIWO!@*OR9X>IF?hbBkC?hjR3a*+@KVNpxb$e{Ti!@ zkKdfcmbjL36$Mst>RS4N#cFH}Sgf9=gT=Zasxe2gO9N``lQ){cv_vizY5zw+lmz_a zI9U=<3{Vu$K3WvwRWtv(DB3_4Ss!cxixmpqnq-9%4;CvFEDBaA3&GMAivE7nXSRFp z6!5PCc6q_S4|vp;%~+rupcq6o!xpPYR3uu*`|;}bk}1YneQ&C69LHyqg)T6NtZ1;N zlBMsA|3xoG|HUV9_!ft0qPs()Dbd|FIm#h9O8(bP2QABK?GW2R z#)^SF{L5Bm$p3L=s{PexIw$UD9FA*GZ~;5+I{O}e8NRVY zYYP{y-nc8Q8QZu4!;Dr}X?0KBvpDn1I$-5PHGCYi&D`Bmv>siu(&|FkGejDamF@FK zcWM{$agOOMDYc2zCR}MvZfi(xDe`XIZpb`794y&Y$?4)3$bwC3Sx9lR^(k2>`>`zO zb{JVt8d{`2yMjrBw!eo>go@yQXwv_`IoL=D_sHHPc)0VK7j1-v6$9v>`1<7- zO9ah(Pt(LruC?f=F}jU9Vz(!@@p8D-hn=FkEtCcRfPW>G-Q6Bnb^w5GX`B!2F#7=i z_>BhiR6VW?q?maeUS%?mYX}zeIDD5JTl?=Vt^Q!K9VWxTV#TrntW{bq>nCyg?54Gr zWl8Awy=rSt;vYk?-L6y?Ss($p+ZFQO^$)h=b@(HIkb(~|P$AKl*5S`Mj88J?;Fkcy z_DH2UrsgSZGS>za%<3*JoKmwQi35vmcokP7Z1=HMr;^qp;UlZ?YpijY+{3@0hRTO~ zl=@2kXHREU>L=404AyF``i%Sd4c8+7-)-VQ2t_0|@m~O&Ht}Prr@o255S(Srs4`e= zK^Hr7*4%u+V$BV=ak8^3!J0$$uokTJG)(OSi*4OM2^QPBe-13By#*H2+JlaHUM;W~ z2A*fViO4I}4J>q%UtS8}lSM8e5W2RWWZZHQ2Ez$-P|xKIC@msdSAM}Hw58<_VZ*)t zm%@f^0RFBsH=}n;}V!9Oy?Q zNA`tn(v;LFFZ*(4UoPy+m3@_BUls5Rx8)>ud6v)xBgBodiQk|f)V@Z$Y6|_+u9|xZ zTaXU_GTUDKWAQ}qN3er4(Z>O{lO)pFL^I?E{(=24hr|oD-&?Bu^FP>zZB_~G9bj9J zy+{CsdOgKZ9X}~lM?D<92oS-_-F1vSZ-SiC)-%FVnO$U54Lmmm0nRjO|jxSN|{!AN*ig zqQurq?1scJEXKoIu1woaV)zRLw z0T#QU4)glxuF#c++j7{G2T@@Z1B(ry*e4%{Ou_q+@GMxgaZX+I_~d0u{j65Ircs}V zgNbXiH+=Sbh%JtErKh>F^97RZv_SH?GuFV%jr!(7oMu5pPQu`0$0@71>+j9#~&zeixc@ zsm-=ix|FI5Ar%78wln#H#UAAB3Kq-xG_c~J)3GysEiLtGp_H7I(8aoTwV+>bfQ-R9 zf1;U|_)Q_#!HGj~(<@vPC;PdGLP+US_$!E(brk+GQIr4|yya>5ckLPFztt6eX|__( z;IIa+V*#Ill{&sz6`qa7Z31l(q23qH)3P1A6_gD`kEyYhmJ#F3X9Sf7`UdX&aWdhG z(=4(eSt+K;`d`Rb-c_Sf75K;4R(Ir5`#179HJ2-J){|w&R3^*f&IG@a_0JP!+A$$- zO~77PaXBaMF*s5gC0>Z%=bF&v5ls3ZStb|{Ve>scc_U`LwuwjBx;?IWB(`u0GvQqf z{RRrW9Fb4>@!jP(tW5%c&<|@^^Q;2UMO%=IdV<9oXAoG-FQUL2NELt=w9IYsx}Oat z^TEPF#L0vM+yt`rfb|VoVU93AWa)+4H#|&b+!>Kt7kq~juXMrIRpp#oRq^!)EL!`~ zm(o&Ia77~*AYjX}tTwnL5!EK1nc~$3y-S6JA##I#vc(zdEIIbNR&6I(F~H9FhZ&N* zpFt79y>ETJp)1+43k)bboVr8RUxqDOhA^<|aW731C#ZXL75U&?YIQ&5U)McOX_yy` z!jx0(CW6Jh;0Lgn7vSWEdBF*J_K7_ER-VlXA!t6L+ux2Z^O5K8j2n(Mm&pyGv+)}T z88&`b2kQalz7C!Ri;v%qtS{m9EZVWwztNB)Yu-3Whg0+YWR*cB)gzKe}JmHM|flGMgD)9s?`6;pE5XPE0 z-YsWM8oN9er#n~+{&k!<)OJ}t65 zpB0&QS0V(`V3Iw4T5Cu@6%&&!nvyxeyffnnylCSy;;az7^$TPw0>uyjy9!4~5k-k({@NOh99> zdn$D27cQ^uqLq6v`H;t>OIZ;!N~$NpyFGcR$f~m4s$&hn+GEW6#fOJ`Y%|=2PnVab=O! ze0Q+qj+HN(*u07E&i`#<#TKW3S+cN$(f<()6N%lsE*z#dQ!jB|~OH2=We z8f;LR2-bf!l(^UU*f{cOLmuuQHH;(waZP>VL^QR+zxTz5KiFhA?m84mD*FsSy&ZIf zz~n4mo4xU-s$Y5kR}(n6^7->*kuP}d^M(2pYPAy+aPgm-D6jZWFGrl1tq|26|0r)N z7iL-^!ptz$oyw_nA}P&}VU=fMGguPlyWL=`7ra=qE4(tXJ0!;XZcs{dOCLx$>o}T& z#kz(bV6p2>yr0SDAGq8*SIZz=d9wR6)>oc=p{hSMWB7^_>svOZ@iM`(RbH|-g9TB0 zSk9W5fY)OB$}(QAmV~sjIdpljSf1R$V)<++vCd$z%UbLpSw2UDwN&I&c-d!M%*dN1 zkb^{CJLqkWbS=YQ6f716wFQuJ5WV%SF;BoAQ<9p=Wa3V|ha#C@vfa{UByOe5kRDqF zUTgjHW=foQrF9{L-G1%`iglF!2(W%2s~=db5@1ZWUeHhVnbv1mIm$iPfB8BHxy-A* zUqsxC4bv9*U6tKGusEOM0zciCfhVc)zRaUUGhdxg_Os=0+_74s7w>DBPHWV7X<+@D zD(tVBe{=_nx%P0dSaY2K7F(B}0TwIEZ@^;f@;`&c*5&tu#n$C-gQcy!e`KjW?RRIM zP~x%W$pv=n%1rI<46LAIZ7O?2bEWtqA9@MEKW<2)?P#BM^G3I`3m$w*v2GJDKGp2Ltf%qcjaCD zJnSLJ8EFTZWEOVyvRnL;UA-Jz@m7Kp-LisdJ1ql!#sW3Fm6g^7>W{pSJ%yEP ztM{>s=?+h&sAFyIuLKksYYRA@vbN9wEH>D;lm&`K`!!Uo)h?b8fMMPLlRYUd8+o9Z zwHI5v8MU*d{Had-DR zpPgnaU;p2ic?B%j*0+Dg^@jf9kZl0_%*80^T>0cwj1StKIjx6vgPw==uvNffJ**E{Y<7?LjM>E& z_Dk$+I9Ly;uk8;OTa6kb&*J=qy}NogSpUP}&b`KG`w zbrPm9bOh7Mp71ji{=(p|H~fXeAO0Vn2>6SHKYVWzz8(IEb_lOtH)Ln`3EH-RowN&=3dPQ>x0zU?8*A1U@yV6hZckQUy}W|+IQ(2E&{_XwHQ zURvFy6(X%DX^B*SdI_zjG^SOLrLUGSZo0OUrT0(q8}*w%NpGy-ZHivxLwsX;MB{*@ z8xE14ffR}ZoF7CM_BX5sT)_H8i6gCf96~De!o8oRA13ulpQRrm^+!HSA20PMK1)AZ z>VN$#{aC3#|5^G3slW7DdVH{e^&;0kOFvQSZ+@13vee&I^m^Zh6R94;x2KXCeR~>N zcn$wh2{El6J%d!}(N7iqr>1BYsWC;f$-)%@8Oq_0hTLo)vBSSkYLpv`+J4Y7w^B2g%8oNZ62+8`py$tyl@v!8tkcH{IN*0# z5ovMh5e!z01z9ms(QxKtjQ*h!L6QC4Os$DY5kU|EE(|xdqth;yP)m3)U_rftSz?G| z368UH&`p=Lfbj6hzyM3IjJ=!V(Y~5gcu54kvk*WgNU% zu*}^|F`)y4O@Wc&kdRfg)EXNDz)<^caS;(r=!+#D z5fI)A{2)Bm5*o?zwxQ9MSSuK`DbfK?g$^kQ4vuIO>F+BOO9^Nb$23UF?xrE;!as3pV`x_s~q zpv7ozNgl`@*54PBK|q60OP_!!2{ZTSKiQY&nCv&?hdZYH-3CWkKHLIb{}b2^V5nq6 zl13q?lHuzdO@^s!&s+xGpz3IhYjiXjE;*X~u(EY*?$RnFC8^9>r3&ypGAivN+ zoTu=DqWVk2Dbatj0J#UV9}Od64%0MXKx8b=RB*<|XFxbG$OL!>1cn5Q{*0jzx8n6F zqI!R41bxpYx?1jkDjHJ zvrzS-ebGD(nr#e@|4<>AQ?5ib2FFZ*Jwt*6dvjc$P8tvO03QmW6EacKpsc*21NuYz z4ebN7X6hnvL=q<(MB>`ZIB{O7o$|O%P0mLMm2Fo2H+-Wdd@Y4flk2n`J zaR7Xv4@?62FG>ctnd9&u_yxU|Btn~nu>!IaW73rjM9?&#M{sybSVO3mlyHht4TH^0 zbQmRtk5=*$~g*(pMo@6`7R2qP}O%ip>=Qs4tV{rZ6E}x;=Ls& z_)zI;@wB!2?GqXl6db|N`^G3gApxu^EHIU3WkPcs78P9~utsE}4x~XiT-Ja;u=Ehr zJTgK{AtBoI6x(%lXaJ7pIK;Jy4v2`s3B7+?2DFX{h-wq*7a9k3r-ct4Ti;l4OO!N^ zq$tG?ui(JQXg;#D(=@g;2#Ds{qpW)c_Y8;)7neZB38GKE`MTw2W?LNZp^Qe5MbpEj>Rs2G^iNu{}rv{ z;1&HFvINDgzDL{EAuw$VV%MYYjas|Avy-q04a*1ofCU0NFs%1V2&TW)pFj{xQSKyR zA1nd5WT7TNM=@dGwzOn{3C%#3I1dT+=Ys}ZuDG|Ze7&B|r&CMi}(jd0}b9yr^lEL4$#L36pv0qa*?IQr{KV zT-^OU{AI2@gTupRo>J>#MgNE4M=7D2V$`2NNU5Q)L}B7(qUyuH6Y>N=cRcezt^R1$ z@p@RMAA&RaUHYz4|2pmVZOYd#>CDJn<39T9F1tO}?#aFBuYKKr^8Dtjz2f%+Q;R8+EFKdDfBMq(H!2VHZYjRc zE||M2KB9cjx1ry991c&vxAB=PeoH(2TGZ?NLtR!@i?1(q0=NFIdw%zFs*M5I-;+sXeZJGz0Yu3FI6}9o}2#0$c<~%C0es#dj zi>Iz<9x~u7uR4Jb7B{Y&-g8#co#HnSHcMB<{ktYn1G?@y`OZDZ(ji@&?|t3wY*~?x z8Y3$-H+@^iq2cLLwH@z$dv&DiSI$M_+<(ltt>o3Y%PPE|R6l-czy0f~yHu<;FlW2f zkw<6TYkS~G%pWCpuiS9r=WDw*9eMQV`I@1YHtCa>EE;;`!0P7T)jnCi=61Wlw_(>u zwYy@Q!P2|N-0&Yn`Q>R8Tw-za?89HSEZlC;+kU<4NACUg-sbtuO`fNIj$Y%{|G=R& z?om_L4<9#SSJOJzV|xG9ZlJlr^5<<^&c6J^na+6%-!3!sShb;5N+p|uA~y!kELgsI z*Cn$OTRy0nf8oP7f33fA>Dh`UjW<5HH}vUmI~%UM_-bKY?+xn*jHvqC;E+B&uk4+* zKHZbC^$$1MG&yHI&*UoSmxj*B`{H&RuMW1QLeB+U>Ywqd$Fb-djsF;(`>yNrW63>T zXDwS7Qgra(!xQRkIBWA&u7#JH0#f_bsa#=)To)JLlr-pZpFUIxh9YO?oLAQ=QJXG%7D|k`cz6Ny4kYSeSSdtOXIh< z2v{AwsD3_=Rp&Zw+mbx}x_u78|Jv5(?Dn!XYApKo;ps5XW=&4Coiz2$xlDnMXMHDl zcK&@|`Du3Z4~}WF|4q@MgswtE*erewXi1m01Tbo~gL`7mr2{2CaSA@Nmer z7SAf*9nYWy=d}=Lh|8_}< z=7&%Ia&_ULne%Sf`>mbLqMuKPSX#g7`Ri2MCj;y@H@efZ>E$!0M~2lO6nHITSd8OA z`@7F-RNdt3H?B>ovDIShK5jm0-QExU( z{N<;}=Xsph)T~jg@W^z>AD;+wD6bXl`2^mP8X%BvRnY&cuE{ovP?uKnGuTbD8iUkbeFLbtce znoSRUU%SrzyRmhSn{y56kbGxz$WQHWkGq{`z_}$q6^Poipjg8`^CBHvp1R^w;)m=b zGmcwXx_s4=!*A^N?2xhZ{=|x{YWdE&TYhKZ3gH_{MQ#pt+c|yW!S3Vxk6o~}=FvZ^ zKH1yp>R*T3mN~h9RZz5hn)g8iJeO$O8{Q|H;u$3MLvar{`t z`lSvYsT;jN!L#QGo0csvjEMTvH|xFdUQfQ-urcJ)gZ}=1xQu+W(C2L7fjeJc3R%(Q zz%84Tk+)9W4?WO5efLU-PBif7vHDu)BVT(tbb06L_WS7*Wu3xr>{(I4>E-z+lM2n> zSz%?yu$F}y#dqizaOU>61w)_Z4b5n7)IM;V=dJ=9z3TT4eHCzHYP~Ea243DfKYZ~Y zuBEe8-&O8GL$he_N7hwNdT5igyZD`_za`|idS|0n*YCHy?TB(Uu0CDgs7^KSQ{wyn zg5kM_+PuH=K6YyMy!nge6~9|J)w+9kqt_DgE%0nNx=vW0YtWAZ|5D$Z_9kxGn(b9K z5uWvLYkakT)T>1!G7l8rR~sE#H+0LdrqsS`U3u^1eE!fralZE-NB*9>VD{0dy+=Mg zY`$=L(O(++-_1`qvg;qwZ?2yn=D2V7R=d5kd!(y>uJPiXLH6G+-f_HZ^02q{nl(7N zB>Nh!@{38qb*S33t@Gz=T=QRI$v=*v-Ms6K|QzCtUlhR)yjLL7FGB< z(`EBZ*XG|89Nl$e>tk(#{C>MR-sk21MtLum3SPPTf!iOsuC%Jzd*GGR<-MNHXgs(_ z(!pFKPQ8x`9v*fp>CTXInO~PFwPkKS=kgOuMnwj844_d!uNY`n- zHhwoZdE)A*I<__Q4;r<#ZvR4YO>gZUQFOKA+gbH~Z#TqtT)!i$Djk{FVaB+q_I10i zdh)z}>1S0!H`q+hc>j;tc0S)%-+gR=%TH~J1w}jMnJ_o(cBS6;-}}XtpYi(b>p$8~ zZJX;x?Ul*yVYPQunZA1EWRH^7%AJedvLZ`{dt;Vu^r@XIs&@Tz*Akz8x3|iO0#94d zJlt*DgNZKVe6IA&(CPA#$wvm?xc+_X1$KS+M%Pif>qd)+BC zuWI9J*M|=5*}vtu?2qomUD{TBX4d%+K6HrUyV1%jqt=BCEpJz5^z5Y#S66SjvER=t!j3O)*mTlVhqmdqcB(hxe(iK~ z+9yr_tICQ$#(6YJKig+}=}qa@6rUG+r+;|Tp@oxXKMgpwx3b^heSXbzHm<+2;>(>6 zvsX<&G5@9?$E|Ok^l(kP>Di~>JlU;kSn;!411s3}&Ud=&#+4t&f7{_g`izJ6F8#B9 zT!pI@qtCC{cV}c`*{C`Dr;lpBApN0f{dO#OulZ=)tRB-ViSRa3$`9Qm*sS? zJ!{Y33aEBw!1h{kEjCx}UgO7^c}_O%KQeaOSet|U>ke@Diws>eal7N$s`(B&4A|d% z+?B6S)f*h-yYN=Cgmi}%*3K~O-onbq&t0-R7{dftbN?F=&-rJ ze!Fw?{c^c~dtdkP!5-HiW-M#kFtQu8nnt~x4i?BzJNEj(n5}cSc~{F6Ws~kum4bOM zZ&_7f^UDd>PQ5EWwMU#og$J$jtloI9-S&bfuC(*pRo~+n=Q1-emZ!?V9Q2p@!O?6jnYQFI2Upf@_jBnU# z-Bqu74SxT9?!l`Qc8nQRuXf4rX4xLN-PES;l966bg6;&`OnkQgp!2OM@0;FPTr4mo z!t}(Z!uMlcCR}JXy0^pO*(DO6HqTdWY0usZCuiPU?eC4(+Vv@Mv+2#JbG*V1|GeqS zs?{0Gy4$=Op6}4`&QwFxPD}=UGvZXbz;)Khh_H+OYYWd&-7cZ+gEnJvB*-P_cp&SZXfoaDOdD| zor^;6w*D^e+PwQm#%?~oC3~ICx!n@`kKS_5?^#?x&5M=~L)Qi8eY!25}fb7{JKz|o=bks==;vE#Ovsg>V7XzCO)+UEjT(R zZtk%XZ%b_mXi@)BI8q0adtV_zl@3-#_6vj5$EkE|~f7tP(5uF{S2t0#Hh zp6u&br~B(1xo-yf=L{{fcEXCW*J}3vzSEY=OMfntP-1EGvd5w>A1hJ%?3EQ27jHf4 zdu{BmS#DPT`NFw+I|_8HmOJs)kxG+GkDauyllz715izBk#}=%8$P_J$d8MgYgEmgY6xdl-Hb%u`^ ze(I=q>FGPdt0hdlwVw?Y*%kRDS!9vopJB- zk68KFq+eVvc6nBMLT|g&maU)nUA^e`(B=JZ7xTF^t8pIZU#^5SzcguY)%D*d|Fw3~$&rs@hTmNkys`Sj z^cm0Psu^M5=Ww-%vjana$ZVTX=g*BF?!{DZ5kEij)Ralt0(#8;@Xn+C$dyf;_x7k+ zXZ^QrkB8did|Z9-X0Q1np-n5yJn?JBtt;|1>|?)jqV0{c1rEfn_^sb`A4|3xt(thO z+|u`lqcdjBJ~(dPcH4{R9FN-_DDFOPNZsO{vpjD)u;h*iray|8f3)ai#l^Zi>=TM|3k{l@klu_N-)&6pJz+PFTZIZ! z&F0}8=@%L9)+dN|{xifaC>k~?uvKeZQm`@a5dq3?x1iu2vAtaJ`2iEIDB75}%X7kT zv%uQCD=e<#dHgdw^HV_`?!odO>hv635wtN6hflPeN1Z*c=fnX9|3L!&Y|I7m6aM-y zT6Wx)Fnu_%)B&8q@QJU|yj`J#w=o<%qlRN=2nUxMZOr(H5vFH&>kHkD;b2i~;S9OZ z?XSUwJh zaPUb^8*^j$#8kYx*QSR)99Cbr>F}R8m?!4z1E(e#@KqFFF>3?_{0`+zThBu z!V*K&bFlSk{#>S1T_cTg1pIMB(7;LeQT#m+?Jjf@z$54PWe4;0 zus*yYqGjRF#*8f*W5A<~Az$SHwK3<1fGUGk{qGBZ8{@)vCTRY=Vspjsjd_P80td?& z54Q$o!Jo3?bCl)?2F4wjTz?G~yHHkABKJDSp)3Oqp zkTs_kal8S}2G*jYHB;y}Y7=KHd}3T9vv%HN45topdf+Gg1%|!eYUI=!~rpJ zZlA0P4rN_F4TuvCpP2V_owvL!ZN!pqwAWC#Jb( z<7EI?$K^{L5trS_Ha0$nxEd4Z6ntV`99r?`8)G;yTtQqS952u15seMuG$qbnNCM6V z+SMPU^oK0(&4`075zDaZw#esA4dFB=P8@`j9ju^CFc&4HoAI-HhDIO)=PB={M^0at*yuE8gk&!+euV~pXnCXT**S{cGYFSRkh zge2qz>)86xAY(ZG#KD$`eN?G6u~XU@!l9AfoD0H1AKRVpcNl)H^F<@OET5Rw8)mjO zgwvklIt8DYuZ|rLK}TyHP6y)X^VQxEPDkSGhEHr?J6_IG%7^)CC*mY>PTL>${H2eJ zad7mvF$>PfBU|PeIbDc@DaZ0TT%+Y;Bd05IVmQa=_5Bh?PB-Gj!6&BqyIS){89CjF zvlKqDd=@y@g^phTiw^lp`Oq@9L{5(nRW9t=<=<@34}8?<|Xin zagC|lUh!2H7q|;>hQlX@b0Bkxx5jXSi8B&Dv3%xjKUKuY=}8=9BB#`)8hwnMUc`Y! zQ2!G*_h%Rwt@Ixa9L$EPdfQ;je>P`B?<@6lPFTBhE{-3+QOgT!^_~3)*K6QcETs-eUZOqqLBlx3E_}8g0<#cKj`+X z!@=6LF-!j`{nuzCr$2E#@e}@vpW1f9$iWh@F<*pF?8i#HU7o^tF@QJ~;S=*!#crc} zoS}RM5~nOA6Z`qmJ?cW|r=^*dGq@eZx1F~n$iB~xJGrOHLaz+scTM+u;qEhI**5QCFKwN?F ziFt1tv%i6nGln>Rob#fd%X}keEO9X9*xpxmZkE}|8K-a>4t!C|$boJG(t|0-aH=-V zbu_cf2S)@9 zXV=){xs9CJ#EImbt2gHzF>>Y*CxCNi_#9B?KdkM{B@UJn_L;>;9DQUA=WF6%Xvhio z+Mj}Nd_x?O=FLT>r{IV4h=ab0;RGFdltMfGmN*~a(*gc2Tn`D+r-$`*SPR;ilJwKi zCEptQx&_4Xg`&kivv;R9J&oZkB#t|LLPAUp?zaeEU5%hccbg|h&Qjutw!ElG;TuNIcM7L$-DVGroMprjZD+s7 zg^fne_ewZ^mzR__a+VVZdk@U}^Bc3W8#!1qHfGUhZpspN%EMI&b=actldkCfMKeu6XVy3I;MovtFz$HRf9YZcBa3I|~7`SIIia-nq^ zwl1L}&g`dYrR3D*h^A`7kyVm|<;V^ZGLGviGJ*fDAXS)FcA%r|oU1T$-kA~yEDSjS-rxotpPZG}eUBFKQOFd%qujvYdk z4m)T%1mbK!JPb&T0a&IV+p0l8v8s2in#L@vr<$EqOy24tiG zS#3Zb7!X?=VwI2!awMCq<#rr#kcfpNc_lJa7fz^oS&E*pNylNHaM^(5%4nS)cLUPL zfJ`$Wdkn~915!4VbzB1s$oB^1kO9H_r0fv&RTc*@I5Nrd@#KisuZ9|sIR<2x0eNIV zis1x^4iS4t12WEltTrI$3`oW-EZkf&7iBquxd=7yPO+Ao={T&GqYcP9j^vObpVe_f z%?DBp`HhalLN1t4nGaIy!NQ^{UbELOKVmZ=N zB42Z)vqbiAq?1G*a3n$^+4Hd2`$(iZM=TO)$B`uxiQ~vTiOlE7EQus>WR66ha^yRS z%4#*x_)NmqcyK2{=b9Qj%z9XT>rBBMCcO(IJ<(nTT%IMPNUH#yQ= zBI)^MTTO|S(tk zDUm3SL`fu(Bi<5O#gPIMImr=ciM-@UD~aSO#M0APBAy&+FOfbR@sY@Mjue#0T8?y; z$SIE4NF+;P7FSh?l;=oEiL~TMDTxf>NSs8La%7-H&T-^hiTuTp1rqtng~dKhBCRw}$i?Y~VBvO?lMI_RdBSj@LmLr8F@*_v$C31)(BPDW=BXuN_sThmB zo#6uztIZ{_5K^$oykr5oJE|KLNsV0%594RM}^sX%S`VuL{kwA$w<48w|^x;Uj zL?&}2QX=a(Vv@))1?kqUrzJAHGK*evZg5UUKx|BIF>yfwmH^_cfls!F6Mqh0yFp%? zm`v%469q0WQH4iojyOrA4M(y_WC%wxOJos8Dof-sM~X|NTnQFedO}>AHm_I>fDITY z{MncQsfvu+9I-IZJQo`B3m`Z_)sQEE;N+o&R5_P~p94Y6=eL&;gfIT~_-b6QJI2CNo1G^7q77*`X?v2c!ttmB*xl5>x9 zG{m(G3&&S-+5&=yhD_p|0g|(ub2Q`~AlNVmNluNj6pRiT3RYl69Mvt@w1na$>e=Qigs z#ElxaYaE8W7XEC^qJwzxV8(ZB7dM{E?}ne818+{kE`h1m0jjFl9&%*Y;VR-Ns`aG8 zf=CB{+xpEc#dayf4^t4R?BSa@2$-hua2TSGeFL1eFGyGjh`lcV-=?yqcbp6!rCb{8HF zaS$;5z{6pPKAg>PRt<;kutn7y9u9F3Fx9{=2@Zzn!`T9;77ms(dr|<|13-o4OdJGE z8+kYk(TB4Y&f1vkz^5(zd4y$d$97D?57P@!<%MtJAYgLF4iOH9=)?ILP%S-JK5R!B zvKxU4(?c8tO#OH`4AF@ffheI3$OmlcR4AF%!Jxu?5eEU&93Bos^x^Dh3$AjepOI8!Z&dcFj;sw4AFH8R|yAc&Nc9p9gO3pAo{qD z04=q+I)e)1LXMikqoi_z&-C!e4w1tCT!kD}bqo+2bIPjeT!kD}b^If$HC%-pRdwPc zs$*P*994CaRL=030shz_^7VkLkfW+j0g_t2^1y5z%MdxB(kj_>np7AU9xF=)w_p~2 zRtFUx#33sT5cDX9=xgv-K;h{#V!`V6o7}D#6FV00aFC;>`3xX7=G>gOw`ScgnraVM zAxBl6B~?+bIemv#!N7Rq0wRFyyGJ^Q6kdPMZcFEBJ$^3gjx} zsHzL3f~hkdm$R&L(Nxp83OTCkH$ZI61xN#9#>ASQn(8Q5AxBkRBo+3ucq}iIr@p32 z<|^cdU3sXQ)Us2krpi+rG59wH@TaOS1ESSemRhg!YAQdjLXN7sLMohx;$g`X zoljE@<|^cISKx2?P7 zO;Y9Js<{Qt(1iLJ(i zF`CM;E}Vn|IjZUbAZ%>H^R+kU9aQhcRcPo{q{Nr;+M^!xo#KxQnC2-_v<2y}L-RCOgsH*3HXen$_f7KgJmA)Q^1T%g3 zQ&leju`xpfro+$03=S?@N+GU7j;i_t5F4||SJq35T{M+HS0P7Ly(AURk?_b6ml?Vi z5myvfAxBj~^*~(tPy&ZJcl20IHJ+=GqpDs5qKys#!L4*3OBr)sKPFuve{998ue5X}!y9w}HzQ?=kK##P8sRUb&@1fO`!f4LB%6>-htD&(lDzW~wlRUpTG z0EB8MS0P7L{Y|Q@@QFv(@;h~Lo#iUzsH$W@Y|J@O0>|Fd@26{Vz2++9s4A0Lugco6 za}P~bz#T(^130S6Oe!08*5ov&>RCsH$|N5@mShN#1Zx)sCx>qpEC3CFTI0 z9}=L|i!vO>Rmf3QwxklZoNH^dP)+qMS0P7Lr6-jbmw(&d5{5Dn*G8^Fj;gXFRUQ*N zqVpAMqp5Ci6>?Nn1|_aJ!5N^F5OFzpu&|J$s_aQ6;wqlaCX1%3!BxmnRT)W@o2T%m z=~-1x706Y{QB|1~)zr-IW@xI3T!kD}m6=q+59eLEJ6Ka~<|^c(_#(X-_?SFWY092>AgLXN7+Mk>+Ubk102n5L@4 zRmf3Qj-<-YOFqWsaiped%2miwRoO`;YPsvifE}8uFIOQ)Rpn4r`&v!yr>W*~6>?Nn zPEv_{ZMP5Vt*Mf@3OTCEiBzHtTTaR~R8w8!D&(lDT%;0X<)IS=c4{iKCo3f6sH)tg z5@ncw&qL_V((w{?<|^cy;+#*L+LpLmZ zzMwY?3^}T*1gS)ieK_6T)0)bitB|9rN|H*HM)_T~Fhq;EdU6$VR8=Wb+46j4u2^A} zrb^^0}ca<{L$PSe(dFRkamWvm#AOXmNRR z6>?Nn9a4$jW=*G$zu0oEg@+Ori`SwXS zb*hO5B=M^*Wdst8x5e=~fV zrh3j*$Wc|kq_XF#_HpKSnyPqX1|vsRH71qt`C~C}D{Cruu0oEgYC82ZD*K!qdR8@0DRXbOHix$^eu0oEg zYC$TI!eX}dfhqj(Emt8&Rrx8Zu6c59(^Lgu)`tgjR8>n-iE;VD&YV{?Rb8$^j;d-! zD$xU+TOB?~Qw4Jsa#U4oB`&+w`s?K}T!kD})rM4J4sf|uuRpc8R&f<_RFyxegl|Mv zbPv%~=eY_ws;Vui#2g^wlXkkfXu77X43VR%+L20>M&70!!2Lyixp5V8R8@OYiCR9s z?qD%Z)q<;#qpCWPO8DUtms&+MRTNhtM^$xHR29v`AX<^a8C-=NRn>`9qCbrK>nEKb zZs98AsH)D2>W{MPVJ0c!y2@3^QB_?O)vRCEHqcbI%~;7JM^$wtl_>d&BVR)JBCaxA zg&bAYO;KInk$!`wYQj~>QB~bZCF*Ou$?1}&3g;^1sHy-(^=Hl+Wi-_!u0oEg>Y=D+ zCpH_XsaA6pa#U3ysYEa8Y;#LjhNrj+IjSm1QTcB;(pih^HCG`=RRxnulzhQeS)tfP z$rotO>I*rlswb&L8QQOOII5}Ya20Y?RWC&q`-@9mP1TjFkfW+X6xC_p9?;2&6b|Pq z_1aCKU~aJ$Wc{cq$PIT!hm{Z3+oi>|fvb?Cs``^kc+{fInSaz&H@ONqsw$3DVq9+A%GW_t zIksfkMUJW(Kq`?hhs~qgXsViAg&b8iP*KHZw~f|R-M9)ls%j9a#JqQM*h<|M{b;U2 zj;b0=Do0*l2djqvq{TI#tB|9rhL9=)R~0^!L3gdUhpUjIs)mv(J6E~c`GP5Y{xVk~ zM^z0|RBfM4)m@vLTd}~9qpF6JN~~~Nc05|4#Z`ip#?Yg%QMg)<5wL>WfA*4NFxCUF&VRMjX_iF{3-*X5O#!sT3r991=% zRH9YJxh~JBsZMYea#YnAQi-dZZ^j*%qN$#96>?P7SW<};9$D4onx@L!n$;I_RMj|A z3Gc0OcgsypRf(&RqpA`}C3*nAupE#oQD05C3OTB3JgI~q`d*(pK~oLnD&(lDL`5}! z_Asb$5!V8)LXN7MK&q_V=ZoG5+oq}ZaTRh@)kIQ37emLp9}jQWRJXYbIjU+Bsj_fY z%$ilYUep$P9z2kvswOLOm8&1%q{ZdRRmf3QQ%EIRN}evAq5X=|@Z>7wsH&-?%E6Li zGR4GI(o`L}3OTB38mS;zbSxgwagU}N&Q-`!Rnti&u5S8|no>nmE$1rasHz!?>h{Ad z&o$Kd*ictnW~UT!kD}^);!4&rcb02WBQB zuB}{!998uVsYEaO_Pas7HPuC~LXN7MN2(&cG+tHzeV3-PZOdTfsH$&CCCYHZ==uFL zRSm8}j;fkZDv__BC+60Tdfm7RIjU*_sl*67V{3&lEv{i)g&bA2P*G**da8@2TEbPx zQB{i+)s6uz-8EGbS0P7LEhd%ljjS2Z7t&M@xe7U|Y6+=C`x^5$GEh@xX~#+)IjU+Y zsf0&eY+5w4rmD$R$Wc|_kqW4EOnTG*l&0#yRmf3Q%Sa_^d8mJSFHO~-tB|9rz9*IF zqh6hQnMqU4=PKl=s^z2-v&u5H7e;BSeO!ecRkeatVkCM$ItYd`(Ndms6>?P74~lAe zIv3q6C3kyPM#xcBKPsvNe(j5Danea#YniQi;;Y)Y2tUQ&rW;)~=?P75mLd0E8yY~)&QbG&##63Bj;cCI zs+3D3JNo-!?5M$2$Wi0^6%g&st~WDG zo}{VTaTRh@)frOZe8YyvpsAv{3OTCkEUBD9f$8%3`FGvw!9=b?j;cCGs+3D(Emt82 zRJvL|PpYC24;ZF$(;mU1g(!^^T!kDpt_!3Rwfrt?<58OGDOVv!RsBXP>_x?uwx-J5 z6<|1!qpB{FN|Z+AwWJ=Jsw7t-M^#-SRm!E&l&g>fDqU$@CY30S$4gfPX>o;d6>`+L zu8=C_(iqQG$Wc{SNtJSGEaNKVsH$tEO1U)la20Y?)pb&(TpD+|3OS(CmBtNHiPDG} zRc<;m*pa>)`$mo$*YBhfrJ=Tz;#`FsRdth8DYq04u0oEgxOQGbE)Co6ETza%RS!s&a%q&~D&&AlR~ipVRS5zG!&GGINoe(=H2xoZZvr1xb^eXt z7z~IgK?5S9Mg&D!3`yABa%bNc5|Su_VMr#BkYr+JBA`N*fQl(rt#!ARx>T#RT6e8V zg$mYPajSdXK(WQTQKjbpea<;|n|tqMP}}$Yz5n0+eD0lR&iOvi+0S{-K1Xm7#^}~| z#-+rDQFFLJa1qAH^(o`B)*S8?T!b-l{he_sv0>C4{wBBx!+m`~LQ)@YaNM_#hK6*e zsUef>YH#UCWRg-)|P6N-O1)ecUy-2Nn}!8a+$A2mTOpo)mPRmL*%u~W#tr8Rc@YICKfJ< z^HDmgeB~94&ztIMPh{j87Kt*)RXOUWl*@6a8=cCks!E;REQiP8s4JTyJDl`onZnW@ z%w*|mOD4MX!Xe=xX{;!hXD{kXCRnZ@Pl3-*5O=a)h%cG3 zmEz=5s>>l1(v|Vl3h!4i5`PRfDg_!cHk>RSlk;)@3!Pb+>eN zCEJAPn#Qh{&J1$_u^=P<6#z;J(y2C+SXeVlfLW4I47kkPHI9a8+#yPrKTg@GzEa?3 zFY8RoB1?ds{q0wT!(qqoOr(=}dLeEtB#y$`uLP?QG(>s&DUqZ^Os$eS)558RN^J7X zEHW#?O;&hC(GnRCATlp!iHjPkOVnGkE@fCHDWWz$&EYST=Rj&Xd4)n!hf4krX$IyN))rP*$M&N^YeKf8FkYc?FFYX`!7r zvU3lQ=c=;oFrom6x-H8_EgF?oV|mpS&veOk@s`F6GzFH3N=hQ?72_!~{*;SGU`joj z@YIr;#Vs9btgB)heAc$Q8ZkGZI+;#pT&ebUWSlT`2D!GQ1(m$Zqj-z8DdAM231)g+ zB+-#T^RGeC0H9pL<4l6cl8&Y(o?{!69fquk2D6UY0Lb%Cb+SEmdeRzAwW|uJe8Jmf zw7`TF%_ajCf6TcQq!x396o2l4%rcBskANRN5oSOv2mJmaKtw($|%;5`)o6j?)wAtc*(SpFhBKON2_vh|ZQw zd!o|}rPNa}N|~_3%4iQ&Ft2{Arp(3-Ff|#Zj*`ukYJn_d`dB&2H6QrTn?hA+hjP@B zwP&e_YyoFQ+=hjfU4i4ZuMJRFEfIo;zy^zEK*R7zLP}{yR%}ksNoW!^j1sq2SV}Nn z;6!lCd3HcJxW8PBl8uWkqLCN305U;a3l$KVqNXbgh#H2Kd=y|yd*l}+t6)OD#Ggu0 zj7UkdmZ+Cb|-&np_|y_H9A^2g#0A7o`3mj?PY0#d6hH)_75s zj&*ezH62ewHKc zM9gv`b7tjUs#l%5N|sWIDr8$3)|IkF%{RqPgif=}0nw#SJ}86oTT6`@DZgBYVkJ}2 z0uTdPwxkNzmRAT}xU8nLtA$!Dtpmg|mM+P;x~oU9oQmiddB6-XG-ON#qK3L9)0VVh zp`_9!3+b9@b*X1=!+^%rz`5?oBEJ=z^MMFvS{vt__&&Y6E&j*(A9(fM~00 z>B@8`+DKt;>&~>KI;_M%e!e&i9VC+-vs1MJ-s83rR~wj};!t}SH5INzIs+uncNQVg zFd{iEFyU0=;#@LnJ1{1>*vg}bA4I&`IkS)*Nb3OZ6na?}Al}bm8H=)1eCIKoy7Z2vJaa10W#et@7vAwhLRJz4F z+p0dRPNAz~nX^?$4Q352l1{acx164`DBG$%DW7(sM!NUsNrL2Z0rvg4z%*-{SR!s# zD*FLN6YaSI!K!4tKq80aw5JgAAvAkWx)!yxHRW(%PK?H^>;P~fHvnGrwzYKH@xwX> zg}WuQ%nkt;`bX4cmgUSzIqjicBQX2LJVniG%4LLn>a_1zaQ4NGT{S5 zyjYl{u{Mx3aAfjVZGfV{wzh{QWl~!N=cK$SlpK=-Dx$V7*445QgL*cQoGqs+MYv<% zhABR_j}ir;4B#-O#N;W?kHmE)8W$yPgQr$VI&H{C7KUFNli|d&RJU!#rqk<8LYVTv zMnx^G5GKPgmkFY`rRLe33VMWn0}Y1^T~w1pEJOJ*1b7B@OxyH>1lHKPWLKsItwI0D zY}MN&kLxZ%CpFnBg~86gYHUL~(VSFfs}+S;(L*W5Fj{3+P)X-xo=4o+$yU9d4~7dt zp~}^Y(X0d@hWQOskX1=~Sba-o5%~ut)|?B}{H*856V{Jl;p3WQ2PqJzTef@xF z_Tdrp9`*n+dt(DYv9@cP$p?XSZg#|b)?A9o9aapK8ir(A#UYu`PH~jko|{uP5VI%N zj!@NPm+hD@^y8u?5jsn_#0OGyfe>^3gCHrKSdeTphso$11F^B~Tuv&|tQ9hyMEH#& z!|W=Lp4q9~woH%z!5xdWvU4L<&-$whSImEJeTdzg3BSq!T8ga?gG+1+u< zGi>ESpd-!JxR}FI8*pKbhB|p=@*r#cc(2YT`!NLXq}eD3GL{V`8@n-}vaF$z<_a1b zQ>n!*Nx2dWnHpS6mwGAWVy?IXX30g1`1JBv%S9&H0E>khG`?Yko+J zg{HQ$-QDexQ#5nb)2CG-NN0n4yFYGfV6U2z?*OMM6uFeuhKBBrB^Y38?(S&BYO}Ez z24cDj8$Zj+Ph-mvqTPT`F-8EBoJ%dX7M_EHc}SPtG#7Y#Y$`B0T(IV_cR^{SEY;u~ z?&RV#yM}toQg^j*zy@lTiS*Sgt$9XLE*48Sa_YMl{%6@vH``>D`LfeGKZV)avAlRK zLza)~ZS7_roR%)Cda#YgV(nT#T-h#JYQ6pEj=b3Nax0f2Yzm>JvpFO%A7oWtyDcND zM$1p@x9~bu8Yr*1It%6)vtY^*UUOA#>DwFa6b&$^7~ibOkwDkMYut&a7#yX%3gCaAabZqI$S@x6E72N!8Dxh2b^4_ z6P#1iGK$R!H43%S%Ch9yp!A}Cu<~Yb@&`-Pd+qz^f(GAw9|3v~?5;LxaC~=}^$xSL zW;1ZA6dREjb3;u+bLfd`U8t9w8*eS%T1m7QZ;Q7UuT+dVbxKnh`r$G1#E@iQc*hsVK+1+HSYH-O7WpO#; z4mmu|pvIncbfhv>Qx_zOPJ_>}s;LaUM1{LTvODaKMMKd5HqlUR1@F+}HbPSIH*#Zj9pyI` z6Ja^z3rAd-<1<7>g0@g%a9RXOA0OrJcqr(Ic)TbjE^m`6$`hA8?qI|j38`LYF_fkq z6jfzaQ#-MpG0mc@t*vTmjmn7B@WfqizsKp4#cVMAE5^+c5ZYX)_%|#EqK=R^=<{n( ztV&a?ogvxh^~9XmP@&mll{wp|Q8l%h?bKMNOI$>BJmho4BEE<*yQmS(YEMOeTz2~c zPPfPF5Sx`m#2PYJK#q9bK~L1{S3xWyS~`$bl%>n6mm_k}9f^A)v6vi%7$wD2d#6|S z`{N;(KNi)3q@*g#d0JMj3^;sIZ@}r0)3jDd@%7ZW#}jo%Vm`T%?K@M=UCv9M=bU9pZowuuIsPbmGgI3gE;JCdpIhefZ|MC4uw5| zSk&n>Fm=;5G6e&;)8p|)ox!M~BEgz4R*j(2!v4ytsZ@hvLMpA*brlgu$QKK{kryhL zrd5H{0?`<m7L{RF-04SUOz;-f*y)ku{s3yGn8M-cz(OZ==au5o3YXjK za=YRI;$Nz=$7EM99twrsKDeh}m!t5Zatb@+F&CoRJnyCh#Y5qMA5|(x#hRN@|B2Z- z1yznR8V<+eLGps?0|X!#ak~PcP#nDG2}Fe(HFhxW47*SV>DJ{cwv}E-&;gJ7Np^=W zTLxrr$QKU;9TY%x5NRuFSBGIyt|9}KVl?P+MqH5~$C}sWs?dNOiX-b{gE{wfZm|J} zHxl)rK(PSk5bKkDE|<>}i&H%ExG=8xRXyNCbMHcH6c9p9i+)w4OOAOQXeC`Smh@@y zbkL*ayP1KA!x=$c!Gq3ba1;^c0iV|ujK(P8w44{0oi1lQ9(9lp40E~)-!x}590X&O zIo#2)KudI|>Eca6W-GE1-v?FJRFGyf_}MjU}`iF z_lKP>Q5JNC!7E3CQIE&t4`++us}d9m2u{H5bGs=QW-TjJA#OS5@cW{nxQ9ZMy_{SJ zi#wxkcZecJL-90J!!{%6jJdu3h=YRMg7T{?!4cUVi#q~gHwBwbxUqR&#eo@Kmj|WR z!&uWsRs$?kO~W4{rH(8AdbzUj;Pb^r8wb%<=IB{9rOxU+~W*KeQu%RAs34E zu!zPN^>jvnnRQ9u=bM2OQF zW0kp9B2ia6oe{q~>T$~E-4hBkRdfDuJRCsT;~|A#g$r3VHUy&LbO)jVCFE93L<~70 zhAijx3VDbgw&qH8k@j;&qwcUnQR~&J&4}~L(B#}+G=ZAWEQ^v~4u?YSNEG!w4}xh` zyXrR7QkU21^r=CxFL^QOq)|kEFsucHvWyzau)A7PM@?-w_Rk zU7CYznUV&8Zs3fe4%FN-0H6)U-LQwgt9h9%tXD*!28}sg92Wz6aQWgPwLeFBl`TBi5T2kT6bpux%tyh0Mu*fDy&CO^_BsF zlI3#6ke8xLA=Ixw*IbHwyxx!_M)en$u26hvjr>yAa@;Sg&q8r5K;a|x|F<_~yu z>1mj|RU}MxMk8*IE5s#KRcbOwxAi;RZsZ&-uJkgrfj!mT={`pktswdbsL9iYiX3U{ zjRpN^oOG3ORzrZg30*3uKZ^L#YHVeIj(Yg2OK~~q_aU87rzrJywlIh62|B|8hr=y~ z2auH6m9j(j`Mt4_6Wt8Xj>OEu#G#bouz~>cqzd61GL$%kU)=6^EbQ@V4jB>9a$Qk3 z4U2>{A-aX+ilmtA^}5hxpqQFq{U~m#PfeAr-xK#ZqF!BQ%dSUJYJH(-I2=OJROMuY(2I;fw+Udt zPsLA>ks=wir0}=Ip9I4F!7Kl=vUI-05_`HarDeQsCp6q zwE^yztm+-rU@V4KH;5{j1F-a1-CCmh(J4oqA&ix{m9nneU7~`}xAb|@3ytei+pyzB zhYX;r?R8_wi#v)i=<9v84yG2u9d$dP(OLp68VH0a6pi~L5$Ly^$4aF{%mkysVAxCD zG_I7385h-)Xh0(|G}IXKWG#hZf>uR^WtTS`_IX*q5E;gL?o)*a+IkiX|lrnF%XLm z4UKc8b;BqQ)TgdM!08h$Cu#IqaW>8438KJ5^#tf;q!1L7(k~{O?9(?shF7XhJ!wg$}$ORxj_{a_6PkDzcZrobJr1IbF1S- zcL&OO%n_D(t{{}yDx!pklF;Fc2ZNa1p|l4?+sL4R(C~O&(7`cCD==a!g91QrJAlzg zmrn&4+NG$B`ih3yVhX>pM#HGS!xMJUIG~VEKWexu0&xu5Mloc72+@qGP6!22`J;Ct z*wBV6lc0*%kn5liIGoWa`r}&mL^$~l6crbcq4mVVPG~+BIJOBzhYewLA{ujttgwc# z!~L+&hl!8?63yT~->0C;^vE8xtLS1QMKm01@e=wuD3lb8d-&omgFN62afW;vLX3Kl zzC4Gh+lUkgqv%Rt8Vn^{MHnQ+WS=wSLLY%@X{t?TrfjES{)7>YHU3gfM!YK!WOBHZUj zmw+im&Ndtigvy5RtWz98849|b4%E%)tWj4pn(8n|GG{DjM-zfgTS-95*=xp&8e-^gZyE)1LF@uVogV)b9O4;vJ{)bbdoSj z67a?X9$grqMV{8J4Xz*?L%9q1Q1yrau#jp(5JDd`Aup6-0l?~l6m~Pw`2(s`4)hCS zzKBP-6iu;?m=h<;su0xP&Un-v4^qF7(vDS>;uKsB=74&JDNP5;yABrC&kaIr4Pf9h z$`pB3((F{HCIw@1&|7_I67^CdIC2tu*;OxL-Y*6P7@a>os@gE&h$N1n7&&|nWg3?G z+lixtQ|+oKlp`lHLDa{qXa>phGsfYd(t5(IvSolQhfs_#;TdzgbP&=^b(5T^jv|<; zN53(ki3w)ScOvh`qL@^`G&ckB0)pz&IN^waBaa(Hqd26GDlU!+9SO%B7ftg4& zJ?K&DK@l7($uQNG)(d*78mi0aIM?ho*YXUKTwP(Z;O6Bv=2I}nUPf6%wgFU%PJqQq z9`Z=7g|*@p3oGFnTN}+gc|oXjss|Er*%UdVE>;%qX#TOlmuG>wluD*PW?6{^LM+%; z_KG`Jc1kLcR+=T2TWKM;XRpk)Jc@bC5}^3Y(o%RVhn?oL9H7cvi?f*5ECGtwEG>oC za@c8J%K@r1bj_4ZVMt7?g98<>S#m4MX~k$tPkT_M+R@0$6FT43*K;bo+;C(RZf{+Hho5!&Jg63va)H@ zfUK;THj~@T9~>^&PZ~Y?$d)v&Uy>#MOm6DJ3Bji)#b4<$5byJAF%%<78eEJUL6Qr) z7mlq_4A+CWNxSNZ8Ou_!b8-gF`q=gk1s4XeHE;fgkJ`ORNunz{da~rn#bvVomJ&jbzLWUs;RpznV#I#(luB3crF&v5x!voWLB?qbA|Yapj;mZaS#rnJs z5N77W_drI4@Eygdv+ylt)GB-_!b&KqdbW>T>)AFlbl#M>L$xz@84F}QZkAcQi`42RykUPK5i zw7{1D&jUXh6c2nQC?0qRC`$VxX*Ry2@s>#Q@ugf)BsJs9ap!^Jk#r3x$~Ps_P52(f zC>Ax8{#H>lbk%JD*`|N%Xhf+#GFGk6tms+3Q_8%6!1Lfzju@oN5q`=MPxRLA9D3;4 zkWIN_8p|7HlsES7l?NPm5iW5e@=vfE)eDB#m3(H19VOEl43#{qMIA*Ok2)$~JW8mw z;}LrbC>}YtfZ|c|h)O*M3J-EKdni}Za{%6fOoITSSi;Zjp~5;);u{u9ThgWMawRc& zRjRCoFQujM(&VMmY+fs2WRO;pk&X#d)p&L?&CC@ThS6~fO-oZ!s-E*s>)_ue2g`@; z@%Ws*Px-@<7o9!&yWX-3uYCLAU5$I}I-|a`{M^QCxBH*-UNoV1TyXxqPj27-*&Qn~ zPyV4|(#L^I zZu(%|GVIlgr93E+{x#n4F$!o7~>SVvL*Ul`@Ll!U7TFLMr{}6*7wB!h-c=Y1Txnq=pT~JNL;(e6uk{3_~gy z$@%rHi{Qa*4A~SGD7j>^bHXM3;xZ8~%8Jq;hM~wLZh8hvLt`Wm^V*F7sKJi~txu~+?kAg`k1}Y|PGU+jyAR5G@ z$a!8dP~{XCC`Jm#X)@^&CIeKi%Y;dhYI2`2*;6&4OF8K&R80zaq%c$C)pL6ju0Xj% zu3+Z~w6+R(ydVf;5x4b><2VVTO`}cDNMB5^Z zHVMjM9$T0@Q}hj8JYz6r${|NJQdu@Ab23 zb9Z(Y=DnBAW*Z2m3IbSVx^(Zf+}dGk9J zj24p^X;Fr51|L&7b+<-Srd5>BKo1iSji!udqbVh*L2xB1d-M%A89atJqqHy#fsf5- z$~0=(bdS|&3N@);0rxbuuz1GcwHp0M!u&9_p65~viibqo;qC|KU}{D2*x^osT@0At z2pk2;N?si1&jNEOwYYffaHqn~2h5EEXXozuz`X)Y1GOV~DA-o+o(J=*ff++B2Oc|l zRDaGE7zV_L$+H;ksRwSMz*4JdH`;Srp7Jult;&{XG1_xsmOQJ`9*Wm%^T1IvyDkqL z#mjwp;HdlXU>-P%|7Y^RQPccl9yn?^Kg>kvec- z9ys#acq^Q)DJL(zgSRpZ_rIfC-)D3SqtVz-^MBju)*?z|?V}9#$eIzOxOx7D9N*ff zWA51~V_a#xGAPhm(E4wI5@S?78^?-)wwdq~A80$CQKVB&Vifh=C*b7+ZB@*SnjR;k zj>LB|qX^A$<)A#wY&yPvMv>Hsj3Pdcqka^Z7X}q#wzKd(hEetSa$Ex_j%xxHWwtH& zmN6=YFUMs-5r2`i3}5P#6-g`box-S9_;TDDP+Z=Hpvavf>F4;8zl)?R@#VN*fjR;& z9~zp&Y;VJtLSG_1gzwRe`ZK;14<*vm_#Vb6{UG9a<8V+OgNVx5PH%*b6czNvmBB&7 zzz!wSQOr4tT0XW(ff&!sD5AM%C@KzTWY*F${Kbnwf7ua63xxV;15}dG^39ygvxuZ8mak zUe^z{^2nzughxJ=Qmt%qTdIC|>7JlwC{kw7e{}&eES7=)qnBk zEC2fXm=7YQ(w}d-`uyz+K5m`wPaJvZwTB(?+K8pUy>{~Lv$~~^mV}%CHe^A*!?&w1 zzrp+a>9g*cF!-*@rLSy=D8smuW=veUcR|d(?2pGTjomkO{^oUKu77FOqcfg#grC3f z=!4#SCwj;=H-1q3M`f6|;^X@_jrxge^}la>^xv~y{_~_I@BaGemmf}jAksK!SAj42KLzvtC^2$YK%piuLz9G5##`MqY%$U6x=6rm~)gf=c^R*d6oyx+3^YA4( z7aV#iCU~;LwKu~k1&|SApR(FNCh&Q+^!g?l0P+>Oe|206gj5~ z6F#g?wkw6nAXUyS!bBU4e@2*SL)8BeCfdOEusyh2gH<_Y!bBVDjtdh$u&rM`L47y7 zVeF-Xi!jE4TgnyMAo1Q)$`C06EL|-K!Wg-zf2s|BzqRA`r5e{C1Q%h9T%=5CdCWNY z{f6KojFF4_)`bPsjMCG%Y+PD%>z{&)Fh(xI7Zy;tp=bHfzdfaKjS|I$Fh;K7Fexk` zY4l92x$vhNSGnLKjFD>uOtc~ManVUI5FV3G7F>ieavi|9D3<71SbG%OeTC~R!9^G& z7j)QqxTyTnbN9IRCp5S27hHrfa?ymlmZRQjd~vPD^_t)!jFF2b zSqlrO&Y|a#@flR!O1QoiT!aCaZnR)DObQF$!PoeVLN)s%4g7a@rx&F&U8D`L+6aGJ zIx7P?$|%3h z>;iVpyB#=*#;NifqE_LyJ2k@T#_3ajY(Ehj+qed;rn170X$Y?m=V@WjweY2yHY$Yn zQ{&_)9Au@#h~!Z~HnSW!XvOcs0c_ZiBE*YyQ}}R3hZl!7#&OD*04OP^AaL@d8>e(Q zaqx&v1(&gcbmnf&c}$s6F}<>s9-8y;vN?~t#!3=qMcI=*=kX;>2atNDe{AMF{*{HZ zn)9HgN)Mn~d|6bD)co6x*}ntK4js;F%)S@=-vG0kR5v`-)@gGJXpqH2?%oH?7J;KG zSi@;6T26^56wN(p9#-;Z!TbSW1`8F0w0jMw#oskZ&^f?- zMG68QH(o0ox${dj(RbjbN6iNr)DpTC$A`i0L111NIBG+!is1E$moe zlLANm6V2VF_{Sg0R|C=fk0liVk6k>+VCMwpVu3T}Q!V~h0k;7dA1McT z?Be+j*j)~cj{<~;dP!FPn*{S)fq7NnjQLq}cLoVTU}jK&@Yvx<-h5!z3Y=YdgTUPi z%$NPhn+)8+=&6SA(qkvD0(LFHT$7DUFEuQ&reHoOFeHyXdz4{dgJ5ITgc}Qsm$Pte z&d37yO&++}kax(TlGKHl9_k@m$(soC`+<31;3%Kk;dTNuwiEz7xo|T|C8-H7J-Kj8 zOC{+By!5EJtT{`nrtU8#g!Wj?rBVKUyi~&wWrd@1{bVWGY7gph(~9>}SU*J{-D4$> z^2hd49SEcqj_SpK}yHtIT$OA{!fHr-;3%FmdEltYUy=uo;$>wXICA&mJaE)wyfhCS)nhm2fur=eB@Z0=?~y!k)J*;< z4;=M~U&;eV`QVd0aMX+!j=@LwSmjf~jmQ&sR311=-{bSZQM!fl#LdkENAcHgh12z_ z0g-47sV58ffAJi=Y10e#m^9SP#u*~n@B~IPTfE)uLCbvRE7G1|Ahtk zNVRwe(pCvEuimtdOyhO+?6>02am;u%T~B7c|LUE-`m2nqH(I>f>zAh!ZD^$ z_dX+bNia_+o@p(qGk8Y$aL6X|6E;PB(X?hCqE2pLlbKJ^L%u!-ZxQqGH;fA5dlKFf zsRmyMqZZ*SGwPy?dS{OvwAMMKH~2-xX6DBIu#mRVhsxn;cuSbLt3Va8rT<;b%p7iW zus<^dDLa03fiQ-ln>j_*3J=2(pm-Qa#p7Yn`Fv+TK3~PeQR{5ubCbtg3;VhUi5SO} zo*LJ*xkruZ)0tRm1i3HAgCf_RE0G1;# z$J^Jvqc<>w1)z8H>Lc04p*1o>Z0el*^XXB8yk#`JP zvip4z7X#Q<8(oAL)9q{)7^+5jj7$L)##_QRUileSh3_?Zi=+s?bD7y3d~alC^YIPf zEs;|AaU zUY2agalNP&XzP3x}f{RWE)AnXEs!Z8ONe+U-3%3sl>C zm@UQ9w%>vrTEBj6WIeW_t!HA^de+DLYOw)rK<~3kta52#-;vxh;^uoG4rfvRKF>!40%)EFd4HKV41;<(n5Ue8v(sSe8* zHuOfev$`KufcSmR@XKmHUH$e)Q<~=;`gV@R_Dg>wE<%8T{wC zWuVqG+ZFgG8MO*uj#~qY<1PfXf!Y2X-)2T#i7&_f64c|&?0S5kVARd{Qo0tgc;dKw z@t@-!0`(NLU61cVMv)E2JqhYrW=0j_3ygXRUkXc+^g6yA_YNpBFOojM_fh*eT=F{%&Wc1G=q3WMYJ0mX6qfqIwO9ssI?Q3r$KxG|tO?nqGYGh3SH zr$!vxk5$}EP#-a~Do_DXC6W(RkWsTh#Ta!8DDroalu&UkDlVhX&8^O$B&IfiX@<_$2lzBA$)j_)g;w}Bc4URzUz#=Q!G8dGKdOrp?f zjtpTM)w~Tw5dCYsMbf_b@|ZDc*ge~e*TGgYbS zR>C6|vQ;^QZo3?qB563jycMIu%H!Y!P~3ZzRJ{G60_VVM(0sR>T85#3@Or)k6qTSX zZERLueeZHwod?afp81nUGE~yO?p=yT+gecHyMx(QJhA$#p}+XkERMyhJQgP2AsPnp zT=zTx6!-f$P;>E?uvNrfqXi+$)jk<`1^#<(^J<)vg1 zSjAp`G@sn*UO(59NHf5W?4rKsdN;E@+y(W0#ad0P3fB3Wav1mZfuN|GD`6|G=P_y; zzBl77Vh0q&nOOwie=)OGe0i9t;Z(yUvYhCgVg+Z7O@Cs$Zgr-vZ&BDfdMo51%alUB zQ#9Z886?S$UfyLy;MOZj>~^7&#?|E7qfRJfL+{<7t_bEyrBgSVw#kaY3OH88wv6+< zM~woHlM_{nVx|Uf32PdtnlE9M98c$;;QuMiYz@9VPN&aISWuVXEn*93DY98DqMQq%<{Txdk!4s6s(~+MDbD&%#o(qSEMY1m_i8Er zCzu%(JGH`@#S4Z~xG{v#&HJc|{GN>?kq+phQWat)bUqV`d~WMi>N`@YmwLN*J%H*{ z>V5vW&sGc?dh7Gf<6b^%=d3ul70X$zJbxINNTDlYTCbZ?K8;clE`Ow~vlPAdF|0ZcwM=U4oaYJ<5J(<2?uOm_2_^<tMa zYIwVcVjA5NYJ$~A`M-xSQGONkK``&dTf|lkFJ)92zRMUj1K%?kCF6T0qbPTs#VD#e zNSi8BU8PWvFYF$&8-SN{QNsTW@9y(c(JYdPp9JHIh_`Ukrd7=VuIs|%pzC_bAKYutl}xG z+>+pNvi5eR+I6PfBXlpFh_-lJH_jQ7{J1|58^M##Zk$Eh;ZLI1jsY4VPOcrGMOX%h8{e6wY6??BQdR z7ruB$dHRlZSAKZ#$;qB`FZb0?KJA)?&s=@ar015rx@f`^kNvK>diC~mye}RvufA&D zpB#5SHsW4a#(&{Wq5VUz4Y~V~Wo`ew_`ZuGMHh8C-b^0Ty#9c%p1$Cirm3&L8@%qB zU0?2etzqfR^tzp|btQ|B-2d9Cdv!c~>41x_@4oTaZ+`N|rB6(my>QINg`Yjuw{HGl zcPyA5-#Gdo<4(TzgJmZq#a912 zAO2zUJ8zGA%H8$kySKjf(U#xceZ!ZBepYqakcam_>WuQgt(^D8AtlA*=DR;yQ8>N$ z+&9ZR2VVbm`P|DoW^NpP>x?B8r?32UQQM6u_w4zxmgG}s%J_W06Ic$05UOS`p7$y0 z@jXE4PduT@%edsc(6r>7D!IY}Y7~eHk84Cz&g8I#Fw{g)l}i|Ms}S#!bvHe;r%BF0 zh9Rws@IrQt-_z5ifrSy9< z%meri!Ta@+%b*icOmPek7ujh3N&S1zckGtr(=w&~fd0)*=R=>%_7CY!g$1+lr4U|y zsJEFf$=CabIx>X?v^>cTYJBigbcHnk@P#nc#1-OLMQ(G*=7Ei74E0e83l77Vd~xcz zGi%KllAvMkd1&alW(@Tj3UTNFmvg~Q?N^yG)a5EHASH)#!1eNo=k*vKhsZ9#D0!o? zX7<-5ro1tNVGv+uv!G-ACcPXU_5&DZ6}}XQQ}4R<&t}X>hPeY@$^mz`opH1t!~H|L zS7E^1MwP)Dc!5;-f z{x+IWKS+5f=kS44qY0^j%EK{h#owW->vt;vW@5de8NAk0(= z*U$n5q?jCJGNIul{wSDfCX;~4WTDCAN|VX+!lY1AByTfe_TUi*4=9*JO(rvh$v_no z5hi=7CP@?5r6!Y2!h~<`p)il8%*r0c^{B~Yk;&w2lgSmrWSHt7WrISoYVwxA?5COx zq#}oBf7N8XFey<@Lc-)A)nu_S8Ks(>Crl1jO>Pk;ho~lx3zN~R$qr#MQZ*StO&XpN zs>yM}MB5;>K$sk$VtR#%wn^v>VWOq!*9McxxFJ=fZ^i#ZC0fGY^Mp zVZlUvsd#OF_v_#A77c%-ZQ!CvV;C}!4kSeb4>!@vA?Zdryd@%Z5L_gOVaPyQF63|% zy_|8dHOk>y3US>j$v>+Lp2xCd_<9^dezlX zG87-i1s7qAT;(v)HuEhT+taFXoh7&kW8`8Q6w{w!C7pTH(epK~>jW2Jj9gUPYN@c=gfVhWWn74E_WUgB_(0=&LvRts$VH>^TFmd?bhVD_8^J{wBiD4sRfsP= z&n_65)Z7|P4FMj)7`aHl)lLKaMPu{J8dtgCB8-u1CgU1_FFjMn`q7zC(yLx@5yr@M zEKIb#G5Vd6uV`Eyf{QRluHzV&60Wx$e?rg|w=Nf4gfVg*&$vqPrRT#x->Qql-w7_l z7`aY>iMCnxy~T^~(cF4Ta1qAHMOw3#doL^QJ4@s06I_Hba#b;|{qd#e;cvq`G_DEM zyy78@kxPb&w(WJ@j9;MnR$`-Ca1qAHjW2Jj9e)2;8OY@SKs-D&WDc)F2WeO+y<_}$FKbxb*H`jT%Vp&veI7p8GKJS;#}Q;de(jS9MxSq|XJJQgnUA34E>z-2GavQIBd zi1BnLp5L$QM>(5(bWca z2%0yt6K$?+?2yJu96OX@O2-UB;+W@n%rG7_)1;3X$VzT^CKb;h(|*s)tmJ4ajb%mRz)m{~23lRlJP=>!NPJ{3i-!Lqm55 z9kJBh-O<>V%#5x24>&TGny>$YGt>V&&P@65I74mve<9M!;fyY$s`aF8y<`FJr}&$~ z!5zuX#WIb~WBJt%2G9N26#xmRa?;Y#oU$*{I)r_h)mE*XqH;DVR6^Ky*Re`uW+#B-Z9(mk-Y>=g{(oy~5q?@TD{vfWV*04ei zRpq(lcpwsU1|vFoYN9Hr@<`C>c7$;_OI2luDnBgyo$jE+5sV1&OaoPT;&LR4%j5&N z8(ze!SO%o>m;1aSAMR~;LFxk4)QPKd9e$rL8pVatJUO(ktRlQ35{cv5*(kB5(;BZ= z_61|^Xvh~3yje|)!e8$8`QtvnoAGPx9@*&)I77~$k_tveRpEB}j+on-1*5f0dRQzR35Hy5 zB$Htk6s>PkVR1Q%`_*yLZ%|%nSn{MIkRGmJ1a|>Pbr7)(N)HMI-4S01cZFv!jnY6q zx=cD44?Ci=<#H(*6}Rc`%44QhOfA(t{oNs1F>U&cDGX010HxRoKo7@px{Daow>kl+ zO*gzF(PMK0Py&OM`p51Bpu;dWccK`dBWKykB^Ial`++%0hqF2Xs2=O z;6z}4C&tof@q?8-8lJuL0POO|OHUDA4X4Sw9p*=l#FRc>dT3V23ik!fBbd){kb`(A zI99l=Fy9NSEk2_a7kKP&$Rg4MSaGozMI;^?__LCC4$Kb*=9dCD*aqh(8HZph4lg}+ z@)}`xDlmT%IJznXlVCh{@;-#!8^Am^fx+0aEW7ZYj(N80Xs!)UE_s`Qxt(U$@K6@lQ7X|J^ zV4!ue$4(xVkGa6yfR`RS91X%hC1Y8VgHZOkQ(-p~n9BujPyE-ytHsN76vQV8fMSyt({G@wX6|hXhWI zzpN9esQed%m?-sQb%G6=B5D6TaASZwCJ!9>XI36Kl6O)bIBL(%$P;%~p12ix;?B+k zHwgY)nFo%VwF~mVQNH|L9yn^o@5lp3@%K!gxaab~QTo1+2aeMBwLEZCPkfsvt}hQ9 z)yIWld~}ahzAuISpgeGt9^>=GO~?~BIZxb_Ja9$uUu7ORikD;az)`(Xl?RT}ZB`yQ z%73+a;7DG59=N@LJ0%Ys$!p3Jw$(SR4&iV14rRlnFnrP z;8y2>qwxMb4;-!Hx;zgY$-5yB9Lc*m4;+Q}o;+|AfA{Bsqj-5V4;-xsc{&f=5a8a- z14pZLw&jW2nFo%-F))IU?y;&T2{$|s9ChCh&jUy4Hp2>+b<*5YB%CJ;XM56I|HrzS zPJ)ZnxEks_)hA4uSynct^ca(UV78~)F*{b>;PyCceGOqxohQr=h|5M+V>@9>dos*N zflr9I8{Eq}674OG;_PV%*PkiZo<6;?vn!Kjn&(M#cO&vn|1X?0cUpG~mIJl@XlKp! zd(s^BT1xP;!*kg$TJZuRGI*^{np;PfhSMOv=ZR|@A*Tpy{ZUQ8!6LR&n7U^r?EW_H zG2K3S>l4==VGI<4ckuGF9Uf(7d7Wg@*Nw}i-d_X;iJwPAS11h-2M#EE-Lc1=A8A4H zvX!uX-CNl&jaTusRygX8EN&05 z12z(8Tdg@4vXzqt>eqU<=pqo&hZq$xs555~OUINcM^H>e5b=MH>O*#d5AJ%kNE zSt~oL`B7mT&R$+DWzxcvIO0(86}I@VUcW4<{Dmj=sm#-uVoveR=nG!uX-w)`wwErz z5moAWe8S<@K81CV5;@8*4h6ZRz|27zV-sF}QWwt{lkmR{FF&m=!6*m5DMro4cOIkY zOUL09vEzn#2BI&|RA++XW*30snd(YVJX5U$#WU4is@X%T*;}Bv4?YIfiMNEE?ZMsM z18xpy?heA2yD<_JNh*=(xE<~WofXF2r~$Q@+0qp|r!uNprI5HRTPxXH`OVJe&zTOz z(6adu$mAKGian>Ofbpz91=L4)i`W%sYSw3`Pt+UFpAvW5u}q4iB1E25kJ7+hl*mE@ zE7q^^?E0jz*RyMAvDCYq4pSLAY#_@bxx^K3@{lGX>BLP`#1)gcVu)k1e8o(ddXx)= z&xsf-Vnc}u{3~IDygW}FivM(48?Q=QnXQ&jPQiZp=0e zW@piqvg2?>z{Ght-9w^voYWtagClYDk--0`xSa?$H|p8w&ke;5eFB;b*R#>R)#cpARke;7UpyC|CSBj?a6C{_iB}eWJb~YAaDYh}sU~orceco`RG1Bz6=EDOu41 zicQK(JiaJ~d3;R(wGeNKM1z1lmW~BQhej1iGAPdB1I0ONKyePr`J5vOYBuAba=|&e zKyi*0pg0Frs+?mjsCvfnb5NY)Do~u`7EqkyPEfkEEB+src1Sa%97{o@j-(`=JU~f0 zc@RrFq}VWd$p35UH7mQ`fi9wH95}>j8BUTcu6SWh?XKRzz10KO3|bQ(Kng}L3_Qg~ zGitT=W;upt!Fb7L<$2J5GEcAsWNEZZO+c1d1JuMign4Rr3fEzbLq;%o#?M{2=$M~= zBXU1hhg0>9T6dVlB9T|;>VJwrUNvS%AnH6ipQ{x$x&AWL%<-*~`F_qLl}k_2TvR-9 zoM-3IOaC-WQ55+3Q!HxqmvWv7r%TwePMn&7|GZQOK{YX33Z^(Ej69<19>uHHYq$3* z%1*`lnF!r4)~jbf=^Um}Ce1js`>7ZA% z^y;*N&7n+Zw>xMPQ3Dhqa}5|P>ivI61$<0jaauq`{Z-Mok$vc^?6>S%MdssR*N-A)6=)hbeMxLVZ%ikGD| zpm@pnC8z~>`E}6LxR*%3!aZnuh3@DC!3Dj8Tm)BL?-&NdKD(>H)XhVFF zRERH^Hv$xwM?T{6>=Zfk`N*0gXY8+h0+;&ful%3Oi>=>TWV_yOWRlVUtqf|VZdrPZ zN&_0!%6v*giFGbFltYp?(gr6y1zXEf@hnTz1Mt;K#qr29*`VI3EqcOSxko_8Mu#mmfQ6-T9l{6@KXCZ!qiWx9bLB$AY%jK8N!-W)?zdd?U107*CD@phTxAp0RQOE z4*D}l{Mk-_hKN7P=!?GDd6fw>kK!n;FPfcK(Zxg9mHz!3TghJ-SPgC7ZO-kWc$;%SDBd}G1XKcViS#_aJb%6his#RFK=Cfo zhoCs_U!XXy0IqY~AW*y`v@a-*qkPSAM}gwFGEltxLu-E$kW?bkfh!zGE^!&9 zV`OjS7(6hxIp2c2pWJKL=CC-Hc&mW3V*mfH|4_cj)_-_jtbh&Ai&da_UL>7<_w^s1 z7qyz+PXFO~v48!C=f(c@AD$Nr)x7wh(SN>XF?a;NkK$#gyNddzX&nrtI8I{zpRJ1< zt1*6VaS=lH3f}CzLv=v5mQcaWzF*#?i&3wEhPRv7uZWMtTO#+b|dqYMw0%Jw{~L!Oo~ZDRVRi zjii;gNnCee+K@6(!2T>sEc;Fj9JES`N<)`2h$$JNa~SSm_+An*-pghEuS7Aw^!-xi zf8!C^{zu5+{~M408;?|jDo3@Cq+2U0#ptO1dYO_6F}s9Y^z@^cXv|tmG0m;a5Ta3F zUB~Pj%(l?{HnZvL=CjuIb(=h|lH1~TDb7}))xKgdbPqrTBk$Y#HhI{8^iDT<-sck7 zwOc)X#|`~y9S&sISF!&I8ZEL+0$=XhwV*ieMo`?f--1dpUh>;~yd|s$z+L+b{&Ux!1I1k3sBght+Xbqd@eagyKK_+R!$5J@MuXz6jRD17qkj1c zyhRd?S0xw+Y11@1fJ;F@an~H6IF9=2+%@X4or$+dIvHQ?S|cd#S_dfZS_Tw%jnL=d zEn?pUbM1Wme}K7mAt>(J&p~nA)u6a*G{VJQyA>37jm90hYwJOA*B%GOU84)j&cjH%@0mWVW02If43W~e-Pf)Ay7D@lcm%BC)<(Rv+A1LnHNKo80I>>b` z;}{1j!CadNibf(aoezq;MmtzIt_l=)%?;`T#v230T{{^RcdZE&cdZo^ckMJ#6iY?Y z5>VW=6`=meTw4W-yS7HfT?~r5b{VLP81Fhz+_hUlao6qz#a;U&DDK(@P**aJCqQx6 zo&)tTbM0kN+_l$L+m}~8zxN8|u+_f`6ao2vL z;?4ubUHd60?%L&`xNGY`ao27G#a;UYDDK(=pnlCVu62Uqu63)p<)FB0D?xGB)`H@$T@H%7 z_G?hwwVOe4*M1L*YJwu^9#Gu1KZ4?}JqC)qwn@c33yQn81r&GfZBX2`ZJ@YoUx4DS zeFKWSR)8tw+nH+vL2=ji1;t$}0mWTAP{kbvio13MDDK)6P~0^-YM8s`1;t$pgW|5$ zfVz{pb}}gLS_7!Pm{|v?Mv1jnptzJCP-$lNQ&4v^+$Es+Nbqk#En&9zfa3Btf?CSV zo&r_RsCPke$)AAYlK-vZ_QY@w$4vr7i(JqWgF2g0GeKR*s47s@dX`8YP|Fz=0(CW` zW`Vk#QT3pH#;AFqu4GgrsPh@s0%|p*QlNgqsBTcy@|H+vf?CU{b3jqMTq2zZ>Zgpl z2-F3Px(w7sjJgKYIgI)>sGl?HW>7RrULxHN>KaDf4eBaJJqW6YQR_jiVbtTGXk@ZP zqPvl4HmXE=0TgKgCDN;)E@RYNpnk!q_d#9DsE{Dv&N^iYs%Dh5c=g0x^)k@w5vC=^UAOPg_SF- zUs$$h;qxG>x!#9)mHUzN_~I*Ci_pyceuzpP0g8vh1B&M~v5zFp_ zS-wl^9@f{rQ+0^VlPLaz!{P!da&-~j5{X<*GO7&U(-gud%DSt~abe%;_i_0xGDF4dYaZSXvVP6AZ{UY{Z|&-Ln5F2=_1;5R zPE@91sN9wE8JQ ztzAo$eqynX8!?~2yb$oOHWXy0u3by=>Hc75)pyT&{ADC{@>bJ7E}CFO0b0oWtZSKb z+-vO1K8#mfhiCc2P<{81r^O9xn6Mm#i<=vIPap^C`d)$4xKc3CdocZPZXS9lRWPtw zyLtz>7D)(vyzfO!a3PKkR6Ijge4Sc*h$DM=lH7v^2NZJ#!nYX#G7ztGC z9(*FL?;c7ZWm3&_Umq>Kj_jy-ng?90wSNsF^-HRQ_|HrA$tp#){~QFRh}Flu#oG)s z-nwl8bvoV>iS?Km^$otfB|8XwLm2N7_%(xnVxqFhOVMA+jArR{f=kUZ7`5F@RVb;j?7xF zeZl=;6OBu6(0u(oWv*p-`6{;zqo^+8W-(CQI}~tEoeGLNsC>Qqqxi?KJG8sePZ`>= zxP_0mFk0Pv2!wGh2{kU={i&?%>FX{QB=&a<5gD?(SXpu0hl@991YN#8B2P zqi{9M+prfL;7VEvs08!-q4+j1>S%mh7&Qam`HXVn%T=ieDBk>R1odaUoA5q~_i4P( z;-!h!7xBJ?_Z7Ua;mzkdK&tfsRUhR)@lq9K_aG72(G8E|w}>6qauTB`Y@8|u^*%Er zSw*1i9+IWFn~hP-vwsHxNadYhIY@=JNTTNY2}V&Ia$m?QCPh+QHOrPtK1C_8 zeUwl?1%y7-Bk_MbGyA?0pRtg*;|EE6&O+iBKS<&W77};k=N2lZFxHs$Nr88rjnHy919ej>%FTZih^D>45wkuTpMa%Gnx|lhMvB!^)v0f}z}wqg=;QTW3bq*69Gz&J=yi&=tG}+iq zF_3C+$N9abM@mNy9*l15yW|NY^FWTF5{%slh41`~u8H$+kA(8eQetz;E$%1n3xKh0~YB^_7{fWy=2m z&ihvANHUYiBo-=vXD63ty1SCf-};s&9PXz5!&%u&lz;qGI(8bNdV-+j>A>Zg$=S;~ zlZcAUF&jqTvhwp0S3NQGlp~(2-IaZZW%iww)5qNV_sZLg#wSvDuIm2duS##;^2+=F zk|x#P`OovuEc@>3gC85%u_bt4V%YRY|NfWtD{5zt*ypSl|F~cK6WgC``uyYDH{O2# zIWJuO-CJ93Jijio;IdR@qZ%7c`!!`okZ^Dn=A{Op?U8ye+B#qqiAqZIoAv8yJn-2B2%?fyUW z`=5S#cKCQnnHy(IzF!{@C|Gs#1s4oI?@xc9IQ`?5 z^FP=z=&I-9pWS-%`B&`kdiwY|nHR4AWXaUB6K}cjuxp-QSu|m!ayRCTGd91w^_j*k zTW{YLpY_2(CnyO4g zwPEI2xBcn2GgsU{ZQ3t4p88GU0{OES-yXl}`H$9YIriY;y+_>ev0VRF@X5vHB|FFc z;h_zaUTy9E>%8lp9v@hL>`Om6<)DM!{Aqpgo4VTHOx$z-m5!cJ_k&;lEZW+2!g){L zE?@Ow!@5tpR$l5_-8JU^Z3S0$u6VuU%J(jD6~FvpaQyR6jCZ_v(MLboc+x9Z44RYN zcvg>l&a+a@i}h?@p!`fAwgn=B(}2JqQ1_LY`hWdcQ*sIpQ++=6ApS zaMIInJpShq2Y<5k_VmhI?>+nR>MKUfIb>SthB*h`m?*vG!Jn;Pd+5-L<0^kM{kBmR zFW+(EbUgq%*S!%F3`9C{=^M?{p00UM=+49)HfM zcMLtE;mi^3FCFkwL1XXOFUupI{Q|$8`0*7H=cf;!eBj}KsJIPPID7tIy$h5&9s}@N z-{DF6p?2RR-Qj6>7wA$T2jX4+*Z61pI}gd6-!@fPK-x69)wJWGQFeEM(lpU1V0v1X z%{I#!44cA&WAP=Q)tvv$HoLn(Z-@O5yi1Q=bBCH6!%z!P`l++H{_keYP=%yGYshrBs{J!>orKO4qt~&(4_Tj4;U=Zjy5V!z>d1x$)?YP^C0KbN`Gq$T?=q z7keIHl5-%#DB;?0-p8Mq=4O$W+A>*N6p_l>VhLpVLyst zD(H(>yO&jeuP?=3VFA^dB*q7sJi~~2?-(81PDz~Ls1X`1EIHU%BGOEBqS7p z5R!!?q>=1WL=X%pVGUw$C?cX*KokoqY5=7OB1#by5ET>!6$BL&&HsDOowBnf84#cM zd4K=+?q_DtocW$}?>)DdnW_9}*jf=DTyRY3pTa?~iBAcH{iu#`(>SLmSV9 zQ{vU$jnmtW6Qkph#qb_vCq2YLC)|aTomEhv_lu_g^qed=4lM=hG4IG6Ur7n`J~zy7 zZk*;K`JqaY>f^>qmN|7*Otu^588^;xH%>Fk;_Otv+&GzToIBh&v?Q+Av)_$F3)y;1 zXQ~v~DZVGVaZ24dw0x|WqUB*d=eQdufGQ4lieKH`IJ7*g$K2}1S?R{1Wmdh^FK!%d zf=%&#h`*~;jvL3}##!ga`NEAu%Z&Q)^l;;hcjL@=<2>)i`NWNL!Hv@%wXWXxXg5xw z8)vD^2~qR&HaE=IZk)RHUH$4RbGoW}#>$-fD(4=V(_H0jlsQ+coIhkvpvnnrApE*k z<>bnoAeHmD%xR)>K9M;sRE}>$p{JqB=_7O6sGP|%r?JX;MCPDa^hr;R{LeUai+U*?$&Xfzs!6i{1e~5C7;7?=n_Hy!aXZX`NMZ%v2EZG zv%Si}rU7~OyB-D{i?;E-Rzs-7h@M9^_Ql`+?- zm{z0&PUB1jhxD{mG0L|bHO?^^Lton#G3`LZ2sn*12^`YXTE#pqV>HeQ855vlLa1{L zr*X!ELwee&m?vb6#yJMg5Ma8fm?q6hi!+B_)!#wKDFUav%ITDt+_NXH+B1hng3jMP z?gp;@Ytq_xkDrkJVvJ6TwEOx{&x;z6CXarZBl^a;kg6a>;}6CVL%JaA5gcdVd*H6G z&j_5Uf;`;iWTEyg>#$(3;26V{9h^=o$63!!;QIRXrZbLqZ3d4M<1buD>mfy%fic98 zew8%~j|Vn|{=8Q+ry zt^d|{FXHIpCB|PQ6^_9og@-Z3kmi6xPH>#V69%qcj~EXU`dwKMV~8RBCF>C!XFY6T zU3j!FmJh+el)|H=0+yX=sH$?D_4EN(A09CtB=lNY4`YZSossnjjEJYZ-)Ie~2 zeU$FV%|B1QRg*d*OA$sdMY~!wzrOkI`No>m@3ItO^iotm_^RLE{`>5=-)T}e(bNJQ zVf0c|-)U0sZTjnPO)5&3B8*;Ys7~tEdv@>Bq(;h8gwacd>!f=AJZFL?HAR*pj9$vb zQc5@L>(#F{)ue8dr3j;!ieRaZIFoz5;gFX!sYhff!sw+U!O_0IUD5KvJ2a_JWGTYv zrJ`8s8l1_k3kzGXNqs9z5k@Z+4UT5{b(L|cn$*=a%>zdmy_6XoO{(MwR-u3puBR+T z7`;>sODXxV$?#PtH7T|s24VI+{ zqnASDokD2a@zq*QYPc*#7`>E*rIZ2Nqk*rLX;PD9DZ=QbhO?An`S@1lM>VMhvJ_$T zQpn;6p;BXiIqFViRVDYXkfjKtmr7$PC2xH3$KxMrQafcS!sw+&u#}?R)|Nijqg)-A zr3j;!O4s={?Z+1bHK_}-6k+sI87w6a&!oz;j-#4X5d0-a7`@a;aI`%C?usB(eo6>$ zl%)uxml~y$T3m4cgeDa!OA$sdHJYWUzeaAyvo;@1YLqNR7`@aOaI_FMJ<;l*CRHd) z5k@a{vra1U{N8n%)a|kqVf0dCbyDM>%E2H>vBo2^6k+sI<5)_m*$$t`=%q=$Buf!S zFEyT}6l(-O+{dZ?+9pd8MlY4gQcZ9sH!CpVCC#rRvJ_$TQWL<@Y}mHh_kU?p)v^>} z^io+Yg@&KqivDAZG^v(yQ$rZN)I@MJzj}6xLs3&~*jJV!j9x06r4+v!b=-4YlS-1M z2&0$EVJXFies7<0YAXw6DZ=QbtSqIZS8S6foZ?k3OA$sdHHoDZ%fH*@`ZHPxACsjB zqnAPx0&7q&ncSiyYc^|A8)PZM=%sSO@%3p$B5?Iy%l<->Ix0&MMlY2Ij;{|Y3wE1! zjzh{Smamqj2&0$E2S<|{_55mxC{pdO6}kwcmzu&-iZ!lU*mb!k6(vg%MlV&MlbZIt z<)S8)BTErRFIC7=EpR4xby24;HK_%%6k+sINL0j2$x%06eH%z6UTb72!U*0cG6xKq zb41mt^4!-euYJ zZEvyqVK2)qvz6kzr|RV-d~MXGUgZ_ptdp&!>h;9p;sU;)z-WTFaz^4(Q-cdt3PC{h z@}^;H7KaP(truZq1++IS+iEXi55$fpW#^R|fYRb(8-HS#If!9dL9qy~Ew{9II&TP* z!c(o2^U7e&^eE+Ptisk#ACQj{`^vK>$C{xc~{N;K6 z^lWKq)=X2h^T*S}V~R@)vuq|=6@520Eh0Q315(g5W(-oix6{4h5$1@9jL@ER(}bHN zO7jY%aGkkvdtpfwR$+oR$xqVk*!uxY-zE*q*fF@{F+-kXv7Fht)O_`N||k~9hg!(1Y7=U1tsQ9&aK@H zmeS%$c?AZnpM+|*G%u^5R(}C3&6`m>EN_MpUyBXp+~lOhT0Io?SFJEh?#!~h?Al>@ z*|fE?c3f#OZTqYhmzp)xR+^Pm-c(5vL`nK|d4;xip#S(FJ{6 z^f^<>m);WtnbJdAqzxB4_^C2O_sprwn>HL9`aQ9+!QT@b8~r`8#UlXjcXST~c)v|g z2e{u&b9z+3!`%X_)jfzN=dY^Mm?ks3xOhsQ)zllqq|B%pGh#5>vBu#M2XqL+z$?g` zSeS{&8+v70XOv`?lv=a%cnqcSONysE@vXVJLb#L1PIhLd6F}{r)?ROBX4;FU=N08l zvKM6+SZ$rO-fyk4ok9@}Ctok8wsZ6TGL&#QTw-xKYI-3$S3pfqy;Z0fUqW^67KBTa zcTE$LuBDRqSaLlE<1!R^3Qx^-txM(XF(8+s!BYroswLSR&K0r85L}9e%MXEEP5*-s z2o0_wxP)ro&2QtfuD()Uyu=2?&G$>!;Tnn>D|a{lYC^MSmkOgsyoU;=M!cv=sAkS9 znpEt)-q#S9QStKx)}>VYT)k;tUPeu;*0ZwTm#4y-s|DiHDoI!WFIn2v>&vJZJ%!=& z)VK!bQYuGJp}0hOSMM*SX7uF!CCXo(_bwHyoDV4<81r70clO?R&FC8MOOkZ<^3tnA zSFbNigL4pSs=-`6s}UQXXA19>hUtHFLyL<{8OmgWn3ttF>`=@KtK43u2q`>Mp482x z2dqt|uykdbfXCd?%w$-4MlBE*&-F6_90c-RW3%_+nNg<9(8wrLLQHHzeA2Kelbn*_ zeR%ReJS@CVc&DhCG83(_FgD3#PE3wSj*Cn(aTo#U&k+3e$tw%*gU7|g`zX(ghxb+` zqoPbn@sZI{mL!WwJZl}^$5sp(?J@H3KKvZHs#2Bh8<~<4m1IdyFo`Ngy#b|((NX3& zb9AguX*N$>g!d6}#glARu4l}!q=?8AONwcR#xqAGCq`KkEvA_oFE-H<8SX$!DM_&@u@Q;UCcCPtXA+DS9UT{8nx^vl z#t(~5jEju7nB+QC@fT)}vBXD3#3e>}^jE-Dzg2}{35oHR#9@hvroy};jhi?u!W@&F zY&PNHdzITeE*76!POwCqxC&Ffj=;Lfump=G1!2g-Y;=yuHcAQ;SoPRB(!COqz7f%p z38pg5lU@n&7ISn|OrohwOXOY&!_4O7q~v&$)d`sx5o1Y79yZKm)sTInljGxKB9mfK z(org03rFwdVKFI@mV`vyj!BHeDLK548bK7ZlH=kdlT%bVo-t9yl9DXZ5$5D5h?Qx^ zOEyKu#KaFvh>JAoYJ5cuWiuvfSaJ#lQj2Ndq=@7wlr)ogGlLq}6jQP#HYy<{KGvjr zS%V6Qj4&lfq$I>9L`9gCbu9VS3o0fF1<*VURdk%m>75ShZHp;7CN45M0yU)mH4jdR zC?sS|tU1D@fAfQifRQb+DG@0s?7EjhI02HQkTsLcDF8UVA3_C0#+YIwlPxjk*kLA5 z?~G7^$YaSCbAmZ0)}*~gLT+ei`5v#-D9y9Yl&7H33QsDq*~_dsQiGfN^y?eqQgmkYOl;T4%TBdoBSM)K%F*^kq$iF@jE@}Hp|EUPc1fwt zg`1R?5tTZ^g_)8Vog9&5PU{dt7C3|BWgKOa4;fC18aOr`FQ6$KTb5U7FThfcy>x7} zwQP#5xMXaRm0#eJSv0xJv_f<)k-f2sc0)+_kf`F4JnPtr_Pm0e?i7@i^muy|Pt2DFN`ssFbf9NUnoHfJdnzRLKPfM}w79Hzk}af5 z>J1?&C9p-_Ef9lGg(bAWOku^F)F^Q{g~Z9}OSa=SQ}jCG@Rw+}<@HR_PAJ-%DL!D< z78JkX4X+thKDc_l`r1vrh|&2wr~InV=Io*VWuIxv`#JH3OuUQDF)C!i7q*TgD---q zK)+Oe-p78{(J-@oVy zhI;bbhWOo1c05~*_Yd*HEmpXq?WMdO1hBd9rH(n8-{5&`g9(vg2YWv^d)NDU%lfze z>#@eeXZf{i-SL_~Uf*%*)S0z&Y&%{F+j`Qs`2^*<)pT3#!J+#~N;dDfcry9PRmw|K z?zraXcB_}IF5I#(^r=+8Czrt!c30{pCUTq=wfJ|gwaEm&K2=V41?gN9lP!IHsLrPB zw(_x}O7{o*>5i`t)z<+yw!ie;4el7q2-=qM9+5ZRD>k^v;o(}^pD|QVD=FvgB_>J= zd)7mt5StwpJ=()U6jpNDgW1;!1~Neiw%pOiHtcqjdBhJ46&%`(ES$obq%c$r z%De0ojGDkI=7<7OIYB;x<)?Cb$sF;Rx^ufh1>aZQYUy*nWhY4vA09W5r3jEqPhq`GBXTj8rb=GyDTp-3(Ov>uaZ;IS1llx(n?zg^{0F<-E`5W7 zYrW;Z+NsPa*Ss}FOm1M@8=VkgjvOYB7BH@)2@TYdYR}d4_#`sYG%PwQIwd|O+T<1_ zr|xSeHeh5Gm?lo@A4*QTsc+BT&i&Tfdb2%4`-Fyukp%T-r~6QE_R$|C=})D+1G7cOdGnX*j$^>IG?5e@nZ=>$)BF3B39m=QLC%}M6L7C} z1YXyKgB+RJlRj#ip9JPZk2ozJ6z*SS3`lmY&qMG1SK#VK3XBi_JoVn`DS|*?x;f#z z>FWzjj1$h2J_?!zn0sWLxA>C3ZvwMl#(7JRxxk$R#ufzvt|om;fq7HLdDC|{bbJQP zq-a)$R?KsHQ21U1X1k2@rf)28-vJXvy)QUDPRlQ(FAJDC9&uXwjt6cjFn@T&>Gida zk)%F2$m#vn^kv~*8ZfWQI6qu_%6}BTL%>|9MIW`}t+lXEx79;|D22g$=ikdb?=hD}b6eWsK11Io)2v&FfO|%3U1f>f`W~zPEzk+k!_; zagfvJXU$*Ye=TDeh!gAcV3+TJ`(4I*vkT=vpW$dTageJi|2+##RBFvQ%700~9FlQr zy4mm&*-lzKRyUBO)4)7FPUw3J9(%G&7u^1;NMMw+C)``OS-%*skjFtzpKkj6{1q^N zd&FtsBY)eKuqyTB&EII?{+6*d`P*))Bn`kpPLI?44aL2YGKPUTdGhxo@b3g}M5#d4 zl%H<}<`Eg^&EK10|2KeXW)u3F>HO8~*B$&Vz?_wFdVjTekiNEd)Em=k*VlDA;*5h_ zP5N#F=5skHHHB~SOuVuWM@{;2V2E#kiKU7Qt~U7x)_oQwX@JVJTzcM@(bFkNnEnAiU4E4ZBlOv`eCtA{@= zzFNAGzOlgUm2v)Fa1VkXG#}qu$3f1UK8o)tU}6?9%xn5~Mt&&*=7Bo|t`YvU@KLCQ zyBdFu@5B@r4su9FC!7|KI?xvf%&>(F;}`pQ)3+0t?`51fef6NPUIoSpi)z=m1enz_ z&YM2^lHm?u>fI&u1?u9VkMHBayd~qj=^F+41Hgn<3Vq)4)g0WO2+UC#=Pi9-1g_m; zN!o^kTmu}M{WLqj34XV`u_A$kTtgh5aFjjMmf%AYILHOy@PsP>|GIlHuE0UgTRceL zW?;1efm}b zb6CcCOJCCWComsV!Go(wU)Vz!o8chmP2WV^D*|S>jPn)`N{>1Z1B-)PO}Hn4Y4k|V zIJ!L)r_W@Zw|e6Ua92NyIO8DaEx%CzCE+oQ&2W(O7QT77*9PE6NdV4UK3IW!`+=GH zIK#a5*XpAD?g8e&69U%+f8O$Q4yHGE;~?iPd{lhuJc)ddgPb?JP_g*zNvwS=CsfV2 zHNb>FRWt5sG`I_Zx#3xX>w`Zn9$G%7dSlRY==0(r*BFO})9Qn(z#sHH)@X2$gL;AU z&_A6GOr?y2IX%u>Q2u>L#(-qU{(8{&C~(i$qK}&USApsIg3#s7&ZBU9Ixrv0IB)4j zI3HA&qp8A#^M)f!I)L$A%`mU|4^@T~4$K}IS5x@ftigBWaFFxnFLhg10Mp?mhIz$N zy*2`vtuoG=zqbI_crE&#ILLV`M}*r9%#fEE<`qZwn+eP(GR|8(ZU)X5otW`B$a%x9 zMMhczjOkT@3&x+8Pbn3I8;HMv*YL`79OS&kBMbND0Q04c^X6|6a7|ywsyq&I-f*Pv zWnh}U!7#5lN{?t@-jH$L!uJ4hXMtI`zIJ_Y0n`0Wf%B&CR@}}5=D3XW7LP5!wR#Kf z77lXW>gVye*ZpneeH`Sx>7!!%4lt89FwCnyswdw7CgvT1^OjFn;`Uv@^nAB=+;m{t zy;n1i>Y<4;Mj*Y{YgXXwGPb6A?KXq@ZU^q(TJ%x9wiK8)RU&jXrEfYgpU60G>9G}R zd^cj8f`eQ`99lWj>ib8*@4pEaco6PK12_s_(`{(CaFDAh9>al|T?>x< zy+_8dLYzE>kNkZNxUXu_N4Q^sX}?`)t0{bafXOm|vjel-0PZzlzA}LO6`1xP)*QY> z-0lO+JQ?SYYfp9|+&jS3-y!sQ!;xLgz)Y2KHQ8kWFfSXxeE`fE1Gu_7(azu?=gr^V zxMv1tri`Qd##4L=_Yg2U4B);8=IW0i0Ow8LDcl~8N)!FyoImO0Pb4IR~Wzr0=LQl?k3>gFo0_d+_wgBk6=PBLl;(liXxNCsxW&lU!dYAzm)f34Ea1_1~25|L(8*Knb<$9t)T#iB9 zBm=lM@Hf{0j_U1s25>>Z%{PFf^tj&ut~qcI8^pa}07vz~y9RKSzWWW}s2=*l0InHu zKN!G~T`n5HQGFoorIY47m7@l@-O>QA32-3>aE*cMVE{+=8)N|23OJJi9HrYx131!G zYyd}gxx)aC(qoAMTvOogH-Mw^vC;sJ>W$Y7;3)sSYXC=f`N#k+1h``caFo7&`*3n{ zp7I}suf72s<>%H0aAfBm265pAa1Ei)VgT0&xSI{&D8EcLfNKui6a%>QTe^s z0FLxMX#hv*`>FvP#p6wbxSa-YRL;LNfTR5KyFpyz{Qx^TZ~3&N0UX)6mjN8*Qg5C4dAFg{m=l8 z?6Thgj`H762655>fSsJDd_ek|8NiX9I~l-*0N2L=j>=oQ0UY_8YXC?2d8Ppzw;u*@ z)Gj<}07vmyX#hw0YP|tmC*Zakz>&Wv4d5uB{%rt9<)iLFoSdAe{6gu`!T^rqd%Xc1 z*}0DaTzlXK8o<#w`DOz+>c7l1fV&R3*#>Z3fP2aSt~GEU8pM5V07vQehXEY*hZ=m2 zlauq5zBCVajR9OM;I21-qj`oQ25@bFi!y+td^Oepj>`EI131z*(*Ta_ywCuS{C(H} zj>^$925{u>8wPL`kF5r9RNwD6fFpe;4B%*-{JQ}hwS#_N;N;{yFa3#M|O!cfTMbMgaI6dZ?XX#>6>lw2j8K;Ji*EKYK6pt5xdCwK+5|2>e_5kC17zA8R z@n{Up)q0#;Jjl+SfeDpy-on=oxM*M|7{J+pS>lRwiAPuHdm5NsGOnh0902Bo9_JPh zN{?TF`Mnk#+1cj^`Y<@id5bUMZUAP8E6zhah66K8#?=&$1;9L@$9as$GGLyr1xM+z z2AB_JoIV~DGvTP8b411{Jg#@0o>?aTdQ1>~?SlKiw`*L^+coHQ`&anw8jd9K$_htP zzzIq$Tw9n}P!;$<)ws>n$zOt;7tAkld59_MXwu{E{9cXx>Rgh`Sx#q5`Kc~x86%kv z`@m9ZK9{qC_*-c`oc?x;KOQw~HSeXXO7qdJ=8J-V2wJ5I^XaYTV}fy%{v6x3m@oQ> z;EiiknRGM_0+cHS%f5HPZ?Q3gp3M!W=?39r1W{T!+1n(3mkw(9Q5@|$_Gu+3xV4Uw|3gP@70HpS5{#UMd zl3TLGF``pIWn?4Aux(-6ICAR=%t!=VaVI!BS69`#5HOLG@rB zUgqMI-SVaU>U=o~y=FR^BihBDTm$O=cbU$~M*lSH#d2a$(fxO_-Y;rO{i&u@W2BtO zdRKw^PiDO}?paS?Q4P;nj$lg8m6YR5h5hu_7|P+&Rw}Kiuee^~B7pY}Id(DS*y2>U z=_Nj!{CIE7P3$MN?!v-DL5U(A2TBxarNFrsv~wN{nkZh>9*aWN9#lU2ay=+fs2m$N zgXT>^^sl%%FnB#F!*Qm1no^

    Ebq?tM=i5QHar-QzRu{@I=wBNAF+K+if}BbGF)6 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

    m7Hy5Sgn~c|Tb?!65X_qrtS$u`>j({k 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

    fmW)E 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℘;~fq#Yi9?9GkOv&4V?YsQ=Lw` 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%0D2bsP0nKi=#Ip1;|n|Q&&IS^0& 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 z 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

    %3`qvf-cM;GGA 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�R2(kx`8aF7 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

    X|$h8ae_tKWGDd!MM?>X?i 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 z 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

    bH2tqQaW;h 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[FMcP2&{8=D05jZy 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%0Ak8%&-9}(i0$%wbqV-f@4*k*c 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�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 qw#VaZQF8aCm`;ZRLwcW_6HNi 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Νi>@&gANo8;B!w5{kd{8AW$bx9o;1lC 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�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≀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%0A{7Xo5;X|c(o_0gS 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≫baQ+cixVz_j3eC{5M=)1tT71*{g9Xn*{K%E$UTC;BKJfZ_US+0nX3fP z-gRq?Qa$JH9 zK3I-4oWRVRzZ_;Kbw^C<77yDf+vO(@HqB3+eX!!>Ooz}*d%dVLQYXeEXH{&QWR8|E z9zKvdLy3>cLbD2V@$r`PS?QQVI<9@`3v)CvJL0rLl76l?U$}(_g{qsZek_FddxK z!vpf?#PsC&6hHseLBkkcGKOxw$NL?8moe1qZ9Z-c(L4E$f7$Q1z1|plvhSZiV+^VH zugw@kyLtcP?Z%Mfz31?!je*{`K4I+X_fEXu*z;7p*FR+Jalha6C1a0z|I86%kMsS@ zuQ2w|`?r2qe}DLm#vbSUYY!NE{sp{;U-a9C=X>&d#<16W=^%#45Apr^J;w0=Veh@6 z_Zv^kyV5ZB?)3fUUpDssh`je*^KL_XC)bR9Pxk$R1!JGr`^r0veNXdy|LC`jUA<4d z%Gm$Iet&Gv*#9)V54`YMhV{Pnh;g9T``E{g1G{~nJ!~BKQGI{iFb+J;?~%f$@uc4W zCT5I074Ogdp)oSZ`)?A)$p6RQ*DUWh{#o9?|25;9r~3WHCyZ+beShWS#x;Y!|KZn- zYkm;m_rc-2jK1%&h;h*C{j&EO2Y(pv`7z_5*Sq~9Ril|?vylCqeqHmfcF_;R^X zt*o1&&~zn$mr*WX*w`>b!8Q8j`!Z%{1Fjl}<7T;FT6K2C%J$4vSK5tc^?19sa(2Gn zXqmG|`758|W@p1EOX0=%W~*`0433+r6y+xx;L1-nZoXAPCVp|ii)WNZZUY_oPml09390xj$+>B>prF1cpHxrfGdUbVnvQ?j* ztgNrsS1PUQ?Btec?d;@odu@%=C7sOy0!rbNY3j(?aRl!}A9 zQp&hs*qjZ7O<=*9P^7ctx>5^(@$NL^KA;obpc6izAt$KpwYg9iFvo-mkKv|Pd7!LZ zNTP8)d#aSX_JkA)8uGcrKTI6xi za5%Dr!6gQ3w7y<%MAoaDs~XsRIGs-Csg!7aV+#X8iv@Qo7ep=!q}{5fD$O%G7`20l zKhdb_8K8>HnY9ULj(0xntSn8)keLxrgySJQn_5+ z*lJxYpI)yoSJum`)%9wtYMQ5rk)EV#^#q{o%jNL73*#p?svGgm$}$G{iE8ESQf0ke zReUitJ;RLAm@QRS&Yp@cM;l!=MUMmmRNmqyP}2|S)Z$WTe7sekOGYNfwY=uTCyz(a zbmW)9i|Z$t^J-;kCU9(3Rcd0jdTe@Tb<+A>J$5WOH8XAht{kfb#vQ+x0}~TLt5Flx z)v3v~)ngXCobc@5!Ku(>W!(NfF|``32JPR=6VsvP75jH}d^J$D>JyrflZl#OC#Jas z1;1P!Us+yT4t9;Og?fEm%r~dPJj&GA9ybF#A``Xsbq!}gSGkbKs}xzBJ&Gx|Wu`!z zg02?o$wuX3bEUGb4?#}EGt<%KS}R&c*)7|0i zR=w0}m`kb3<|+zI7a2r{JJvNQ1v~NMc0uNLvt^p$CZf4yG#1D3pPkX>sYuk!C$FCm&oR$#iUu>Tt{THy#=^db9OS4oD0v)2JwYY5cPOyHfSXTD^BIZ$x<;HH%sV- z7FDW-RJG07$@Zqqg(lW5;x9ws5+Vt5+)ZP(}&yy zJA*t|d%aZwm6m2a$7o+uEN3>r3|D~(5-g|8Q%S*DOH(93fb~$F<|`XpZaR;|Pv-Ms zn$P+`EQ*4NsoRhuObtOPn$LzU*nHjzo!)F!Pgh;sF%nPfP#_RpTEUdXb+mGI=1I^4 z)}mZ4*P4}b z&1!W;8&ePti}6f4mPkX)oSB_$R8Q9+H$#4=QL?g9Z8q21>liaawB!sF3$rN@qQ6A6 z0I-N~AX=9MJ12|wDWhEIE=5kj1CELy5l4*{F2EB;GvqNfY@F;aP_hOhf-w|Hl4T)1 zTgc{8xqQ*gS}bBB7fa*|(PG>TudZ65p?EqKiH4&wCAw!_qWfeiR*Xb4g)q7VVw{z5 zIvOrT(z#>=;b3LWsvQ$cB-617=r3BwDyvT1MpSFM5RF9=*+|Kpt8T56bfaQskOno$ zht1+vwNYs~3Yv)*BQZ1utPx~Z+giV9r2O>Lz$| zU1p^*@o3tNl;V+8DVIQ+>V+*#WxU|1oEF^DP7lhiS!Kl{W+InMq~g(%iRp88a-*^d z{=6cZ2)o=u}~={@})$ylpQFk1KT+>6HjHr*+kev_c$%|VvWjqO!ACb zHLBDACSl)-qXFfV5Qvf!jrvBu+Nvy6Fz8h#%;!j|01;C}A)k|rjznUCrOOn><%2;U z4XtXkr6M3wNQq}z@o=G1P^)XdZzLnlgWynsfZsRGju80;VPk&pUI5I8<8fXd=z!fk zlmR_qSwhiJ3Aq#^DZL13vq#I#${O)k61U407L$P45)qmy=0iqPI1F~<3a9h|Jq$Cq zoY;s%M8QoX`C=lSD4A>CYwr5`#nW|A^U8W{OHx2dglV-#z9-XK4aQAfP|VAIB^oNN z*J;IMD=#QHfjcEjcY@UM9VN-tJQk#)48Kw+iEk-hiE{Pxx$3#91$OIzbaw*@RHX>kP~BsG z_UJ-ARfoi%GUJ=8waO-Qi&NoLIFdRMLY`~2(`G=*-3m6X!(vIB?t&E)TqIJA#q&`! zX*DhwNrw~RL^@_B?66oen=3>MNpsE)0}qF~34_d`)Jo-(P-~^Zsx7!sDw&L=3-LVR zJ<+5Oo2iG2*<=hk=gdN}5Vz7qawg_IsLiqkOfEGN6gMyx(fqQ;8kQDuai{JpmNlc% zNGVdn!f2t=I9ICivb;DfPpGd%A(`U8>MW$P?rxot`1X!yP)1(Q>dPYf zuxOk%GrEbsTR}U2zV`apyO*OhTBH~u<)jr`GeiQAP#XoL`Y13ie+T7vK+QeS(m+Va zfn5?3xoQwm!H~9~$*8t4!>nrDEK)Gj$t3t$&QFmqbrVh&h_y#1jvWL{O5WQ4db_pN z245uQzrAFLrcBa!MDtm{U4z;tCtGV^^ep3soJ| z>L>-D`kXs{BE%~8JQmKhuSJZ5vdCAOXI0-Z1-i2dy7FOmOd?+wErKC2JE}59yW>fj zip+!%ENU=MIzjK2a2v3KRf`1@`dHG}1z*!z9MJHw1YSLq#a*?CkP8c?T_PP)4w?ef zvCiPE=mW}gsc>|sX0_#nGnB=1)^}s)tVf=XJ+w&H%oL*WLJSLAr7^6mg1}bJ)JQ2v zYQq*U=^VPltci7X0n!JnIV!ZK1o6|Tvq%z>z!rA@Wa2v0cCts6c)LbzknvVm58$p% zuO6^+i>oihL|=$d4+yb~wYnN5tU*i?i$&Sb=+@x)1obX`5rIO#(GxNfV><2+Hdto7 zf!secR`~S?W09plnA*_n4=FTHkmPCqtp}2sMwZf0OcVPEV}ryRW8gL6r3uMYqU+U4 zqfbV>@g_C~UA@J-4b)MhS{^VF=vuie1w@ROzucdV>ZZH%vHD;YGVlJmisDK@_$y&+ z5i4db)+)q7Hl;@Oslw45c1$7B^~N@#LPN4(t^=h+wN+11D%O)@Uqtaav89Pk9DRGl z=5}_?`hv>sQK@&dvLF^1?q8&2h7Nw|Q=kHjRG>Cm@)cLHZS+;MsZtqEn|YK;$AoAK^SjC+-hscPV|9n+e~s%yxJ_Dpn_J>gY0Ccy#9 zmIGkUF=hIcZb3TBw*vJVaB$Z&;gd0ww#9;&kLi$}Q^o*oL&kFQ&}SJvcc=U&j65*> zNy{u(^Q22A7`eM`t??l^a}UX>jGhi(a%4$#HWa6a~GKl5v zU??4n*+i~L!38ULJe|vxBFV4_)`}c2#ItcMh6|LU=qPr)kSs=XX>2`FR*r~?LZpz3 zr?Cmf5m0UlyE-<2D8`C~XqGk3NTe%1Q_xh#^4XNR&}iF>@yS>woJnC>gjMglbCa-;EX4}gkd)=ia%RC%oqE<8Yyf3p55Y^J*2S%=u5Q5gRxt*nhj7v? z(3V`ab*3(tRZ3~la@7ZWhNWmUozFz{g*Y|~vF_g7faY8!bsBUOO;VgkOBwVPHlMw> zOt3Kn<$DEL*y@IO(u~BD;YhTQfsS6qhv%c|^z0<;aqFwRu~);>X4BsNE19K4K9b89 zKt-U9rD}teqSRNx*${SiWG@RdiwewL8@z!=Oph1%PNR$oNb`d4$pw;MDzGpQNE!o> zq5Bs>fG7cq2F%4x{PL2L?_$-r~H+-$AZ>g6pM1+>=6 zbpdCZ$IMVU8^)Gh4=BVoH$_57!Mx5-)HYY+7u>7;(iF5OB{E86Y)F<)>&2xIKE-4K zUP5i4*&{$WvpJp$=7}d@+PN{D%q@W2##tN}dlbodF_tJLF~scE{Zu{*MOO^lZ$w74 zS?q{}fl(xqil(!vxJd*-`v+|PT4|ke1EwQ|2<;qjJ{UCV4Yfy%jE}~0^y%I%BI}}L zK3B{~%(i3e8w*1a{TgZYP>x+!*yR=@iDW7VH6Yg(Du~r87D-TwwV*4Tom{V+e zU}H%pP8P4iHgY1Dj%F}0Q4N>_<2^~c-$?2xp=d_K$#6Uw6}k?#ky@*_Q6Hfo#OjSO z@5DZ|_UI;F@ke6lP(@^7wI~vx`<+R$*dSFM@6)BwANb@3p0i4saXCt^5S5@{kP}j# z2rU54T&gs%(bY25>XvGw(mN}pwV^9*SEFVFT4GCOC4@z`h0|)s)U0p!2BL*hArekS zO{L?o5KezTpB_ZE|lV_WX$e} zCfnudL@av5PKRNEjSQG-IjSjY2Sb(G2CQX(PE}DmS=NkaQ;|fh7`7>M3ktVJoecMA zTCfQwU?;;CO(L3zC1H{poy#R?PkgnF6tklH6dFahfCDR5f%&zR&LpE`$3!bKuVR>9 z1@mznRf!f%Na>|$k;jm2AGU&{Iu)3T$=2DlZkJht-Ag!}kAgvKmSqjt*RYU>+_0T5 z$j?d!!?I{90hNE4WMps|bhm!`MYU4j|BA)TC`=a8u<^19CSC+luhntj<2;wBk~Zz) zU>}i>ri<}Z0yZGFX>tR-w|N!_u9I0a52Q6Ls2!L=fvH5am@meob{}e^$QoOD>9Ux1mHHTOUinDmBcw_p>Gj0Nq0U-g)$u(QL)MDX0=gU5vSlp zrCSwlJ&4s(3n3}?P{>fXL3X08i?B&uTc?8f@DuM4dFDi=IWv+KfG(j|eq9w?s8eTp zRx7fTYKeUGO38H$SBdv+N{(#xiklM;F5jm;EaXyFb>(!DvEdA`T^S; zZ~Y+$&Qfi^_0Ljmt@Vd=?5_0(79&LLWa((MmMXNF9KQhOvC`sg8=qAOtuBFkpjU0~ z;8E?n@fMe!ztojtnGwN(9#=Qfffo>Yxxkz1fRQ#$U0~R=kHOSdP-tt8PU`B#K+*$9 z-U5-!T{jSoDDCq{MneRQ7fU%kXWa7Hdhelv{+cChC;0KuEkW0aFdm#tAIX==1;<*@pUN+8ZvU3O}jA zVKj8t&mY9fMJQ|HklLfkOw2rCQ9v-Chp3xPWGN&a#Q|rA^=R9xI>udcIq*$P0T?klx7?<`N4Q5ywiTpLOtGI zhu+Vb05&S&@FMag!y0@MY_wWi*MQjYkz%Rf=sM0bRadV6Fp(Mx70sZMaViW46g=~y2B;an3wLZYYHRcaGWYN8msgB)8o@ClNI|&W_3BRGPMTB2FsJx)fwyPXebam7Fb(d zRtFVAfffCCP#E2TUSh}FIEUBRB*BAc0DAz@m?IR3{RS+CGMQ8=pDUS;BuqPUP&$IG zoU9S+CbVu~$#N}PqoQLlovLi&sE!MKo(^$Z)IpsPzEEq1Nfpoys_-cL9>9WhyYjRE zPlOu92A1YnoVLy=TVJG8?8hgig8_*Cc2b8c4Q5(wLb(Y9cJ$B?bhW`EU!oOw!#Epm z`85-0Q3NLHP#_!Sbvlpet^xP79EkH6%Uf;;iv(?4D?*%{nVOhhUL^t&NO5qLCBdsT z>KRW*F?FV~M4216*wlC?S1jZ*SYOOd*n!y$G*7v7#GJEFn2zVr;l(Tr+2-u^c_@>| zVc87MndMs-Ld4@NHs-367io0?pMb@s!oQ?n?{vimHhM7q1FgKX?J5jr-HN-_H=vRr zBEqB@S@5=6Qd;}_X!Vjc9u(hPWA6e%gzMegzThz z3GHsbcS4AY3J+ZgB5|u$AvA*q1HfVN+1}XfkqE=uMq}C%BvoJgRnNP$x%&AX7Ue2O zaakVyKs2#A39_2tL+XND6r4>?ISkQovlsO_IuAJqq|nS}u%eZ!>YTX^?Z6LJhx|kM zVZ|xuP$x+EKAnJ6{1+&(m4GRQd9Zbi&(ZJp1U=bgU zA$M-;tj!;^GE@o7Y^~Z#nY2}{8Z-bBg?9)j|~;DkJ8sO;m_w+iy3=3P+rkG@1@Y-1PVrXu*Y?ZVVUTh_@ z2T!z7Z#JQAfdUs+>BNw=rudEpVr1Pd@dWp3PVeM6BjlGzQG*kIcBzt?s{z=}Z6yXg zg$#n$xk#2aIax6*J;m`q6+00JosaDru!RX+K;S(%>3A|;@3=p+ni46q%x zb}`XtV+W|cVe$jMEmn0Rv{Y->ma&0``B@0XQesnS^EC({7Y0fxK|N?qWkxjDw+`v! zX=jIWe^?ousbCwjZx)~k_-X@Wueyj{9V9P>Tb#U?T!&{D_@UT3gVCU60g;aSNgF<5 zU5>_=u=XX77<3-hBb7&@1q_@bmdxvwEm)o{aL=8>3g$#eg>tVs1^}HA3qiF=dTB`~ z(`(`sy!yRn|EA-Leu9$Q`-4kLQ_+@OC7nb_FqNzO+a;yBbFp%Ry%~CaV+$wLYB*j@ zBx{nnPt(GIhzOcX<3Sv`q@E$C48q;gVzk{jSCuS>lB#im6Ys(yq{%Ltl&&-2g2&oT zoLmdU*_EYqa%tBEe9DmoQnxCA7Hzg;B^`_#;SK1_tryr%s^eWJY4+<`AWW@AvxD3? z&cF(ra5R{z=sK~-i0_rTw2Ys&vz8%b6&s1e*+Mu~fQ@T`w#ciS_4a9)4)0)U6QiX6vKMPCV>69-_vX9*0lef0HN-S!ok|kKw zVpHF_$zi7wWlb(ab9L4}C_@$Kg%Ds?ZH2+Hri~UYT%ITFi(SW|6gwxc11bG#H6a5PZCd9Br5uTNZp0N+oV@dULgUK~D+?A}X<^NFoLd1wPD*9Tj5bDtr}kxXl-BwG}&{ z?467j8`NAf+1tQoqn<01%ql&rq{$W98pkxlIs?|`a-m25yB%02u`?bEw)>y;e==~Wcc|*usfuS zYKV1v`biK+SD<+x6t#><=?idxH1?1pQHcF4InWQPr3IeW;Vf;{(b*0-bQ2+caSJY6 zoG3@`UHxa%vMmfv%&Z2Nr-PPPQEVl#%%Oy%(Dcg0Btq2hW#v^=sf}XkXttD3rcCw~ zi^-mMI79ga*#N`NGYdOwOW8jejlv{6K`wIGiMIluOu_0Xn~f!9)2wiq)xot2EYx8= z25M8`Q>k<@6OL!IoINbC?TAb|5C3fi6tGpT*ePbBsXR8=i&64LM4L=@)UgPTK7_;A z=qff>;EI$Gsq!PghH?0P==6RGA92dM&0&TP zYl28LRVYOh38!y20Zg`xWB@=|!*>xPoIUZvAfXt`z+So-@lVOL(Up|kUc^$RLLU3Z zl)nwdHf}5RMx(t&u7gnCYOT3~ozj|Z-3Cb^1p_tU0oHZO{=w0@^EfIGtA;HYYO#%k zg+5qD!j>ZzCl`yh^&i0je1&9EDiG$QD8EYXhNS-r7&jIR5jdID(yc%;p%V%sp=~^9 zrHh5lOr{hrOL#?yctUsGpT3+2a6^x8&9VlcmdUhMJ7&d0fLr9 zwY3^5>;x&AMN9yNFph6o&Ih@A4$3N-$s{?d%8C6_pN1Pc91&XstCs}`2-G+OQn{Im`O&lqnXYo%@Qoe z*}~6>Fqw^9_Gnse!kCR&s8K(sL6&5w5XGEb@2sI`-#dXFnX-!6Hb^1Lvs74f@Z;Q-uTxXPS~p5!?fx(o zNR(o7bSc$w@CB@59!hFkp9mnetsR7eMtI>|H4|{cIY%6&0fPaVn_MM!XFy#lc-my7 zm`dYNOxB!FzbcN^eA=S1$v8a16_VMoIS;u>i<(L&lBGm34g0WSt~jU1fzK5(1x&r{ z1V@WQ?gb3zXaQ#~mY}tLl!{+E84KGiPy`hxDb@m500eel4a3ORvUd>X|Z~5+QlF zE64FX*qsL2f{o`{f7oVwS(v&@f1c(9IH}zrqFv-@L#?okWlp5%93*K0%+R>gzcTsJ zrvqS%X{sC3zCHl3D(wM-j?pYduvrVA^~<+;VHbfpOESw#h;7wrs{M4*D~y2ubxt4-m2dKQku z#IZcLAN{bIO{6mUB>ZVcS=5Bghyxs~K3hYR@r%%lGcVXtwT_nRK482Ws41{)|1bSP z^&Z8N&Y>UE5uq1BacWFxiEN~33A)|Ic-75TsW};d&_~fdH$D5$PQ0Yo+!Z0K?WL)+ z{r`B?&aJ2GSsOR7UL~(sSub~#jZhH-|1b`p8UFRO{mAry@v7ChqifNUJor;ANX@2yDkg{I~L6unO8A98kW>K z2-cBNfr6Wo-q1Q2VQDpcw+A9x72}Xyzp2Gh3a%kf~Dz#3{yi(apHBy8`=-yEdpgjEykGm`(ELeG} z{S~{=oz$pbYE>I4`a?v4pOy7x2%#cuF$OhBp6*{k>o zC-%FtvG+}EC!JkDl2?)V5zOS$B{)~dAs=A?t%QNDM9h%9d}ww-dd!sGZMG(;UeRh! z=qg5}23z+|?ZIigvfws3n5+Wu6^ zEPuS?co)Ve9i!GKPEIa9v10RYc1EkOP?uR6qGP=x^SvUAJtFxerWP;90H$rr2Mi;X zs{{8aK(|jETNi8D3YtmD-_wLw+tRF!-wbVn!yx8)h!A~S;<_Moez8z>{V zLqZ!*!2&tt?he+Vt;w%Et%b{pDyao_PefXD*X*Ok$|=VqY{DZfq=j*9gr{9+Q`HOr z^)G3^s-~8RVxb#^#uqU-jS8KLQibCXX&z)qG-&CN^~4af$*F);DwC6Ep-i&C8M#_{ zw6P5dh9jsrkJPgP?>^yeQf$j*;Q%RKz>QblrZnhFdof1)?b0XFDTY#Kqk$P-=)sn_Xl(`v=$GLOq5V!a^fq zJXWVHgnZ{lpkwC%-rIn5B!-tX@CyfKSudQgoUKwmxoTxi?>gck4rrN+Rt4|Ed56J* zvrBhoMh%erl0aH17KeMPf)CcAxt^WGH38VhBV#@6=g8}D=lLSP6P0snz+z&g4So?W zmB?ZW2Ahqwg|{eEPX^s6^ek)uXdQ<_VYKtkYC;{FWMsL<(n`^xkS8I*t0LgYt_rYK z0m((;}8b9jwV2EIHG(o{tPA!Fn8*7Q+1wuJY41 zO(!A=cyfY^E%QWp$=YrS6(jLTE>_Ip+RWE$*G*3rO4&jjmjar&K~&#*5998gNC9K6 zBvC@1Z|E9h_(WY{7xU)o&*h@#(;NDIgH6)L9RvNLXY&*Y;z*AK?SIi`^ zM~qD-;o*uin4RG);6!ZYOq*Qh@UE_%68=Ep?k1B;!$!jLaV1mA3i_wTH4!9#7-_>#3g&$ zXeA%1r9>i9DB*rc5bf+SHe(U&R175c{pB2R@d)f>BgITQ?wSW#=?9aP6)5WE$RTw< zQKF;$q8WprK)W9gJ78T{;By~zIbL@Z%^&Xc0{@IVYo%mio@6?jb*QEikjs;v>Ukr; z0=89MMJT#t$9RA{Yiy?xE6{2~6r(WVO3vyW9YU=Z#kHt99=%dKN>_!5EL<0lI@221UVO=~2Q)9%SwEO=E`nAXxG%cu z3C9^0praI~=Dr1sRnS~}6P_|)W#$V<{VJhwDV$$398gJrC^$Q_bIbX|IiTiyL(QM9 zZNaVE06=^Wz_}l6l$UA|0T|5^0kwgh2dg5cxox zNTNJU_)ww6MG?~n?BYO~QPI7Nq%!Xu(_g{qsZek_FddxK!vpf?#8hBXJpa_eV}@be zbL)`tuHcaI_)p+%4jJ!A4jHe1+mLbQ=ZB1$UmG%R|HmQY(}(vMPu#l4czv#i zfbsET2aLmK4;aSR4;Y(;5hM0*MvOoF%!rZrn-OFG@-@cSe*YTdi7#GbeEcid7{C4x z*BF5xTw~lde9(xD9W>tivV+Fh{6XVI?Ssb6orA_J-*wPHb&Ok#=NmT~FE^fpziIqE z*SNzNHAWCVYV0u%;`y4Kg0pn)l8HgP*uHhJpz1?`8F@@L>W0Ieri`;HE zZUgi!#tnG79pTSI%6$mmht$vIeC|N(%kg|0%5(mW;Ma}#yU7^iZ;GSeq8uuV@_!!x zR(bD33HwmO_1uc<@Od3l?8Emyw2pqi+&F}g>p1*Iz}?ddB&~yMY$66KKyzy;GTo}--;0WycMxifT#3S0)@N`zp31pq2(_{{2}~3gTJo_ z9OXzQO!4#e2%kjQ^YKTe--7oPO25@Of{^QtV|aQlAgK=58!zP4*CRIyIf9gv_@-2Z zc@cjEy+x%{xcHku$Ss`H2+|xfevDI%pnlY+*Bc@Hz7@Sq&y=rd)gi8n$l=+Xj@l~f zK`o#jzYcZ275(%={C+;3C?9GMJrjngTHAe~0lm3TVpXnJ9o)Ko@L7}=LQAMN0_FzL*Ygohoa_1c zyc2)>0DU7MZoxP4q~{pp_ zeTG{y&AHuT><9eyC{u8sI~jtY#NUlZke~Jdn)>P)%t;0H5>-<=N=cX|x)v=X4tNb} zNPjcd-$C$P^+$Z^85mvkcOCL2NNR)lCd?njUx+bEG5ffz=YSe+W;{@s$axH9O#q*J z0P`HK&CQ_45%lRx0dtd;^D*#=8_-&!%scT-n7t0~edzU<0e%|w5tK^5p9$z=h&u?F zJ*XGaEn#3k{`TU6X9z8O&0 zB5YS@HhF{XU&6Hl{yzJj`i)w3CG%5#eY1Pj5437?rLt~$;8mSk zChDPGW%=x)Y4zE~E$v64*TPB%?taoF^upT!%ezp;NR6KJz!BG%KCs?2{SFE%dq(Mw zQSF-tBGt{6GaHr0SxY@2x6lIiwg=@)3d-51__(o;#@)kLME7L}Y8%k|7KGj=;y#-) zp3VqZr$Q$&$gu z6Edi)qz+jFUD7Y2vRdp07dEb4jirh zP%ZvS-)H z&)HXYW9?H2E@2tNG@rcv!@l)(1SsY&T_vSf>zu1`CW0%c^)uuS;Au_k!H}{6K zd?fGMR%X`U0kc&Je-NvDKC>{OcLn`oS}$%bH*0i2KYnck_u&6sKm+HdOP$nRuDrSo zzEr%&ou1vEOQv-$tkP1bZlpbJ8-XeyCsS5oI!jiePR^^s^vTo;#WgC`RR_0K5t76`kzE7Q|v!RLH4 z{2@nUaflGuFLj<4_r5{R?>KY}w@*cjAg5K^z{vBE^h6#(2^%bAp zmugdXAs@FA@pLK@4M(v-j62{^iLC1yxZan{f*`rBpbZibhpUaP6RWA)Sv0j4n5;GCNFFhX1vx z{s)kE>Y1bWJ$(L#0eT%G!=ZQvN9|ivRAx5#0p3Wt4O_)5_t?)M;OC-~=2ppnd zZ@tyP4KP+rJOh)dFpRIF*ymi)>^*wjuZZgm6It9T3U?~7-L-wLO#9xvh?s%y@%8uh zGJ{rthrqEsj3r=Whr1qBGiKt&2(Irc;@;BsdaFjxkF6*#mkxq@dKt9L^t?~Fm)n`A z@QTR+4c7+obMw!9VQkdQP9lR}o4ErwdON#ea~HNs zktA%Da@lAGHhY$LnzJ~@4g)u7s{p=WyM>7C(611j&*Y0aNQMbhipa1Q#A)R%*z;9e z?8MJ0BS7`LqYHW?JHJ$PrxqQN-MdE0nwdg0UWj32E8?lF(j|RxO@uG9{c^j@L1{a` z(0f<+q=IWgkjJrdT!2K^ER#Q6GEfl)nk}e(H0cd~o_2h*>dx<~dJ^8GB6-{|n@wes z*^KRt2>xGJYiJm5x00+?Z`3aDe$AW3IPU#Tq#E2q;@b7dZm*dwnCWB^_jmc3)MEfvTX0;ZjlQSdQaJMT-iC{beV1-YpNvKG?p!#~ ziX%!lqwebV-re5$hE>dy@yUkNxH=a1yZanPsJC0T5uGKZ8CNEdsXRQ)+c5|e=U(WDwg=mxx4I{k1)cXuf| zC3{-kjgqLbn@iXuW+In^_8%2qsAENgqhc74D?%TGF+om*X}n0bWA);0Jhl_t$N7RE z@mt>$W}0X%4k-$1t#i0qPVie?)5}-I*PSfS#%IEW^Uqi@3$1JI;emHYq0*n z;)Is+7Q?bPf1o>$go}lIF$;OB(Wq}$>uq$I-iP#iosKQo^F<8o^vSrWjs0-%w~u0Z z6e+>#Y@yOPT?IcEOJ7>gy{?Tb*MR~sb#cgR#l~~iOyGn^DFG)E+T_~6X+>H!Pr{up z5;sXkvggQH4*n%GnPM~s=d3lv5~NuDqf@+4ZIu{@Vla^}C88xL2L?#$&>!yRD4Jlh zHokhzsPfGWu4*g(%hs*tsp$_1ZxnO4F;aoD2(0k2Mk-^Tg5~n4|WH_FT3aN*c zpKIh4OH&#=g-)Oax=Us$k%#wl+#F3_!Iy9$4-KWGv4VE>_-xtN1psd9kOqs&V8P4S z5VlClXMjl1*L#{DxSy$my98AmvON&qx5(Oot*d-McbIdxDTQagT?Q38l+&z2kI`)3 z9N5qs1amG|oMr^)ijzhddO@}+hAZ4*?5xM=W*K^%(>Ozq(M>d5ac)Bmn8i8ju9<6S zDO2XDBu=NE#8LDqN`WJt;zZ$&U0M!gLTZXb+wgX|=lpP>8wK@W+o;EqUA|x$3LUpooL^x^65v&uG zGr~CM-ACh+U7?nFK4z!!MOxp(t7pS-)s!VTvfDegF% zZrm|C@p#2b3UWu;Bd{yRF$~>tI`O$l!U~iEHy2i5a3FjY7uVgfZ?kIh3iq$Y8v? z_dQ*CjCUD#%S=7G7=9K9>|%l(q>FX9-rWM&zC6T+88k1yE>=1Dbn!%Y7k6EE#vX^= zT|9srVlVG1UR^xV-Nl|>SSEbB*wdZa09`CiPss^#pHB9M^y?Z2bdQeih8jG-?#_1S z*45n>fV0D`Kzk;zg7hgs3zj3>3bV(y9pvElR-oSbR=Bl51`kD9fWl7ISuFhG&57J;TVxWd zjx@=mPUIO&aZ_@tMRynpY9VOHmV(x2D1r#R6v0&_NaMH!h6`%O+w1U3Pmu8RP42Iv*(NDF)#fsP~A(g!526|3NU;e`qFINgtmt8?m`g1NIxNfjw)fdOxK zv+pWX=_OV$PdNGu=9)zFR;B{jI&wA;@Coev!e$csN$H^7b=jOew(TfH+}6ewB3+WB zLOjt~wQ*cG)&r^=YZ`D@@v5hM5F&YClP^x+BtMetEEKu$2xp&aV)g;GuxNwQcKi;- z3f{=yX&P8itiar_fh*sW)jG^m_z6nZQ*icd``sPKW#oJn8{NP@ORa>1G^TGSj^Ifj zK1k76xO-C<0{DA$#w`IlyJSD+NDT+P_|%8g_=!+t9XCLzJAb(vxM(0>X`bzwP0*E( zNa*QJIt`Pi7o&DyAG*&OrImIG!sd?K_| zYu1*r&)2$Wa$TrvWmP!sleqj)di))vPzg#@<+?ENN#3NmUg1`dlij}cNFPr-N0dUh z$ly$63pa!jB75U+5sOzq_G-x%%xebAOZDxzDJxU0G?eJ1mYh7Ny4+4+PS!5_?z`}% z1jMmDF5Yno8ALite9)4p`p|l^doRcfbcZ=xlS}U^DEY$&N*6&yn_(Z|T2Ao9M~g8V zK=BtIJ1o7>P!V%Xbe*zLv$2Gb>~g{%#wtbTLI-;kv$VMzc(p8>PyR4z@np{e2yk2|yw;PVj1ZfH^5{&&)svfmzJDxc}}{n86foFtZ3k zed@2Pq*~%mRNOguMz1MJdE83^Kyng?z~OLxE?FCFQ0O*yRcl9o^ z^(~Ieg-O~689P{&6HssqT@S@6giJfgZCnC|wJNwJ(mfLC5+i{P91*DYyjCWLdv5r$ zOqVP=Pi~y7dHSjGv>&UV-^3;0P-ApaqPP=*u4qll10QY}x?0zYb4z2~SS04j+m-pr zynNY$S6;4ds60xNI^I=U??k0_C}h0L@h*iD_?F_6M3_!?6+;&o*#5CFQ{v^FgMBG0 z(VFHB=gHr88^=ZHwCHnEeI$NT-6McQiYG!jT)wRY;n`gs*E2WF3J{F?46Fn2!hWft?^TUKin)3*`cLF5F_na!tu_Jj*DVpC&A+kM5$y zo!n_G^KfYLlx&}-R&krjT@fQhA(nV6SAb%il~+=rxDZBHPTMIo1-zET3Ec%_Kbfs4mwy2(eknRM?TA#YuyXqC$T# zS6y4jJ@lmX#6rL~C+9MW`L(D&Pi+4Ab!E3uC+hO7R>VJ>?rMpA^h!zU`LEck-r?sua zQ5Q+5EQ6zQ48OB`aJ}xV6IcNa%1iH%Gv5fQkpwSfQFOV$qLG489t72F$>c0%eSlzL z-QL(#OQtSX!IQWehS-U)((T|vDVp`&Hw&{mfFiK(?!=dz`NIWkAQq|h&GonDbsgE0}QZiCaLvF-j*CYnPQqs5D7?AAN11nx+o~2z72xzid z#L=l_vAzMS^G(yY(unKXsGb)dbEJn{goUyt63X@ubh#Ih#*Rs}VAla?4+ zUYC`jG>JWTok1)34_LJ(hU#Rh7>E)}47tSVfiq_Ukft+978m_6UV%5umP*$G!dimL z^~i0f_g$l9)Hic{JF!Ey;lYl*Lk<_+M?`Eh@`a1g>{GS7Fe2tPv=MbY5h6H?tvlPT z(mR{3VXG^xSA&q>U!}|t>pjMWR*v;`idV8cC;3jA z&Ifl}agbVrhLRwQG)~oQ5c|+NgqHW3DoL!R)7TJ!a{NTKa#lDUW**C(#Rbb%PkOUS z%D(~Z#=v4}^?TfzQmoeO3; z1Fe$MLNPowf!jN?JG+*OWXLtLB$C%$sWtMvkZ`&7gWO$}t2Va6J-3e?D>t+`kQWqA z>Ne~iG;s`F?%}w0c}eZ)z&h>RN-^D?bfM1bKKC{;k+7CS;CPr70|agLcWJ$X9gO~I z(d&d0E$zJ6(CV8wuL{P6Yu)$;uUB&d_@%^-CnO7NSmY^iC#>*}VQ-!=jVT?6B~I#F17C7iV1pGn6mxe6re2|0qUqOyTGdwg3`6Xf zV0Lq3VR5Tf+n~bj84evv)>QfwC)g451dk+Wx!8#;wp*uhZho+dyo5W(Peqrb4UL`% zi%<#*EHbwyfyskyOZAVCyMiUUvyggIB`GzkTa7xow5m7I|D>>>{;FV(ZCHBbc}k^c z#Caesj9ef*^xo|TFH_2TmLF)ei&ZjMkgdI^s%Y8u*b#SS>4NN&ty8q*8IxI-R!2*& z?v<5VI$1)MJ0At0XX1NrdonUPIf-80iFGy%x+kZ0k!YvpS|}$R!fWT%3-6{VawoV$ zH0(GDye8B)v<(ScgHGiAWUhOsh3xKy+_~yX8w2ooyS8$6p4J7kNBIkS0-`l+&wru;6`4t8DuqjYjEQ8O37E_3Rtp(|T1*OhngIiw%n`lVJi zk_)Ukg>RY8tA12T7Jz8dashbP-36p$w_gpsW+mAtD$1u+6}^M<)XbzOfwsZY25MBv zSWfr=wQER0~R52uHXi$Z6O0OEaA^(UPX5A1m| zYKy?8TD9>*b_v_KrC5uCu22{6ZN2~F5I%%R21z$NugWh>9PkzK_I zb)@1oT{@2W>S=N$y-OV(*_~^OQLtI92(g^?0uy=@d~&s|d_r9tZ=9veP=hjbuP0~$ zjj|oV-KYNi(wzu#G9HrRu6gWx;sr*pswXvwg2kVNp1?*tN`=m{%e0>h6M9FP>bNtN zC%j-~>OMbiQdqfo!6lEV6$+DLF)2`5ico+M{~dSKL=Fh&%*Rs|cK!uTyS9ZVlwSNK zm1wtBq63)fwS|nX(34qs?6Q@DKn6)3zIS@{os~RMSzlj<{=}salI)vTmKh(IxHN1ll7sf)1LssJw)|jxDK^@kpi7 zgq?_1&hsRlNVO^n8Z5~2LJ_^&b(|E_A0bp<>JbxkZm0I?<6ir&ejR+awiPet%y4t1 zR+Ai?Dtn6bP55Um>^uSSTGtm$_BQ~I{~Ew>iYTKNMD#F811R^E&f)zxgm zH@`)!T-$wuP{_<&ZV^qGu)@XvQizVPFY;xMm{r8UX;qM`w=_E6f(q9!s=cgDA2imb zh;Y94`qz6|O{?>{n8nC!NlNx=OUJ{Wl%_jL?RfOFCY4Z_yR@~!0`_c**!x)lz2Ve6RDXODIX4qTH#(%QXep}-?qkM@gXwJ>xo-EoqyrZ? z(YMK?IZnPMAy$JoKp41`{#;z&6)wn`b>81(05e)xA>iTio30uW?`8g5OZ* zc7PNoG!BZMk_IkRQ-QjjNM|R`;7GrRQti~@QfPdIPRc+L98d6KIR<~u^y?_T#aHK}%G?uwR_+~DXFM{=Qv$a~Qm$zsa zX{}rraHe_843)EC15j{v-nv*my(fzsK5v;MGa>-9=2IJHoRA$p}nLlBpdC#gy`(yt;RstRMxC8z3- zu?hj*3Iq@9N}%&BD~TP%BIk<7I7mVmh>Jw|lKRz8a`n z?Fa=z8a#d<3#_d!tNcTO75#T`T!$am%L`5D^$kr-a|^8eCS33#pa3r`e%cj3y)rTB zh@W1YUZa_)`aY zlk0rFarTbYTI1DonDpRt;?>OYm*Exr%mxfJ?x-){V|W7&0)zeeR*x*2>>;e&6bAG? z0JkvH^ocHCY@aK)=u~q*z`=k{SNi3{(s-jU6sdMGPxphX)%!tUCC>MT^@Cem>x-*Z zoD%Jq4Z)P1NDI-Bg#G?%dB%Q4^VRn*{5>n zpeL&L8bhz61G(&lsYlJw@iI*T^1A?rGdPL*q)t*FqS}h9u@}M>0fTTxREA2*4 z!r=Ha$gD>m%j6RuY^S_jzt9704OUH%JaN#WQSH?Y42Pu+LG~gxhFhtuoaseK4ZfPN zH(j5rG-{R2UOloxH-GeK+H&no@7OY}y?WIXIh3(r6sFsK@>*`g8)OfdChzc-&sWY3 z1XNxV1|j`{!D(OtG5~y~O-tb3(+peC^(eDKI?pnM15#@++`&7QXdxvGKM4c^=G4^G z*x2~^%rPZ_yA|#iRY^Fr|}6q{N|AQCBF|IHttxhF1Jq~ zomVjr;bCo$`X#Hg*FUorCaOtPqaC;GcR>BY*y%+A9TT$%sW=joNZ2pR8pgar$2SU83$4J*w~$ka5|Sxt^~@wxCqajqPTM;4RiTzn~>`w1_|Ijq-lWG7c!ri{a)svSm!fkEuE1h0RtV?g^DiEw zMtvLa58-{z7`hf;M)a;%FTz-~`RZnEqYY(XwcU6%w$jc*nf>a`>gH)kDCN!5x1QU; z@*QM`z44chy?iWM->Ow#%|rd=RFzkIOU51|^j*d)t{r+Y_4;#++l`;wHmvV_Z3T{D z>T9jBTjyRnCJk`GxKY@~7AE9|vDo?M@$ZZtP9GUP@zCfUpZ>M){c-FK*C7Cd#xTA! z`r3!TGkR_O@h`_8@BEL~eDX^CaSE2do{z^D;=SMaa`?z6DZ<^u&qde)D&o>N56>^1 z=zRb3;-hm{4|JYMz@4G1rNHI$dzUW9A1htXKl%s-mM#|$@k1y7-A??`?ZRFJZ13lw zFTdt-R4o7a=$)MY+(hR9BJVM-5Vad?qni(XXY}h2J^aXx|9kZ0-aipxuR_>sKaDmN zk8mF4*Zw3mhCvh#pko}K4Jv%N!@qEh~bkUju^xML=(^9X$v}e(67cf8t#E1s{9cOP=}R^>6=0@=t&D zcmC=p|HDK7e*L}wclmeT8U2l4`pdwJ4m=Qg>xUmsCf;!Q`iix`h$klu(bVveqO6ZC5`qa@mc^`+h;?{~m=VR$Yp+3J&U~m} zhKGnz61jZx`_FiyyDW+s9wH`5wO{*-|9Y=8M+EU}jAI31=pob+J><9wFjT60WXOIi zhV4O_jzlZj-49 zMo)DOry{J<>tpXc{bP2jyJaeZK`IBk2UkZ~#PIdkGE&UWo?`XCwDY2~e1RZu9nB`~ z2s*w%;dX4Rj-$R#06w`E!QG1R*8}Fg5{{bg1s6s5 z`vLR!63%LeOIo7pKa+Tjq(Zbg~9a5F9Z+tQW zl@NDEAQGIo$GBXGT}hZ|gu&B31?2eYE%%NXt?PxD00Cl-g&`>@#I_Tua_3VdBYa}7 z@jN7^_YvbJ>*?iqx)JaFRM=a;`2Zf@gSRp9C)*IzzR-!7_dnFWe*69lSFc|EGJkgR zk57D#OD4(V(qo73y#}(>p1=E5O7*9gJ~1+S<69_)PUNx6b7R~0eeR7&+KGH+JNCKz zI+3s9>t{QWui@(#I*~{4^(&poH}UnGoyep3dVeSKU3`7$(!(Q{zJK_QAH8Sv^8J*- zJw}PkL{afyx%9_}zB77~hbF$`zeykOr;iWO#~;$iAJfNY>EqA8GkS_aQE^Cb+=hwI ziMCkHps8jI@BPLd_}{N z|Fm~|?-x7xvH19QYATz1zqYLhm;6k3Y73EoJ?>y~rbZ_Y-gWMCWj43$c%P z?nMPY)5(2i@AiT1;@-}^k6%t+Md78Z?L$=jyueNT@a5tV@V%Wsgm(RG09_#k-!Gvm z0zE*$@p(|GqR39dgn&(yvESTInBSN>ad~OvkBF5?ghU>{Ja=R}@-^!D$RpJ8k#ADJ zM;-;yY)8I(>FoDo z^6Tl8z-cnpUrwo*`geGUCSrPeUv>CWw^Y2BVSa#5n%~~>PcNA1hM}=KJVX;PO_IM| z{BL~DwubR0{-o7|3i)LjGGc{%Scce=JQg(kvZek1B|~i4{s1)sy2bm3Y zg-e$uyEv6-mdo(((Qd%lr3~fw%GvTty?(YM6#IWUv z+Nd`U-Z?F|cn4f#Ob2EpB&{)qd5!TR&>oQ+y}Z^KKP#f_PmeXmM-W?(M5q9Hjp34! zuS4X1Me7O>REtXeh-e;v7p+=oD_+A^p{hG zLDS0c5K)f)B35{3&?0E2>watO;MDlI7yv~72blhU7X^?=PcJX}zuiUGh6nvWgtXss z!FjE*#{lcfIbS4xAHWX4Z%|+-yjOmY$nQh^{mEfOiV{eu5GBxWQNj!GmR;8{6D{R<@NVHdehwxJo0D%`-z)>>m@IH`)~ctvHzuhBN4xz zPG0noEYtpS3eALr;h`~n(n$Ntm!1G(3G+_%H^u1c@8K@>w-C_B07=lFO1$LV-T4Rs z-Kj?3$N3x(HEFI#Li`M3BG?1qGW^%5b!t$yNLgnU^Gaq?lY7$6Rzzn%pI z^l_1jV>&&KbGenX!d^UGWW}tlowb6!Oq_Ra6Ww1lbK70#>ZgVOSG{6(Fjef%U`XzH zi+QH+j5HY-4>2gsNXK|ax(l88=Mu^88R;Uh{WuMA=gVV8`Uv9Nv>tH0ct%=oHXT70 zB{{?1ayamiljo$=gfLXCwty=cVPaQ5E(8xejS zFrSlfL|rzVp5JqzYzUCT0WZJ&UW@t_0P}ugW_Xca!!N%#VNm^B8d!Mw<@YYc{Q+Q( z6MMspQ0|xCdjRus3FnvJ%TT|s0A@cS4lm-Bc78Tqh_8MWFrSxjNahK58R1_7OqCMg zfc`k%(d51sSf;kNIDh3 zyiUSV{k$ZdmmvHN5{B}l7vs+(zjp)f_xj{VX!{6YKI?$<>W?%k^xpt;@HyFlS z@urtmt_S|U0GPj)aDM$kbp8zq!x`ekuRp#8xF-h4Z-khKs%GXVDj32W7_c|kLp zq2c}GuKbKW0pkt^J93mWxKn_;U&7LC=>-=;_%8wGa}tj5=3B8hPUN9J@J2Pxg!H zz_r5sG%C~>vtjt@U+xOC%N!2YXXW{YSh`qF&lk%l(y@4Xz7&t96Y2QeJlnlh*2#() zc4jbctKQXheC#K>LaYO2-8!(!<|aAPsY)YrPrEt`Mi^K#jMI>AK$E$rO>t!%@OU!I zVS_fR?zu`*i?RA1`YbJ-;O~h)DP4|#ca`KGqx1bv()_|B!X)i|L+xkYGkW#BuxPvV z$0L_cn?JZ*yx~fcMcOM#VgbgLBnt#rk~A=l(FgaDJXFFr{VrXdB%rI4l;Y|n@#d?O zMEO@I@ga7VuOv-+zLIS2%fOxUBiKNG{{7!;U3a-4g6E-x*H$UBt&jQ{@j5GLr7l& z-bal83!n4+^auFN^3z}7^WWmV-}pK{mpJVE_&mW+L%=|ipRUD|2z%!{I}1lgE=LY^ zGT)u}G&lPr05SfKK1kYs9o|Q{X+MXj{cOcY^8{~Z4niZqJxx2tQ;zg=Tpywwf%Mz( zBpN@BC(-x}oT{NBth_EF6;f|9}f&RI7dkqo*?Rj#Y6{mrQ zE%>YN8)}WcZ*TkBdqz(ngyb|X{Tn0qES%scu!znT7y)P_3N|3tnEDyUxZS-W{1#&> zf+sPi>Ua`k>b&*zChO@w>xp_#z`fIY`q$PI5sesAAI6gyQ~wE1Vod!do&;I_EuI8f z{Ue?PS?#gL)U&NIHGwBlzn{QU8n8!<9gx~DBEgPH?c1FKp&m)4S*|wR-XwV3Rq!~; z%kCMmx&b`y0E~46kNaMHWT^Fwdk$F~u=A;2okVDNGQM&A7RY)fo&>Uv<4GXv6rRKw ztXW}{g9zIJiY_CO3q@q#0fUS$Jc60%?#|Mo`~OSp_D+1{SmH?gXeWN?SmL_&4W0bq zwYWB*-5ze#Z*?7@mF&@BPL@`20P7`Yb;G9Y6h7e7=vLXiWSTKYbOS@8zfe zflr#*ju_v>CymS_#&@hI8Znz3MzfHJ9l?_b8@0loi>D2Sd!ZFZ!pP{=_6TDDe1lBI zt^rJ*;Sf9D`7$hIhOd^6blM}G#4CshI>W6SI&ZqJ^O?@MBZ#<^eZ`*bH(XcVZXS6p z5HVuB<=#Ue`Wre+*LB`>q&3ko4ExNC8w^NEKa8G!-Tp`{a`ppVn?;X9+Z zf4cKY1dl%W(C7yrzU|wiAADjve|Y#Yf;~L?AV(e^{ov<0K7RP&zaM$)-x^n;SwqZQ z{~9un@$e(4WBl;&_dEZ2^uhn~@ZaIr=SM&I--bWU(N|HzLl6J;$nf_^AN&kT7^ZxO zuTT>{NmTv?yxFu4bl-{GaCi8I_QKmE7$bppt`ix%J3Q8obs|Ua4j*m5q7%9G?(nVc zP$zQx-QnBYx4%6Syek}RA02%#EU*ynENq2_sK3S^qEDhcVh7R^Duj+Z z(V53s9lh@yy1Vm+Bllk&z3(hNMz7nBKYIT|qxZcAzpg|{GBlPbb_T!EKX?7X2tscA z^!B~q#jmN4)35FLSMYrIcK%B;62GRm<6pzqvF-df#&?GA4~0O$q0_w#X}i~RHp=$hB_)4TBW27V$-oj3B+uj7ft-2HqE zji%}S2APg3u07J(PvfjKLW~zfQ?lVJ3GVwViR+NUkVj8;v2-X)>(na=UOT+@lXoLK zArwTdCz2OMSjl>#Sxkhz+Ik`xQiPqxlMo*8z%8Y34A4FFc?RzT{;fovc&d5rCkgl^ z^uaHY_%(RuBSoIvPe>TxewV&^9UnN_1|gh3bpQ88?|T#pJLMzy|K;d?#FabA>u4a+ z;$Y%WVTVaSK8GKpH=4%8Lj?8v^y|Um%tv`lePMeMqvJ$q^uad=wih40bmg&+qU($= z{!M0k@sUecc}&pkfiZEJzTW<}n}m~a3s=KME;%Scpxg`z;ssp{QNn3j zYqeFYzQU^Z!0Gd+v$B+PA;Y|J~2|o|$>} znc3Od+1Z)d*%@q7#mrGMh(St+SV79&eKf7w5-AGvr8KO`ZLY~~?z;mWCFNjOOp|H2 zeq+PI&O8@qRDEPrJ&)rQ;&jTJIBw(+vu#>sh&rUuXG&Iv1vJL|y0 zbq6M{EHgD3EXQc!_?2bH$1KMgwP~FZc8v*-)t34v11rl;SQX^|XftGXeHYb>m`T?6 zE4e*JYnxQhj7JzD<#qV___0g~0 z+rVDdSuq~hz2h6F=T+6^)Njf{6s|CpDE{-QO7X;z1eRybCHXvSnlH(1z9hT3PrOpc z1KO`@h($b=rFxhnHH2Vp{V3`Jv0B-5d6cu$je;(B^6^MX)7cn)G5(DLC%wEmgFbR7i|&>`*Ov5Z!E$b1}mwexz+N|1ndJ8H*JP z8Cz;NQhu5c<#OEsIq?{!drdxq#H6*YwIfJQFvsc=w{^$%GsuC&_6Mvv`fM-Iw#1&6 zZI0HGI7toC3^SRjZE}9q+9tVjmbOVecT~fPCx5V{AF%(yg!1uLXT)$OzSLJFj7x7W7fmf zuj=*ApQq@>a)E^PSjrwH?dsH|id__oJ+aM1KrU!%1Y-Nel)&Y&X(IZxw(+MoiKsgP zTWfKQ-FVyf**!L|zkk-az|mf$z9gnf5}nR6ZZrk`~4>8mF0Jy(fH1^TYr2;NWJ*a;dSBW zLtowZc|qqn*S&v5|I?5E*$;l!quZ$a8~*3gnmcbQy5RVdro-muFOP-u>mN+N>a3jS z&-zKnyI$XNZ`bpld-AQOlFJ|Y^!#gk^t|_t-nAWPb~-TX=2>^0aF6G}t)2dU>F7`H zT6S!^TYt3X+1*>pE_K=e?WCSFEmF^x2)u54-&AzkTKJ^6KU%S3LH3 z@b&VXSG#XH^O+mox%vnG{ii(m_=YpLfBfW;UC(I0=GdoxbM>!R{o%K7zg52Z!K)s9 zS#8=F`0I_kU)yziKmY&yx$6g)uB;rh>i%~YJhgZ1mXY85<(*(mul=XLdhM6LJoovh zF6n#a1IMm=>%2vme%))6wERw^K z_I+wNxf$U|0p|7G%)f-#>7#LU^QDJ#SVlO9W`rX}fY&2qNRGtz^4DK|l$<_h)WG3d zM+#oKh_l*#`Aw$I5n4y8#G-R=UCB+EIzFxQD_7^J5$~UzsUrow*CWNcgj0R*Ih3Jd zOHRWMT1UoB-mK zTra7$csx(TposZKx0sdthQF_szGIhGJ$Lo=Y zv>dB+z~w|uhm({(`p!!EY`;rJ`kbJ{Arg8!tE30Dne^)=Er--}J|QEVfY$l;a8Aq! zC!oVYtXn5yo}dEy_)1yg)LTpvC6eXk2njlCL?Q$%N=0$_-tNM_rvRabMe9i9as+mn-qbB}cj!ze8M7;7ao2k_oQl zxVYpJSJEji`LQcGA};xZD>*za+2%?*#wDM-l4Ii%{Ti3E$%{)CxsR(OKlK7zP ze_To8qqD^PI{`JvGnWuOl1M4r%dRgK4|!LH#4C?Gy~VEJ@fnhm49T<kr8^R@N1k+v zfMdRvyS_xngn3g!DJ`7SbvSaCvN@~ozbEELsb^eYqLX^`Gms>%@_-FX-c0z~<@yqx zR9`)`uh?0B^XdB^Bz&DL3BV>gslFsvcs(&+?M7d=C*f&xVvhySUw$n&J`=v?xxPdPUr8g@dTC!$Ti}LNe;+WH3>b^=wXQGG zNj+9??Mrf`__{;=c1yz7FI``vlj^IF_9fR#e3>nFEZtj-NOV$tNy%h#i|CdwdF|}P zv0ieIB|53Tr1bK7T275mU0 z7Zot8zFwe5Ty4+wU)AzL0eT&PqN)jQV1&h#?<_pPngBKPnK!kzS``&b|CTkxObM?Y zGnoI>>Mh>_vtTi61WoMceoxZdtk^NcEJl#w#e`)1N!;W9+!Z1CEV^V)ZK<9R-(4SD zlqa*uf}AD0$IqTKt91pLer`rhb!=^I87g>#kmr6k6tDSe&L+T)U771z9`c{Mmdd ztrupH2(!NSQ2iZvpVkzLgL>`lqCOd&hZV71Rpl-1lk2E6R#ouZc7NMq7G*Wn)k7Gy z+~P_XdJV6Vd9v#*l7T#&hXx(V1UdZhENn|G39z;)8IrAwEV)i7+? zti)JTK(SUmdo~MEGdX3qqSo(@RJCutQ&Lr1O2t%-)>2foX4NgYXwHIJ3)_lXl3p8e zt6OmCoCPy$Wi<~1Z9_RV0%@05@eYl$$fcS|pttU(g(aRnK^jJ$6v@;=2@QSV}lD7B)%a*l~5{oKo-V~{M5 z9Xwg)9ye2zIArQRsm8=7H)&-$l76uTPI~njlrkf9Ti?3&>pQR@pf~x}^%(uF>rQHP z!*tz_UdNWs_Kle&@y@jHTKd*Y^gcRBy?-5~-e(7?_r*c#eSMI6x+!InS^u|ozU?HFByFwf z9deL*haaR~hlA8R`XKd=IY_u$0hZ(}vdqICnkSCE`QS3>#LQ;@f~l)cWhW$oK+Ss>CER=oT5K= zQn6Di+~d1Orfi&ErAMa^Cq5SB=pjyY8eyyAzf{|9=Kox6i|{W!cR6}wy7ZmosIDZW zrEQYv#xGZb6wj3um(FV$VJG7wWw?2`GGB%rXJfT5lMC@Be#6CFh+;H~U>ItRM-cK>uOH;-`F5pWFGq#=x3p~q z|B?}N)UWwJN!!-&-(B1O!oT!Y=BVxbmuZ{4XOK6RIq5^vVqM45ZI>}5jZ31pPA%=s za(8ytJ8!q|Irpzicb*sgm|Lu{x_CL5b_{pzc*^+L@^G-Z7(z_^(?G{uSU zi&>IiluPx>>yb*J+&6@#^+ zZXwy^WtNeY8v%Y|l3G`ico}+&D@jaBwAPh~5$kX^qQfu}-NM(^opFR{nC)rT6rEIG zc}Nnz_SLSvE#d1G*O%y|`jSUT!q=nAHj-emW4-VC5}j0EL@3GE?yZ9_Ncj5P^(8u~ zzRcj6Sc)#$H2R^0uN=uFY@(CuOI~>-Vt8Nl3EmXNVkn;*$tF6fzT~B9!q>TH&Z4A? z`8w70B|53Tj!f}2I_J55g^P8^ z;CEVf`Jh&j9@FMR(;3So6tubO>~~#d_WQ0T+s5j#ZLIbhU!C>PUVZ!aF})Y&zpdVm zzJmuO^>*ax-i~7_&rf!*eoMU_d)>?v&mb-Ic1WSRCYDEC#g=+IppaL$uo;hf^JFgBIM1kj_AqOT5rdNJlksI`Nk&4ZLPQCN>@iK^4D5;SEKji zg9z`IgADIB^zKU!uZ7-@HEH3sG^0s~ct4h=_kXLE`v7NH^WT`$R=08!Yqoyh7VhrO ze6382DmOgF-&nafJj&l#vAggYUqdc=lFw@SR;+MLXJ5k?oZrNPX49n>cZBOj>dSC9bseb+e58~I-cE_A`H_EyM6}#oUgL&b~9p#)=;g`N^21_f7(+cMM zdTpqh?)#}D-=Ot%^h6;+&Mg4?12Mfo7~ehGSM?5rugb%}uR%U|kydI4ObNu#cSz{T zq5|FWbg0^zD^}b{X^rOxad*h>wu6vWJ>O0tlIpXV73`Y4i6t^<@NGs*-1!xFMOZ;I zyyuG|l%Ol*6Xi`@L4=%jhl>2hX?sk=I6SR$!As#XzQoO?6&?1{7#_VfT$)|5S!|oa zrMcnhe!j^Yxt&kg1~1L?ja-^n_;MJ*`bH9GBMUN&{K7YSUE#}(%W{3AUoYHG;`y57 zb2(O+D16!1bfQ>C(de$o?Geo7INoQP{6B7_ZSMGfBsr(Yw7kY?dG@j{s&-WPnT9v6 zstmu(w{r2dCb-7^n}%hRS5{8V<=exuf#GR;6RrW_X?t83zUn{p)ICpc3~m2ihZEKz z^6~An;V(b^UH$xAPq@tAKp%e40Ydk!F6%rv*rn#Vq~HrS53a~va%5xn zkBeQ6!cD}g=Hn!t*r$!erjkP*3w||&{{ZCBr^G}&ekLEN3{ULLd27I%M@AVoVl9Me3GU5mxf{O)(IPSRL& zsYawWYyWRFj}uMbOF2Wc1$0^|b*t-6G@%(}rME;AdZ#N9Beltq+F(v?sC?@BavRJ^ zO%Bsw4!QdihTI?D-l90TCP&)XlJjLvcKyP4avF}n=@}-<{t4rrlhi{8!I~0vdBbVv%o_}`=npNz*(}M z0&6Gq?H^kVL09P8tj`zpO`56qG+mz`#$)qFH(Ar`^PeH_nO0wJY3_KrD^E`~lp?7N=;SD8(yIKk_>H9J{$Vk|Y-XQ5OW0MlBrSx0Q364bPIq5TFlXOq$ zE!8slqmM>~x#b>~+m21j#)MvCCfBps@i%ljNe>R21ly9{1R`_=IxkA^3!7w}gkI`# z4<}LsC1Px?9k(Mps?e#E{tGs#&9)R?338eAu2C)wTk3HW=P{h{oyvv=m-H zcyOL|U-Op@(E^wzt&lK)!DrxMR9I}V-lbiK6puDmXp;_8?XIj*wYnL}d|b3Lb&Cfs6c>1}s+KE}o%Rs{cM62YO~vCOpXvGg(t?scmN8XkL=NLvnyj-B~7i z!kxu#`UZI>4+81QPF~^6G(yUd>G^g3-2lpC0fdiWj<@z<&s>)3?qXK9HnZ}$1vh%; zkdmqOtUNMfR#u^>ZosM%zsxCjR=6a)usFN!)Nn~|VR3HV3E`5w!s5KTj^UF0!s7h8 zBUY6heRlEDbvb4(tOxYGSiGU;^yMXW;d!+KT04sdX6}p4*T+nA+00m)%d}0*U6QRD z&toDdZIgT5Bvnsr1EGaUI_r1mGF#A{>|_be#AL3krseW--2N(masQ+_>1Kuc+ntiIws-SD9n5TbpqeQrO&YsbJ-4wvE&dfh zmLPJ(uW!w#O%=P>ee7NLzB?N$^Rg{w0zZ13_Dql^ME&+x^e)->D0rjHzRJ^F=d;ga zRR;U2=H@!OD0a2`6Z@LO?dN9A&2G%|%DhDM4uw0(Y-rLq)T}Ls*Rw-jpn*N?rF%XmWc^1b;8I4{{k>`bu?*PfBx&V?QH%VwXKMM zUf`f7rJMzRJprZ2{d!J0V+-Rp7g?^MxyVmrqppmee8esof%Y(GSnqbjhO zV~oRQX}!tVOvs_QZ8kP@46cE0HR)M7lO|}~kug`S+_Z8x`c)VHhilu3{Lh9Q{qfoe zEtA19y90M(H%qwAl5VsLKZ9gCOJ}0*k*$r>b`-qPSn(d+P!sFF%=fL3^_A9eTZuJ}znb0ciX{y{iw;fYC`d0;+8m?kLm-(ElnQ+gy zCb)0OXz!-_f8q*$?q-AFXWG&f+&$MbH+u|ynEG0JmhB-YNSEAdVj2$aZu0+G;v9Y^ z{LQ+ZS>8`R{oT%+a7#`~4~x0hti~g}8=1^X=CEt7UC2Cc%$p@EBB=1&zVhwi4o%s& zOK>b^x}$lVzsFaN%c9|BJL)%PF%1{lw7na(R2g*%KO%FxlYLoFkBhz`e zl6lsj5+$Q9e@AADtADqvlub?9o0_uMH)TJ?DK;}PAz9IsM&7rHA9sP|!q?>dTg-(| zu*bKCF<-&Y}9@R93T&hp7l>^FIO-MUxEX$fCXZ_qY;c3x^H|mztLrbyl4oD&{ zh1-4C{GLRYMQo=RJU2yql)iMS37GQpSJ+G`S4Pqsn~lwsI?=eSo?LDA{u!Iudm71a zWM9N>eJQ-mUP`CbIjwbPedgnmQY%+VBBq*M=4XCbSpd15*)Ple;STGfS!0?9a96t$ z+@72VJeiLMdZY_B`yO$)4s;STJ)>{+e!9S!l9JMoV&jCd`rIcLd~VWU6LX(7FoE9= zUvOVz-Fxn{wPADJ@kWu#Q(vcr!&G*b*)+2xtIDJZ64zyU?%gg0D7CRpW5$MGAjl0Yy`mytsJ}cWmkBaK|Q#C+*O$ zSLSsJcf|6|%8_S#w5=IiR``gghYa>M*Kf=w1pF6%QL|;IT+ZYGf2sqt`6pwK@ibXk zf6`Tg)h|kbv%D{ckMKS6IxmPmY_CJJ-`yWRV&(aRvv@Ud#JUf&a65me|9!9raTlK) zY??oQy!&p)|M(L) zHIFaf{Qx`f1pP?fGht$)UPz^oc}dBX4U2fe)%b9Tf0;)wJDk&0v2E^=W5dtOlOjL3 zja%Zqrn+rU(7B^n#e4{gCXZ1XWW}bFrf!ubi)Zhe6|Q(?R{a;A+OGU()gHsYxArLh z52-zz|3hor_jPujN=Brld9R?kv0=6xIQTkK<*sa)DN*_JRQ*3m{+AuVkEb?A{MVh> ztYg{KAiKsiKP=kj2GU-n0D4$XCj7kbk>I4U)Lvwu=qmPw zo8+8*YxEh-^^6I3Knv|xhSu*t#CP45T&dJ4V#7B{=rYsh?nd%UiQhz?7c^&@T+;lo zoJ@fmDXkrrdm9hjPr*OS-o|A+WXg7K?&5gXdb(jDdsOqoa_0JsR%r?Meacs3Fx>hxO^ty1u!_Kh#an2068{<_yCsZ26nFQUcTtjGe;Z;r=DZhh;X< z>_dyg+1EAdhlkDzg+u){JHlJT=E4wjr|ur!i;gAMro}+4c2;o#<#E=m6TC@ZI2>|R zlL$JN^-nUZwy&Wt$~!x=C)}hH@TJC^88pZbF=gs>eTjj zFkdo{+}`y&ul6*FS1FzTN3!FZ;Laxhb+H;nmOhR8ou0bAJ8gG&W0THc@lzD2C{fa38>)}7ktg#oZTkl{X(Rd7er#j)F%DoGr)|;|E6_w1~wCO z>2fr-!Pr8Oqf@JuQnr3~&pXj+p@`+xIupbPw}nS{87xC3Rh<=)?vAs|d)E!Plk-u9 z<$=1Mcjjtax4M(=%+t2+b)E0b*S4N@M?{Xsc6NCmGnua&&N=aL`o_cQ9uMb)csTxe zIETi&{FH3@v>u{kKCRn%Y6J>ldra{Y@2b`X)NFbf1K;L-5U&!5zHcmM2JX=c@9~ zD}x_WL(|S(tI7xE1)dJRmGyLRcVK1kqi~M-zAhY#JK!w%^N@?7)L!Li4!ZMmn%XY5x|b{nDjwwX$MMeQ;YgQyyivpM1LGt1v?<{nwM^H6G7;pGxr@A`0dgSKdAV{j{;D*2oI zqOaHbCGGfzM85Bs#;BN{>*mq~d}G{%mBBZNzI3(pW`c17P8?@U)_>t3`TvDujLG@m zIEZ`6Dz}6yww1(Et$rO3_-&1qTMD=Ot{E$}Mpm5Ay^U#A#`MRxl+2SLN55n;Eg&gl z7iw8i+$JTakx7|oY}4Yli{rLS;x-$bDa)^m+kO(a{UUC=J8oMYw@F>q_}zeQ5#*?6 z`IoZLuNPRApdFRTNl@pC#BIloaclI&%$P&OHCD?8w++Ax&nFnV`5@ z+rF#+DRKXE{w@D<|C{5_*Easx>;nF%zF1&G1RRKh;=0L)Z2{;F7L0)qECL%=!u4=7 zMBrX{03HPgHo;cd4pG+mML1yOhx z-h=mH2Yd*-;bYhXpTJ)D9QMPPZ~(pmsg!#l3%rmG?H~u*LoOTwhr(fy2ZzHE;DdbV z07t@6;D@83BXok!a10y^$3Yi39!`L+5P%cmBsdwm!6|SmoCe+DbT|WgKugCgkT0-2p7RjsD@c^G0cWJFc*FR^I$$KfQ7IK zE`b_Y47E@POW;yi3YWpM=pBzy#HR3F=x*P}gCC zT8Rm&5fjuZOi*D=P(Q>3)r1M^N0^{~j0x&`Oi(|;1a$)@sGnkjx)Br9O_-p5h6(ED zn4oUP1a%80s9P~X{Q?uzZJ3~L#{_i;CaC|x1Qo#qbtfjMUt)s#6(*>=FhSjo3F;n9 zP`}0mbuT8U-(Z6JEhebnVS>636V&~fpni`DYBeUP2QWeX0Ta}Nn4liQ1ocNuP!D5* zT7wDd5lm2zVuJb;CaA|SK|PKMYAq(HKVyRW3nr*1FhMz(pw?l6T8{~8116{^F+n|r z3F>J~P#ZBpZNdb#857hqn4q4;1hoYd)N`1ip2r0B0w$=fn4n(71oaXosFyK8ZNmih zS4>c^V1jxT6V!H0P_JQvdL0wg8Oi*uOf_fVhR1_1`JD8x}#RTQ1P~TvJYQ_ZVp0U6NN4jb}xWNVo zR2FWq!2#vP4K_HSvT=hA4ybmx!3GCZ4sNi)0o5Ki*x-Q5#SJz%pbo(eHaMUT#SJz% zpboQvldg9GX`++c$PsylA5!2xwTZm_`tbp~#*!2#6+H`w5S>WLd{a6p}j8*Feu zorN20a6t9K4K_HSdgBHg98i65gAER-zPP~#2UG!Wu)zV<4>#E0fa;GMY;ZsgzzsGy zpa$Xw8yrxBaDxpFsKL0w1_#vHxWNVoR3UD#!2xv+Zm_`tbuMnO!2xw1Zm_`tRfHRC zaDam|>JT?Lpo(#W4GyRh++c$PsuVZa;D8!}8*Feu1#yE74yZERV1omy95>kDfEtP$ zY;Zsg!woh#poZfH8yrw0aDxpFsFAqA1_x9HZm_`tH3~P_;D8#98*Feujlm5zIH1Pj z1{)ku<8Xrw4yf_C!3GD^`MALb2UI0)u)zT}0XNv-fSQOKY;ZtL!VNY!peEx68yrv< z;07BUP*ZS&4GyTOxWNVo)HK{+g9Bd5V1omy8aLSBfSQFHY;Ztbj2molK+VPtHaMW>;07BUP;+sE4GyRu;07BU zQ1ftu4GyUJxWNVo)B@aKg9BO_Jai>upt5tL_uY-A1nxg4H0l43d+lV zupk6BM8JV4Nc|xI7KFft2sjW0sZRvJf)Lmc0SBTW^@{*l5CR(_;6N0lz7YTmLSRD# z9EgI{KLTJu2yBRe15uFrNB}GdfejIGAPQ1H34jG5upt5tL_z8+0k9whHblUIC`kP! z02YM6h6p$i1*y*jz=9Ci5CI3GAoZI7SP%jmBH%z2q`ngX3qoK+1RRKh)PDkCK?rP! zfCEvG`cMEY2!Ra|a3Bg&KMH^aA+R9=4n#rfO98MT1U5v#fhb7*DF7CPz=jAo5Cy4E z1;Bz3*bo5+q9FCF09X(L8zSI96r{ct01HB3Lj)X%g4DkPU_l6Mh=2o8kos5vEC_)O z5pW<1Qa=lT1tG8@0uDq$>T3b8AOto0pZQBWtcA1nxg4H0l43Q|7|fCVA2 zAp#CWLF$VEupk6BM8JV4Nc}MY7KFft2sjW0sZR#Lf)Lmc0SBTW^~(TQ5CR(_;6N0l zz8L@uLSRD#9EgI{KLcPv2yBRe15uFrXaFn-fejIGAPQ1H4S)q9upt5tL_zAS0k9wh zHblUIC`kP^02YM6h6p$i1*y*lz=9Ci5CI3GAobe-SP%jmBH%z2q`n&f3qoK+1RRKh z)PDnDK?rP!fCEvG`fva&2!Ra|a3Bg&KMsHeA+R9=4n#rf%K@+;1U5v#fhb7*IRF-f zz=jAo5Cy4E2f%_5*bo5+q9FC_09X(L8zSI96r{c#01HB3Lj)X%g4DkQU_l6Mh=2o8 zkotH4EC_)O5pW<1Qa=xX1tG8@0uDq$>gxfpAOtowNU_%5Phyo|B0$@Q1Y>0pZQBcL~2Ma=ALj)X% zf+}G@SP%jmBH%z2R4Mzxf)Lmc0SBTW?S}wZ5CR(_;6N0lJrMv4LSRD#9EgInF9Kje z2yBRe15uFnMgS}bfejIGAPUm{2!I74upt5tL_yjk0k9whHblUIC`kJx02YM6h6p$i z1!=DYz=9Ci5CI3GAnlg`SP%jmBH%z2q&*V=3qoK+1RRKhv~L1nK?rP!fCEvG_D%pS z2!Ra|a3BiO{t18uA+R9=4n#rPLjkZL1U5v#fhb7(C;%3Oz=jAo5Cv&31;Bz3*bo5+ zq9E<309X(L8zSI96r?>B01HB3Lj)X%g0!y!U_l6Mh=2o8koHypEC_)O5pW<1(*6p7 z1tG8@0uDq$+G7E*AOto0pZQIPgt04xZB4H0l43KV)O02YM6h6p$i1vP{H zU_l6Mh=2o8koI8!EC_)O5pW<1>LT`o1tG8@0uDq$+K&OSAOtoY;s0vjUWKoq3?82}4HU_%5Ph=R0717JZ2Y>0pZQIPg& z04xZB4H0l43esK;fCVA2Ap#CWLE5hYupk6BM8JV4NP9K_7KFft2sjW0Y2OCGf)Lmc z0SBTW?cD%a5CR(_;6N0l{Tl!aLSRD#9EgInhXY_i2yBRe15uFnaR4j`fejIGAPUl6 z4uAzAupt5tL_ylm0k9whHblUIC`fxc02YM6h6p$i1!-Rgz=9Ci5CI3GAnok{SP%jm zBH%z2r2QQL3qoK+1RRKhw8sNrK?rP!fCEvG_IUs-2!Ra|a3BiOUJrl;A+R9=4n#rP z?*XtN1U5v#fhb6OJ^&Vkz=jAo5Cv)92f%_5*bo5+q9E=409X(L8zSI96!d1xKSLC3 z8K%IH3|od}Fn+_9F&qqluw@WLJ4{eHn4sEYf=usegG}LRgM5T*gE|ZoWY~l);}aQ@ zW`jBc6J!XbU5;t<1GO9z)HRqO!*Og-D=>v2DJ(kR2UQF zQ#TvrQxO}~k1#>~7;_`0K0}rL|H%A*e0;r1_~-@mE(Qs{WG^6wdU;K3_I=GuWzWDH}%!Niyyf2miLdJ zTwQB{@R#dim{p?V~21p7-jA-wnO? z`m;yA`?ImPcNy(J`-2Z29`dVnbN}6+2ku%ttzT>b>2>UL4;v;M5ykUnNx$l2#`lHVz*QRWlvjeY9*)NXdX^W&_@p_JO zb?!L%#h@;DQgq~&G)q29vGkK^A2GyC3Z~>4d!;~1o!ZDOxR`t_DXiKGr+r2^X4%N( zaHNp)dOGtj+n)RDC`HoaBL!e;d|F$kdZ-SCVzhcR!xD8kNmHmu!RhskBlQ^neLD`O00i7$%Ko*wI&HNbbmx zY;YyVsF<(6xe{+&@|i2ijZ2P~8-q=j5SFx}rRYjz(OhF);!3jP68Usoww$=+9#m?n-2lVSP4lVbVD8^Ni3`@a*O8n2`M1)j2$_6I)_AA?eReDBqSg_CI$DYeHX}(6rwh`=vc9|D+4pNx0*Ll>d`XF}bwr?U zb;B`|Z)!NE6ct~uy5VRY5vVTmFkv&2!9TCK*%uPu4 zxgpD5lSzAs7k4v~stif;qDe;QsSKSjGbCrpqbw!l)P+csmmTejp4X#SfWX$_^|gblU}?UvphwqLb?D6eM2HY2tlx(1NZHy`g#0HaJS?iJWL?$7qK-)`z!nt^ zPG4hBuaj9^Qkf)AUbnQ5UVO7`-ke35^BGo+>aAx(ym-dQg)`!7e-0ZRTPTw06^kb% zrdPya)@-y;F^hVhfANg*GnT|xuT1e;lH}E0JaY7+>ID{aD^@SQY%#4I3CCSJm9_ia zuvu>w?TP&=7S61;+{I_lUpRE(;#w=XVCI||3*5OMNgqj~iTz3!E|@jvV#{4-w1pKd zzr)IvMYHBDoKf3n!1)Wy#KI!4T#1TuNu{E07qb5C45CpnOiPPP%u<p{iC4@<`XeOR(n2XXHrj=VrV!f~^i~X{mpwSG*f~^{r zh=2|wzQHs-^G&E%F^P9%m@UqtGTn{lZ`qiR%n%30e zBZK-J&?`?;G@g^vfmu08z3;OkD2MzvvuA8QOIiAo)_S+1e>0~`B)*g9`;u-i%u5G}TWx{U;0h#-(~a-!w0Y)qdr% z6Zex4Yfl$f&7ZNLcFy9(Gc2oMY{{?^RdjJx_0mPGD!!mLNwjd*ti>$v9@9D4wS$LQ z6(h?=RFsY`x1>k8sDG?Wxv0O+7)5>Lx)t@&J-$9a&yFB*^2tXi$9FU|HBWILsPaQCvP|bU8~eo37%b{&N8<1h%RL?HeHT$8F!$S)}Ei!+RQDVji&^-|7wf{uSQJe0PPf z`L4^yS7Arrbuwd*Ot0c=*ukC0^seC-!kxlTqs&BWOv%M0nm5W+C(p3ADercPbYsvd zcuD5hs$APx`6$yf4H&mWC%#E~PDT~pfNPfTg01XiA>H?##Gdlb$nh{; z_QgE1h)(4LEYF)zds;+0OemYs#QnY#zBI3~E}BpZ?s3D~B&+a5ooL+5U+_sY$J$uzezOqJ_Uau>y~V5}!6$ta-+OJ^n^-IOo2otC z=j#>K{+1lVDo6TA_sJAD5@dem4rJ+PvLhZtiJq_5R$u)+BAjX4Wo6^5afg?! zt>2j2IPFbe*CA#NqX*buy-og@XQo5-7WtC{2LC93_ezwz#G<_2M7i>hI?A_6l=+*= z|BWIp3dQ(|sDPPp`MJ-?Zs=OCl@IJCk5ZmM(u!j&A?#BX?Ext2I=8eFk^Ng%w8^{gD7w3D+}F$IvbGW&?)!WU|G6EdN4 z^LQ$p`uTUUGFE;?#MdyNpu?S-%DXVl5wjnMUl`BCv(4l3n(Nl;`;e=dHmQxwh0IiR z?#yKDZ(*iN_KzDMenE$jGNGO8S^DdxyVFcjc9ynn;NKK(^!e&n0)8bka}3gZ3*t7J z`o+j3vl^RBM|L85esv=EnUP(N&B&gM%XU*V^w;5ypl~rq`$62+giX5a{i>@+NY_HM~L0WpcYF zDYRI&>MEulT}QDyFg(E@-p)Ez;f>6RSonI~Va&2#=<}_ZjG}#2ALU!|EMCJMS)*(9 zy72Q&*;c%aeNPG;nUyA%N5ao?Q*7{cXHhW9!<}8jWJa?Px!h&X5kVz0pRO~-8n@1L zy_TA2lTWAZiQkK|$`-Q=>vB>`KX&T^w*IO-U~-SV*;uhxj${p8UT-&jf>k{=%vE|lp%oDNPn?df~4#E90|MG85t3>-b3L;~Z!CAtdoqV+UVOnXCTyG_my~mD=qK|;wJ&&y zhap#W-x9xE;7v^|$ySlK^B8u@B67ZlhUAMHzoL8Oiq2&hkPhia$r)#=j|N*2iuCjN1yiRA%oYZ1Muluhw8Qe&51&CbAqgf|ALET#e1_ zU4YH_y)kZE7q@lfwl;f*VhiYyFTrN~uE))WTW=gkZ!$Ka)d`&BC3kyW8j~t|lBJUl za!RD`_%u@zNqa}ibeU_*hU9Heacph4O#|v5+0$_26X}Dye*4PA-M{#KpSzE|`i}jd ze0B4UzwK7`z~9bY`czwkvEF>K^st+c3yz5mx{58u9zA0EpN14)^XU~$$Ic&8kUu&W z8|%NghMW^SXxvP0v&#i)YhaT+SyBg`cryl_w9`7$T9=mJp|3qTK65aQT$jY)o@?GN z-rL$5a?(ndmidF8na?DLW7_e#I-FS6GRwJ>EmH<{Nq0eNoLd`2_3h!vK!((C4%O$5 zSPzF1Gclk<7t=@*!(z%sL2m)~1!`qXz&#_ePOO61E-o=8mD~+6onL17+L9spI75={ z-gk*XFkM`U+_C2912ZHekVx4s16;f+c^FC_(!?v?ysF(lj~`Mkb;EIeC9RPpVWkdP zFxOrD{tjPqJ++Pq)N5`y2}!PrsNQR==VVAmr$~}tOG{@(BF?Fcu1|J-iB9Tka_N#t z_*(MtKbl0tY;#1N7S`};+l2Ei zn!}7nY4x0WR>h3k+4>;7Db}kC7Rei7{X(`Pc5r#|Y9)7~&aS@b2UQm>T=;`I)mA_0 zUoBm_w5(>v{A%+SyruwI(rdc5&N<`dR~sHOUU0RcPi*QITsmjLO!qZbTk1vfe&aj7 z5IC4l<^sL0A}cFaRn=6_m}eEt8YBxXihJq&`BuL^?tU%I{8POO3i{Ab7vI|In;y`o zAgOP93H>@UxVymA+{iK9;<-)Hf|bT`Ui(q^-3+-MQ#p?&?Z` z)LNhJih~UAI`n?tMtB!+oIBC^DoL-UzUfoZYo{wYi4$o_FN+iIf!>+&Fl3XGrzJf} zV;Kl_nH0Hf^2}>VuQ&1!(CH+_C7Yy6OL~2fpNP)5HuNq*Zz?*^wV}5dy;sp0E(I=I zYsZ!Ad%mlq75UTgYhiuDiRfLN6kcoB_mYDQuNJ)(>ET_tSfU=^(z2+Q+xfkn(3S4tnfOPl4EU`1siAi7Hv{j9_7oYQ#`k7mT!=?&euUnADnb2 zg#&HTn?vOdHS8{4yb1xry$ zU!b2)>-sQzWpiC;8s5RYrr>Q8-0qkm(jAksxP4Q_Z9525HMWm=Zuq>;8@|LJUe=j4 zue{;Q=!akMbXfPR(;r3WbV~pG#zfcqM(KQt_f6146gB;xK{|q}w)?t2Nk>F5&)17y zuPSl>!ls*$VK^FVjs~zF( zvc}3D-|A<*6?>cfD}8H9SYheV#^4{Zc^fP4^Q{@~X$(F}6dEfYpkE2k_Z4nhd;+_9 zJF*s|9j`<%avJINUsKY)F}P`0HV0fgy72AAC$fCUgN?y0zBNN0Bp8-|AM#)p>kWwM zZ47SLnp+5*AWudAB-uf@Z;DC4Q85YmJuwM-hxR~U7#%53NC{86@cKY^5=y!}Czs0f zy-k(33HqJMx?NpKS?btKd5Dhm*3#$GQ@UO%>3zSzX{;cnr;_AGiGAyP><@3GpR%c9 zEeq1zW?tkxE(Z+n=`rmeou|;S3YTnDA<-3Z!!3&nf+p|}C zaM44qUAc(f%v)KkWh;xbL~&)Y*W_y2()tCrUroU#k72*Mf&Ws-QTN4dAIEJ+aYAOV z%wsMcJATzSZp)!zVfIQVwZ+~Xbw*rP7MD%OR-pY#7q+qeJZ}4a+@`yfm+IT|05`I% zr|9S2>^fbh61R&QOS3nY=8A1&DJ@95NcX*)o3$?KWSw$a`Vo`lPfAfDR@mWdt;!19Ik!}(xd9*|2*1^I3i;qLQ*pE|sne&VD#U^)F zao(=uDSU3m8jQqt2XBk*4&F>jBaWza@NZpwa#QvaREI2=l5^y8%Ch`(mJ>@+p--9) z_FbI_?p|N_FLBM^?d$#&X7vtwSHsKp`?~KFMbWOa>sv7=H!kyeXK|; z_wzS@FOQ}Roax;8d+?3N_3J*=Z(jc@>TV&jNf*mg-7^el?qasjB2VW^PB7Z&2_ov<%s(<&LaifHzZUjrA$^}F|J%( zvYN_tvpA}xulClHW?evC6HtlH~&cR0wh`TuW zsD8Mno1Ga4Ur#jHD0B73CDL1W{#)&HKV9#XLK);bCT)9)KRf-fz$vHZdM5s4Qvb(` zo_cfAfUCbe!*kid^V>E5>dvd4eLCH}VZy+Ulm7ha{Ap9~xo!UZ-ZxKccl?66U+r7? zc+X#FU-++&N2t+%ocikiHE(=#LjK~0H?mH6yKDBo4u!w}$LCAF39qPYI=8KU_E_X% z{pwFoos~87u;xksTm9?O1ChFAex&TAD&WfOUyogqnag)`hj4eK^i@lhIkk_uwf^;Q z4@bHLQp0Jje_eVSBzrtQ?tyu3e3CvK&eh?_{UqDqM;o8W)G__*Swu)$mnSr>IWx1L zo?%?XM|u~eM`7GeuiKeAvd8O@DviYFqwb?Afy9=ahSV9*k)lfWTzG}=yi6VGy6}3W zM?rLs8v5#_OdaWF@Ol=zI#p}iQ=3XZmNb9c`UqFfI5nMH`$#!Fy}=;=OD&ex{|~Pwjo!Nc>l1{6+32^w8rqJyub59Q3~;qrh^-5$V4QBl=UYjU~%hHKcE z0YSdy;zJ?%(29=l`HN~VtGamJ!V722qhEthcdFfQjV86J@E`BvH*W!?Kb!IG7uD9) zRGUuyZ+mAjY(Z`H#nm5K<99Y7@I^h5ne)1#?MSc z=L=Ww+m73Vsz{|&N7!0BuB6v8S4S)Ir;pphTL_ud>UvjK@=HtkK*GEAAj7*Iz5CO{ zOZ##_YA=tZh1b%T1KrTun5L)SLL|M}M@997UFda^Dj1tQz*^JmfzHG>^v=is572qS z)sy_v(%TQYp6%Q>M_BdNlAesMJiH~nq-U#mj>73_djB`xen?K0ml*fM!vES!j5!Ox z|LY5;=4|ULgtIs)shDMcg&>WJ_7Xt&2!^`14}0{&m>YHRH+_TnkRsM>=DUS+aJ2B< z!h}0Tso<%k70my&LqyF>vbD+3usG-@n;zMj3gWLGW*eXU-#a8#T26NtZxk$7%+&=sQyQJ`H z9+Mm9>xcKm!^U7#jHZexYj?FTvlF85#-s~VWjd0x6`w#HhUhEB8nj_I<1NkIm0i%xCn!$sDdAl1&aPq4_z7Xv zymf_BcUX8M^25U@z5S3!LfUm$-#6kb+pgM>dA)Ku3#O6QXCo~qbG>?Clb((oJ;9fp zuU}2(-(0ySMmyuk7+Jr&#k7^8!HldosdpmoFC2)DddwcFYaS+Zi=m{)|6kHJ(#fpmtpkcywseeIPS5`Smbd zc{7xwFYOF%8_NH5Z5z#hA^7zgq-Sf}H2#fEGPSYMZJJtoOqh5lJ5vfi`eF4+h4(i! z*Pd%~fvm5cmz)XmUF=KdlrxY*MTRwFw7N+lCuNu@9PAM2QgqD_=&{=NUHu2+{wuXjjw`9&+9szT zJ4VcmB}uv&+n$G*ne^}pf&C3mw@~*nt`s~iTzx;dfsKrmNeskrVjaT0C{J)%e(|ympaN>)P zFP^bw-96qIByhz^U#=?i_iC#n`=p=TvGlALy|2IZ&xgv-84!FiHgG&< z4w>*w&8Lw&zxed|&O^4|b&YTKbHBeZuy?;)8om8D2avCg9W-txcfiT*kmv$4Dp{_k zJd|V;9Xhj;8qBh%tzqYK7o>Kxwl*(ktRC0$e45gLNDZg8c{!ztEHSgkZx5M&s?nV;OnY{HQ}W^PJ}*}&{8ip`MnpuIswRt(Ex+3@9z!7`+PlRI{!9E?%ZT!ozKAug=I%Fr+{cD$GL;nk+hNRyLEXdha=s!ZFRxRQy}%4CT8W6@?W+@ zx41kTWJ}CDd8HBXAJ7d}J>|12i%EXrx)U=$K9u3>g$&8=3`sjlaJEEO{;{qk(cxa^ zN)ny>i(N^gEB{xnB+&)`rYlLDg+F%dsn}VZl_44LN@SqEv0jm(^RpC5@+SaCb0#L` z<(xigcz?8*X8Wz{OI|jZeDEw1$)|}q9KCJ^Nl1#3h)#ao*X6EGLh>ghr=TM*B+Smw zT%CkuAX!s#c|vj-63Mv<$>T_*v@nw7c@<5kd^h&V_Q{7g-fiw~aea+1*|d&I_SFe# z>Zc8fSslA_gGhX|j(As-mN_+Qlu61-cLy*WBCnVP-J@U=Pd^kmt{L185e0n`{hO!+OwO&?keqse% z*O%y|zWg{2iI;9%v)%aTPTXd(%$6gO{{Pr}7x*Zu^L>1mjUi%mg07ls)J393gOZSN z4K|z0<^tIy5W+QBl#N z1)()s3aCha&vVYq&dy#WXzTy`>F0kSv+um;ecyALGiT1_eb0+P8i~u&FvOa-Lny&! z-OUJ7C9=}IgHUx;mfP9t!Z?c2_|!2 zB0JrT6lc}->fkp`a&M2cO6MMu7?J7wGg>Xe6t| z>QW~3ZI3+sj^`MP=XU&437y};CMD7XLxY?>yJp_Z`r5|i>=Sr+x_L?9aJ}C1hMpmJ zBF!Ky*%M$6O*cx*2yYj%xrQZuV*JTNu(>5oasqXBf)XMeX?TJXXr%Pr@*qz_WC`l# z&1y)F*a@&r85F&57=g@bHcKbO8Jy$^G>XtPPmDD<(GzID2T&VQ0B+XPIkEaehH@9*;X4YD}1UvYIhtmItBngH=1j1J@jj zHETLczrmSlLjwk00FGzlHFDT+jh?%;$zr$mDU2C!);`jac59!~hBJZhc!b^B4n!^p z8j6rs?A8WNDv3J}f5R{YsL%!uR@_J1eX9b^+#tG0yKkHlE(Fb1jgBKhV;6A|?qp!P zhd^_NHXh>W)SxqV8!rYvT^}<^)`)aRkkBO1m2qT@z@JF++AvOf4UrQ$&PBKse+HeA zKdyOpV}^DiR}B$ZxMcSxh<^NqBNcrx(kb7mS8BGEB_m-K>;@&@;Uj*A5& zdO^p0=kiV`0<+chW1Reh?NtE%9x5uj7xmLwVN=G|) z!@lhZ3>o~R?_;E|rTfKg*!oC4;%nLApPc5a+9}SlgY}wcSL#;f>O(x2u;nN%-IS}j z3ytHhx|PArX>rOeWq3bTOAf5(euz`xaMqL0(_N@~j(FE5c-JRD6wc!Ed5&Zq@g%FR z9sbdNrl=(39kH#2(HoLRR`xvv9K?bRxnd-&Y97vdRcZYZB4GH^+)h)H{MZ!0c}LV1 z7}g|A?F-!0sf?Kd)5mGFCds2&jjLVI4k9hhQ38>;>F-)8BGV9Q3yK5W-?d6aWs)x@ zD2_M%U3b7*q8+~vgGd}+w*k);)^A1&sv@9o`S>+u{= zR`-<_f68iQ#m@GsjjCrO>`e}g>+!&3vh3?|f{mE=!mml(gCp@)7ao&L5`RqMVQ^X4 zBk}EpJ^mYGR2R-%%y+g|ABA;fmTS+_AEB_K)$O|vjU(d_b8|Z&W%XCe>Yd8!P9Emw z+T!i(16E~q2dy%BZlba}=a|13rnnmlI`_u4=X?poS3C)mH(a^H2TTtVPY4vO?u)X+PfaMp0NGwL>e+NW%WDArj}mmG5-Rj_j2dHzBhfr zT})8^S^O4u!iEKj<7pLq86_Ioac^rc_$pF#VS54cSin5u=*zhFg0Hi_TzcESl}JP8 z@n%5ZoX1t*XZ~z!uasHa_^iy@MnrsNb8Qjm_EJ<+aLiGgYnv8>Itz{wnJH{9JsQZ+ zeX4u6TD2>WCs(e{NkjLdJf35>y5d#WvuaViIzNV;N!CuaYA0XJm7jdo({r`7LXNYn zLJ1;%`?!=(2Qlxh(oUR?G9YcXqb$YP+> zx-!#VK_rx(1QgJH63R^b*u4u`!4>pZAiddfO6%3*?Bsstp*Q&oU26tO&8 zbh_ZZ6_8AWTY=XJ-0uNNy|NBK*9+XH0M3dQ#%F4`oC|27h`kU{vw$uIG*3YM#_?&z zT806Vxz7SrD{xLgGS7v8WKK&1P#vHf1RWanJ^;{SlfR)_Yr7+=-Xw!VYOSRRi1%`c z$d1j0zgSU1IYjKjJpx}r29#6;2d+_-a0ZA-j$PSqPDJ@eS6tD5$*U&~QDK4EVSht? zuvnpqmn|SWt^)<+z_ma?*vn|Fffjrpn%1Pb4y5_oudEg#val@?xcA*^2HP<>)Ol%O+&^S}>C8Q8XMt9qQTQ-&NS}87d_p|d2m1hlNzW2G3!xFh)-ait{7CZ_Qp)2|*A52^M z@R>^<$+=_9Yh}xSb-}yEU#EWc)5M!v2j8>cq+d_lJ9zVsfnTh?xAkxT9QT*QV=%h^ewBz0uf9)44#IuhS*s`f;)oaJ|f zA+l9$9Aa!%uH9lu)^dK$NOb?qeXx29SN?2PuG_MIdvV<(_}CaUa>cfvpka@968^qE zuw(tnVd^$q89bhvOuV2;z?CU5oDwF7IX#}7(*#YhoKuAyN@T4v7-v=TnK4kw0>wmN zf5>3ioL(dDdC_V3C6YnMaKOr73()XOE`v_0SYkn0*lWf&dy5w>V zW2o);!)X4ZVGQfqPr_)@WfefYE}3WT%AjNBhhbC`CRhPS0jr^QQQK1gsxHl9`K881 z)gGI01)GT>+-^J~(K3k{!XZDu=)?%8u0uG?Zwkg_@M|B7S0O-?!7p-?3B%TTwkBE1 zA=iTe3~nqPka{M5sl>!L3uoJDIW#al9-Qe&Ot3Nw+nddrOg03nC>(#_~&WCE{1m5Mg;olVe~K$)*Lf>dNWB+N^wk8Gc;< z6AZ1i;#k}o7ir8~TrD%6m+yuHMF!Vwjf*s9E{+(CwEjHlBXnSTS~qK4q%m``u5DKK z3=DbsY>YbBeHs^O%v@6SNsG4h{rvB94K6B7F_6a0bv7_Yxeh-v=sAPyHI0ijW-ivg z;f%F2<?MM-1k zIv*ID)hT$e?y>dx27_y(mKJHuTo(u~e(4xi7Vdi9;Ie6G(wMm%z}T!=xH8nte{iG0 zb*{$cK#ZAd05CS|a9kPA`PZe#46cb97ir8~7Xo9r-2LkL@p#qr+PF>QB8|kY*Dye6 zn72%r;GLU+LbBe%&8}(xrg4!5`3c%5NfulVzC@<*FL3->4>EscWtkce>)2&|a&^ak*Sn)iM)GGx%WZd_kzu<~PMY&S1Ta6Flqq zxO!zg!9cIR<5x(SiqZ+OCsRWyM91mG1W?T?Sg|Ks@eCEG6Otduo~Gq=V$7k6KZff> zHW|?k|q*o>0=0(WU%nahaOEL zLm(y-S(sd(q5s;idwsdSs5vt5NHh^=X&I{b-1$pITo!Sxzyhhes3r(uzykfIV zrh$_?^hYzaJijbAcT6dZz{AdUe0~Y~fH7mr^76}iC9=N3U@day=9HDX%f`B#f%TBk zqVXQ-p@0Ftykci=xhuD*yrck6Kwl8i3PKl_#?#=k&k4GrgdSMt3F(1l4jqwcoZ4}k z&;z>@Q%$kLjIU`VJ+OTJW3PX0Bj|yxK^$i$!6A|!*iwA#yFm9tPAw2PqmHKU^ngYq z2z9y$`cAM2usp5Na!?RW-|59(%7aCy1vW$?M3eVplwlWW=5i{Jz?rxxN8`+z<{E(# z7mjVd&}ejQBs~(+!A{5&qS0CLyn;g{I?mBf3Zui>(joaH-IBy|!*%ZS}lsQx?p{ zaXiyK*WwhUOC6Ux@*3vX)lQx6sjHuP`P`-jGp5d>uY-jRjn`c*N$X$F8eoQ zY#ZT|$@__woF2HagKNno@6zNrI2hzfs@w^%Jj*u@8VJqFDavgx;|398?zI1;S*w`c zjTt?*4wN7n8B9=8cKenlCn}Tv0pC)$SwOBfBRiWBpX9eci6oGgBj95SwDDQT6u%E? zs7sR*;64jd>?*eC6I0zu)QCvJd9Dfll$7oAsOTM5ut1Rk=XFkb7pfB5@Vf;RF;?hb z;7HP`IOel|40({zsZh%3-v<$Pt8GFu4$16qCs`tZL>tl>*_<4|^d2Ofs3Pww@`ze- z;Cxo;Hfuwnw=>4u1^tRCTUjdn{+$JZ;Em$A)hYjEX&~{yzm%&wabW81tfk4x%F2td z4}u(sY69_kWzr__id!7GI!n1?|bgWJNs1wgPNKDk*4*Ojv1q9#09n9*30M{>10i zlIT5_pxlf#01FMcvmrcy?;`gcXu~irs_)ab|j>> zBq>*KR1$Kxc{>yQPN#poQ<;Xd&vREP3C<@3h@XV~5gh{NZ-P_8_({l>B=|{iZj;p8 zfRzOJNpS9#*xgwr$%B^Og@-XHYpde_ikWFiRM+EO+nNd`p-tW+G0IBzAjp@0oXu~) z3t7W69Hbs&Ia0syej4MCY47~BkGCVH&>#P2>BjJ zpG+C+e67iM0GK#wLw@pTi{)3&j2=K-{Bep-2RBZl@#`QGzxmpIvUXpj-KS{xCEEQU z?Y>;QPt)!vX!n`g{bcQa1n+Gfh2A4^OON2Bm!-+}4Xw${D+w|VA?ZaVnHA`{)clpB zefgP7@tcI-sn2r2khO8C-m?eww9rdKM|&)3DNZ()eX8hQ@h&F3z#4>B-fg!4K&R~=jfnYcQobvaeZW4TW8?-JG9~))m=%6kV9WeUl<93tmBGC^9 z_m1%_Kym`aYdvQ4P8O8-a-eTykBIk;&lot3j}Jp>yH#|IT=>OlH;^2&R7u$k|FZXJsYQ`e2#Ta9B!ua zMrX(GHQK#X`<((?Sb(zzxw5t*BkHo-1_32_w8pl6`u0DIY?6k=lAG> zaE+d5;5T?fl)bLa$_X1MX+`Ip93Q+PDos-m2^vx|L_S-9P2Rj29PPY_ZVLx@=>Mm3d__&JDOoBG4us7Bmm&trE?kgG>Y0O-5b6V$`IIQX# zJ%1LU%c4hHbK2HRdD}tvw@`UOuLZNiZ|pxp zi>B{P}l*eCFR})Tv zLcm}M=%Wd+M;0)kx_z2$Jx+_CCQ6SRA)*?^Z!hRWq>u}IR%Z~hi|-0Q;WFqQ69<7& zCyi92=o>hlEdB8G_xIbMT(t4-k@r3^_D{RAKYHwnqETyqePCO9#hREGUpU^_PfOYI ze{C$sj+LQx+na-GQ3dtgYIw|IhJFG$}neP;oNYVSi~G}OxXLeocLcy!|7TPH`VAhMKI}xs4w)k|gZ7tB7h?wnV?$k2CDPbo zPso@c(%4}gs`NK{ThMAd(%6A|Lv!%tTeYXpW)W%Zz$SB>-a<5af-b_h{uiKoEJ$9Y zZ#^fQVogSq#h*y&K8Fmw7b)G4^AflXaW~(jpb$wO>3-J>y1P+#&w*|{+bjZ?&?3oW z6(?{85EP=-%Nd{>sL`^XBh?G#UEWK1X`pk4$_v@AVh1!PL|&x*uR)+I>jfPj#ga&L zA!Dyqpt~`I?tg3S^$be5_8p%`55y#Yg*Bri>os3xx8lMUT0H!$!8xEm{wh$!+~$wT#lq%v0qI7or-N56EQ7o>YurTPQUDy%?E3ii&tx68A@y2rqqvi(>X) zDl_>i$W)OHJ)`4-GipVV)v9hhpRBi(n>|=*tya6l+2S0ALj(*w2V=y2J4Wdm0-j)j zyh|dy2U1j+(eCsv!k$$t)tZ+tN^>Y}RJLBeC>{G)b%4Ar4s2e&4(FQj6DO(gK-j-> zudii~(#qw@*%&fNJ3{pc+9dG4mU!C4I}rKj<)|cm^?UBC(f9(>}YiRB_5XIYygV-PuUk``$ViHr~C z431Q{AqMs6{nDn~JP(;bQIS*`rW6^6d{yuzxzFc8UG|^b?H_B+dTl|0w$BWr{8!;Z z@hxRA{5gKG03H}ODuZ{bol3!aW$6_#w|h&gbIlXG4C^z zmAi4Fx8D9PEWP)SPZsYtq{EHhx|p{_JFPva3|@yw{NA!ozIt=xu@zm_ko?(jW!3bll?t=(eMYo zui|~_KR2#vHA_8s=HVFS=AYm>LAWrj_7_+)Hf41|wk{RLr>w(FVGvT7ItXqzr@;s3 zIvw4AE($07K*k(aKZAHzeA6?ao*Rc6*grbRK2tnWQF619rgkWP60#A8r?jsIjT{2# z(RlBII97SeU-!oa zg?nI8^YEM~K%rcKGZAnzla8B%+F$L#f~>D zl`Up6>sAoL6|(mDfWd>iH6NwmYt?-6BvEEO=s-bBQ0EuoPg;y#21vTuO%=E`xLzu7 zn{bu5w*X1Hj{`WUfNOL%v=>SDb3hjZZ@16_=n6owmKA`wa~Es*5g_W2$6D?Hlp^Tv z0d$Fg9tc2#&?O`b++;u_1V=ldfdbcsD+2CCK#C$baE&@K9Uvlw<=`xMMW-oUgQKRt zzF`KmQXJX`)G?#JZvK3J5^EY8Yk1B!`lxJu=i-c$cjerB!TYBy{j_z}y_Ju?dFr}p zPn`6^KR^7{pc^i{t>ZFPH>KA8&xFmG z!Jmgz8NRCt+fpe8R|h|?2!9Y)Y3?L3pK2I`Mn5syz|aS;47wa)+XEC$&twhOXf#}P zkeHh^3{CSS<{1rR>`lF@VT^SMDp%;iywjopZ5Z!#JpPB@$hJyqU3rr z)^whEpTSkDr9~PE-WN4>wl`z{%DfZxTaAk}=6xP%w6zL&b9e?E|79bNO6Qaucw&^E z0E15k&Zfabd3{5(X_bY>4sH<)BL}x;wjdbfEGCSn7^k9UCzn&@*-3he2$zsoTUYON z*EG)-dgxPf+-_QFd^f{{>^yuACf3w@YA0Z0s|5ZRxaCz{DrK7@3$YP}laNE>%Vn8z z7S##XVmG{3Y68r~q6WR#Ld#Aw$|@`|bhnDh)lD_CYBdj+)#3x?45}BQf{)xy&cQPY z#iJ%dj*K>x^pCH*e_VC-JRHNB>nyR`xW-ifK= z+J!eLgD1x~HRE3BYvI?GL?+CUrgTljWwU-18uryX%84Zcig5CF5N5myZtVGWkQVWS zu+`Tg4;G^^_-IoeUuYLo9$U9R=1(%pyUsqX`s%8#ByrY^138MdJdP_>sq7YNFG*-K zAgShr@_P^1aay6zbJV+xix)g&X8AJKL4N_U4*CL;bs&m^YA8l7f~w(TyqUl_F^`+t z#c8~Ehlb&l7OP6Et4V8~&Ic1TuXM$~RRty!M$G*aMO874IIJN&K225~?~`mhA(ex39B@{e29z7gOxE*M z32~FPhd8LCbDvFZL3XCPSqSWBKK_=_{O<4WhLA4XH0GPeG`4@`0jT`Gr(FFG z;;(mimA3_+61PUT>z26Li|N}S@NJT!s;4|L}%pbb39XamfFD^YbP z1hE1)#dRQU8qPYRPK||54v_y&Pf&>IPB9^lf-uFV=m($(gQ)D*&W%{vCKK}cjJAU^})sMUHzOSYBjL&16 zyrYjdh1I95|JP4n;n$mAsvlf9{e$r78)Ix%e!1D?KlsIu@EB0trs<@dy6ROOd5XtR zzFBcE+UYCbEJsdVgQtppE#mEjeCCzG*nquABCsUl(54=R8is8Qg+lOX7-MpT8IK6Y z1d1y^GLS2>|N3s71i$9Vk(^5Fxie2{*zOrfW9E{RYn{t%&)$!Z0D&~-sgRs*b3|bd ze3!oeZRBq^2f~-TXk6G7DB85Cpq|#6p|hUoqiaoHE;D2JEULs=1`kV1KapMOjFBTo zN_vjAPZgu>J$Mk8Y84)7w9QixO`%@`tRrdem0Y3YI{>^FLKkVYeI4k2ftTcDt!c0+ zL>g_A?hMc@I}Y84h;PT=95z7&PNpNt<9m5N8(dI`HYy(gx^#_}`HMCx&+4VTAA+tl zR9=Kp`Q#9Jkw)e0JEn%wMYd+Fk3<(TdY=t>OGD`X|Iz!mw`Qa!U3ERIBL5Sk_a09Q z2T{r10~`s$+JScx#4t__yL+`)L0XK7K+6%U*hPv-o+CHps=AUbGtda6JphKx|J_8b zVyqgLsP{lT#_4j9z7emp9HhS>AP&->0>rFiz?x8rqKI)UEe;c^Fs@DzUrG!aU*=Ys z>!>ne9e&+MlnGlfUSB|DQeeYuE_WcoQ+rgJ>p@}hihs%tw5o%@JhU!<$vKGSaGe%7 zQy^&?EO%(N)1N8#uS(coh97%CVC_*UaPAQ)uqr{h;$tbWGDskJnPKj8O@q*>7@0$s zkgB=|al8B=IvcPu4~oixjWYP)f=nglLnUQDvQ%jodu9n$c=l6)gAI|)5o={CD5N-d z;{JXt0IQ0l{e+Rq;3GI@8a*IxhC(cUr(v9*P{SF`hv4%JLcTuMW05KfvVgUagT1pY zh+|R|I2ndi{oRSm;BnZVazLVzLSrMym{L1P8T|2rGXZ_1q`V0-R@UTQ08k$=q)OQ* z38(JgKLC=g%HS^LRv!N=g>44}w3cf;5m^hHL@oS#!4 ze{!8N;Z$ zKUHjf+LN36iq~4Rss)XBD@6<7#0L^5R~{uRnhstn*=(y47Pg5QSBhxpqL66fSUo@! z=aZJD)5;1it}y7VvXFM|brFR;fY`Z5WFfINy;-?s8Io2m_-~X?^g%47K7F3dy6Ev`xUvs<1GKy&dd9Jq^xdu<(>iB=|YHwT~?yl_&=P(T+8 z4xUXXp_c&3+2|HPiHNmZ-UB41oP!Qj(hUeezXl{Z9t9*h*yT!&E=WLt1QC!k5ja7O zx<@OOhdBp@k>QQOf8bgk{HJfpPPqE1CD*LU%38G}_x^j%%^JJ%UvDfrhsj~vnOt!e#K{x|9@#j)`0?=L-4jGE7E4=xRzD@XeMZM(d5kme{z5qscoBFMldK0EB4r z?nYcOXg<*BSUu6?rK4LYW!HcZO&(n@*MnvRKMx24@fS(n7~p@373JMrRYow^vr&KS z-7dDnod^CH*uM#RLFzxmlWq)XuF~k(4kA5Y=6j|_15ku$@~#El!d}R`sh9FvL8to^ z3*;}ve;-BtB1B#^|9ww}(1{hBpp$-CxMcjj(F?jkp!*VZ7juM#z`%@$8x+2nlD1>LRKoTL55D{BqcbY561U! za6wLSNpXR@xWb(?A+KoEh1Kqgyy}Ur@mHpgOiQ~kLVWQA*Z7XN!|3un#RRfy7Q~^7tgDiTQ@^H!wkanT?ILnB@;@Db4Ojs!_MY6 zHiux{6%+HuPY6MlmE@P^xLp+&I@lsV!{2KBE&AT{3~+4Zf`)pJ@U8Kk%}y-G^$D1U z!pUAxtO($a!&zS05k&F{IO%@IX1rAHcO9JhAYte-lxbd@V4{(Vo!z|xy%3&$JU?hV z)ST!qm8dy!6GaqEK=#{Uz3VU2NZki#`o#A46nS=&@BqWn&;yz=@t-Fs`Yr4U~&JG}0lWEEg96hT%^-M3he@DCb9x zlk+Mej(x?6<{bW*9=0|+9**(!pQB6+c9FF|Zq9_j<5Jg$6s0T15-7}7B6SW}jKUP* z&TetyIz&Jm*HCNSZaINsT?dA5ejpKA<7aAVoK_C`5KN77nQW9jXp~yxn-iz&@v~9( zg)1@nEDyQjtj(v)iH}?d((77KB~*&MvKh%rV6kOO{UIRPQpW+3t#S$=*;4BQxP<{+ zP!%1o&CUSRH&)S22X=!*Yq&mFH>_-oH}^BH=%We1@Jn?k`CO}fch+NlsCmFQS$FLF zAwGsUf2;L#v~>9QYyAYj-j+m*a@#II>O{N$c{`-21u!?810R}S`0gyiz2E(-4Q-4- zek>c>5;e$oXA&S^n}gSu<(j`u@mg(gJw)2s`0LRhsdUG=!L>#rI}imoi|cU3&qm5# z@7ePzDyZ#z{vt8a$YP;*r;G5UQO}pz2?>dLy zwR^qm6(qkCboklDA75KO3KVe1wwpM0<9gRox!2-%-wU{pkTS`JtP(BE>e zzw%xs|Cr)>L-j28J-?KdQ+WqYm>iG82qwbG;~g8?<^xHw^hRnsOLz-}SH(MQ4JSdW6JxTzP#3_@s#3PW z*S3gw*D4z<=$2=#SNgYQ0-=<2t6l1i@gtuXBA%WJ+zX;KB?6P$#zcM3CzG~lJsdZ# zO7$}ZrD&@SCqX3mGjGb+H1bYC_4HIml*t?aHDtVVGOk%~D*iK2p-5eQo~iOc&9)Q( zYMYZ(u9a#Vk6!b+TGh4@0%%u7hJ7t}D;GE|S#8Xi;-}V~+Q!GAtS(A}Zj7jN4o*_YYG2EVrx%^-fWAcdP1WCG9_%l&BgIKRp2mKOzDq0DS1Zgij*7@aWZLfpqbr5~YczGm8*=s6F`1scLNj=XIYsflTbMsk- zBR!7Dh1TC*XvHads%WXQO*&Q4)(U+Zj?E>%x~Yx#Vk< zO0;%Wv~au-xjxzY@!;^tl*fzg^8K*Aijz-PesUBH;sx{0O|+_Sg2C5vhk8W5bV}O_ z#Otr;6W0CipssQJY?Q_#tri6+-eI#5+&A5YcrjGn-5IY)5zu%`M8B?k4&(q^epZSB zHRCVVQi|&h0^(qTACFkeWL$~23;%&`0j!8Yysp!)0dy_? zVuepXIcCFHT|WD*(?ljH)rmjp<51QlZi8&X98OvE2YbG`9(*c%$u8((-KPtOwXLjxWPb_jGE#sok!@fT~+`Eg?kOdB7zsDWuw z-X#1$-eKx`mf<9?<%&M!0y^Nz_Uj1T6lV|??hDQ1~Y?$ZB z7&3kSdm5yXH`F>(Fw?yhaghRZZYzg%o-o+SaRaUOD~u{{O}n+ujd|4|Y@NQ(d3S&M`N(D0SUz0U|FN;v1OC$Qwi3UV&j0uQH=T0BsCU1z zC%w68oo;1&V07&rr;J{C@ssUCDn>n@uGo)U^yFXGUcPh388^NB$h1dxzgM{F$z{)O zw`|KoX+=tIDg^SgJ-?r>$+;qxXsi=)x!TZE8g>vFXryMI-*<(8C=}`C~XRQ12$5* zMZE}+Y@~)G%7yp;W@|K6Xm*Kgy^$SS#v#U#Lx+}96*_o3{A58h2Um96*MIROzR#ig zVHaYS6U`AN-w&pG_CLn22$#c`(2&D&MYH1N2FpNDdlpW@)Q~kETtBA?Ib(2T9d1A8 zrbnbB%HVSG<1M$$S(>~zt$Kcfwp7^lnYYyyQ47IxXiIv$^TkdNlhZ#;&KbRs!%u=a zKW7LzK#Ql$-~JYdcs|kzG%;A7)i4~$F`N;=a2Ozi!%}DE5P@}R4%Y{6bvZYNVOE7< zHilvT9)^k25;GJC9D(HZv_@(eLjk`uj7C=uFiLuR7|l}}#!&6oZJG`1?SBSw)mb@! z3m^h{KUM!?So9oH8BGQqgF^yEFdUiQ6h`x47-oGKW^WkglE64fPiwk{Q3Cl{5=O%l zh#6=FE=4{PL{n!iMqGGFsmvsU&h>5>=5QD$iQSC|I@fR$CfG^onV_>-*{T_C`trSh zONiI88kb?GUaw&|oRi7ku3_Q>7+rPhv;gKLc3TJrW;`(LgAB|sf#LgSU=CGx;A3PD4J zrCpOFF~QDGxm0X8JN<_(Ced)r`!u-7A!sPZ^0g*MVuIzIgIIHZ45z6yQ)PYx4aHdI zvhzhSFn4MgV$JF}=K>?0a0Z%uU?}!5xcHz+W9CW{T)Y~Bwai;OH7>?VnSV8iLgetP z9qq(|ek>FMY0Rl})6r%f%1DGeleW&#Q^Ka8#zh)4*9E}XtZX3++1J+ZGq|Q}T%<8` zIe;--fFAqT$A34texh-a#>_Q9aA_}zWyg$Iyl{H`{zl^>jm{-EEH4yXd@FTY1M1Yc zNCU2*?aP6Ji{-WA?{CBAWEx!WXk4T*r`VsIVSxJYB>x=3*G6(yGp zdR`R{SP)2K=DHXd=^mD}g$v#qWu$e9#zh)4*Cm20a%~i8T%-Y4P;I0LF1|s`;UE9T zw?ofimBvLHb6S@QF1(*E;iSXVt(BVvant2zFlr5>r@lfa&B(nH7thnrr9MFDDPb zfOF5>y5_tFY(hKTwR0O97i(u@xQevsirICuq7!7NXD8?IAS7qLV1%}u6Q{c4RE*l1 zMrTEHBTh=vBPKHbF>{eAc-So) zKt*kHSneS}H0t7<+)8m!Zb3ui+?r-MZJW_pha)2!=HUbu>GW0PA*abyF0iv)-^9$6 znYU0rtp$aYMl?7)!4P!N!;2O(3`d;kturTQVp_UW9#j*K*SrX$p_0XXG72gl%)}32 zR-D1!3I5ZrYVrC+X~T31JG*AyOdQggj6;3CsXd!WzkM4F^JDw1MI}dYiu>(_WkM4+ z#KZ2l7d8aK%oQ8CF_FsfxEraL3#0gk2N@*kI8Ra*RP)t){Kswx{?=6zs9i15?;^-l zXVKnZ{b?G7jQj}D>W4SO3w3qfyjcxS=dfHSPq!K#_QL29!BPb7zj^*qeu1;NU`*K< zSE0)p)Z=Flm5bc)4~$jr?4jB+x5zmiALkZ2OUg>d=8ehAacZmF*+b8I8)HE-s)ov|a0Fp2~Hiam< z@b87t30?TMrO|P^XXI}Y?qp!P z)R+H4qvH~aL1&bMDk*25VzCV7YAgba9f^)hT0V_N5JsVU7WjTxZSCTUD`EUalJ`%f zdokudcCMBp@HrZEMmZ{hkHKoq6t37Hut^wnMmbJG0e=aahqSpi=Drc>4gtS_YcD|| zlDrR)zj|cK&Gig~X!Y_j;(iMnKi4Y|0?#+3U9CdgU7)#yD-;N9ijmTt3j9LQY}e?b zmA45A{QwVnCFkG>(elUV{;@_Q2yqeV1}%IO&uQpB(0!rNvK*1xALZG&Vi6Rg$%_Tu zSsHCXUWo3$sD}`F(RBY)Lg*st;O8S>C7@fS(Q?^9(1r8|EN>TRUf1aO9)V8NA;*mt z_+Edh(df8Hy7i+GgHnEfz8YpU z)HgI%&k_^r?|i_A=$(=Mo}mBYC1dYIJR(FCFAjjj2jh6F;{hWCM2Rn$Cdb6XFPo0P z0Pt>hp-W|tYr?auKN5uRh7KN3_z?hGpiWN|VZPPZ0MPKJ{5ye!mixH9Bvx@a+sRq3 zcuy?+jYC=84@VB}qjO^932r!^jh-8T=WBR1{_JAE^(q1VM}!>LTEQjK!bPmT^Oq}@ zycXjxlC{G9j5HZ5d`pG>TF8+K`%egn%feC{?Fv9LV?k=$krno9Kx)T799N1zskS{` z;81_w1Ib!$g|Cj!@Hi%^BeRwzdD2$o*hdwlc~aDzn5+Va$D!uLWfdfQ64jjetb!Cz zf|`?%RWQgCw<71vQ3dJEr>z)gZ++c!t{SUu?J2icKVhAwx{n5_7REqjIOojr@jcfk z^jsg`bA4RT^)Y_;E~y8aCm%3Fxd8oRFa4%mrBFB!R3Kx-P)=6( zEYy>%zgq!~6Sa0Xt`!1$2v-^V5g-l-?ZS9R;`&&niksbX8X$=iHC|EyuNWRZ05 zy~^r^I2ki9Q&~NBsIt0ZSm!@&KF=Ote;}ZPfX;=EHE&$IK{(v!fls`J=cr5Kp;gM5 zPei2qD0~?BD(NS}*Rr#%$8$>cH2BBkA%-#Vgs^91gLogpL-iDKT3BV&c&i`DsVn^D~aBuAR(ANgALn?GyO3$C;I9_qq0{u8ocBRoCu7rgkG!%FRol zJ+*H$l4r)YF=Lz`1{{pb{Ow@=lv{p^t6H@S{nX~vwW%-rTu=Gj8&&sif93_ab8k`I zd-%JKS;ub&^Nrs%%r}0Yg(AG3^^I!FI_7(-$f?Z!aOAc_ZP|%Z;StJ0tdWIywp|di zj!~UEP$Jd!RO6GVfO5o63`vE%FoGf0R=uMX3Hz@f%5wi zi>^G(gvIB17O$|cZ`Da!F#JUmD2*&F>8o~d!FXgW=lH3zP}~okedJR z9coG2!!QY`8`qQB#%RB*Ly*ai-n%ZLTnOfnLGbzA9gxhyh`8}p_x!Vq z&Rjw>0yrulN!*QqiUgfM0NoRS*g9n_JGSTW7i&2cH8c&7-I5AOe#2dW9u%=9fZQT> zCZO8{t{%{R0%`;_M#Q!PDiIJBi=>o$0LhWS3xIwlI9>uYR?zJMR3jkO{m?!Duu56u z-ECD`xn$z4U2{ywuSK;Bf)G9QF%KO_3B6c|=POtypo;>~m4Ia8tTqWT`#$`|imz$V zI3%e;eQTnx3SYduG;hZd?~z31)+)3KW%Y89TY8d3+ktCWWp#mFm>r@2emu{vx1tzy z^0W`58kAa*sE&=F1ak`a5q9i*X)wkk)#O)B_UZ>HR=H&>&_DTVa;iG9o=87 zthVA80~o8fvroJ0>;1zG3~mw8$J=RZcOBb*epm#sh_}H+wcQ1~oFi(51E2d$)pK;< z8%TM?_D}vChpeP-M9=;DhXPhszpcJ;Sy9sV{jkwVR9y$R|7~D-GGGi6oFfAa0cto= zi@R*hdD}6b81sYeyKOtcqL!zCVK~!pW<_JUK(L$}U>O9KVS;58sydYGvQm_;i!7z* zkVU+0TGx%^pt}QIcNIKQi3f!z>8m=5hqXrU6JUGOUfsvL!M6Wg4GE08wsUVn=l;a@!anWQHh%gm55U=3uIfJGt2~fZVOMS* z3MWabYcHO@6VDu;r*1x-7#qAfStpL~X|nft_Vkp;S5JGws(lWPF%lbt2v!*^p}+Wg zM+`ACShe3i+OO?I=^c>Xh`(6jKdDJT*|_H85B96LdIat+To(w4u5siy>=i)r8@3P7 zQW4t?s6{}ncq5tx)DFlipoal16wsr9776GHK#K+R6rdXf^emty0@?{^nSgcyVh(MXc+D{?E**|n9d9=7h5@QjR!XPeQ{x!*=hxT@WlE&5ysMiwM4Seo(r z$cgp^^%%XTzNNbNa_EY;4Wlvw2UjuWX4@e<4z`Q8H1|0ql5g&h2Bdn9tcbTBdaXS^ zRz+TsAEFPco`XT?T(miyOrAB--uSfYI)I_ATD2Pu?LbyRVq@#o(l$4NGh3WAk5?J} z8D0szd{KI<129xS*%+gXE^DIN&Hm~L`>O&xKn$A1&}-7Hz>qYfXXFyQatoKog_kvu zfl<5I4SbRaU)SvuZQk{m z0dyDQS!AJ7ZtfNx06JK907uvXYz3y8YYZ46jbj&}zTD$EfKI^Z1HR3RDql*@2jy^b zAfCo`qS0Rls9r$S^qngpS_RJ&5C=*P0_p%XUqI^sacB|CrX!qT;>*>NKr7NMKvzr* zJbIMFA2UjAel5nI^qP9cYe)Q}JMqO-`>JIzKAY-__l?C@5Hqf`eG6kKV#AI3=*4Mg z9lt&+{*9(9;3m_%HV!!PV#KKxG3wIJ81)oi{CagO-U8o*&KO??-q>S66c-X9Ef)he9atIMtO1Kaudv0PdWG6|N+fy*-C7&_ur4*T?u4$N8qj`=kXk zvNEwfM|wHH2Xs<rO@+>`)rdH~1gE9uy+N;>g8<0@8MWgj&qt@*NEOt|RM9uszD zb?%wo&ZP2+p2mcp#`vDbxSqzCo*^RV_;!(`KT?qsBJL|aj=xx;nfj=J9JtB}(ItT7 zH0X)|#CFR+40G98jlLhSnB*L-KyN)sNhrnX!pjN<%~IZgBf=E)EZsiW7WlM}TTyk8 zlLUA?T;^Jb7#zfj8TIb0iAm@r7!%K!jey?bGz8Q5{I+%Q7Yg2Zb!po={3c*Jz+bzJ z+Tpo))U-6u04ySYtCV%v$S78Jj)fzJo#CgoPgiBkdmV5KtVh934riKNrw=yo$M&9Lq&b7tMsw z(y~&Q8@wby&<8f%*z zH4bjqIe1`BZDSJ@=mt5OYHJG|15DzolNz33wSH`GQi)Fv;j@~++eKHPQEUBBY){pf!z-5E4=;LX(vXK9 zy=Bu+?tAdPO=apU>)!L{-tf%7%I|O6b2En-1@hM7smA*zW%FHHis*M)Ie;A zvRM<&1lpbcijW4H%t4#LjImkS5is0vefqf);&r$Nl7=~uqYkEEV19|aG!te!?uty9 zSQPOZ6NdIpoCX+j<^i+Hgn1B{hfSEbf$1<|XqU7zfC*M&ISE*sH62&x{H1}pA4n*e zCbkzeeFe>VxFYc=7LM!+%ob|VED9%ql4Xu;nb=RrVOo4nv`ma9iPprMKipZUvwX#6mkhR+YP0{q#m z{9v%AYQNYYf0~7LADo{AK||G)GXahI{XI_v%aO_}{RIuxQW$QU`99{Ktnpwur{msc zrAi9RKKQb~uMMX;L(qJTE4iPQuv~Bd zp&K*a(EM;LWV2EQh57m9qz};CLTSzxG<=>6kq<;>?V8)q*arAhxRT{*DyZ_U^sP`L8tji80J@Dm_LSLwuNCn(=diTrJ1X8~&43is% zsS3l~5Qe#3!x(md4{Mmy0%>j6F!lhZA74uZ!+P;@4Rd;c<~j|N5Ww*Gat7Ms$s&HF zVa^I*V);5C7&fYMVLaG_ZjDBBW`OHn4Pyyl)`VfY!!Z5WrHP>DXRwAjBOqsnhB0hH zf23h(V<=1UmoPbRm@vWijQn6oD>jjEY{4xu2fTiwaY>6pV(561a|2p#%7>847tDmY z5g5Li2F)5^1_Ut4C8g=ZaOV&h4#9xQ7=gQuR(UwNO<+a>!+EjjH;75+_uvW*Be>Fs z0Fz#(uqmMA2A~JObS{POq0oS zak(tOH6#s~d+-f}I^}#CjLGEp{XlS9nXE%Dy&0)9&s@tk zQfHpOFkzVISdB}RYX~LNfcsOd)UBCn3WoaSo0X^d|+h%ti9ZVf^<0ON#hbU z7J2lljJW_mhV|kb+5UFQm7xzm7zm`%Ez|@;~{mm`d805AsEt(TW| z8C;iYT%<9lb)ktXf7$eX2G^Au7ir8~0|l4f^*q+Lrp(|Pr*V91+WdPxB^;uqagoN%HAryr9cMVYXXwiYmsjH=4Y-2T11|># z?gXsl2@bypM>eO-uso95yCF z`}P6~YMPoyAe?Z@6$|TbxS`%`!740zT?outY3;Q&&2Fs=L!fWHPdr*%ko|BJZGVSDsmUXsI$1p znQPz*id?QS`RGY<0=Ueg!ou9*QkR=%o&`<3%nU@P=N9J_RyeMaEQC^-dGB-qI{#a*TUT%4Axx3gY_egYE*+cbRlI)>1*+aRaojr7h6OX*Q zi5){7#sM>=EoYcdU_hYuO)2nxru z4jno&ZG4qPp-m)uu)2KmEdeAFn~&`No`7P&zFMxxtH_ zL~`2uHs}s(v>ba!vsSZWX4fBo45W)>{YH7`f@VYzT{L;QpyA@k#Z{`cmQWjeMnzXwk& zTqCpNFWk22Lg4xy-<3;r0c^1mjH6(11oM~snWV`=sw!T6S+(_)$536fCqeD@9_y#v zd<9&U@q?DP{3};!`$&tZM8xt8Bp}mD3oWY zB6EO6m}8yOM^BgpGIO(_Lo>^JB(B+oYhrUYu8!uBvyoX#kXq1Qac?rg2sy1?=&i=V z3?)u|S#U#}O|?x@oe4eLT01;_1#bVNYUSQ%g{&pUCm3>Tvuq0Ec`KTIQkxk|L56lM|>^2S#k7VfeK4dyz8Uam-39e zn~HXp?YpV)-O-$*c{PVd@SoYeAO7IaJSy3ooRZtAE0D**f{F^{dzgl6FSM4B)j5_q z!$h{dEqg7?3e>82*fg~4Qf+?sfjKeb&{WIq$_wsKl^0z9?EE0kwh_QTbl`vheDTi| zWO?>3eOW~fwCu*CW0{m^HhRB^Q(7-Vmc3sjDy?@RS+)wLjT`UYC5f+b z-0@js6C0n~cM2tn?pi$AXpeWuJNy2|+TcSv0KnpN#j}dUOEwl6LPLztc-@DWw-e=J zy>Dv1B4VCwTAs$*vtC1}Zd>Zc!#mII7}&|$^10#`3}2P8sqOVmWt z1atu^RBXCf_(0PHj;f&C^og|$1~dSW-7*Z2LqJysAU@u~f{q8sa*Hh1@?$`4<) zzruD4?K`C8wSYzoI&QDYG^hhUK+x>~t z?~Q;Y$FBj&9NcHqc^?3jD|mkkNao;CKvK$|07)s&1t4zBN_o!&AisOtJ_xb+-8;o^ zsOia;h+Ypa1c&rbFi=3rxbn{~7U(Yr6e~6~FA}&eToI5D5vnXAOh-ebgG<&_EGwv~tB0;ybAzKso*G!|Xz(=8_cS}EduGk5ZH!D(H;)vv8ZikD zkZDVDj=Cnte8{S8#_>cmBeNsEwz-){_v`v=9gog#owM%9Wuf|Mq4%o~zWdo9ZvXVX z#?f<1oSSZ)dpvzI>tpKX?0@XaUp1=a!=H}3FG<(?dZniSWf?oG(p}d)&^<1;{btKe z4?j3`p~rj1Eej9Vm-qecd%t+_Q0-50mY{Y;_&)W&INdXc;E5jFoIFRI&EmVB#m-kS zx*T>&W{s6-XR&i?HvrTRT+;n}DN*KGPU_->98T*vl{@`B+au95r}Q@}vIY(3jpqDB z)13NdIs62g zFnoHNoFLb;rvYoTa_Y*u?pgl#0mfO;=b=&(fE6_Og~piHzZsavf_gj&eqh1`?{-S< zGqxQD^X}_e+M_0odEb&bum#RAetY_i`J|9xxW+{qGgp7XHBh5_w7L{swa(S3agoN% zb-Li^OL22bsA}XpmCAL%*DBt>;V8+E@qXt)h zt@)Bh=2|*&B&CoOG{t87uvs4#F~OH9knzoXXxwG^PMd7mxpU{2G}O%0H#dsQ#A3eO zqcDzs8{)+NRgpN=(g_l|sgwQP_7jXFYh8Mpa+@M>l&#!YKwgM<1}`+8;BlVczK~(7 z^xs-ka)ed;Z!au#75`gH3SG1R_JXJwaH5;<-)h-kuG$}eExW)urZ7LhY%CVmF(NY- zvIAo>d1j+FF3TP|KCrTmHTN+ttd--8NI5La9@^Z1b#HB8hC?F7$SixP7;_nHMNW54 zVR@c=tUC&y7_K2FV!RgM%PmF*%Sy13z#Vw8Q**7< z?o}s?w4ToS$m!?|pXw{A*nvk{ho-xW+4xGHqOBcsm=cMOpXr83>&qdh=kfD-7se>i zY!iVW;7Ia*k1t{jzI%_!)i$938HtXHkJH)P2ZcygYbGQ7tmp?wwuY8p_%jF4)dx}4M zc@c+>B&52Ykc)%2{R;0pPS8+Wo=V+->|-(PHa}2GLSB;U=}=!*`n&ePb~0~}zaR-G zsl4GjD8)>J>(;7!u~L_&R&IkKyRGVO<#C+Su+26t9wl5+l%_m>7z>Na>P{NGS8cR; zo=_g|wl&84JUdpwNY;DgWaZXZ@%oyNQBYfU_{UmR&n}#nVAzQBoC<$&jIw&%SNe}jHboS1Lxm9)M;t*I2V4*p&Hujl-rBmlv+4MK|M$#&o~k~5 z>OJS4yWgt1bq_wue)yq>9{TPdZ+&rP!O^-eU9~&+EfxCKdmh_-OWi*@xHqgn;?Bv{ zT~9~vn~lqX%v}x1uE2ZPwyFO+4a?p2c{}D^vwB)P=*6ZOUt_x?;awHmMl|-vP7`V0 z!{sWx)Yj*%abrJ=-Rr-Px-uI+VDSZLw9B(rgQM9%-VXR(HLgbE`6XP_u1)(9-gehe zdhI)SjJh`MsF3~9vo`zam~DZ~O`bG-biNy3;KO`wBDKY{iY{39{h7rCD^uI)R$fFa zJ!?CpW6z0*t~sz#6oO~1XEm~X$CZT-1Zp41pA3^a;FSH-WNhMuEc#hK3C16MVvH?2 zI^+Nh4IQ8+?Pr`48%;#u(3Oes%4@?k0u!kqc{`9pu)1zj%9W9LBwJs*`^uSJkJ9Qn zusTrqN&t_*@gy1hMCH8+-Ek;)&tr*R?%nYwDgdj5s0^ORlDzJNbqlw;P!&9@4#L%J z1NO6eRYoK?v#@^8il^{Lhpe-GcDga#H|{RAU4@&&<~SUY+FG3Z4;?*>rA1chGZ(gQ0&-i<@=Sny1DJ6uJ}?gd#Xx|bN)y=<*7yuE(e zCeO+#uu1kX6F{N;S^AeN(G4~DpF*u!*&tjmiygeSuiB#e7IY}8YeB6Rz0OtaV9?{B zkKsijM2m7Z`&aPS=y9&$zxvu6>hsW1i9QA%!^x9@`w=EdlG79YqaT83i3HE{emeq@NKh zw>`=CtYkwG8=u7CeTe6=+-?&ayf}=5x(Ey_~_mTc@BK1Pak{2w|6{#IoqU2r&-3s7@ ze%aBwOE|swnfY`H^NHWnprQ5mN4v2xL08nanEr)P?jp=L4tO5h$bG5c#672RN(A0< z1rFlv=)e}dKASZI{V>1!_hQb_ts%Py-rRM;RxI4sWdinRiOIo^Eiu!g_jkt6DNF|3 z*n0}LcnaRGI}r1=r}NC-*j=yl)ZTz~&gcz^&Jn#uUs3PxhV4G!wtVn+JFwG<*a&9T z2g||i*5LgEHDUk8pV#ke=l<&JhXej2b$eZa)$U@RWqSi}A$_YpXoxr#J8uNCyLqzS zT=fBZFEWavJz1~RVS}9I9Rq2oC;sS$9(D2SM){*X+5YG;>z7@CU3T)KJlT0s{a>li z<0g+NXHic6C>YfByf=>qeuf=^S4H%=4hs-%=D{(qE;}v|5lF1(csSGg{AdXZjiCF=^f8YcIcf|uU8eDRE} zUuHb+QpIAF&tzCI90x`?oW}}k2F~(r+-y+&aCo(Iapq?rUa_Hzr0&B1L>!UYD>$

    sdCU1{g12GWQyh6xy9H)>8)`BCv1Dqi)>*n%rZu$xd;G-@RH%l3ZlDN2p-6f^=} z%RfJX>jxyJ@CZb(>rmlNM%ed#@C%RPFC#6)PDDin5m~g})A#SVn#b*l@&K9np{MT~ zRKCO07b=Ci>4gWr_Dt)Ee>i65!=~x)fl)x?c$%37wbL^RVuCu0R8_$K&Y9bB;Y(Nu zb2cKjA7KtqmAF>8-cx|h4J$IYg8vVZy3PxCf&V(>Dx*Dp|1Hfdq!r5!;1*v?9}H?(_`W@2N`z zQ{>sq%tqLnMvW8Jfy6%9~l|r zhcJwo>Bp(FABouni~PvNnQwafqL`-pX)p1zN{D~Rh#2t<#M5^JkniAtSm!+0-`S7o zV*GOFIov`97%}SlV;6aiH0^SOIg?ZONpaXC%=6gy9Knz|1KxCFjLh4F-L^a8Rm>U1ldDmc;wen7sctcX-m{&Y2Ip*LBHoqBxn};YM zqkChih*o!ibc*Pzy|Sy$k@r*7v*US0icVk;_eJVJ_1njMy?it~Pbxzn8D%Q5_4ky9 zr7)~M;?86#`O(EF;+V{X`!-2q{NLQlhz|cF5)RSRRX|vvv1(={k+tRUXOyQo3|4iv4ZBU2Z!G$_( z7rZr)wCtMG>Pei1K7y5H)H-v?pT%_UNk5j0wEq$@syOjXU({`jOB+ z=Ab9z<@$+H^-0)lF=otHp6vIyO;>(2BJDrEe`b!WWy={(>2zHxgm z+*s21yDcZYx2xOuJ^rbk$3Izi($cFpHMdYgUl`H<_)MPRryhI)%|F(~ z7IFaupT|ex$|rw(?tl~10ax5EK8xr3fhl8>Z+2oR?RN1wJj0xezr~}7;JA*#mFBko zU~23O7yh>_fLOqUA(#sn9+3EJXvI3rQ6GU%GK9h@=;=W4}~OCl)$tPO+jP--g6`Gkpqnu`{eE?iitdj%s0 z8%K;Bfvdkq*TLSyEjS}V@rjke8Nz2*=fG}q53EDuzu4X9Vv; zy5q0p;E%T5uvvpW*2Nab;c7UC(fW2S#Mq_8!VVY5H-_7;JADcfGU!{r5F>eWXow1u zQ)}Z`?ZFE!*uxghu=wfE8gwn#5KT!D1A8p*ZDPQ2yH?hqdZGuZAPc8K@}bS{?Ig*HG$9fyx5Rot0~doX3Dl!_O`wz$NK40xcW3tI6R zFTlj6mX|GZ0`cuCFAAVYiw%;Sh);jTSG|eli{=+6<1@O->avAr2*DY ze{&Q0J+1trHn*62@2O9IZR+sFG71GBj0)Strh4}4&JT#4U)83TSHhukW^v7YQI^va z%pwl zFt7bBa~6Ik7~;jhr2?9JS4N=@%H%d}4DDnB&+rA+Vz|appH{ z+rjS-OryeareNYseRILjMyK`!J2nK)1WcT%kMW*}^=a`q7?>>r7vdfMIAAg@xKQu# zS3tf1nD-Tq{jeFYX&>Wl1f~ZkK?vc}TYzh$fw@-Un$q_yFz+>^?{et-2AB&^V61YU z7S6s`f%#nF!r7M$9qql?+7JhW9cNGPJYecV;>_|m9Xjp?W|P8kv@`89aV6mI0A{RO zr(v&GCaw|%dJ{11yFvhg$uaer_Emtt5tzZQ^TF-5ZDAl={pYIwnwUNvG5t`C>X-{l@g@YlS zz9rCC7>oJOX#&=yzUz7c!vaJIr;mO#DuCJDTjH9s?~Xp$LhcNS3#X6iy%3mvd^dy8 zl)n2h-Ri=}#R%c_-HvN@!1U}VU>ek0%GWHnW#FF$%%2plsd~Q&m`_6DOnuKmUn4Nj z_LuS6>y?S)9l#j8ead46Ltr-;uKw)@rrSUP3tRvA2+jvge4NCwIfc?U1pM}cvH2+u z2Hp*tIMY7d6l!I_T%vGB`wh{bUJuMY3dej7)t_Dr{v*JgMFSARl?Tf$9+)?p!EwgD zQ(>r&Ayhh89b2uc<%ooaghYD53NyHl>U%CQ!rox8H7wQu`=NZ~m zIzs5P~r7QEe@7|4>-ggK)UR!1NkM zDS4+74mTW_InCf`-(rOk3ULahuN?eafs5p=9zsVPp>Ryc0$^@ZxNzwx0q!ASI*kB< z!0{-QKH}yBv$X}dGe%DvR$1imC|2KPr`B1bomn+?pSW^l}xQ^&w35)OuN z`7#sNW&!h@!g0P9DqpCt<5;}^!@&?vA1_bD>2igOz<;4HXzgPU@E--{RfXeIr%*Wd zV=?1!vV>5$lX1OE3vle_2ZhD;uF|9Nf|w56LWMQb%Pl*4S5@mc_E(nz^Ps}X{y_Ic zZ0h4Q_eo$j+HpSlWWdBRy{`lFb~8BU-!5Q|D4b!R<(UB>+6A}}J)V>$pfUa5S?l=- z5?1+Jto5u|SYA|9eC{t_>517v;DFtWUdYe=;ZCI6st;<48z#l5FV6R}5Ep2H*96fp zX)M3`7Ib5^PyFJgd>O*X=5wfBL z(xPNV!TO_Kfkjc+OT*ge*h>7|bfGcu@~XqNABC(=wid(}YDNRP50*qCOYnd~B#(Cy zvRo5EIhw;aj-0kPhaZJH-r|O74*7TEntk(-Ho8~-qloGRoTcSwfReS3byMcOr6GrQ zuWUBtgF;;smWS*KccL>B4aeH|S&OHo-Jh+5#5+%;hzJ5`@mHLL;(%@M6#GBA+J&cPS3@4wfJ|w`vaXr~SV2Z6=U3b+oMTMRtLbdI*#p51#^c5e~2RwsCbAC^<6z07_PocBmAx z+HgIvtSrZYl9lCnP_nX|1WHzsSc5tfl&mbAoye=$v_>v{o{ldJ+C2QqK{|N&-Q#Gj zyjfU{1Fj))md&m!C^@Y50wo7s4!@E&%;5Pzt-#?GUT@^p+4wKJ>QYdAloctOaF{`6 za;QGqRW3_axzt}+`GFX^;HQ*mC~MM=Sq-PG|Xe?U#)Ve}x9lEWFy^ah8+aJ)q=tmXlaHH|YpU z&P`%K$+<}vP;zd<37wpqoCZqHKDb^~QiDLrxe52*lf3^+)7cY|s$aiBFvot22GLj> zgL!OiwAmJ7T6t?1^Pjr4ix#(bF}7Pf>|h%7FnL2Xav$$@as0Bj@E2&f1cz697iZZP zJ_aS*!cU-NTWF8+mTiF>dCIoHRw3I0TZL>3JwVCYe!4;Np^R(`gALxV(-!0t*5HZ$ zZ+&ZbDpK|9w}t;c<7mb0!WvZ6U)B)#jN<|v|Giyk`|Sb;%%FxaIUl=IN2|x2fj9XW zBkw3S%w2*HYXZmAcf^O=o0FoD@7m_12>z_vQad=18qE)YQt`QQ&GGd)_%Nq2H3A<2 ziKh%v8vX<})aOT;9DLvdsJk9}c_-rAp{V-FQS}oeMrB3Ux&ab+B^$p^5z&ZCK9+Di zk_`7o15xzh*XO_X>x_G0iuH*JpPM?KE<2xI*k59NCzRNpF5^?JLj?_4#>S=RB8=fug zkLHsk@#qpyk^-CcD1RrulPknCOP0)X9A2?UQ<-Ig%Eb95LCwZl4o-ZgDhDUN zM393M*A&RXiLF`=PE4g7ocMH4QVpQw;B4-oz#Udvhk=ltk%SSV3 zgOV+20w@k!Uh%Y8me*bQFU#vmP_n$92PMmEJt$dTFN2ch^%^KyUT=evrNoJjq;`Xn z<@LG2vrHy}=K=?sc+A@q3e1Ooy+r5LcKIKz(qk{u(qz3801_?+?Dec0`eO*;hYSfFCmZt`~Xu2>93Bq6TzM1jYVta{j zwfla^SZ5Mx_%El$IiTdUxE>Vy7q9jx&a$uKL|XP$8$n44)@1owa}TH$IK0|^oZ0($ zHTKxDo9DDxN{j*}B`yXfHLn6CHD7DsZZU9AfLbB+Jqt=|eg%}&tZ#F!{{}aY?T+RV z0bTO_1^Z$7#-leV*-+R#c!MmrJHHeEy!6rW8MDs8hsl6qz7horQ=R(B5%}nNR8|z{D^bnQSLA%B zb09A&aQro+Vrq^F_z-vPx2V>g;guke6kXW3+cAoTc)^qxCFWvP*z6_>ZLocPYSjMD zFs;L8A1i_ec70+LaypO{A+Ja1*V(vmJ)%A_Xa?7q9sv(2Xm14Q&F^uSrNN1OiO_70 zMifs}Q1$`$;D{6p+~p|4n(derHMc(EYoWxP6m7tN1h@RrP?1F_!?}ZSxCKJL*iK#( z>kv9$eDs*1sw!AI_ZcM2aO4TLneyUl$au-zKQpIKLsN-^%*#hV^fW zcxgRvEo9AkM^HYTw+o7S|E{2D{de7{$0dN>pu__^M040 zd^mq7C|duKplJQaf}-`i1vMMzPXwj+Crkw*2pf2f{rsmmWS_<7y0X=CiWe?WPLCrP zqxa$ZuYR3l3PThQE(emS{tW+QU-eHxG1Z?7%7^n_K{3_)1jST;AtD}vLZ|EE5^zePljz&tR=$Y}hNqlwp`VnOjuk={$=ZJVB8}iS9cGdS!XbDfexMP0*EgK%0 zH)Yjsxhe;rhfsZ#Z%7r=w21_@b2WB6NLKx5h;+`(fSpJENa^acTKi*S>q_ zEsxe!oIUT_Kds;Fed4uKO9%WVdG3<(e#vLG^JUH$u&~3Ur4Q`yedD%K?K*DUGHv9X z;OoKvN7SqzpA>!UZe2dm$F=K@acAB7B0D&N5A-S^+sQxWwWw29xiyd zzn+fc9%<*UoUvtP%@cE9yy4<+#s~f}^H%>qFALoI&R>7u`L=J5+qwFgC*JMZ^MlX- zd1LOiN8^rrK^&!(wQlQ|`G?XwbvtwYny21)?&EclbH87(du73g5glsI8+l9l zLwde6x3AEp7gy%IaOuj`AN~8uw6VkeZ)JN&fByN?Dfj5V`|e!PWx4yu5B2MtJKng@ z-93M%eqFn2PS+Pt{;Ia6zq;Jhhwj<1;isn`)b+PN`sOFzE~no&`okZ+J>K84N#E~i z(dC&FqaW6aUP^uVFQ+}ZtNNp~El(_e<{fQik3-sfD__3j4@13ozR>gYC0FL509V0&nVnXV;w|7lyeeUS>3o)x(}W;^w;J2Lew+fnqkbPQ!p z*Kq=KInK0x_xOj<`LYbH`P@lhPT?5`^Z7VO{&)l?Sz*pQ<%CU6d)U>Q_FUxoZl}kg zr?bGEjx%$mwD70jS@p;-c8?dB5}a8#{=UFjZ~AT?B^nE9TV0mAkHW>N!zh&c>N#nmBlJNf(Ent^(7vJ?#JO_H=dV z;SIUl)wG_I9ePf3=;pMFyxXS#Yg^mKRV5w*g_eFK=!TNmwI;M8-fP0t@6 zJgw*yhn}7S({#FGZF*Q;B()?mg3?=PZF?jTO0)wg6crY_@!v-cMlI zT6u-xEQg-{;JRHG<4jCSyPq)G7kVt-Uj_(_UKS7jW$^vhe3oUwRAb*doEauu{P(Y% zn1Q(Bb}^q>UR?_ppm5AGm3cTwVDvtUeceEZ&2a)l9SotJ@(sondmkR>(8C;VZg0DI zhn^uq57?rY;BTB3E7BpiGbcwgIFx4?VsP>#1Ls(+%yk}qT?R)d&esV;>JkU%8V6^C zgY$#pbTIUAL7@z~&HU`a&Y9%klqk-znl81}fw|tndECL->fr2ka3WbHM9|~v<=`Yc zI5Qm_dUdtyxlwUW({#-rE6xCeqwfkg(BRBg742+;bF1R?GB_I*$8^uQS8+NU7~Kh; zEcYv5noBp(_#MrG2f<@VO;Mcw24|V#oM~|GQJmuq&g+WP#o&CcI6VzccXloaT@6l> z;+$k~$`q%&!MR3pPB1usQJhl@&L@h~+u*cUcV&GH&Y6mHmcj8UPJ4qhU2%>xIF*XS zJd{OO@8GO)aNbfJw;|Pm(?Ah)J-uukt82=kz`0#13V-p8k%K+7bwmk zgL8}GoNjQoDNaX&)2KKx2Iq84<2XX}H8^?TFqoVMaL6<{FX1oy`x6bR@066u8HCB! zWMETj4w)uq2maDRlhYX!XIf}-CW1o?O->y+w9w@I6&zYE-E zw9w?7g=q>c>|t0qlM@#k=SFa7p^4cB4lOh}9Z;Q^hbG4d4lOh}_#RYPXmYq894$0C z`@x}wCZ~62X`$D!kUP3Dn4D|Cp@k-A3pljUCZ`4*=Ap@X1RPpu za{dVpEi^ej5z%CDPBkpdW7IazwcyY~6Z1MagqfUUaDze%O^zQNT4-`E1&0=zoEN~M zg(l~FaA={)8HO$b84F!{OPR|~!^XK8oK$ck4a{E^#^ihs4m%2yb3CS&)NFFbfx}do zocZ9KZsS}J4pU)bUId4!Fgg3cVd!Mob1ZMF5F!L;pkn%JN{{4N^^Cw(x67(W-aAn0u+k$i zWM~6;+lL@IRy`xZHT68d_{P5SIRMdfAw_!xh79dSrAKnCdYF&)+>rO(lzK%;35+c_ zMhmHOoYB#0dr!RWGkG_GKia>Pl)#Xo#hxS`^+=92_A$6>rh>UD?~W-o6;e!vz>uL` z0S<%YSoMqr*X=67nZr((Q7?Tf@BZ*ddtONi3>n%%Wsl@o^^C(+yB>L$O{p_Z<{68< zaL5tl9B^2VB*&^}JTW$V_Nvk&Fl1=19?~AkvFb^} zReQP1yIM+(f)vYLV93zsgTo*>Rz1n!x?MAIro?Nz6Z*@ibNHkEUP%cI8QP2BFn=V+ zswV|p(;l`a`4o#%pFxV+1%?bQino#ol4I552iNTyi*p2yPPcwsBA+_qk2U~OY#IVX zhE}Qcn4BjShga>pPP4alGefbsLl2RPco|ZRkC=9Xw=b-oG+Yn2=k=+47=u8JJ@yIU z;7J89A{=+!h}ZR)P}`IgF?OkRaNMqb6hWAyb%z3JAC{acDPnXfx!2W1aNI5oO9s}Y z9#c}pK+3Y?)+8a-7iSla{ChU9F{R#7QpDKf$`DcU$+cj9n^INb!b* zQZnf2>fTfSC&n(71&%C1V$&Ay9BsxmPDv3XHO*HXFcjw^8^^i>cs4L@7x(kBhgFbh zeh2V`c(EUI;xw^qbo0*6i;B)Iubfj{UQ|+AURqNscXL+K2}Suz8TN7J_Q*9QMKz^W z3+d>gR7*&te`jAx>Ad3F@*44{xCUEI$ED@^e7T7^P*N~7cWHG^=|W$e+E7rrtk9<@nTN-I8R6znOjp;R&lOmCi%rS<=Aza8)hdAwO&i~W9xEU z$w^8PyJ?q~7FYS~fNAiWo{%uu&J-@zr<7Kg*7)*^tICQiYD8S=iGB$mYURQ#8B0-? zv>@cg2~AuRg_aOnsWLsxRk1&Lm}}U(U1dsYRcWa$Auw4aB)7CC3B_8qH27*!R!)+v zO9_L6k|XjaanT~|{qAexEoxq(A1_zaSq->@e9~m|P3sW8c8yni#^+R({#vT0l+tZM zGe#k0rdceL7D@%Bz^qP9=YgtTO@l<1CKRPLjbhUhm8i(yLSVf0-F9vw+ZYw3mDc1G zSCyhtTd!l=dF0Gsv_17hsBF5)d@~OLJ3i5$t}16@Nr`|2Uw7(j4k_Dd^C;QWn#YM& z*E~$*Yx6Ma4WOCCCZ!0k0?ljF%QLyWvZ6FN>y+z-c%MvZ2#ir&5+T~StvvP4DlUkt z_l60BgD;4#aCkRI)EP49x7SJ1_%j#Ku&s9BW8p+*39?y`R*e~7H;y^E@g=auS1 zk9`3KN1jBCB6e<*{sb^YC0}qsYE|*V(h0>CCFP}6@ffyB=g*gadWY=YZGaYb0kBH% z&(Jn(8j{7x(sZ+AS6~z3_!f2*3i?mxmR%rpgSKH>)MAT@YAcq&m&3f;in$p7d$*{a z_Z|#u+9DTcPet=BL*#ByOf8Y>-RhV`+i|3-`M4-2Vr#XPLNY{7wlL1&&N67Br(m0ko`S6|dd}tAQ1lRM zThUXnO+`<^HWfVu+f?)vY*W!wuuVlz!8R2=1zTP8oS(O$=poj&qNiY+ik^aPDtZdG zspu)#rlO}{n~I)-Z7O;Swz}xmJy#n_UrM&E0w~!w)d3~jrfQ&M+f);jY?~^Bl5JCc zP_k{R5=u6xRy2F>?5GXRNr+ltnPVn|xy5!U4g(BTtHMD;WNJ7lZ-ayGPr^Y%RIhN* z5Va{BG(?3D2W368=4hyA6Lv&fo+3~K?|I8A=2eD&E?^?s_+UV0dQI`1^3vWdeZJ^? zxL}&m@}~>7m|HGp&y|)um9RzB(gzu4iW0&<$uL2!dX%AZyM;2=1UG+&XqhjlXj&-K zx@c?RUf8X57rtUW>Xfr^AGBBLOi?<>fYNnLfE5ei;jeZq7gMq z7nK%qnDP0BC;9M(v1mjS-Kv0;;muVpUTflkY-NQn-~JF?ynlonWD6T_)u=bwR}?pN zV$OubNfVNjp&~USp?7i;ezWM_RsoVG`6gy1`?FFq6MgcN%YN#7CD2!)hvV z6rYPVj!lVtrOg?ug@Ny3tdA})(SV6@@<9hL#Z zm6{C1h4KTr9{f6BQq)RJt{5}@HeP^#GBDl;fO$#bxE9I8$uB~P6{l{99&cKenCbDP42vo8R7`twau>pHo1D4f0eb)l>sKSNQcRJ*^0`qT$L0K;@DnkgTkIRmHz!WK5xcb6xY^s4-s@6?0d(8Bj@s0++ z8cH8g>zTNU&BU4c!uqyPVL*x?aF(yp$Yl5PC2&70Y`AuQJ8)64*!2hpL%8yY!?j0a zi7-Pb`;Or9N3qyd<1~qDs@!_?!n#Hr4B_&bYu5@CMgVaN74LK4UqXGSOO#!ona?cW z0$^%F;>>(L6S(Vuc~;@t;eV)jqj2GMVBYN`<87*Z-#7y+aj6&~T=}|j&95*5h*P-o zodDc4g$-A})HkPv`bvST4b~UrS9c`zT@s{EYZqr*2Ti-L!tod2l39QV9dLy5lS*7Y zFuEV>aJb&U%{U7uO9-WJ0IpvG+`|gXatnnU3jW`K`C8$aPoZ$s*SQ~7Gvip}3TNbVkbhf_E9U`I9jq@1Hx{@nfZ3>UoVtnh2I1H(Pd^*=83%(=uR`FS z2j=}|aE$j9d~h)x2Sd1c*+2hVVFVB-(>~L0EvFgZ02eh#qKy2rtls4n4jVmy8Le=# zorm_9n*z*KJ1(TZ+*!cPZ3f5uTL?_O!Ws67{IjRy55W967#EZd_KPn8^O3?em5#l@ z9I@jZ={N@Z(Cui)a$q8jBUC;!9X){=(+rN~kqyk;U|di-IDJ?G%ykOaR61@4W{n-^ zNXK!|w-%U<3TJO0W~+HsC_u>H;g zW^OY$=JP^eE>$=qy+Qt@58}d&3Pbxu=!h{rHg-^IVtPh;YG!(FX5!T338Q-zW#%Rq z<@=|M8$2p5u2+cb=~Mkv5~pTQDN6At<)sy6`1Ac4<3b^))K=7#EiBC_n^T3g$m23o zic*$V6fZ2BI|VDpi>phaJjI`yn3pj%BRy$!uZ7i%=Ps(M3F2nv<|j{?8pO=bNXbgf z^yl`9DxY)aw96Fv(6;W(XjUgkj&AOp#<6`NmazT%Lo8J<($+1!q9k?WFRb%aa z%2{>bHC$#3kdX?IWmDE*FV)WiDZNzZKqykAn;gn}}`?wvlAe~v?eETcV$6xk}ma@igl(H>O2Ul3IwvK2eSqdj!M zrueEo`1PIQA8^&gJ`hpcd4W4$^_xOqf7F6#qbUXLaW6fk8e3RDArit4OyyPL3+H%!|K=Uwv~Ox&zv^bFe|{fx+B_WZJo;m|CnX6#O?aCkKi$dbp$ z+_Ds}1|_>_OLub6;S9n9nAtJ!!M|2_C*MmyHvbXFNlyub%f8b7<`&kp`9Xg8lf4VhcjxGlTrgY~rs>8b@&y+!Z{t{WN!e=)NIk%4Vu zdQ9gu03Lv=l?MM_z}rjz^H3(VtXx+cG30~&-asatyzF(a&zTIbT;j@;uEyE}g5nK{ zpK~+VB^dkL4fz1E9%IB3Shjn!U)YLvae-(RX-(hG@Tq{%74CLM#jNgQ)*uF`J_Su~ zNz?*Y0WzYat^vb%;AePO`b?P+GAjd_+aVJz(jdwJbA*BVoEa159)a5JNK$uwF0jDN z&;5}Qe%ZzH6Gp9uL;4_>j2k)aSc5})kCE*$4*%tlKMd3bIJ{yj1(%DsBK()PRP#VZ z2p((H%>oy|d9k3L#93bD0JvQ6-o<&5pgzV~w(n!1LFzjNl;n*CCHsLCgEt+N><5;E zk}c+HP;&bA6ewx)I#6<&@(w6DP5A(nl>O4+p(5>r5y+i`>UXdB4fZzkilc*xfYhBh zyu$0(J%VC;=6$qR+;Yn9XE6S6z!51njFIGmcvatbqR5k2)8g7Mg)e?r%NMzx}=5l>2jg)=_0PT(WeU< z6F1*RlWC@*vtU}(&~08~;GpL-=72Gu{tMJtZ^c&OzpT8sfs)mocdfFzv${y$`=Df% zZN;##8$v;YU2sADAN0Dzo<@4zk^R@@`0p4|o4bK~D@4{|L@j`KsHG8s??g>-znoK` zJK(L`6jOweH3njGWbFZ}21kg=*#E@HTC+gIIBJfrG5^z}>*D|1=-T~%@7Ve$QLVb+ z{L9DI-$6^YsA23>QMxF)LQu50UQo37 zNV%MF6UsmU<3$r!GItaMSu(OupsTq`K%$qj5!e7 zew;8|N6{ry?tE-YRgyhtLFrt%-I}=g70zbmg^&o;6=Tz&onZe9fZncrLPVaV0nC59 z0Tzh3^QR9oS#~{adSPf@5|$+R(zC@U8A8r(qdqv$M(Hcfs$AZ8L#+p3pn7wx&|wElH*)6*WyyQ%eeCoK35UofBr6sAS_J2oXXh zMViQ@*iEEBD155WO1#}|nB4_g%afzq#_Y;4EN1M=+nFGPP6SIs*zlwwx&yMA3Fq}F z8gO7=u!FHrpLy-t%G7(?>kh=O>ApGFd-+Eh9dqLzz5LzrlT(KO;SZ&G3-{;_#XhZm z^rNRA7`<0_bR#nKJwsS z=DyZX|DSUImcli|>k{<;y5lfUec{nzf4k#F-M(N)VxGFg3lDWln2;Oy_JuF>tJw0! z*=K$C%@@ZH+S+OCpCk8sKALsPJ2#v>`^C$3hhaB7wEf}DY4gwN`dvZV=RZIGvL0VJ zM`Dffiw6Js@MjMu&WT-dN6-5n()BmzVC?fppI>w3mwi%pHa>k@!fF2=t^eu{#dHT? zE4HpX;e(I-V{`{$`fo69?Z&_}&w9S~=+||*U_FoJE&BHEOOL&bAeF)*XwzvN`tM8xHK;AI`Cujyrtl81LziH1>b#{2>=Ve)9T{#xGj( z)1Z0p)o(cGuajRr*`?{Y$NMbb6PNwmGdKM>YvP#^PsMzgy79~ByRB^e`HFSt{v0{= z2Oan7p)SWgQ~3CiaQbw|X4kBnT)2PVX$OMs)Ai_0;eVUsvr}Lg8}qe=|B92#9+d;N zR9ei@!S19coa3|gK=P$SS#9h;l^)@s=K}ELz-c-;qGPXcj?dUdF&uoP_G+g+?Cb6J zgmZkB2qdk)^tIP8q2j1ubu>mxO?&7dES%#rzH4Bt@wHFPcj{q}X6m8yrf`nWIQQ*< zA)z);dtnH zf#Fk$V{ojGNdCmB=LCV#^)T(nJM?fa>vp|>GjqJ5V(OPpJzX4nybe7l3e4|uW?6Lo z*Az^UgVWX3q31-09@Z|mi*rU7j?hlKcuVSbJ%}^Q>riaYW@lU{3yhw2*5`1J&z2F1 zBee4`&Ux+iC!FK6o9xeYc$TB#_p<2 z_nhj;pICum-C=n3vi&nu+AW_+orWv+HW=&B(@S9Vd=Bl9i#6HpLZ>6bQ(KF1yI_{7 z{G^EUf4A!h&Mb?vkH21F#mIE^5g5HJSPy$U>^VbV`r^zG+WFU+xYC^SFKRH$i)|;I z<1=bwYHpwL@BwRC$aM7+diW6(%WLS_SD?DFMq2wQuBWq?S3gI(1_%u67ei=AV`t-v zy}SlE^b8c3ru7VR=rNsEu&0$FR-{^f=s}L@xJoZ+P17;smCQhcGh1p^D_#NquRLq9|F>yiNnbGj7YG&9gy2}?@ThAGY|2IoA*F>U^XgTtrP3~oc} zUk(gQS_VC?o(|4P2j?;e=V=G$3kN4wFGj_u zAwfn$_2g+ETQE|}V^j`Z&p-z!&%s&c;5@B3rW3I@ESNG^T}XTODGXgBNqZ7h_twkc z+@v_B!?L#(=L`eWjh!Zf>1ZrXagH%CRf-d1aPC$dS)Z?hyh~`Yp59cL-iFiwc6JD- z8=S?8V>&*2P;pFWWIGhcbj@}w2TKvynyv@sjD5TXBlBmbgL938^Q?pOcL%2(rw$_M zIX}+9DRXdcQk+;L?Q0e1Sc3yEwIa|FlC=2?i=HyqUAXE@X(Xp02ptS5(`C1=CtYDQ z15*eN$Cm!!xHYTWHTGw2*GQ^FSo*j7>m|kWZAy=nBIjdpm_;V%^ke1c#wO=na2OX| z;K^omKR65~=U?DZkI9M0B$V?$ld}{YhE9f_yA-FZ!Ff$_PB1u!6vuSdHtIO3r-y;5 zQ5@4T+{21PH-ggUe<}`L=}Ar&r?&_v8=MBki8MH`D30lmu1C&@D0aQlBQRuW+m#;4vFeG(RlD0G z)8WgBEE)uXv3>5#XO?z1F>=02^ms_Ilm&(iZGqAwIo8;R;i}uEBPU%w>uos?r_{}m zqM*Q#p}nZ|NRCy{a9lO*q5CA$4bwj%MSBE>YP3PTjX;nbtDX_y+Vz-jhL%E#dIW~z z+S5vph+>;glEHV+&I$+5=H zd9s*fuXpzR_T!(tDdpA zYTCn6Hk}iF2PxVkFjS+(d&Q69SoPq>z+w;c$8=b>2vW31V1$Ajl^)5l>fzkYZjZcc zquBG1qCEmbhPFrPF*%)h+oyu=+D86Oz>nKSJ7nKZu0D*O1}P5c#Mq^L;7Dgls^Q|l zE;U+75o4E16jD8KR)Z%fT`EgS5o4E1YC>v>k|M?~l`N!KMotUwRZ_&*rBZ~HnvQ52 zZtjkePS2O;AjLq8E+s#G^@9`6?Gd+4VIT%lmJdTy!Ew7z#o2}9)8Pw-nsMz{QpDKf zN)u8nZ%WzS9(CZ2I|4CwsR`gn*HM&`K~GmtB}I%~Djl3~ZjVMNDPrtW6NMD3pdN!s zO;b|DK+2LElY|uS&uHPrr=8Kwlv=2yh_T0&A*A%&Sk|ErDuN#CN+m^%T`E&Zp=b@P zN!_fZh_Op$2`ScI#xVPYqtBaC4=E{P>{8i6Ds*nVtfYv6lqENEgj9E&nH%0C-OvN; z>H1Jf5o3>QvXIhqO?b_EN87`xO|aKg2e@k)vqNLg|tPe={HnYr<=j`NS0ag{46V(f9{3n@J}>~-UI zB}I%~sz6AEt{bl?DPrtW(}Yy$y77&YBE~K?-6mysD|Qy@KLat4vgF1&;J94_ab|9O z*tdHxB4jv6NfBd@YX&&xa|wIDak-Kr#x6BeNU=X;Tr%i!J*uRLu}c+#6RwosQ&Pkz zO>FckK#%3q^jYA#UHmxR9!`KnQ4x2bn_FC7{=dsl8ullgTB*F_WMyWE7nIWzg2zi!cfhq?&>f!@FD_*+!Vgw;X_ZeepInwtV!m`E z#8=Dl@LVRc8*Z@*hALlaB3HoRHl+zdLwHrZLYG=eDT8wol_RB$%Hk5{zj`Yl!Uh1- zVTT?O0D1&2(&#F|QMr4T>FH+6nhX>p0gaoz;s@F^}FAkpvRmap)i)C5AP z80=WPkqKdOsVFVfHMK`6_IUI+b(u+FZuzWBF5pj!?&(sHL0A<~RaLyymx6+#rTz=b zs%xrkX!ubQXkMOBTs=SdA{U;>Mkq>&u*~8`Q!5kaR9BYQ!Zo5b>bxX>I6SthD6T0( z88wfGr#Bmjp7IRWZegxC9PWi#GZ4bjVcw0`lP6WMUa`B>SpDadwDG?gE7(BA!mooU0aB8WB2idI`49%=8DPhh7)Y9^D=jC*VqTJHb^P0m=fM->}rj*W;y^}I_ z3PywGMD^S)z{a>C5@xqY_ZgabUP@V&Q?rq_gu#v+(o5ZOK{o&+MfhuQq{ouasj2em z`K;EuiQWq%2KD=_Tl~&1oqL|z=+{S=2F>^o#5f*qn#CdBIm>dmUTCd`P);FQts{g7 zhF0sKD-Mfm29C+$vO-KfT96m5*AXf=+Mp#wezZYLP>#TRaPZPqHT|(=9ESZ+I90)e zp`qsiHk8q!H?u6#Hc+5+(Er%R&t<%h@=9;H1Tbcvg3(K{2ZxLy49cdess7w&^^V-mmStL?yzoN%z=c+hEG0j**U4^ffmY1VQ zev1TjD_aCMJh`;M5{Wg_)QSkKLd}d+G8Vg!8ku{J>8+X47U{J3s|lk}#%=MT69> z6vAoEpphd6W4B%-H0P;i@Zh0wQh=Un1_@6!Kj1~xz3NR%u&0`D!7n%8+DlXzPc_9{ zO<)PWFrI2o!CSV`eA9-&*Gu6%2&4cr)q)GLp5kfMDWGeY87WVFVB-fwL?zC!f(}05?-%SstPCnfm6nP+u8v zOPkTh^E=;-7f%B=I%1!%N&$l^naSj~wS>62)vE>in9sdifMfoh(E=Rv zuYU`0Cj&RQ1vqxglUjgdzD#Waj*G+!T7csck9nbRmSqcoXcwRZy(|dFud*;eJ9pH_ z2KGg{Q&ZBji_&wmiwe?H{6)Dr{^a!3bpMpxkXz^f|G5eOqsW*=zu6}Icys=Xx8R3s zxxgWPTS&1PJ{zQ_Z}iRy5l418ketFxBDgtxish*tsG!B0#E*fL*f9{hb_SM31>TrX zJ$rcy6h;Sv0!;FtyNb#}TPVmGX;y) z*VXhDdDKhhk-jgf%%jb?d`tlF9oTiW-IK1siDIMDDLq0(#ttkUhjc}7m!Ohx&KDF{ z3l7EM75ip!(iSQ9|0xqx1F7S#I>qH^Rk_`fN+haA?=Wl?n(`LvqIx{D@gwH@m&iqJeO`CU_>){D&m=EE`-pmY5YD)vdszz@T)7T_FKza5HL}548 z-VLd)oW|Oi$(BapSvi%aYy_x%0Qk389rmpJ4&$7s=SoIk(<{ugM)bIAUssCzV>Yik z@H6*(Xl$(8tJR!Tx7SrWbb&7?r?I+QW3}!z!@K`@Y}SW%Y2n4x3&~aMJS$fq+68JW z%BQI={;HQ_H|)U`kN;r()4M^a{dPSoxx-H&FDCwQ|MzN!)qUZr&9A#C zrhV;+f!uC^YA;NgJVmeP-u*-PKmP6b!xrAD0v{#u`y+VOA`=rhC@mOsux7MuuMNp# zMPA75dIhP>4gVwJXdg)KhJsm_lP`oCRvkn_<~JgfL-cXEXF|OKZ0S?HD zVxH|BKP?`ykxN{iY$R2dUtt%@jd?y`e2Rc4DiVzoWSZoAb|2vg_R zo|t4M?m1^&-GQjDJe?zY3t&^Z5Txl2y>d2I$6756yt02_L&JXL#^i=cF^o?;yyIE^ zoV>2rD)OJf8rl#lut((=3UcSA zy9C8`#$3A^Db~HpKJGmH=W5YNu@|D`Ex~_Dtp=4SuHJ(4Y(d?Hv%LB;DA_+A0wpyc zF|M{l`BExUI|h`L7!HazkzQ>gD6Tp7YI8uzVZIX7S%UY1fqToK4uO&q{5D*U0-Zp~ zQNRmoo`~%vP;&)!DyUIHUmsAi?;l`L@t`<3!_|qw%K}v{WQ#zZEv_yCHC#{^fvOZ& z`8BId(G{So1n+8tcONKe-y@(d5?7xD#Zf6zdj?dkpk4qa?b`%O+V`44y$wp*x6|Mq z044M4FesV3KZ26B#GnsdE;M%sC9NL-N?Jb{l$00=N=lpq>QW)WuV|&jVo)l*prpiQ zprpjrpso-SzX!#>JyQFFarJRfyh-zFe*wkH8L4do#X%-gdjk|}RHU{Yl+^cuLG1=5 zWBc6T9RekD@_SG>3E4(a*9$5FgKe##jsZ0alvj%ZC3CW?L7fUp=42m(mjFtR&J#c- z2`w3*{DR5>l_sdEpi%@i4OFV2W`arP0|n5aCRm!|vAES6qCCz>O5h!@-_GKMPWv`r|An z#|?gO4#w8n7;M~&?QmsJ6V$Wu3ZR&xccEb9?jVFLXVVMvnAyRZa z>7Y1{<40`!soTr{!GYJ1r`iM@a)YoeLA6$Xq9M<&4jm7&b6iJlM!&*XExn?qw5p=G zJT@^mIXykLv|?^0m+i)ufvBj)5?64R#+H=UV5hXwlGr8l@$MvcQB~#K(&}pBYKqT| zJySaq-`S2E*QaE3pAyZ7Th1A$K{ejz^HS`*V#t)l)>Ot~;e6%X;+j%uSFz41tAHD} z*g3WH=9N}a2^5U$Gfx}W3l(6THnpm@R7))`uP)WHDq|Ox*37RIiYjYs7S-11k;m37 zT~rF;@g23X`K49WWtA1<1`mwG-&7;&O02Mptyowdt3=P#Y6flW@!(}&pLpR{pFXkZ z{64FLx1|c+hHBfM+UuWBuD$jB%9q!a{yp$|b+>nJo7VmP+rM9SXiWLE#_N)9+*5l? z|83_rw=L7ro6r2>)Ammlrp&nX!jC3RedoAshsGV3^m?BTtLD|Ep8M5keS0PS7eyw* zA2&Vv)*H1K@0{50qWa%0-LvQ6&S~DiCBJic+mP4Sezob)!`IJxP9=YQW&yf^W) z@jVl-9d*cc%o^UFc3Ne!J6sUwm=fM_=b$@zqP^ua-V~{3BO+ zyQYk|dd7|q&L8u~_&4=*{94;1eXA=pe$}={xn#7%;dcGixTX`?+_hNnuLuk0|k!BK!W5%3FJeZkmx3@B5s3jujYo$9&>8b>BNh9UXdjZ|`>Ly>IC4 zNsbd3+RM~1L_73!0=GFm9)Ypy>EzJEt8N!_n{gfA?wfC9U9fI>#itPVvIw_55+`M> zNk2aJ`O}iZACas4<%jINiZ?OhEI-GW91fE*=$Jg6VMxtY9CI^?OAU-3+g*xdZi(@* zfzdU;qB#6yU&emCOR~(35V%Pn;9aG{+{*1-^#WUxOtii)D zx8syYvo1@kL)*y z{z&N&7&5dj>=gKm1Nm%u=X4@D;`44^mq9P4OeIB(0$NfD!e8c3beEv6~exb*94Qz}Bv`-JOEyVOaLG<&4b?K|!Ib(`NfBe0 ziWO3N9V-<6cD1n}te>7`s$&n^gY%*%;7tsd^epRCDoMrQb`eG zm*OK0IZ}hrcCEc5$&_l(E(?JeyHr1L+%C2thS%;NaEB??LrD>1m*Sn6+jR^@5Ux-B z0o{+DH#tg*7`qhj+RPpxCidj*rc{NJBE~Ltwvggng<*s5Umu!MS12iB>{5I@AU|!V zlsobM22<)OB}I(1`U}M&R&su_ajYLS528L7-woPB2V_SAR&Xy|RI{|`-15pf#pOjM zaDt6*Z+z1e@fp!HemvA9Kzx;&P?QI}`Rz=;DUCHlyx}V^s;((1t1Mbnh5NpFMU{(c zaEDfn6-8wW7XhNK&aGUyu(G0PakYfua&?6w6ZmauesNV)E0#n#j*p zaj)63FIEY}H%XyCux;Ciui>Ql-Dr~S!`i$&Kku(geHDq-bIZ!)pDJc|dJet>%SrT$ z99`NhO2EWNV_YOwy%e|U3-xcxkT;@TtObFuU-d>@77S3#Nf!4cAGYkKZNUA@f|Q$+llXO{dznm|3CZr z)vs2a^tIev3yx;h`&X-|;sYhiXHqS$fFUgk)oy~Tu8PrI)&8qzQcdxk^3q=~i_m*m z*F3j6hb-o_B!AFPX3JhJx2CeH_}o$-Dlq!a@V%eUH_A7(Xi}n)So^fDLFAY1s75?5_%_3!f#f>FazLE z^CkJy5|fg%Ci?Uzj0wZUBgTYbc%mqtF(wRC4;c-y_~eYV7ATfk`OO`4Ee$S?9`k|$%(0e`4cT{f9Ax*)bvR{i^`!Bb0#ECnvk5V zry(gQ4Z~6$?8K0e!os~Q(Wr9iv(qLZ8O3KRcr)SW3nZ9|(wIS&l897O5iP`$KWaHA{ zq=^&#lQNPMaS4e**D1?6%b%G&DK$e%80?`Fax&9XGAB*&@zJWm9+o*NB|AMm(I=j@ z8tkM=zRc{Dob0s3G+!1HCm+Ddgv#frpo21JWKLq{q)C~`R^$vH%-RZaNS1$+KQS#w z6lAugIC6YBshLR`nOP_#)Is$ampL&wVQ3tFt>C0gUruszdgjEWR9MWX%gQD^OVww%V9hJ9sjV(8(K-$q6*n9!q>RwqD&`TxhsQ}US24$m zRm=l0-8)ZBuYy-GZvfw`PmUEv3$u#(y&znuRm>xx zO9-_(IR)3x0B(W8vTBD~ZA$*_q4Wi0>kN+5#LQr-s4>tv1!ra0Ue7_}CMDqjR-s zW^Qs(zJJQN!K32hdWE>2KGi=ZaccIIq7;8pURqIxKi{7bauMp3+KQU8g{2u~bE@#- za9n0eQOeSaVr)8uO>s)$ED6d}{Hcj~8B;UTlScPiSiN}eqNFD{jrBzFR`Pxyerp(O`)J7Eq7Dr+I+ev|CF<2#6&^WyD z9W3*LxARWoLhZkbX2o-fW+1X?7Jiytae5~5f=`TP|1JnTRp2k5(TG>%3mWJ1f63iE z=j4l@_?IlJ^$zXjm2fLtEh{_e{CK0``gjb4q+ed@m#YN_fbxnp71A)v;=|A$dO2!( zMG6vy5{^E6!Y`H_8n5*y3k%_sw{Sx=_Ey$cZ8(;w)*bMMT%}qVz3Kzc$|B^;YIpn= zuBLsbJ}z~hsed18s^*wM9-$t%W;uK8iLd+Zp`%1_3+HKq`V-E1 zf_fNdxzOWrP(yKG-4V{5AbGVH4eBL>+G@g>vqXe_r8Oj*}*@#&v4as_~%C z1us%~`zjF>orDz&YBDGp?=(;{UN#E83iE374BkS6sxhcKP||_`DA~GSHh9|%-p`<< zEpAkhSt8zJK+O;oSHQ^}Isufl0oxL^-IqX zBoG`h&cflvD`9=TSZ`3W)8UmA9Fd~GGCG}n^g4ms=*d`3B)c6h#Epqxho!`kqt1`P z3d&jRh4?CSAP&({LBC7=_o`q#YVzE+fMd<~L*t2HgOSC zSv3|xl`bl+imjPnToGGdxumoj3y`WxOJghWL>FpKJ1y2oIt%(7X% z+8wLAcUu_0u-)c={=QycM>OQF(FgBe`};L#bepw%_>7M~*4GO?+Oy&II}6`BQ(s@S zdhtnB5z}vOcTty!84r#heeIpE9#{BH%=Uh#m3S_if7yaH=ljx6-seAcBML)=Uu)fu zss|Wlxqce<>O}(%bXbYGj12}kBRxNfBO&^PO{8*Y@yc= z;o%A})_e}P?nm#)LhI@5&|^9d(EA@c)IbIzuoGl3SLdWj2F^N$1Fj4@XP){WVPKZ) z5QB58gY&e5vrTd6K115`sp4?`hvW=)NtU^$hl|D;%#}$GDh^kcNU42_W2S-ws0=#h z3e>}arKfUXW*v`0H#xt zrxnKJbU_ial}L_tT?=cV-OYq-UyQL<6}-UMzQpF};&!Fr%$9QbzO`73LyF;MNX6n; zV93zEQhH2ImJY^M`@3GIB-|R2IweJnT?((PA;o-Sc=@@T{vUf^0vJ_w{r!f7A!0O9 zqN1P#hysET2>W6t%VdFUgjEGYga8SUV3@F|C<<7^G*+v&?z>g%QmfXw8v(_wxKu0d z+G-0zTU?4uwfTO(bMM<`-Xudx{rdg?-%Z|~^UnL7bI-f)-23j^&TS?_rCYTWF>a}& zz_F$7IeZkl5L4=RT8bFAR8NsIcfkDyMgqGuBx2lB?41&P<@~D9jv=NB?*p zZATt*A`sXa&pj*bNA~LV0;SEROFd$zvRDFm?y-Qno%&r;vqnw_#(JrNnygm^>~c*t z5(>tQ9Io_Gvoat`m6FdM&By8X!*$fM^?W~SOQ#;vm)3-;L)DAQs+ZN|VU&$2)%hv| zL$694bJJd1w+dXVYQLbiegO^<4vMpmDn=`LeW3KgrQFPs$hkLs*Tj;^Z0B%h25fDD z)7mnjZ3NzP2sj@L?PrWuFTdj>XIvXBSX$GV!8ca0UkAtsqn_IzNbMOOfl3dk{>+Gn z@v-X8e!Jj67LUSRLCp@R?#PGt_9J(CYWq*(JA8*Rk27cp>Y0 z9t~h|Zdq<#Uaoo`jR(QS`WlxwJUlI7o;TU`D7M1~;JL+t(vrf`lJe5rfPHz)=l6Kr z+OSX?GS+%p9P{b@@WNnuenCYco^0FbykMX_x1g}71jX=CaqWuiQR)gC&vMa>vPY?F zY^>oT8&7o`tb$4clM70U^Csh|H1-P5?XirKYj0Pzj4sV9Dh%f5l`8$v=qSECke5@K z6D-Vw4wQ}ybv(!CmAa}Uk4MJC#*G|-XB$@P=s9uLs1Z6m7M~NJDbI<6#fEXWJ|}xU zCw`olD9#k)Iq|vXFi>N?o)bTdZR0tt<&YGKLj|wrrt`rs0On4O;}xQfv!BCqgmVan zr6+P|ip1TB_55-qF!>Ig*Yiv2;{;qw9JpBent<8pzLW?2OYl##+*9Hjaw~cFynDM9F;Rn5A@wQ+rIw5l>)O| z;BNrt99}>maSU(cY<=hgj3gL2m4+g@+oi29 z6&3MwU~cC{0ur0NmpG$4lQR@E^p%+rp{GBLl#&Ct>og*9Pun!0Hcffqf3P%cHv2k|&O$I+S z2Gd+(Vd6EvjkER9uMQn+7{A2A6w9x8uk1mM5g;-zeUF0wE^t2^r%>(r--E!s>WQ=M zqx|1BMrqXLdPK?l9Jnsy6^i@e)xS_*vc`0zF9onB$K!c_ z960gkIB+LI-zRb4*!894Aaf+IdLgbT4%~6TogW8|{pSr)xYVfVkgVq$qj1qtBzgXL zHV)kJ!2K-_9Q~k2E;2{*su%iwK^!tO}mP%D$x(_1MUfp^yqt*FcG?DCIwt4A`IG-N_+@6>?HMunP z@pgbeh)X0aOx%C*1IM(m>#T;ytCz_$ zXWhgD=6bjE8@&6sjYAn@TOp4)ev;J>`yZoaRjPigv861zxoJ;x>CSCA3P*o6p2d5O zI|W$Q+hbdTYzuD(EK$MACwjpA3bxJlj-UC8->p#ZH*kZ+xD7?Bm%+Xl-csasSkjD( zEb1~)lY<41Ju>RI~Do+So}s6@@s_G;k(9j1cprRMJQy}dm*r? z3)ip0vVReGe=ZVHp6%(@;ld>4)(9cm53zOYd=<{ubMa2Mes2}gclR~D@9F$e?r6PQ zeKRcaOHZ$Sl4C{XlR2Q~VM#L_Z$5q*>Q(UjE-y&*x z=T2EU5Y#*@u3C+bg6FQ)cOVc^t7t;f)$9u<`9cTRrOuQ!8uBb&8cmdYimDlNG^czQ z2V?5YI$vF~mJPoGeDjR&Hog{Gg*QaQ2Q_yOmnLt^O@f56Emu0njn6j?4;Lgi=O!YD z2Oi#BkrdwCR*={{Gnp^xZ%#6>65iZAGs)(Ja~Lu@p}8UvRC8`p^VFo~$%*62lA96$ z61C~3!?@BxALD2Zw8 z_((#$C>&%%cLuaJU&_Zf9jAo-Eu|mV9W*t(y{#gx?x2?7$BR*(72Y-(udSa@*VT)i zqQXs&c&Cj4r*|KwRv+-G)h@1}s(3lw6;qYhE%(cQ(WjI@4*~Tr;f+WB6D(;)HS#V# zR^lR1TuYM>pIwD_uEl#Clxl#nUbOyDcQ;;vBI%y&M^!*+rH6fhqS%l98H?ZGUCbDr z5klj7I9FYUw59OZ_&|VT3iT}n&J}_7h8N{&+X{KZ-e@k}6FIQxA_@_bxGnq@h91zE z03g1UD06&UAV*M@tiFBF9~We`;fNou1CG~a*bO~;kb!r+XW4xcyWF&O1EIE9E=|sIIOTs57LP z{>ZNqY65cQ5&=-3WAPgtQZ@5fc(5{7axML33(? zidike8)ur0Ar&7`b$b$)7`q27=1)uMyCMK5QGw7MjKKm_z91lx(1(Af{vGkou1Toz zaPU5aiw`YXzq3oIufu&rM1(bd*L5g09DH#7*S?gCuOuyQEx09e7#V8kt;1HfKpmc0;RN!w5SQ7ehTerMlmS9iS9QlkSoozKq<|qgHq)#2Bpg2 zr(voL#;H_gtO2FU;1)&w2o!5B&A8a&@rFR_nN;%q$Uh@t_=Rc|u{)Zei94c=^z+1t#E z(c4VJ8Q%8z86yTfSlC)|T>#75I)-M5n1yh`xYGp78sW4d40kFz3lG>vv8H z^+I=(vf&c6eo@iZv{!z2F%Csbu5VgJb5QMt$cJBOE)@-rV)G_n`16S;r)-!8;fej5 zj-19RHOwpXWXSDeAdT>>)QJi3vSMVICu8Hbpqz@f1s~+$XeoUVX29)K?>B2E7*e@yO%G!O z)az~${ZV3b(+-7CFxfx}x~1Hw^`aVq+~gaQsY}p%iQ7~(@0Tzf)%#7PdF&-W+|+Gi zpy^;*jE{h6)5Pwfly%vMgu1Ug&(}R=%-i`gdLo2<&V1) z!gF_I?Q3p&rMc;)jqikdE7zVT>g2@o3Ie(ZzrfZouLaOp42}a6Q6un?ow_B^@Z^Lo z3ESYK>&Bj(vhh6>g^nYut$FQp&1<*f#56$pF`4^xW5p##64o~o#3@&rwuYNt!FdW_ zQHMr`OFvw{%Lt{e-{osMs$!OIbGr|+NPH~H%Xaimvs#K%#b8wg2BFWvOdO-F>PNg? zRZtL4lEi__S`0&8QJY`l&#p&ND{zjaiQ`f(E+suQWkZm^C#7uQIAUVIl#Lv*|JK%@?Gu-@g)Y?IyL;^TiTY9+`$7iWmVsm!_ z%hfI@frCu}08GOJT64m)TK6>G31d4J1P%ZypH?Ko3ONXSV0NAAg%(30%IIw>+r?d} zOBA*lzJDw3a5VL)^O>fgS6ttksC!oI9Q~@d*@F;S%g>3+|pV z&Fqg6fg#kZ&gbl2AoW)73^8nXn%%=Eg0KCAK6O%4B3fE1)$7ti_G{N0-(a#F?wHkY4}}&tha-Wfh}qp$ zepHi`JrJNiwan7L(4;BnR`W_W(d$CQUEbX&%FW^F)XljllCyh_3$VM+y?UB^wFC#- z(X+thO{#$ShP)XrZ4N~{VOG0CTd%!m$HzKhv2CA zQYcj%g;fbCRVkA zx>l&&*4BO2))R5wyI8i40@WfEBZ;3WR2e9xuhyb|3yS0ZG-DSiRU7+2seL=RtC~(H z%{T^>+S(74(vlBK)#MrE$sR2N#qbI^=Aage=5s;uYfyxe0ChTee&c7LmdVyzKq)Qv zgQ^kSV;1gZ3-_*t+X<>!WWNPPcTY2t;Hb-mIvkWb9>;;I7hV=9<)_7`y&Q+Rb2uMyNV;jOWF=Y!%klHd3-D7BZDT3fFHwM4ew1d3Nneu=ZD_WUmJ zRBhZ3O4Y$57S#&sQmF&p$W)fT42q`@zwrhrRodI2l)eu@DSdwirS$#PqP_&B>hzx$ zFC2VbowH8af&uF;l*WOs{=GHg_a(i)RsUY@`i;Dwb4k>-7W`0OVWogN1527bUR@$o zAB#5tl;RBo#nDNcMCMRbwuLLSa8;nx725((pJMTgd&j(D8|it))|4Ec1X-h?PF+pS zYXZEk8yK{xZH&RY`eP9E67?VB?pr|(JX zz&3bFfDsZckkin*lLuiHN81SH;lj$)&Qa*PY>e)B2d{9NdAXGYX%dGpOl_ zf^ET8NTAHE>gOf(^BjL#g18WSg=JxsvMsnnZF-$Q;pZ^KO%#hT)(W;_tt;kD+$kK? z4{yo*mbl<^7_7|Xw230JinKyYPsCA=TxZ?Q@FpTxCy*Ra zf5ZacLT;TvI{74?kJG~ie7ue)@p$eoPvVo@PvVpDFkW-QIf;PcNqiD0Jj8FFn%F!! zX`<8iFTyJP}^!CWhqU31g>Hu#Bg#=fW1gDlX z8+pvITI~F~$&Af6g1QOI%~)>1ax0d*vD}a4K`c*Vc^b>JSoSCU7O|!&5RFRQ#-lM8 zi<)kbH;DZEJzb$K|N4H(b3ErRpTh=!T>Hp22mV{+ccEDbOn5U8_(%k#hiJw@Iu>GX27=1C}5?s|kqs zHA~nGzA9mhP&}<|6^f^|XM`GvoDT`vU8?jkiXlZUT(~ch7J%hSv?$VRodDCKpMX#n zZNp~2k&c{0HFfl!7b+k5S3;E_|5_+y?WQY5FY9Cl7QeLWkWlo`l|s>Pn}lLLtP+ZK zewI+y+@i)rgf^LEAST1orUf-Beqb>I4KA)}tf@y(Ktyf945!xYqzh{1FRgB@=A<_W z16W$ksU8-j_t)a-3u+q?cd&LPV+hW$qY%zt3>nP1+DKKN;Jk*Wr3(;!FqGa{v$VE; zNqS=gXar|41?66)kL!<;+hXTe+K*eemlhNK&1W!qy zUtP~#I-@3?;rY#aM2KhFkBE(o#JK;0X00!%Sy)?N%R}L`#|YZ7A2~nIg7g)&XUQ?t z^V2G`EtG7jb#$g3+EnALU$gdCNUSD!jnyEWD2IN`)G_Q%cs+Yox2WqF0Mya)w)`!p7_GRk+m9> z*?`kmswuD_DZx$4YF43!R;n3~#TORWR4)Ka0-2-_M3_{@H#OTOokasonc4;Duxc09 zq6za5q99DL3=uO8t;k_tYZ%{R!6l3}ow9fvJC*bj_+0_|o6?$P4G3VK?f_X{r+XjK z6p^v><&$z08!6kR^ zcYEcw@^~;n7Kd9Q>zyd_!vn=2qQw;-5yG`mZ-8SUbkJf&D?v(PM z-q(6!zkc@nQ=69m>4UG&yY0wd4SDm0En}O9&Y5Ngw*9hT@72q14!pdp zzR!16b6>6*x3|xz4gTks{3HF8UdPW0XS=T9G+^UhyOBPZ*K?=PM$g7#NxBwFMR&~b07Y_v7z^8#ve93d;N7I({6a8&tFzu zG^1kEJs;IS^X1f+O8)iaN5KydJ^hjVoC`Sgl=R;gK$zFxy!JRDbtx`%IR;h%a#xGB z9BC%_<|Ai!I_TZ&D-$G?iZh5VuP{3bGR!W_9sD-d#No#R$qvwaB6D5^x%G65vgaVd z9FLrP^TzxSFtnEaa)cz|-njL|3Lwm0l*xNSbav5hJqJhGbBJKpA!lv&-tflu=z2a> zFx+=uU97t47uyes(vu>XS;(o!I|wt!{_Y^mDN%Y36HFd+EK82&t6-a{bTI4*YU%xjGmz=hbDa;XqS<4(t%7ue)acEIT0E;t1b8JjNa|T(MGomoOzoU|=`COA> zNud#2iM5C^q_u8Jy%NRYLok(0%s|cQYH1EcVfcE1TWVz#=h7(7Ls6V}qBvhiaSm5I zgW^mJ2Ww7>#R)`VPL1NMisD=r#rbs<=XX(@y-^&$c9}HGo(j$BZ*i{CoZ~IdtD2Kx zaSrC`0qF>fGg5O7u{ft_P7jN7f#$G&YJKb>e4@pf-K8;ySyEdZQfi0(syPW3CV^d& zB(vs^j^glzAUEdpC{B~+^tCiUqB%!docA@SkHtAmUp*abaSAl&Xp6I4b9z}EzRu&e z=ea1(-=a82@nj&$+|!ezI5kn6a1=*A|90u&%PA_En%R%LIfJ7(c~P9XQJi&AoZB?# zV5>HMr#am$&L^64ki|*nuuGC@;Q$w>YFW*)`OE27OvE??=??}k!N>C((<>utTZNEp zg4UA?Ddp^QH0K11bG_yqX>oq9Ifq)DL=O6p4!1Z1!6^VI(c(t>C#7ui^>OL9-H$Z zI2`HNobDKern@-vz`;LoX02YzRTt+ua4Nt_w=mr}P<3%iz@d>g=2CDtHncf^0EhKs zb9$$!`ms6H;0$(QegRIFi?bV?2`)}1c0A9;X#$7)ew=0VL#!MZ=X-Eihc+f3r&tVQ z5J}UljkEMg*XBF~4h(Q$J_m=RP8%~6Lp_eOY)&0Gtk~X`=9|H}9~|~J2}VXq+3?|5 z`%F0I&7K{=FexeLG!V4X4*vi7rw5bVf;huQ5>h9Vc2Txd2Hns1J(5orH0_5 zf%XW74C8cOMj$DUQ%@$i?%Gh-DMVkYr3B-u4c2#pZw_*n^WulugVj|nR*Z+Vlwim( z-U25Bzl!55eFV6+p0vkDCaO^`rM}mC1Ve^|38o&!aq7te*RBm79d%VgsT*;5L@NbD zhVdFNn2;35sb?g(3BC=;>2Y(8q|LD0U&F*q{VMhVh)%tT;|Rqp{VVd?f3#yqnZj5~U7C!%4@lV8}3X*_4nJ$Ejxw zxCy>_$a%_bcy;EZ>M98<##xY>h+n~wVLSj1_siz|6&%`Za|W@CaB0S&RiI z!N)5#>m+R5l5K)iBDN5t#y?lO^nh)==;Am7Ua|L2@ZnS;sq2vkZ#K1nakSzRa}oMT*CX>Ar+N_p_z$(Ne^?rLw_McRVO{?wpzrZK*f36fth8 z05}Og_HRtd1s~3}r4BhpaRc~qOXYx*;A6XE>RI+o*p@2PQpC8Wa=}UPoj?(!b+c|p zHFr@f#`#)`7`GJ9YOyAic|=PQ_3?&}rrJ`+_aaY?uG~_E;3oLS$yVHjIJ^aCI@!|Eh z)N@*j7`N1PaO|Tztp8gMKWx)d#JHtqh?LoH^hjJi(=Ka_Hk=r@6hJ5|7dg|Oc|SSW zmTJ&a#JHtqfs^1feQ49pzkh2>{X$C-ussWv=lLJDY!VwGJPXB z@(6SZX34K=DPr7Gr;3z${(ASJ>#>Wb)J`o$j9cn7kvar9)8Kd4p_)ypHZ4VrTWStC z>fBAK6-`rj*;0KuP)8!hEj1UM1m7@jM7sEAC;Y*dnysaXaZ8;JPJ-_UiXh!~{ElyI zsh?;mV%$ZDfRFP85h}7PiQG(+*0$vvCrm9-rImq!mN$IXenacQq>~G@e0%B z!-G(4O8L^sGYn$fQfGjZ;M3iu(Q8lODqHHPbZkT-#w|4;9NRaZ9(ebew$$WwY(yf) zEwuog1YcinL`uBkr#IVDOVWjD5aX7r0mt_FwY{Fnv88U+QpC8W7K)Tv8?Vpz2*Vk4%zT8ymC~G1h*q zAY>_)1Ru{|J}fhD*><;W;T>9v7OErL_dH`YzSH3mgmO8v2SV+VuO_MZ-T*awyah#*~<-ph@w3Wa4q{Wmmj8nA~ zF|fxGq!rBoQWu$BE!I@3gG6@r2$>jcb}=UQ>Ue&;>@1*XSLDP27lqkXGaTx(tJ<6U zuBxhb*>X%R7HX`YzihdYor71q<_Gd?7FIVc4arJ%sG%{C$yZpWVJ@@T#j{3ETeBim zvn-G~LMFn?ui=En(IQHdlB4mK9Oi-JZkv;^saJ9IWNDm^ZFZ*Gi{aTBIgO3gYXT9I z@{OD3m_#o(NRfOh%pU37kQ2{FJRn{zDT0Or8_6FPvM02K^pAHp-ckveR z?LQ}qRf0+Q^7Auk0jg@Dduu7SX${y|>)u$TZQH;30xN4))P$_5_*lQi=JbLiXR24O zq%xYEJ^~ZxO||FI8$p3AaA^Wx`oznh2SQaP-U?e;(}5=JnQayg zh*K(J4=AY)eEW4Udp3aCXbbIClvHVURbl%mvj@qp3dRY{nqF#`Cf1(UJDKs;9WgyE==W3>gemfqX3hv zMS*lpMaoKv71fO^YEUShrLh4oqpoOZ%r{?U4#?I?spQs1OY6DuEm|t6~Yll6JnlDpzc9l)_(;I^2(>y>Z8~@TJPFqsDJXjw>2NA7H z!&K1(PFs$CI5v=#HDgA84PSZ=)Qi3#US!8Rq_nKKA~#rEkrR|oXH8tFa&#QxMk~}A zt+-tEoVo0Iiez$3Yu3_I7HYa5+*7KRl^rE(R;_*d$_nT{IC_#(b>@oZtA06}FTL)6 zezH_{I5|zBhKf*Qz^n;fJLbtnw`6lKgVB6b-qj+Vu>a_srg3)5?#|pbD{8#mvr8zR zuG%f&-O0K!UfrlURVZg7#SkpRv$M_Me5Ptj(e`np;>2aei5nd!Ze*M|k9l9cPA(Z^ zpwBV0t=S*{8y$aC{r&qo#mb1Iasae?9P0z1)#HdC0IeSWb^x@}OB_c(o>O+z;f+H` zT9u<5)AHyua#fl4SwE`O{Z`@CviDz!M>E}jB_3_F6H40g-ni>EV?=a!vj3*EUv7yBC+uN}g`EMmMF<*uDj;^nZNQ4`U|WgsRs>l(pFkAyw< zA$s?t$I!71k4x6WA>*|;!^4H*mW`{H%%Q4z(ICUrsw#Y7HGgr2T$n`fqnAwlHRLJH zI;vT0zz&+_~mf@1zc=q4AFpT_wja<}56}k)^Ak_(WWV#2$@0j!%2T(NOgn zOKZFbqY;PM><$mW*i09CKr}k5BaX3v)kA9=;uCQeVp{Fh*4iIEMC|tdC~z9kiC#Ez zuREtA(un9Ci0+NON{&;mB zs~W?v`m1W|7d8X}qjLkoYUh@pKx%Q{a~i&q#-(IKePCwA(&`Yu&X((S$ue;)EH3WI z8rcydB@K)8qXFJ4vSe(w2xV901*$T~m6aEj7v~n2qSX9S{T(sLGBK8jQB!gXa!T_H ziUonsfn8h26cj;0QAuGy#|E(EMoz9M%9&D>mj}552<7GCw=8><1<0KoD9$gNT$*2A z7$~*^A!LtYon?=ztp`=TD0@`)SX&||ke@pxucRnR*_9!dXfHKS0WR;koA1Elz zD=rTf6$B*0LiQ-cBgh`5Vl3bncT@HLFwBCZ7V-)qIVG5%Us@VaUrGblz=9+YL-r^$ z)J1@!ax2L4HYINd@Y`asfMzLw2UB z&PWf-%qy!X%grgu3s{EW0Ogk#yxvT&==+e zvPanMW@J%CX>oojdcNt6P4@8^RXQcVyttSLW9bT;T^5)U%qb}>C~%wO>~l*4lMBnr zE6NHBq|asLJAzxpYDjq%fzr~PoYFjWP|mKjgB{JqQ7_8N&qX7Y(ir~2eIT4&9iH1v zDJ#p*&B;SsQ&BNgvtEej0j^GQ49uTgfwmpcr#S0~WEJODl;`Fa70F{Ko}qct%Pk2M zm6jF+bLC8+dpt9uM)oKjQo~im$Y60%ZeC7azIncz64{p6Byw{La*7HA5`+VKR1^-~ zm{gbzw$~>1hL(xLD=NzKD+-Iscm^)F*jc3|C1p5qu;u1WcG&{=EGoz=FD-|^Ssk`C zShEbPWCrsPm6aG*;9*tjuc(j95|n9(DLkI5V}e58X3 za(HIu=+UF`J8H}*{2s9#+fx`45tR`LxiNt=wx5?uFo=mSz|qVPT?~HqI`0FZj#w z65-qjZqqPxsCuDwLiR%F)c0=}rM8 zYd_SBt?~jW`SjD{fGN;8b=)#r)ytB$KKe@qF!S8FKqQW@c-8^a&;gE{*C4w><1G6e zuUi6Q%!WaCY7EyUp`XJEZCF80aY=DOY4NnuoauQ*`>z7VX_zcUhv8*tB zhjGvH#?P6t0^_(jD{7ZD;bu)uQ{$ZcniWez4a?`$*VHent*@!7Uo>##vMOoLi)tDN zrJt0Z*RZ^{X3iN+czf$4nlfi$BZj)G8XA`j#l49++U7a+%a&Fxs;RGOterm;Vd#wU z#>B&X{rF{E4}5icX*0k4RllXR^BWshG%O6I53C%NUcMZ4QF|7H?eYCi42K(OYloAl zpA3-db=i5TltBM7a-=L?LxdOH?1QT77iMekzt9(Hp2@kLS;&wk4C6F>!}(4ojx-8&`<^bR0xTYfEs z+O<5&@VKTQUm|J`N3N`7cN0~s-qVlUw%rwNTRhW`S3oQcku=mdrZTa2Cxf26* z#NKF^iP0($y!<~h{dg_Ra5f3LQq&>qs3F`UN_eh~(Gb?}$@H4B#G170m6CButsxqp2I_rTvl+ zXxxfzX==h4%x1?KIjBg2%!j&$E0QpY>ub$3_He^f+|YC5J1HA}L#i}YV%uZNIjprz zo2Vx~34fE)Cm%(IUyu?pk;mL{xA3Z@qJ*a8^N; z1;4n+zkB$myfplrxGJS{Yb3mb^0aYZtJW!}GNK}A2U8o;}I#sA!LGhBs zZ`=XuT%qm;b)Hc7fm$cjgBJBLsPl#QI4IiV#|%Jfh96AGxC;zxJ#ylOR?mqSR6oK2 z8P8j3_%p5J;8S%|!$IAP#V=pLTRzVjcJ?H>-3e~rJmWih)YA}99>r6R?NQfYO+4yr z5C%PJ9f>%6>fi{UI=GWQ^|i~VzIOT4ceYQBgilqSexL8O@F#P(TtXXTrRmt9e1N{P z6pLRXnJFJ&Z=rnPK2XXB_JShTZ_t10g<^g1dml_qf_%A9ywXrqBB(Qk$B0%Oqxhr8 z7zd``!9<*~`W?&(t-Bp*Xkkun)Vy{tr}()TCUNE~uFlN^L1iZf@Fx z2~)S_C;)Z@(=1?qB2m^-*4txSH&xJf&fBSAt0p!#?c7$NRIuq9VQ%d%ThZZ}y-Am> zHn6+Uw#NwyrmkO|XtWe1rfj$y>skB4JDM?dVnTQt`mY(%f1RiMuat+nRJ08bzbqf$LgsmPdQhow2iQ#Cu45zE>mUxZJRl$tufJF>(#a*IXt{=gy=@~gcCqc~>>IIAUH&CYt?^{rFgzDDC?8DMQT?C%r$N+_l08pI9XOmDv zK!t_M1odN~MuKV)iWBIlV+)t6O=c$?F5R>KX*Cg!i`82c0KNX{ zR86X0``_)Yc@@HbC=Idr(3=W140*0l$E3+`od$>#ZEVQn*5v{8mo70O{>vFE5bvak3 zw2iT$Y+c=~)}`eKwXI_7(rdli8rizWSgq?tt92!XXGrV%1MFIV7FyS2-MXqy4{teb z?iSb`GmXO*-c?Z33@QI*uKbsEqA2#zielSR{(Ctn<-a$BQvS=csp7p3Dul&v>_FZm z6no#5LVbvQl~5le=P~iitYvG2+JpQop)juQs`uyivbHg?gVNwRSfa+*|&g*OCv(Rwx(n#D;& z@Dnq2#TJ}?+6W*PJ#5UxZHZX2v8ZVCHwx8x`CIo(p0>KnzeD8rXCEOT$!W7$<>of$ zues0b!Bmr~Y!E69`9`7Ak^f34+Ho+bSc$sKa!ri6ZXQw77VamL`RiA!ut6o0e~?~J z!tVoE)FdxI5h@coM+kli5p}6h0pvdwstEaILh)3>F3c|-))hj{L;f?N=vhA(YB};N zg<>~#l~BmqO^;%$U-n{(P_(l|sAS}2LZu?-sY+e7mkZSsd8JUuq7r4Fz@ogcRVZYV z;+gZ{K_JbVRQLKRO08R5Ta0Jjt5`D+SOBz{lqod16^q|6=Q}vdfy>`*iFfAKblb_V!Qy zc~sZX*u>xeyYmlR+vWR3-;^Kwk~zPCIiG;}8#(_#*Y95WDD8;;w{81+^qn8{c=kzi zUV(Vy*qiknn2-CnLu(gY+T7L0E-S$ZEUc*x4b9BF)aP5LIV&5M4qdiD`ccJkJ|bol zOz`R6)KrUK=i^~E#ROlgW2+*akA~SyJBmBcChCsY94mhPIv|Pmj?YdyNDJa$#A`1O3qOX~wu zzCv#6QI9bX2QR_L2fW9D3LSDY4vCFn*Qu;X@LdRs)*pNMt!alFJiR%6jHj3c-(KXj zY-;YN*PVJ)Sw{%wTI4LjJC6C0f*FXM$vckuQP|Q^9CP+>ZvTlDzn;g6$vckuG1%g6 z7qQ~kx38ynlpZ@WBU=HJ9cTG?#Xz1eKB;0@l4(a?=6GKv6EojrSW=-V&M%@k?`w`7 zhk9QWhS$(4nPm-$;siCvj(vP;6ebkKiH=%+dlcp$nv-mprE^MKCOdNXCe5)UT(@ct zBONP}Q^_*f(Y^cYgVxo;6lsnf)A>yEzyee2n+kcKXmMs&Ym6P``F@9#D)#Ltj?X;s zR_OzyIOS2CbD}txMRA^r;_Qmz^kx&5WY*7A&9S4F->5lur1j4=C&jXPB0C@?MvGQ^ zxM5GTxdfHe zIhxa5IEW)WDhopFs}93rM;7MQGC8O?98#5AXSGqW(v38w{GX`sS zIyobTV-4LSu0VC^V?h{`G)GDwM^1^8GdvS(r@1)P!%HaYv29-E;?U+FyEwG@YKsHH zxDoZk=HiS3XRM3E+L+|xaOaCH z4pxkP`gkdO$f?9|fFlB%b1znTrm;EQadp9qN=E7zn@4jm(&3VFj^ik$lau!92^ zq;xC^E_?ct;~RpUeHY_vtMMvUj2V!kJ%S;__>tD5I8J-|VXM0~)Hst;k7_BwxJu_y z#OMn-yXQl%{$PO}qx=I%@wf{HzlitDriP?A&eAi$P4JzA9EZ!8TN%DyjnJ@ST&$%8 zLx%AuaJXi3#?j?;GNZz&)#LFKE2eV^q!O{67*k5U#B_p4v0q}Xs$^0Px-4QK<#!_R zMrj(z6NOHSGr`4iM!RF{P4MvrEO!b*;y)4KuDy_UKVS?yeqZYuqi(D-l3Z?_G3wN3 z!A?mtu-kAqQ$p{=jssU15g%?U4amvSF^GnHg=2#VqFn`7yCQl`!S^sT8PF>yH`dIS zS&Xk&k!wYrQf2)A;BJUi74Jvh|E~piGvkVN6a+38ABdnDI)+I|tBzq3P7E;50C8|s zGg@2D%#k`wSN3p;Yk==hoI$7dBdh`98&)G8U{r7k^}Vj`_1w=;gKne2`le-p%9@2s z@vQ`=sgeB0y*S8chRT2SP`YYtJ+} z*dDfd>S@Oy>IpbMnps>ke~JEdCcy9-Re7sd7w{EW74EH(pCR}t~{6E2~613OrDX2*`}U}0SK{qG#Ps7NaZN^^!sq@e?*+av1F0n^Rc zMh>@f=~b<+GoIakJ$G8KR}iHGW3g96n**fTBYM;U(%g~Hb-tcGVxS!;oBwmw;SrMR zKpFj?tLbrQe-ZKa4v^6v0n`qVX57MKr{M^@<8c|_MszZykt=3UCv`XtjsKM9Dmi{J zXJPT33S9-oC*mq3_UY3;KCa__AkLpUXv_iB>)a=o+D><3R>Sf#w)0v$8N>!3ZU4{v zuzT3>%;BT(5u2Gh`i^_V=*%qji8sIFE|TxKTW~iuQ{SF(KBVXEn$1|IfT4xJ+fVtmK_8gPHtSQaba$9jBM`VBA#>D#2ld3{&94*VX#T&8inX=i_LyBcdM z@gcxt!0gbt1gzUQ`@7fs!QThW9s0&5Z<5+Lx4y4|IYQrpjHPcD{&KlC*NbGOFvW}dyjHjXz`TQvrxBrhBvl6(wY z4?Y_}!u@=QKHI)}@K*uziN?{zy!0Ipebaj2g-qUYMdEV?8|T*d8ZZGqiARd1kM`XQ z%zH;FTzmHA9ECT^urS5aHwOBS?TI#`-|lNq-^0M1z^Cr*=o{>emMUqKCeJ(Pv2F*bmQ{~q*(f{#kMA34ofFW-D0+nhwU$Gv8`7+?8Cy; zo}WIHZWzDE!sN!;`uH&Yvvhoj(@$U#-{0GQkb}*K!l}#Y*hqY;>Sf#oAx`%QwJW!KWKYvG#+H zF>cTp0V1=@wfFZ?@V5bXJ_V56<+_i@4Zu9^iL>>w`*~YqL?JS-a#_wEFPz7D>+is| zX)O2G>%2vM2k|M4BT2a)`jUa`t+AHAhulXOzYxHEuxHV$0+P{f_U!W7Fsn)N;~-G>P*X8o05^Krn`X`CPHUiC+PzX0a7 z4)pOQfJc-S~e5!HE z@4e$mdL#4%f5(s5&>)|)fkp5sXO|P|1t3- z?!_)G|DobZEJQSj0}xE2!&nkauv2Oz$rH9pDwae8R{lF;N!$oa)GPRW6VWekzw{O= z2V3f~#1Tv4DuHoV_h3;G8Lk%I{saaXo6^S!9~FK%oLSLUnY?jd$ozo3E^(&*hJGiM z8u+*pt9&INVKz3lHoe$Vo+caciw$hNvf8$)r^Y94E5xW7W3ZRE70Lk-ez^3@1wW0(vnKnnetXAexyS;u-vRA-}@LP5G;#xVO{?uAKIKOJ9?{xBu>n@_x`-|&DRUW^o zRv%`!H6`nBs$2N&b#nB#*WE+}fhZi`UhAgUyf%4bThozQt*%zYZ|XNE8R3MM(&Rd0 zYWT&r)US5*YV99P_JXmgJ&Q$stE>(&M+nQXq{&;GswY~Hb>*BlSkx~;tq|OU$X5#W z8ghku7u0g$9hh%<)fc~!-|~JO6?uUt{*6*@3UcK_yryS=pJwz!-Y68uk&4H+Bo!|J z>MSg25@SMboriVh$u*#O?(oZ-sxdm(PPyB~(ELNVn>d-r2mb9kSyC(~OB5$VJ9Ic% zQnZsLqQVU0W-R}nlRXCw%C+cZ2hz2?KNJ6}p*rLT(zX6q^g7HLbs&4W|Be%A8}{nJpFppH)*r&{+L}_s+c9XfJuY=Whis{_&Zfz7HcfS%O;e-K zrpaOgv&3d8b$d&t)9KQd(dUv*x+3y$&cpI1ZT zZvWHIt6xc7xz4Mdj34vEM2}QgdQq3nGk@Udk-V&Q-tRdX>rwX^yrW0j_ZiqNw|n;{ z=G9sA+&y&}(yNE}uHTx7C}HN^fPJCBHeSFOW=CI;tk#nF(^8hUtsoUWjNuVrP2CDW zD9C;Kihbk0rZkVs^)2DNp16^bvi|IJBXm#&bSg{E#iduMChQMy5BHfB4kS-viA~B( z;E%2I&4Oayp%=V;Q*L*cwpTX3gPV6MbW>g8G~g1WabcFwbbWa4o^T#+;~{e8YDTVX z1DO*}+W35ELY<0=*&N&pUca!v4pF_78Hcn4_lCEtAYHo=E^RMHV{Na5x0z}l3qKom z_S(XVd<%=SGs(m{FRjxgP?oygz{_@ZPI?rSIw!pX>Rc>-<4xpiv7{NFB3E9*3v+dU z@NiIy$IrMg6x=LOXM^$^3pABx)MZ#VCQx%*BEyVzeA?n84|QXTH}TGwg7_3)-8aYr zr95*is1y|ImzuLK?!q&Ya1(6fYfas0vxVni zT^+FsQ0j=;cXS@W$xx=V^c7h zKWx#LU`dlO^Q(nItx-#YLrb@CAdT>Fq?E?`9N5Efg%U`^G>8tpfK8(J83di*?iL1%WGl5FDY}+gBOg968#FHZv9757UYXR+`aj2`?J7WQrLW7(gGXz@mUTME4@-qt5VnSrqOUw+qq$#(^s z=MlU7zlwZ3`$&wOj3D8acsR`cFt?kB$ow@Ao%w6>{aS$fzr>;5 zp#sQ%Ayg6a+lAs8=MJG}BfnFqdB}e$)DLC-*HYR*+cbY*54~s0Qs+kqV@L) zMeBbp6s^BssCmdA5bB4rp63o#_rDQ});}Z^t>^s(zY#$Guu!!A5us>3M|CRd-D5({ zL(Y3(erZ8Tpkk#1t7U#b^nr3wElNO%|pIjs2|GuB+L3&q+DA6 zs!+6^HwcvH{9Y(p|GH4Lo_DL1=lnsadB}M^;J5k{?ga{nnYhi}uO*8;lw+S4D^V_1 zpJnpR-y~ppRj54dZLBE|dq*hl<-0-!kgNWcd#NZ>$Nuj}nv`hDo4?f41=?dJcR!yD zn6jfMsGg!RmZZt=BPiCXy2j$(pMyok?L1GYROIIhm4OZtwEqJw2}K zDAweyQ@^|Ufs8{Y?N~hc`OWt%tlYTg{DR+43~ao5?$bHH-hAXkjaO$Tt^Kz3o41l5 zd~(gw&o6!BhO6#fUw_iV+t$6)_GQ`7#c#g;-KpD+Q)cB2>JlhDZOF0Nqx#KS`p;87df?`L$+v7iH46XMcc1=q)0V*T zYfmrRvTxQKgH1b6yyX6$x6bqTed;e=&Ut3kjGJ#gGyQ~tjUT^1cxT0$^w2Tan7H5F zGU&4tThsHOnfU6Sy)}yyKhM1Q7hUcxdUIg*P0{}*Cv^3>{1&Ul9$VEy;S)a0;+ z9mz*855c&f&DR+-l3VPUh>SfME2icwAlWr}$L8$r(!VEg6WT(-LZFU&O-&0ft;!QlYdTd?z?)8Jq245eEiUZ)?abva9n*v)(^YP z1Rt-f4#slM;*q{sF*Vtn9Ry6$mLSffk$Mhy>A7UsMJ0zt?H8}*Iwj*QZCM3kPR1j7$&sOR-Zj$R(EhyA#1&&_xCt%?;>v;BHL#-)e# z94n^gwLr3Vz2mL+7Cmd3WATo+daPh12SuOn9kuVr35Flf(33W01-^>j_dbHjLC%xl zmKO%!d|Z^Cbir^S!1UNz%U39`b^3E(Y)SB~N6sO{vU9%z0|mRUMkQu^14wUxR?N=412^~`>3aFjhK35G42Y4rzxzr(p-st$)@OM;I+$mAVIb{Mv}W`X}ZgKkQgFo2f%+{O}EzVChr?DP`=^D9#0%!w9Sj^DE7<2Gl+X-Y*sY!}BFAD8V_MTn%9P{9f8{B)Y8rBqy7 zGDDg(1Z61~ct~@OwK%&q$BvKNJ4q=_wlD#3rh<96#o=_}Og85}a5zq~IlIB(xW?w3 zfI(6(7pEGW6I`5Y!C?<-OT7usI2VUeQS)7#QgCSDF_wiJz+tjEPlH1XZO*^Ip@lYQ z0syqo=Bx&X7TTQOfI|yy&gbCJLYp%TgIQW=bC!Zb3mH3E9gCa6VX`^zg9B9#&M_G9 z(n1?E6C7G-bAAdAEwnk?!J&mVr~9GGLYq?n4lT4f7l19sjvbNuFW@lQoD*OS z>(J)ZfI|yy&aGIbg*N9;;Lt*w(+?K}w9w{MgF_2#&W+&ELYwmeFC&l!T6LI;i-rtv z`dFMvyo_*hmV<*s=D^$n4zChysXu6`ewLo^G$%!H{8W(0UZdS^6k!b?Z@A0hD@9>k$kY#=o>4#c}ExjjgsG zceLP9s2tiO7^*QAvAU2H$EjxwxbE6eSH47Ft)&Fxs*SNCwE#IfNaKic&-_DOS7OC@ zN=pfb4C5c*@F**evvhh)g3qZ(U4Kz(NKfXiiSE@x?v;yCr346f}h^j>wnL#ZlA(OU#VhH)u4Op4>wlMQZy zuLQXt%M*7^*r2XGv0`l1Qi37F_*~ngI8HqQY<1hCt}7|k7o89731Ct6T*U4ODS*Wt zGdqVIpV{uFTztBon+0rRIi%P{3x*8ia;?YaJfb<=YQ|S4t>*fR6>a(@NF{2FDWyJL z&I32Wmxf%8_dr-Ww%SaJKh0 zZC;G65|^FtC$HanxFc0~vw zekJy?8UNReb?gW^3o;7cw_qgw?)CuTiQ@x?jlvc&{SDd9j&PpkWvexyU{3987x0PQ^AUtEpKQHMU;h3 z6w&r=FH?RPrAIj;d*_12nwn@Gs^4~tDGv?&|7h45IO{vx?lf~Wz+kFYH0-$A9Q-CK zuxy-y86F{e;}!J?lpC+8N4(m2MHw$WB8YChqGLKQ>JcP4-clJrx041l%JKd>gEZ^T zl}OP}JA?>#)+I!^vrZwxoplQl?yO^oaA#dZggfgTBHS7G;2^hi-T}!@I|pSu>l>8q ztZPuVvz|fO&N>EVJL?ye?W|i+wliMA0aoX{0+OBf3d(lYD=6Dpub^yay@Ilx^$N;% z)+;F6S+AgMXS{-g>CSltBs=XDlYQUJ;ZFO87VoTkXz|W^h!*dxlW6hI`iU0rtgC48&U%X$k8qfHt{z=O*p99wqr9pE z0WVMLNW{Z?IuePPkSXTnu4`YtXZ|9@o~^;_wx%1=se5H+HR|aQI;q2HXuP-3B1(>5 z%vo4`Q)B!PvuVV6k!PJIb%n<-=G^VLq&V{LRB>8xzYD~evQyp?b-=Ec5}$~(kPdps$i3+p?o{4RU+OZu9h_5LtWMXZ z%Nz9nXM3rtTDUaSw4!E#f!SV0Wg^71nL3*7Wpw5U4d-kxN6Bn2t#~nOhJGmOHQUSG z>KVC4;KyUOm#tve^NF=11w3YZ;hPd8td|xQI98PV$-teev3!*56*Yej_zQq()i^%o z^@`Tt9SU9t=6$|ZfW+5*Y}{($F*^|pUo5;{zc|QUvT^DaXyQhqpl5;kmT#vZ@#(V{ zj#YO!--mJ}!FfdWKLWVpH8$4%Qs1yR^^E{7H&S23ECJlVk_df9mrU2ICNzBrmI~m` z(OA~A9aWtOm3SB~iO}bT)Ut2|Q75C}%Ej(K6*;HbrAvICFgpWsX z>G0a5@XK}G7n2|E)>hFoJU7`4sI;5`mG&V(%Al};ynow@)QVX`LWs5g)+>RpTalSQ?ZChfwC3UT9zXRxv54=!Nlg^cPSe-!w09$GOKWIQp=35Q-0f8*QGi5b$Ci*<+L!| zH#1!NU3g_6JVENYVkRPi&*}+1Ei+PpsqE0V)yso}2?SA6|0 zBh-EUuEbE+^}BpcM*@!$>JqmFzvidWm0G4Cb^X^}Q-1UX3~kHUh};MlSYgEcj2IMv z&!=oSpIhktXCtDL(`8aN?Byo<%shr3d#!C{PqAcW8d}lraw#`CT##0m*o^q)zDk<9 zd#qw3o)R}OqLQ`g*znBs@Cz+#e4BhZ8(N#b2`3DGd1@tht!H>G6s4};$sOCt9oy+^ z$})GmNBG4$V^(-?TP5Oqw#-N#{BkpV8MS29CF-ZnnAuj5T6NleKAEb(;oEIZ--%;O z7Tc}$@v1s)L~Epmiv5t+0g5k^BiaI}!9ooIb&^n-pg8XH z$BGHW!Ai`SKpgpXGuYFZK>^~8%P>O9T1$4q&$08#U$p&^19Y z<_KW#Jxv!YIjx6pyUOdl_RF;7Bt(4_$x&>AZw_*ny5y8Fu2yKHvn;TH;q?r!VT|cV zRyi@N$%8-sANIZlK8ou4e`7+3G`hPQ6)kGih*1y%K|rf!H_3)1WJ7p_WQ8OI2omHW zkRViPsSrzCVr|uG>kF;*RjRbbU$xqnmjo0Mm0D1w_^4uy7Av*bs{Fs-bML%%C&_~T z{rBHrXFoH0=gjwE%uCGZuzl;E32%07<&Tt zU{X3BPzG_l@(6ZP(31hfr6V8MDT8xx_L+k+2xl3PZgLG~Z^NbP7KL(tY*KLI>4lg% z_T%zBd&c(oO&j5D|v%6I2d5swAH`4PUVhvZwXQz;k`^t6^^ zQId@+gX`+zPzPmz&F2_fLvj*Z5Vv*NtL7R!Xi1uj7~`{Zfyw9l$w~UVdC&M2@1xOZ zH9RXc7wfi@%MXf`8}DT7`n$#Td(B0RlZ$JmEDhH_`t$oOuAQ2T7$?{9!lhR}c%FTr z|6LZ>Cz^{GCl?n8Bqy=`a=R(`&l4@K^K~(*MFjRd(V-;}`{Mg6?__{!7xVtQ<_t{fk!7uV08IM*(U8UuM*V=+*K=5uBT##hX&Z<;n|-Ym&WIppA@Xp=fP5cI^dILpiAvB<)dS62|I z%NY_XDb6nl78D}ZqO!cKf|2+y&$}Risw05>vOu_EL`gw@{>XqahRwS`4`TB!(4*MA z3-X4WEV%_`BMJ&b_|iCUc;1k_q2`4lr4_}&k;MfCMr8T1k&O(5M-^6#8W9{3D4!$J zF&fUhpb23$9!9wSaz|{#D}v#XBg2q692YT4c0^egD9EoESuk=`DdH>)WAu!_@rywrVM_D7MyxEFGH1>ejSV2# z=I<{YjLAJ?>u&!3f?>HD%K7_bnZLgk_i&@9w~ubwXAZ=^!r6ItI)DFU3{K|nW9BD& z1M_Xf=h!d=gi?+v!hhq*z?pOEr+yiefeSwV*}ujY?`gm82SaZ-_LV=sWn{^h^;p89 zb8ZPeme>l6ql4rm7MXM7{kGS@L4$IK7}XB{-POE7!-otVCV1AoVySr_U<&G>mK|I3 z)`LFI7)luNySzE#-TlOv8E>~YM;y0qi@~|Qap7#n%fNl4v8=3}y>a;rm}5A!#YUXl z8>S_op9IXU8pq7D;$4U{wK3k`1G8J>nE4jYdUI3-`agjg&0#LKuH-EO=7$>BnY;qX zSOd&ITyakQPQU~J-LvL&xrMk)E%+v^AS~SkAS4|BIo3gC(y#u)K0n?9z za%`R9F2{unfVqRiaBLK7#cP$@Y|tw(=>8oC-q_frESwc@9SXERhS^cQXxk~z!f_fl z504YZVrpmovv4zj>o6WW5a#9-wI_jlh|>+&I;($+ajhMgLN+LD zPMno5ygV6)Z@c2Gbj%0tPGEeeQCjEa%Y4ZK<{^#iEMG1M?gfpZJZ^6J5(0fVCR!JB zvK5LhAf;$(KRE1vQrW=aw&&H!?wa<-pa( z%CpUKP@mq|r^m>1dn29&+>#iayy>>he^6e3?Dqk;U1N{Jd1tt{fbpG0E>%xE!({P)n_`bzcyMf)>MC@v`rpFvO zS08&!LP$RL=-%_rC(#jU$`d7CYM&XsGHpguMJIlCHo+a(p7s%JNuKr*@;uW%g6+@a z_}szaMCm46RW5U0mQX(&e=VUPj&;}*aCg5#U`*=Iuq%gYZ9+p{#U$|_(7zOS_cuyZ z95pM=`ywgJL>ExCHLQaead2yXyAh&UpVJ{0TC-bx^2ukWo8 zOk@yoMn-3X@Ft1a-vGLpUvErGi%E~G79}Z`8c3F_7K|g3g^P^dRE4_LGiF0^s1+HV z4T4RT>Jn&QUEe=WDaixh$;jsV6iKY)4$}ySUJ)k1kQ=Zv#DBEPh5)mnSPDR88a;wB z^?oU%Nr*F2O?4`aoMEoiBSTVHz@5jme6khY z<_&EhBSd`1cnEhgeg*?Ka`h;%xq^`T=-~dP>y#H|<7)SADSIIHIieq@A9kNPXpO*e7ByLhl%P zu{HD{{CJ||km~;j9a3sWdn(x42 z@ok6<3i@lnikyhB_Mor^J~yw2x9a`(f{-R9=^eOkUN4-88t8FUd@9#|5@88 z*SGjKrROYBb~R!Lu@ccn!iXT!%n*iX5oqL}gX%JIJBCd-rwZ?2N41{_wI;sptztH_ zDMY3LCmFNDJ8=CxKLmn$; zk0GR_tVgI>IP#M{9(Gl!o+^Y?H-Y>0(hl?jA0mU|(5XVr1{tyG zv9;)>hdA`)ikQH`A`hjb@bO>cThPOsz4^VKGVHE-1|$qJ2W}*FJE^E$HE4dmdPKAF zDiBb$YBqKg$!O#}cw%~9)IGFLqucd`kyh1*AnlR0NZmX|<$bRN;x(8)z>$gMc(yCFkzJ^b!E3=CES%U`QlTH&Y(L3PJNSHSpod+97 zq?RqBC`}qa>PhWZ>3}79kr!%lZI?Mhj6gL%A(EtlF+K*IR}1@cX<~dyVW>Ph=dg z`#l_UU5JQZ5j6^MRNcqFO(W+EpbS|sp+aorD#S*vLTuzAETRaosK=n3Wi>(x+&Q-< zVWmj`4wB(1d2Q1$Qi3VDYg<0{7H)^@ZyiOBr^oBOSA-16J9$h>~*HXIGD zJFur>_jp2bv<}}wP-dcz@QLWF@n@_C<5ERfQ$s#1VL|08%tA(>_d`&R)a0V=O6=W% zU5Lr%xKW@y@$f``+!lBbVD87=7IYQoo%D3%-1XQqJQtgxh#6uH39_IuL6a6e?#2s! zSbxOo(){<_wNZa7oMGpu*BsglTuh&$hrShUp#xKY0(l+?K+U--I#0a0e++N#Me*L; zgK4N&^yV(tW4yWNr?dtQZ|;UK_Y$tyiJ3@Ton(7L()T^bsxM759d3Ug>ZOXce$^pe zhx51&sk@msCel9hwjSr$lGUHQ2xX9Y+v%!`338EBf>eq9nf<2ExNjO(OvGyaWYG5!s@ z>R#0M;=cl3c`D`2Q+X=ARYL4cZ<9~}#~(?k7{?z=r~=2^B~*>$9TJ*^3569^e;;nFognHx1fp4m3yu2XrRHLq4=BWZHexs}Z{AO3LTeK!~mMSK5n|BQ}dA1^Q*l|J#ppQipXzwW26k6F|Agm?E|^T_L4 zgCE^>?r*;Jm${eTKKAimZw-t*xnS?@17aPKzWw?mOPW8ce#PK>c-h|GJvJUldH3?O zmgZb?`Jmk!+efX4ymOP`SakA=lb^Wk+XJ_yPWfcU-epyE)Nlyey5pi#Pl)!t@BXx5&1>dv&HC5){0F~(Uf~t3!|!^%Z0ap9 zzjQ(I@E`xC?_GOFZ29H49)HQRtj~v@mzQn2>&_t=cmMYEcdlAqS#kZ(U!VQ-fzeyb zKL6e8p+Du--w`vp zA27t?KmLQp$8A?t(7yJGeN=Li(c}GT>j`*{#gnFEeH8oB?wpmf&vmXfN{L$^#r`ij zX$g*$*k{=vw%Oxa2pVr+MqJd4PX0PuXT{Eka@?Jaa!6-63#4P8x?Jw`*4Cx2Su8J)ij~kepO12=uD{jfdhf#|nl61a7Y^ug3!b zyFa@e&Mzh>@s7=H?lvx6ip8)8Pfof<5E#y0vc?7D7fe)Rw%>jsrYmFR94DBwaAb{e zcbx|{_E@P`lz~bqF`p@$WozW)Xp4{ z^2lya?Ze&@D&ocY0?FCL2d??oK`X;!1Z;J&5(S*K`s)(X;K9A-isWv-^s`5fyuzI)Y_vrI~=x`1g319P#aSWX!iXo}_h@@`GB zR;zB*6gm`C!S^+VIo6mo6R{_W4)()|tS;E-Oi{rHXo{83m2nhf6{UswP8{a8ILae& zl#QC=H)DTCQ!M9~UfwLR(fORx&~Vskx!$}?V@@$Ki#5e^z4=p3v0RhBpee_jTpwu4 z878G?4;4Gzzp2>!Y6@M=DN3QHSZ*~NG{th*`F%~XTxLF{DVF2U_cSHblx(>0v>cii zaWI07PAgUH^EJgPiRwAY6{nND>F7?4;z0J)gNvJB z9M-iMpL310>cfd%3N9vAFeG?3X*r5wk9{DnI^|ey|9T;FC`T|9;|VakuqldNP7bJ+ z9J>9p)@)y;!-2Pea z@sc=n#U>aDT>=VYuqfZu7+!X+Qs%v-Gk0rk;7Y-DVw_wxK6$#n@RojIR-KywkJB)zC9l&&a$ zc2Mjq>iMi;SqdPB!Go8knu{1i9|3ss@Mm#d^XGg1W^oZ_1&TalBwa6YL z?cQS*HGn@SR}d5{t_6?%xy|A_M{^P5>Ftdr7S~mpix?-@ z2vF2~0=fQjV*QUTuDdiBG2pU&4PGo<0i%e>D%;cG=-#@);rb%{ufIX%<|@XopYp?Y zC01`w#metaUF1~;>Ca6Z>A^Q%jO#jFF+Ao~%xn0vL>-Ya@c)I*_h5~?V0z=ssZRfU zQeO0o2D1$`Ih{9lF5IVu>zk&Fp@T>;EYyOA#+mWdqM38%%!?-nVQ;~OS}}&gon*|T<4;46BK3O3TD>Nf@8cue8i~L zI!C&K1oJBaq)lyj02NW;`paiGHZ{YNNEb4Lljpl%W|J(gpFchJYB4XUQg9W^%Tjcm zUL6DbEOTZ#;MLIicp6u(IOLl%%atJ*5;HRtq*y3CuP`sGNy$ZV zshSm6ZH%&ZfQ!2UkC_82bB%Lms~TDzT-Yde8nrc7IGJ~FG>Ax{h7%m=8eBAnMG?^D zL31x`dm<+oz;x!R!F1JkME$D6VZ`A$OE9BN%vXZVi(Eo( z2M?>Z#TmRgtjg-S&C>Y4g2?j#=>-^b)4Xz6l zP<3_l=pr~rZve}A?y$kbrd&`z#XN7AoHJ$Uv|;r*lP_qPI(({0pEg`Ljq@QnLoUpj zHg&RfKE-)HXs`o6+2UU~YgS;`G_`g153z))ICFA3`xpB{+FlS=He>7FzR=*o%C;5l z3tcSsg^oH8Z&&qGv73FNCQcICHy8UtPvQDdJ!@(}11_E^_!jMNz$60R+XW7l*7X-AEG)vFv zbtUf>V1B7_oyp@o%XVOn*YinEoKwF+z?8e=e&&j^^qTHE?`U$M8w#^N9E3RJy-0`O=pfg`A z{r-%22LW?proyqhy2-l>^c#Tbe}=+!CXe-{6qvU)4&q(qaUOcV#wdyIxZmJn?=$fk zA9ilec%9|DADCm#a>H5a{RR~32h6lAh2uP}TY4GK|7eUtYMe_y^aOBQG?wXg>xU@s zr3B@@4BXqX@?7lW?2nP>W*=uN;!Qgnbr3r@)+@0)5@R2SqBdy^aopT+{Xzc=a3}JW z9X9qGo#D;{W_$v;8NmFo8yxj}SYsG3H#hq!Y(Cq7`-{f%osr=9CWK6SV?EC~$2e2} zz^%2vH6WG!&c*S#IJ+avhY<v73Jgm?xY#oi7%y2XGsJ+1w3|<@O>lv}MT6)X&9^&Qa_NWt~g z1aZ9*#2uRej`?z291eDBY;PQ>`d(!0nK8KkEc-L7k;-{rh5ebi&Gk(U^JZh(>DKm484{&N5Y|0d*`Aq<-EGfUy4@>69J;CXt%I;WY7y3WauM@rE=Vg?_Fa5OfiQzB zsbod#WM0CGX2Y@wmL)UDHO(8jo>?t%=8|VDImC)ph_Mh5MKE|Gn-rKqf{S51MGV{k z9eGW`Adj%fV4mXt4Yh`mLf$4fRLUou+Pp~_P;w%eu*g?ij7h{Q$t+}uvPx1aAyl&? zTs!v_TNB|L>Z<4`(dM+J9a&Kp+X&{y+V;Y%OnhmchkqH<QDJGTrKtt4|{xd=UR%8x)a=Oh8{*}8g^wS zMqS;G^HtcDnV2bZ^)nnF6&fGf@eLR_XeQ>DLZg`&MeB#qV?v{u7)8rR=y9QqFlk@C znV7kvGiFz0L0yLDB!oEL$Piat4H7!fq+NiJq6HAT9D9bR7)Ql12_bbGBIbM8m6@1M zZjoR0TKwxpA@+%?GF*yK+|AW}ExvVg{jmsf-dw|2Vo&QuV%dRf@+Z{MLv00L^8}KpkNPu^MC`!`~SgHNZ)7zmn?m_|FX84z;{%}iLlE=l_ z5G-?xxNU4kj2+%hTRh&#W(+cTl@;_w?5Up9aU6v`LmF*`gxHW(PO(94#hxm*s8pYe zo>tP(7TU42VQKsG9P z_^o}^#s)iHU?K$&k^0_hE!N;`3-5UEZY6`V2wp>4)Wn5%h+M|I9{m$?uwgF_i+8Bu zU+68I(D0D288>TRi#f9tM-C%vMnK!MiB)78JJznCpN|~GeFEgK_3gLbCaT(HYlvJg9?FA zeUPk7fw0m_)aQVpIQ-%5(0d~i@D@9%&^{|U5k|$Ll+H*_ScV)D$qDmHpBQ$MqG1~2 z*;RvRec|4)YvdiUnQi==$Acg(*qgn}oBaa1o%i~IB%J^nHHK=czEmDi=3k_?AeIR7 zIYJ%$Nl}3Od@}L#LBwB@&Zd7Ot9NHx4lZzBU718up%o_WUWA&lr;2?y_NN)1bvUZf z>t={GUC}N?Rac=>OslFsWhO$ZC;7G+T8q#EaHV><*5xV*ZANIJgtj8INJ85Yx<*1f z5c;Ns=n3p<3881gz-*WVnm3xSGNe900 zILnWq7eSV9Jp6G^T)C^yWKRV=2o+E;k z_0dgmC`>xShQcUFOWzX+Z42#3T+kY(u3AI8+d>^;zr)7{7FpjK+S?Y|2Q@1Xw1(b_ z7XEg3+r=8#Kv7s|@0<#F zMccrFfo)OOKw!YGGA0KO+siVcCi4uv}4>o2pdKQ z)5pTfVA>21Ze2TDn;+MAOIX)SZx!oYU$8yxK;jyBNT59dW@}G=v><6t+q-E_I}&M5 zTN7wb8>5xmr8#YF4XtVmt=%PN%V@EW&1rQT?funOZf*^&L33KwMRVHWY)9rHo00v!s zPn0ejORD(%tw$)sGZIHtEh-VRs)cGi(?L^>XE#Esk#(4%9w-UL;YCPsoP?0#cnu*n zut$ra$u!;_#b(-R2+&%kZ#*imjMt6fF2?AF@xyA2-Hq|O8hwX8MIpotd(Z4**sJFW z5RYx-n_BA_`NF2uB}k9bo#S4W7uO=BQYO03NScwZ&GSZ46Vh5MKNSN+crrPQ(8;YE-X)LP6kNunm1Q`Tf=HtI-*pM+w9u@^NlODBE8DElB&hm;XLjM z)7`j|^@NEPGZ11uVUCUNhV87SZ|z6rs*GNd(mFFMh2w_ds5j>W>lq)N@2iSlox%Ew zj#W&e_C!6c!igC86T_>V$x~;n)0{`F-p3FoY&v5_o_K)G=>#GvCgF|a2aM;_wD%*{lH$izemJ2m%g%- zqf}+AG_+k=b+oP^rMTF@`>~|(`p}_W9L!L^O>cRYp&ELtUc)?Rv>?s9=~X-@?yN() zYrT=Z-s;_6e{YN%qi;^wa4K>~-9DNTQtf3iLeFDQmFb_+2xZ8vT0K*;XHX&bA}VwU zAthx!Lf9~VlMVfcY$Z5$YUhgmS5KLUT8{xefn$q=s&Qm}PW4Q}@w*aA#DW#<7BK@QrACJFJa*$XK39ja zD^pGU&Lq{ep~ScjkN@_=;^*Mn8UNkFpGX=3>~eb&SCyTs=@LrAu~9c4ha8C?7Lyp>W?#PPniBl<8&!sFs^X7sj?TROjN8tCbWhW}e?IFP!$wuC?WrEmt+;0X8)v6|wCTZDV`ORPx{>{e``+EHkDzM>Vd~T zYq;=^_V=mqE`mVdG3&s@e`rNQh_5af5)KjQf&dqMa zh~0U2_N3S|IPFO#$JtL|57M1IDYg^K4ixQ4^@x+hQE+ln6^@M6-JTSC5K9j2!t{)j zbF^Rzc*O2*PpX$g4(&-D9Vh2&f_Vi;ZnHm`_?YU8?0Lv;Avx(R9N9~`+h*dRqC2}w z#|nmDd{XDz|G8U!*Pc?H9-J&!}^RnJX$XTk1CVHP5!zTr(ynvD>(r)?&0T)Ob7 zDD>fYfN{CoIbsY}KC`_1adM6q%mf^%#pZ%b8|?b1?*rMVCnxbG5o^Hu9U0HYV@?nZ zzv`sK6FRP45s%>~p~*@7qLZb&;kVy?BOZh70OoQWxs5tw{?vF3`{Cpy-eH+`-`(x# z#H~D3I&%n`oW!p?NHh7(pV$c5!N4d7Um8eyzz?wEMEcOXGFU6b#eEZ9sm%ALu%7`$qE&TygdZ znQ?KQDVVP1oE0bMOpyb!^Z@+N#82J-&*rIY1|?UYpJ`$$HHCbNYf2o2FXhx`U^p&y zQaA!~Qq~v*Q}Q#KLVGSMt`9WDvf9H}qTDRoI>R-^vh~xTDVEiqsHRvpde&%)Wm~61 zQ!INxUspvhhC!?Jw{4L#8IZlQ6AJ3%OcO( zILvEtl#exqc5{>>U*pX{HiL3@9OWCDV%ZgH(G<%%(soUujUFXAl{YSImKCairdaly z8a1Vd$#sLKSQd+Zttrg0M(KN#lwjL&ug1`dkc$1FjZ0BZHwTjj<{}3rtE_wox)~4i zQTj{|DU9TP?4+cUasesN*(pOwIbf#@BZad>Cf6W78Sz2Gq6`A%d^=@0xk4s|XXVh4 z&yuuemF%(GRLTO?vZ-|Jp69j@ueR%Tx)c{_TS4I+%c2~M;Q;Rk7Nr6d_Nf--2cYzI zPoqh4Cbu}8*P>;$`nnZ z^)cjz?R)UEflE%BiX$N>T=?|g)qNQ!p6_Zd!I0qD2nzF0QS5SJ!!E?EmqbT;+vvJiaM~w=|^)oF;FeG?h*K!oa zF6UfawdBwelNt?@t2e3v^$`pSo>Eo}Y>Hx+a~`P9+)$%9q8Do}!I0p&S5p{vS~=+l zN@o_79s^ejt`h?;+c)q1g^ObZZpV#WvWp0{?bLAz#$*2io)bICN&2#9)!@IjSzLXz zFk+kLLI{^TUqt0e4ByGxH~E@GT0ixo72+JO3g(KxNP73Ukple(q5}*$c(KW9ACMmA$LP8uBKI7Evp1w zsdv{b{CGJ~lat$_q*Up~_%xrX@_W&Oii znjVu57h@@gaKlteEQhPLl;F&nbEX6e8>ZDa&uo&DdbkS?UVcGaH&3;#rg=#a9hRlMnWVsM^>DF)d_TOQE?R*f>#}q5G(LP1EPhmMRF_ zGo9F1aTG&Eer2vwjMfN(^XAnr3KXi!9Slj;${R8k7KLVCZV-dP@u=&tF2hKbnGz>} zh7R)FOr*eY)O@7EZXK&c*+l@{PDR=z>fnEEW*J%B#oB*uTLO95HAt0a-H5JHtg|fH zyt+_=Kz9QZd5PJ~3fRpSOmCQSMcowiA&m`zA+Q2aSFmtl(Y*Ru4aG3;gT5;lG@JFB z!))D#*$SGyKpV`m*-?sZ>-n_AX4yrO%HFkYnuH{DX`Ch@30+#JNk{_oRhjQN(tPOB zK21V8bZMX_Aqibts7XkIGErkQo#gDq*jOBu?LWYzlbgMlMDoh4F-`T8XEq#eyOC_P zqISD6I4#y3VNN@2(j1|ThUu1~iCf@u#GE*rJ+eglZlm4mQb>%&5lJUKbza@DrbSma z)HTkYHYX4mnlBb^hIP^V3#4&&!@{OO-q1W{V6KZ{97Zs_O7YrYoJ8ZJegpacQgVv}_|2R$ZbY^46pwrgQ;G7|u z*4CY^oxvAekULo5w6!x*Z0)q;9lKgkjJd(7^WZsaL4!Ob;; zZ@>bb*xD(@v*+ddiIoqgVhh9e{)GH|&YcU)cWgK}8y8D}ivshtV-di{nJCM)hI;2m zI^X={0#l)JoR73{maUE|&}RcfOT65=lJ`C^z4+1*TW9hLa4j2{D_n6-{aS&!-xX)+ zN8bz^HAW)F!7UwUfqpWkhcD(7F*eScxZ(Krtpb=1jWf$5#@5bfxbQJBA94B{+lkmM zc~&}RgZ?}&UUCvqYR=liS?Rz8uIFdKtkJm6;^hLl-vRS(ZxI($9+o`5t@WP_dokF# zIm^S+kM&>`Fk4)4mb{aZVeb&b7m(Ok4c*f580gmmGmL_!1yzXQuW&n z*Mw`o$Rxtr+;BsYFK3^DH4bMgoU@)<>9_>ArNFFZg}~OCe$21GX^a4Ika%6%<==tp zk)==&4_ha`eEWNNUdhMq1!lAj=avrYJwap0$E~w?>wueMljjyMKNngA%;PqkTf7(H zJ;-`sKIODEHWZI*xqXZT`ugJ?#sGnJS`YXZZaFYFaWWPg`!Bb6+1_$<(MGUyWB$3} zICr~CV~FGChWicZNtl#<5<54RqlI(U`(40%?25DM3pp}4U2EGcc^2+`Twej)6B^rD zI>rFE0hkjwnTyS-pCzvX*K&bb+6}G`BDx2d-wqRTG+$y%uO)9Q=w}S~c;3g(4aMz> zTL60Qg+y4JTY9PYLvA>i_OS}Mr!w|dz z0nG82PzzhViYX6tyPk72Mu0fDl?QSC62P(F9vFv%Ev1-viOWk6H!49~og2>fE(cM1 zs!>pLVsQUiHk^KrRL=P-Y&gwQCi%ax0Vn9&tqrH?0I|ub2N4PAN3QSTdyH38t?)2Zy;h$P(^FTqYC*TCGy&3D^H%)u&tzV$~4Y z{k?FdgtBCzI$>BcZ1G@CvBi_6c}juzmFRetxNJL9e>>9<#pIigr9J-AOtC^G`c^<3 zmzV05^u9?zDq$BZeqS||B!Ua%gTkKU&Bijq2r`3otT&7>i41RK7%4RI;PsbceJk-y zpvi#rnG8st$pCdC5$NDA&Cpy-;RiNOB(nNF(EdmovY@)RinpE$2a)RPzkpgnm`&^I z4iG1yIQ*rE!aoC1_@<{FW7z=#8<8JfEgH*5T+~Rm{CG+NeYXD1;rBZmxAh_aq(f85BssS$`f#$CZQu= zarxDl54*z9(%BC$?dU(&&E(Fm87VW$_JPL}J;a*LIb!tvtQ8xuZ3_uRW*$96EY7g+4t>WVV&}ak-YF;@bvT4+XpG;@0MU z?L|sNDn&$jwWk7x(tbly%i8ERZ)p1%A-;E1?jh8?(LhFkVC1rTZ z5&ENCtue3i6K{334WU=$>K*3Q`^>9b5qeFozG_~5)4ckB(?-_D+|5!YI5hCQ%L5+- zxx696!`WEX6>u(-<2hv`>jx6z=aq`anG!_{AapZ!Wg|;norLq1LTkWr4R&QC>mH$@ zYpF4#z1kox?I`1AW%vMNP*k=m8U$RNh6+-|J{a}@8Dyn{Nk9g12|*BiMZDV-W}!a& zidd;(4v@hV38pg$UQk6C+fHE?u5lHyVYfrf5`}k4&fo%;^5;J1^`)UM?!;}*=k-_a ziv}{i{+_KNSPX$ckVg0@82_30&%r-#*;rZZ_j)(2tHl2ZTJJ;nVTN&6TkqYpz7i|n z*+@rGiz@0m0(UN65fqaMn?IXgB&Ld~8j)RBD_W^q&wfgcxxS6ia_kwh(6&`VXP^eH zlu-N-wMyqNY)KrL`V)XWu(~)R4eQ;{_MYyEUYRx{sY3UP5+C|W-KRu1wS3&X$F*~G zG)!8uF^!QviU{mOa4bNHA0oP2B3lWl8Y2E)gq)0{S$DqEaWfLB)6yFH)Uav5q8%@F zAse?u+8#6P8NdRJ-Fz2tVgO;h)D~p16TGViT~ZAGSjv_fh4P7oZ+F6X?Nj~aF;Lor zmEqYhw1?2tXnCuari*GTx2swbUIST0*}H0XKspboifWu!l(n>j^|f*}4mGQAK!sOB zLtT$iWoX-mjUiHwlmmc)9LI>P{t+&b2MLCDIGm($$q39nfP$vrFJmk4k7ENcOglgU zT9Q;t;=NU@!!)PiE9#?9*7Br3Y;07twe-hbraiQoNy60%VmBHU2A4ZNKXi!ZN)TMd zpm9kX?*e%y1OTy$K^KJACkWL7{Y3$sUjq&pyR1OlSb_gZ_`d`HSDFoD1Lsavvj`wG z1AB(&N;AX`S9L7qap}{Tf2;76PVZ6mh<1OjYT~+ABP$$rvwT5;?Lm921?Xb6&$qd9lXNPE+ zls7T{XXt;QzOIHM=(;prjUJQ*Q^{N8b@bVa@l|pXZQjxHanlKhnzzG5N(EvSDh!;# zDhYD5t~U2M(-g^ipG*y^Y-@)2<=8W1p?s5sZo~0<3H=Pml@gL<_C}+FjjXDcElupO zir5>M_m38(w2t{#pErGr6#@{HDBDaBhFt)EHvz=mIrXkj4{hw%RQ zzUIa13v9$l&5+bZpSKxwkryQ!p6U>20q`Fnr+S`6=(`AI zcy=N5q0rtpac85+|5IoK5K_2{5mLAcgp|Bx=GB`J`b;?PFllHQM6~Y4xB%QNI zkjZBu3l}2=81$~=tgO6*<-f6g3jvvfM(bMlM#_@KKF(-2^+Fj-NAVtObKzhbg^#8W zZcU4p4Nhq-PQhPVD=n|X>UwR>`gHjyM786#U_fG$8?O-!{yF}Zm>5U&1>Wmpqxofy zMDt5V^GlyZ^UF*}G{-}TiU!r^I~_}K3jJipGRR6@axo5#sG+pI=3B%XUyr-3*afAf zIU==1Of;oPa5w;?**GIPa_5m5#~>P5giqRrU3(!AtL7kw;IcNkX%RM398?ekoIwmF z(G>_G@^^1GCYvHKx{Ld#Ka6<&;U&s6-t*pUm=%Q)PGX^Ygc|$9fTDgxN)Tg&>QiQ9 zE~14ET!aKU8YyAykqAbzOj;w=qLPNOQO-J=DS&1~`@{QqxDlc_$rdTWU7fc+ik!HK zs=%Zkej5b134pb#2y6}_nJVK;pqI)l>g;dWh(qOe$i&1Y!g9%1kJ2}1G6D0Q zj4Mn>Y&J@+fKH3fkWkClIzVKRJ!2>uitW#x2E&QPsxXK<=63ya+ z$VkZ0LavyplnP{~azB8~Jfr+sT++AR!E~Y)MZ!CDVx;S40WD%aZ$*F>oef52T%=wk z;fkv1I;sBfDsMKe#G(w)EvW{J&RPseM^raL9?=Xuw5nVUEaOlacMxFIHh=gj;Mng* zN>CA0HhzjT^?Hgj-r`w0uXzW^V~QA0P8+;d&0zteAA4$Fzzq@%OEBYwq5Ly6hVBd9 zsJyPIla;Wd>N78`hACwbFzHs2vpPwM+l856HTeE3Lbki5#OAP8OtNCyNKg5=O%`!3NlzBZypfC$G4W_j7FDTfBDaYo8e46z z%YDwA1HvnTUMOodol%I8demz&L!9$ewABcydQycdvK(iyw2zQ_B)k(LH48*L(P|cm z4~J?NXa_=S7HE%2>p*CwNRd%oCZ6){!KtcuOBVO`pw3lhzy@|2M~SF~zShTzk@VI( z12`hHZn=^(T+1$moVJ>$+GPTau6j zW+O;<7UJYdz5wD$1^ywX-=A9VtVS^R)oIhbr!S*IROG0(3Fz`C20x9q@G9y)x|`}C zTChLGw{*QPD)IqLL1Uko6m4Pb8pY5z#Gz~x~`WQ7M@YtxN zlE9wm4FJPYVnZm}LY+n4(sjP2Kj*AqlDB07{-Q0+7IXwp)zxAuWCB84F)+t$dkBUv zF$<4g3jaAWMJQEH*(LzD19F8(t4CuwMFVN}uQ zL7b?r(Z-;@7P<}Oz2s>bxTVN}@PHe6$ne7^|kCC69FOjaE6%YNx$mEZyic zdYiVENoIDU6G9A`JU7c@?`KANSY4FnWpA{>F}u3K>Wt=_-NP1yRCjY4`Un*oh7dcc z49{3IGzFm>gtov8ElxH%o<|UBldF#-v_e8pBc!^jHxW|Z*ZT;mPV0afN=CP`QaI36 z9ifM?ug0kI6^54o3ydm1g0$Md`nnG1GbR0p@vYaBBE<2s4Bt?RVQjoiz^qSF>rpUk z9W6omWklDv=Vy}Ip0DN-^Lf9)S(f@6qW;pqEEg$Mk`ZFHeK$x&wGo8qAR%k8knMhF~?J!}+tywB#4nlnq{-q_(EK z5QV+&!WU9#$h+``v?h#f4QCtv!WYs-icHslF22wl#B(8A-R7AZ6-$X3LVPlFW6Z*~ zru>5Qu7$tABrIb4MW!>hUnrf8*z$2J^B3BQ=a{h#Hscs!hGbx{49))@kc#N_zVPuB^-cz^_<8>VF&GI@9_hw&c z70x?Q^m1#)+j3R@d{NHw=ZkXOw%ZZPvEFLiddj}Y8#TD9MTj%^8S*`c>e*Uwu6nlb zA*6b?ADW?u&8uroT87#4O8y6M+7?)P;h5W&wcnPv-34(Zz!IKW2obkUB|NHU3TD_@LxrR>+B-ikX z0ds8=CRlU$)?))7o>VTe;i+^Gj*jGM^eKq!9VE?Mji$8|A zlzH)=N{CrsC=t`!sCpRTByL{3 zQ6&3td`dz`&cF7s_|Lh;n&+F z#2mX-La5*#eio>{ExSWP;iiQ{JY#Y^V+MJ~4EBu41u=f(eeq4~${_jM5;9PU7$o29 z;4oSTrM~O9;^}an;>;-J0K&$mROyXVyDH38d(Il+*ndhfu}gSj?1tg;o?|zMH}pt8 z>WdmKf92!vJu`CptV?1Im(M@{=3o7!<^1YbAAKR6WpZ>72n-;{!_P)8U5(xH@9Cg^TSt0 zY`OEH*B)!i?6+t9kmny;_phdz-+c4Fx5nqJ_OJcHo9}JD_||ocHdSR4Y~bpQZ6zn%cJRZj-&9|;XT+9Ye(Ujw@joA|F`UwP{`|FIt4kL>!ee@{+28b@}lqyHMfz=9z= z#xEEy)#sgT@siIc$78ter8}eQ#|y?@rpLwU!@Ep!5|`&6gU~yl4%rnS7sq-qhK?gs z^FsN)mGKznN^%mHb!IS~LlAObH0G)q@o{D1N^%mH+as$z=T7;< zw0O)Jg5gqomg&hqo3lP1bEaUp%%16g{N8I(ZAE9Bp^CEv!;uHCxEqwu5==IZ+}sVy zpN%Ws8I!TkI;fwFi^Kf!PbeJ_OGdiZIVeC{uptvI5{Jm2q~hS61QT+}u> zX#tMhF8uW`#>Qg?;7W3mQJ>un|!%fp-meP;`8R9I`6lLBO*zM;e5xsyS^V>LQTH=3b2O#D zN%^g&SjPSTqA8XGfZn=W$}qVu)fCHZz${HU)x`WnQ?gCUOPXRi2}on-i!I)q{dp$W z0*yJ>q&%uAC!3UgnnHu=DjPC67?I7Ol*CbH#8GaEqdXT!If{+YA$edNr8q{#Qhp8!$6FSq0~C&ZEJ{BBc(=DGGeGId%GE3HB$698^C9d_ou>TN zsFIS$@&=DhFcNA5CCjAPjn@wW)oHxmGUdNn%Mpyjl>Y_7)gMQeEKT{V`!Y^Ee*qUO zo?uAuoPVtRX^K7ep}1g~;HMll7A1ZzxF|<3BzPXsaumfbXBe(pa-638_h>nS5jj2% z$+0PlUCwY&ow;F|@-NU_f)W1dn!*zp1h*MQVf{!>3h)B9VK4va4=Tjt)tZYKr}6QN zKl?zQyGu|1`j3CAN(E%kdL0)rPOgiEOWzng=WqSiYKv=^<|4+) zh2b(ZG`MDd*6@(U^?~Lh#>sW5gX_^pim$b}k~uKJMvRk-BVH@65AGg|jz{$)aL=H* zh%va7*_D8BWe6Py*$l4pHCF&saM_Ho1VQP{l>cbWMT|49eBt8dBCBY>lbVYdCFyNVp>#$0#6hteS_z3{)-7u@^hxGJCpKaX zeT3jC!k=Z7-)Ua|c+EwOlWT-<8LHec`R)ORejd+Rnu{1GSFwYu=~vT#Y;l!pE@GTq zB@V7nZpd0~an03S#5lQ19b8Ta0Jmu_V!&lH8Z%P3Xg0>V{T>|uCJq3;I&1BgX==mb zJuSPtSe>scH*B{XcIO=ou14qc3YF3PA(j&Ynq-HKRqcepa4!%8t1E}?c6cCQj2bev zsD8d-SKcm8`zZ*{cUqKhps|0Lpm%|m!L>lwaGLaI^w1N>oUlrIVZ)R;v#y*2X9zK( zVFcgiE+7X6xfQ^01du3Wj+>)`ar5eD&!1V})Hr9hlIn=v($uB_b8YOD`k4)f!$5BZ zhT7_1Wt|m6OsYh&X|&*fIJ)KJSa$r6OoGioFUrP}W>sXn`YshYwi-L&uGP3;&a7FD zX637DY?^M=TecO$Gr$Pb@4=8*2(&QO9s>6e^g95!Aw_GD2$$ttAwCj#C~(BWgd&zP zbFMP#j7tn~Lt(Vz!GRK0)4^0QXJ+%P*@wvo<+_Rt`jt3bI;hyd)lF=jFiMqeXsW0A z`_8h^wLIghic7x4o7ET37FPOl4L1`piIUc5Rs{=Xc)$n~&{_YZ;rSue0kNJ0=PUmv zDup(Ht=!x?4$Cu&ozrN}(8i4kIpb~~8#Ndz85dOzJ}f6K25XENcj{BAx>^JAUnd{z zRp2WFRj`EqSR{K!JKQ`3$LE5|nsh|=;}hiy<~yQge2H3(|NqU&2XFYf%+bJ?;^#wE zW^?r6(wi7Y@?D%;bj#eehmY>ryL9i-J$skFJ-TP_(y>SP>|J{G=$^exmmb}-cj?cg zd-nf2^RVBpjmLs6nn#=`k8bn$zivDN<>4~PS~+O1OHS7%iTUJk_zOvlQ2~BzB~C)10e9Vm+ z84d=<7#Nc)#4$s<^E{GQ zHzo(erY>NC;Y`<<+%6yrF}PdApkN>`Cm0CfFRKh*_5!w6#Sw+%CHtSc`3+N==OLH1 z2P=@K&1`C(-(dRSP#!pPa&X1X2S=`U$zi~Ze}fLTg|lV_jMLc5#(4}Z79ImL9DH>4 z?}6Ws+~JnnkIZiUe&i0lQ27a=-;W~k`;mtk+Y~+1=jQh#1+NnvTPJ=$HpSoqo%sE@ z7B3O*)-Mtmt=L(&eR9CKI05$%Fi+TUZuZlc0Ji}c!!sx+2`#(r#w&MaZubgI`!Clo z3^+k-;VgUcRiNJw%x4+NZ#r zuBWm&pXZhie*BON%<~#&=CkcH2|(mSU}G|!=iJ=nWgsJ3Q7CtE-WuE4*xhiCAtLXI z__*aHfywJE3umQwHZEV=+vC}fog1r;g|o`zIwY_b-_5+mw_w=#X4DP0nDjo-4?8z! z{#o(zLyaea+3AY2;++cI$G}`h25g<>A75Kc1?KK#RKPz~x7PDIK72o#h|Z8mBP|>8{^zaPb=8h7MFHXL_CGI}Vt+t~e`S)r5VB0t7WifH=672dDj86TtBW#)}EyCIQ!*Z(D7f zTfD4J3lqSd3EZ6t;Hcm46U6lxVp9%5H~p9|BNM=}e%$PabGgsl3fu!4%X;c|pP{^8 zBq(nUa2sRgx%lbW79+1SKOJuaSIT$Q*p9|7ehq9d+DS)O;JHs@c+SlY*B|uFz#Y(7 zw)4(#X?Tl0gm1F3b%iSirl}ho^;@nnA`l0O*Y--9bmCUU;yi|*2_n?S?t43M9U99o zR775ke+IV0!F-Eu+uU$0-(d;jE=mx0NvAlc|BV1}<22UHXWOe^s?L6LIxshCoT{fr zzF6|uzyBDRhn+ZA{~K$7d7>K}^LYa>f6_QpznFYZ0q!G>K~Ofgd?xN63F7{h0FLQB z6o-SK4%@3wDw6}ny~7!@ZTQ>=HNRm}WfK&1xuXoIJ07-l9vwg>{9CX4lVZ zoH7P(rt9Z7KzL!OC|FrG4$op2ojGg%f+<(dYl@+U$Br);GcJZWs;sa)7!Hj+Gm|;` zA@-kR{|fzO#=9Z_hc&XyIn(V zX}(^>ab(+x=5dP8NIBG;whs&*E({GHnA&;_Pa<5XX&OU*5|mVY4`^t~t}rfF-Th@) zy1gJm9J;}@okaa{C@rb!YcqV~O+_|gp>m3R_k0uBGCU{XI9Wm{j3Zq4|J9iGpJ`}G zJ1I0S$#FQ0ql)>Iwu-d2`Dy)j-iXD|m%$*BZ!+w=(Tr7+H+w7oXpzWwoLC-mxXb{= zUv|nt1q!Ca%n89b(1I7uEg2S}{N*%dL?d;P2v(a%MrVq_ewv4^hDjzGb@TUKy2-cn zuP|0}71rF^EE>FxO%%!6OHR!$L=@_w!6;NP%- z_~0~L0KZts9MQ)>QBGzTT+vPBs{>=I*i=mug;LxV>SHLBW+*hm*M)4YQ7UyvvnkY7 zDlC19Qfvy*aFac2XvSCT_z@)AvZ%|{+BLHC8_7vfvoxD#>D_5|_<3bi2d3;WHM8eg zpBT-0$K=^*hU`SLjCOy0FlnzUs$H`#tAMRIZJE|HMl&DE&njQ2shiBM)1sS{Nnceh zGu*2s>?KG$If4YG+p_p@69T*WU2PoGvGYpx6yTVI@ouW89HB<+8M1C4pV%Sv2#zYW z10jX`6G95t3w-M8rDmuRAuRqLQ39BgcQfiX6PV7cY-(7^C?0r zCB#p0?~zanLU&0h4WXY%C>^1@CFDcsUJ1nwH2$LN^HVA?}( z@unj;3d5la8nX5V6X#B*j}}3hdpqNWIs457;NUBOtw8O@CDX>cy*-4=920Nnj$Bqr z@%6@04dXcVr3M0J2&tjyQiRmdj>WD*4~BXxnlADt6__rB$vbqao}O+Sd`9 zEi^7xx=lhw2)!;>X%9|atuwD)ixBb<@@_J(-fmv~>Rq+mDmr^{R71Oy5Lzy@GjWVc z=sc6gNfJd1Ak>CkxoS}ylW?v^m<1FR#<)KA}|+~O)Tw-En;OJ zpGGJBVT{9Q0~*#}#BAx)90y_iw2dA8to=ANAK+*UfyEexwR3#LK~Tc*f8@Ukq5Z29h;vY77VGR`a z^uaxg96UP~{}3lehZ%!^8nS94O!)e1(!_?Zn6HO@OBt?mJX(p7rZN1a2|nhHnHq?N zjm@r86ISX2Nrwe00oxJS>CJu}e+|fI4sAo!W_%_>mC%@$i2damI1BGrx`-9@T1uz^ zk`{CQ4JgHp2=4-MqnLIUZE4dD$x&)^)Q$b{)voM_!ZNBajN~iDsq<#+$Xma-E}@qM ze{CNbW2J~`m1!vS49{8||Ajr((~S0~Xg46FX#H_ZQnV04iWYZ6aPtoKf71=l6QVBb ztm@df0weCp&)p4<_2jojggBo3;C@3nOO%&3?Z^aqke~^3Uj@t!uk%*1j>+>-S`>BP zA50e`$^Ow8TyF4Iz0@A$#1jVlerdp?!Rar_Xb)zRTC;&qvFgUH9&KPB33jL;JwTwc zL>1tetxzmcQBF#h@hA+#LQ6Mh)NEik&Td<#0902JiWx44e7kD)3A40gL=ei@RfD== z8|;VDch#UZ+9}{d?YC3Fh3aikq9G1;chww_r>z4RA?T+qsD?PC^2q~L10wgagYq@Q ziuGssr{D-I`@V!fS~G`XTI3&%P)Dc*n?KwD`a``Driov66xA@v8`+8-w!HmxGYC8K z()y|wYnXpJ;-v*)|3WrJ_LTu#n)nRt1e;@OKXX)k8i?iXVl-3Oz2sDaQhPC?5U`QNfL%! ziNF~oO>jz&!t9{k??4|V1YER>9)Z>EYG?@iyf{p!@^CC+D&I`y7o%rU>Up!Fov#vI zj*kT=Jt^~=D$wxt+t^`h9+~Q|M%IaNZB&^xyBPV4?kHjy!!AZM}>9o$Eb+85`7L0JtI*NB)P|KJ&?%+7&@|Fq-k+U$}H3unr>hGsT2;2 z-&eU$Ir(Jfvyx1Lu!*QkxF$so#TcQ8XKrl1g7&PuY_J}qvPQy4 z?MAB_N$qD+-e4q9jbW74Bkhv@=)Nh4^j@7J1G!n{uQkjk-ROuGY zQGb*c>m{6;*nd3dtd6yICZX`yGsm@lBV!LVS7{ z6g?)B%>wE6^wfD(rkL}+0C^IR)9`3Aj64o@@+p@%s7X3DX>bQQ6Ihhli6fjj z&^NEF>YrX!!prnvlZVrw&v0h zbbQqXE6R&arWQR78ZRVAj>XPlWCX5~ntg~$T$FIM?T3r4kG(BRPzNzn3#-m4za4hn z1)%F;H)imct!<+IAx`Dm04Yja1;_#55=QH-dJDl>aO1VsTLla9{)PkID!3l>H{j-i ze$~IYBAr zs4NjLj8+|CW^`_a|7_;BnGeuvfaHvs5ljR#Vh5y*$4zFpnG=y|tb(V>XaRaFpC6(f zZ#)f#!qSgdZdCVFjy;%s8Hgag^3Wu{Cg8UP?nZE^k&JZ7L+Rtyj0j_qSrY%^HRM~1 zLo>~$uBk<6){ba+hg9p(Mq78Bi-hXO7=#XDPxVydsQSAJW{4O?TZE8$+*ymz<=8W1 zIzxr_VMLZTo>QM^P5+yGulP)gXgFb}lY$ehN+C)~78G!oe4@k>EWRcOm zb>$kvsKwI=*?n^v%OG4s<@3*@EGj`i6+Zeoi7WzWA}Xu@o0J#nLjXiY7;Pj11fS^r zmw}||Py&vCcnYk@;pmG41CHHgB$iJpN8>7UK>3;%*FI|S0LSl?PdVWOxX#|k@Z!z^ zl5&%w#ii+bEVwu?8B)dBOV{$DMV^uOLM(HaiU?sJ2&Ghrkwvy+-;bSfB4N__nb(r1 ze&(HIlH`V@8rouPh*yO))T0V`rdbiBPtSsEDMmj6%rRd*#vL5hscb?Xs8>_+7|EVM z3KpJ%7(%YgNKlGWJQH$!wO-E-J&Q)~uY3!K8YE1*KKk<6XwD98{3>UM!cfFl2}OK0 zyP0?Fk(i;#Na@Zv$D@jKEvW48$1_7~dn?uDE*illdl#PAycA0lcL&DIQgp`LfjFeE zWCu(6Dr)9?Eec)@{80^#FzWp>8^c?V8ZvK&B%Nx%_?D%kTz_q*o{f1LU5V-(_8_D> zj69c4u`+a7=z;AeQIjHOc_L?UKtWwM=WArj2d&H+&Zyoczy_w3FT7Zx z08sb=HPz#nkSN3&v&-NIwzNACF`B4WQ_KET+`@{r46i!;iM%7141e4s95tHZ2uJw> z@Tt*9Ieco=Bi&*Qsf-~_l2xvZh)5-3s(K$z7b#7hQ*cbAnLM2?jO&lr6^J2I=xcXNTrk>Q{uA{Cq<~!C`QU*z#Q{5->EFk zO%kN8ggl|5c z9dv!(i26;#9y3nHDiUn4?1LPPH?bEiMw+zL&SB;;vNJ4bvQ0sLZ|v%TaZU~hDd@GZ zd93VEfGWytL_JBSDkRN_J97B~sJF?~fH2KUpX4!au}1@Gc%R60urH8CpVYH-`T+I? zGU!XIT$iqvyD&4P#LLwrOC?F<9?d5Qb?B#GvlI-PhOR9zFVuK#T z>3FMRyW6d^ezz5-=yEqVoN!sP|Bg~zB^b{^ev}eKH29rLni+=w9r>yz9}{08&X0?)1m`EjSBCSG;+ux^Q{s!o{JUwqoLDo%z#QTDj14k~L)lp0D8BE` z|H4u6_W;@*{>#E2OB&fb1MF}|x_3ae_pi7rGxj%&kA2aP#K&Id7V)uut`r|D=8wh4 zhIE_w@MmR~ZN?s?2uDeu;86MdsrXD#EH><4cX61dNvZo>PmC|!x41Kl(GS1rR8*J% zXH>*4J?rZd=V98VzkT6~!iuaXe*CZ6rSEEwe%Nt+@*lq^b5ZW=9YYR0eaQ zd34-+WqVG$?bWwVe5BXqUp{eY+_#tB`HTO4_xNY-{^a^oMm=`*o7crZv}e|l?90En zuI8C7>#lz}cfmh8-g)$*!3~e@d34;&&KI-)d)7~K`o5KT!V@zdx$0MMOq=k{RWIHD zkJm~s#iGY#+0t{6_W z#(7rZOn26~aeEcoDW?~n#CiC;=(+F>xOeWckrMod{pTOIB1jJYw!i)3@aJ;aUT96%2IiI&FddH<*1+isMY@a?9JCe8uRDN@BI_&3g~mj z=OhVhxW+W>u6!mEbFyIgJLswK{o#S^-$r7%C@Ib}3TL{y`Ol!}x`xF*JSX=lt-KC8NMmS990e6+cKW<=dc6ATqA)|#Hr zT!@bjUE_SV3-gEjPHv9Goa4g$rn-1_BnDALx~S68mH#R}GZK@ICnyU+z((q_CmxE# zu*JlA@-=4P%;fe+%z1*DrZK(J3XzDe={jF9lt#CDQm>mMF&TIg=V9vTlE12f{?k=X zA3U++^MhNqqe!}9E{Fkhp#m{RX5r>|gG=5*2R#H0EmKCH{+rt2F~?)^Zu zZL&s}(_b)7Im+HVC8FaJXIm>b^U*NUq$Vn>#RS>5d8oK4J(2ns5fb|&VBCc)zR zWdsGyQ9F~1Dxz{Gg^I14@=udsN$&44Nha5<2+Hjdlnt64@&T9n5$<#dbkrl#1I>`lYIw&nO?y2{x0=DBK`u8$?>mzrYR zcYjw?Y}@2~W6{}`$OD>UTcBU8DQTAEUu(+Q7UeBXv2E?gvjc*&Eyw3+ifw&=k*1tv z$>AG<&bF-ov8K?@x5}84*&V~#R`c^TCCDx;CfhG7ifyT6T(DIVY+HPw*u`E9_Q&= zjXBnmbE|_(<>9jtlF=K}eLNHu)-wW3`1C(rr%QrtM38WBWY;jUJF=|vI zniggVDc?9L1MuoFZb8&6%zy!)^wnXBWW4DOV}_HGO)jq75beT>PaCMD*zxfrEQ=!X z`KOa2@p%@ZTNnwe6=7MFVGwAHMlH7}66XXRx~df4Ajif7$Gs8UHu4!$+eZGH56@ah zdCFxTtFDTR{(4ZT|Jjt^fKIf8N7$j=h4zBscj(6+tOqi|z90xnj2!H{75P0LXfXXvc_wrzX2 zjr=SO8Yo9F6l2tK7y+j!PC0Bcwj8&O{Cl+=!3h8BT8^SP<*;JAbHlcg--8VcPB7xT zKvQ@Fo7oP71Z)nroHbcyC7#%-UQO{O~=`PJa!3xXIo7wcl2M|bhYo^Ss9 z6ICi88_RT9#JIUG7A{p2v5SGrM*c4}7cp)w_EWZwbn4D&UYA9OcY4k+DOyEk`TAVx|0iIxL`raa`LIIZ31ie%Oj+nMoMrMZYP zn;yA*3%TMipSj-nstQFJHCRq`4qEbiIH#sF} zXmn~_UHuGyUT|i0OI@>Az^`tuZ}exAG!zTX?4he3w~mjfgObO<7$nX&(WrjV#(Imx*c!ivYN+cV}iY%(1ipUsro|u*QuR zd(p5_tV~!(H_mUR_FuPlt!$Vp+n}z9mtUgnAm`H1`=O%UM_}O&7Z;xC4|f zzzr@x8t~)*a)lJlZaUdb!?fz^&aw!*{B{rIgvY#F zfs#Hxs&#wXY0YVDtX|~LlWrR*X@w)RCt^p8d9zF+w%EWf9O&d&HI-R!H=vAdcjN#! zQAAA$HlcSYt!}KXp4Tk$%uNtR4scS;!V~@dx`r+7Pu%Ui9_84raACCS1*-&@bP(MsYS@pXc z8|sH=bs6%G@)B^{6aP+~soDN?{Jx_MXGCM&ouW&~v9mb?i_IYVf7*t+D&?cMp*}XR z;IfjEoYAzQo@E+}TAQ_xnbk{V%b2`D>)G&hR8NwWBVsnA{X> zY^rFgo!f$)Q64P~SMGUrlXeg|^aJ(HNZ3{BJOKxsDOV9GJRT->W!b*6rF>PO|kh z%%yoh{bk{UJKh;`^O2U6=@1M*H}C6LTXRcW4^L+&gZ9r1RyX&{%)G_pS)wWP>+AZ> zt&wOcinHagcEx#g%uTVl_EWWdB1x=daUQlCw{tFyVWRCR=jfm1Ipt|j-%?gw#OHlZ zkRM47KS8V6JzfszU$d|suDc$O=FAFoO}Ba|$8s}@I2E$S19K${6^^2#+58@Y z2iF1fr2bHB;iA|e-mEbq5T|H1h}ouIioiwM3@!xjoi4clT|MY;kixnD6Fq1{UG==+ zzutv*NNoygCi$+I|e3=xRJotwvhaa0jOjQ>yOv7CoRy&VePd}@%)A9Ww zmW1(N4gR!Z8-|D^3xjSYDKh-^k@pV+n`<_muM|To@Ho zR&bDnV`-e0%N$q_5{whj@vu_imvWc^Ms49=Ma2h8A-9CWXEPnl^)kfXSD1kl4deKx zA!+i9HGe7MAKVpU&WOcQQN~kY;uK{l0A@{SA%%ZBe~V))p5dQ+8mYnm)8${{b~lbM zmcQ;@mZxecD@S=QPQGHM3V%1-*_I26+~qQH?iwitGn%o^brwu6lAvnHCO(R+kt)1& zJd{7R%@Cvokc ziNA>_8Xuv|R8{I@RV8*y5Wd8DnCjkD?|$(>($v2#{pCG(EH3*)-8J*3Y+Sf+acyeO zH)r?1ysmM2bD!<|_gvaLXJ@aeYw~ig|MEY%LO&Mu&+K{k4ml318;}{M8p%(?qMEtY zw(itFDh^Zvk{a&0D{>{NQvawl2xiB0lpw>RGu1zPWf@mT&~dd6@#;TSUTqceI^JsM z{t`~@!2W*j-eZ1+<{-w+#VVyzN{IXW`5h#|5##=T&c#voDq~`ldkzlPdy0GSd|XKZ`_cqh{`C7W=qAD@zaLMHfEO zxIa7FsRj2EEjSVF^CF!c(X`+^Rk9j^OB5}51IP(lV>N-%wBTWo^#X8ltY>iSC!%Ss zFMvKsV~C@RhWi!jW+!kDv&7*Tg=o0PK;H<=Le>K~R_SQCr$N6Sm`gF%r|S;)E}j(v zbDmzD)*a3dT&BjrD^9|VqJ1}X!9~-)*#w(oz)?$I7=eS9-X&b(Rz$;fnGb0I?v5_F z|6SVrlStu${|Rk=Rrphj z0#yq)&<(_*ZZa&qiFryf#v&$nX>f+Rn*8f6)?dXY51(n$K`@K8CRlZXb)#hd6mA;Q z^0oN9lV0^s+UK3L$=m-m1_N!t$E4sl^2X`j{;xJxhWPV%#pRTEE=ml^fYDK$3RP4q zp!HPHY!Z|ZTBC*LS1}sk3hLwKv<|2Y^X&!+R;#wazztQuig!MK9>To+UudlL_TSW4 z;|PW^G^K9<^shMHvZYh71fitwWC+Lx7)byfxvrw=HEq|Mp>EnU1z~tI-T~@epd=KO z4YIo;GL&-K5Rijms@!w9%AWumoG;T6Nh9Hv$b!yTJKGOg((i%hnc3TnB@iy4Pv zSP9#N2qGOEq~KtZm5{GXwX^SD0V@_!}Vo*Ws?SP^h73DC<$!Hns zG0n@CqXCtn-D*)ZkER+L%#nE~$?9Kk|F!cI2Da0D1sBu$3I(h^v*%&an$Lb=3)jhN5N{-V;#w!=b3+ba+5!wCbF zG6<*IUrx)nH1NbWot(JJ!?^87yv~+tcnD`zU6Y*^64j4W53rkuI5P<{K1;BT=*gsm z44Gu8WllCEvpC%r_<9U%haCk~0cIi&zFyLG`bra3Uso2-fiJ=+L+8Sh^TQZ2le-Q6 zY0Mqml$U^r{3}D9FZ%!)vIAMl4mCM-m8Wuj9#X+^v9k9ATN@PMn~Tyb{}i5N9OaOt zMz`RSaT5Aoj>R)R1nO-SH0p|snHX#ttizSX}oJ8Niqv5$9Ryb2!VmaF-Zl- z^I%|o|MzzZG4%(Mtf?O(Squ2mkn!i2-pc2tDDkSYyNOqk6D%#}P7K||ZAhcl^+7U? zkozXHSmaHFe6L_vTQM00uIzOo{0cr}s}>t?l?=Ud{emqQ;xB?FBVlUb2hIZlEO8#@ z0QS=N){Lw39{1TZzrAsN^U6;r=APK&`a{Eg;}>3@_YQm@5<~7d561=^4=i6l7H>D)xPCWQ16_^_ z_+;h#7nDU})Bu%Z0%Gb1y)+{d!+}SfhvNZa?s@T~A4X!-;M0%ibnpKe@r``QG~Mx@Rw;yycO0Bn!?|9)WFaD zjgg%0p*RLWNV}PW-B0;iJ1p~y zGcj&1zUOQ%_hfm@PZa*TNRk3^h@V;;8~fy9lRcvYh;b9OIfKkVZ7NsYBR_^dw= zt1C_AUuGK0bM*RYPA81PSJt9=&G-z952kvipbHvHyqz-)*zP%nmkU0^~?R7LQj!GPYIX1%_a4<^O`5slX7JK%x?H2IE%Z) zyCjFRFlypu)?6gk8G7v8ky9=M2Tq?c1KXEI-?@IsOy#<}9>q+}kRj2&S2{mp;`xBg z%)x^P<2rBN#M|d>choJxd``DK`UE$cz3a-nH4vY3-jZsLJM`py#4{?vgh+7o{&Ifr3uGt{8FqW5mUuYv!D~`hC&UkrE>=JsQsOzF{bvaAbGE{qLG#dlV`BAK7Df zW@AfJbIaU+$IM!2?RpjtJ42^S!;O6PR-e3^PsSFZDcChMG4x938*z)1T0ir&?60~4 zmIi(Dxw9i)Y92PJxl--eO1sDWbWU=LF)_3QgV)ww`(R~sa%fI`TU~m5Xz$X!el+s? zfWUsWZGnTKQHi0~LYF0VERVs_Sh@>KgWGdaAlU+FR4paP3&0jxz%W=Yts<(N`lf1(EGQ3{_8V z8=NKK35X~ClO%CrwlD)~x z+i_XG*}Lo~C`@EaPNH{XyW#D#e3j$~jBd+)^73i=K2_h}tMB{j`!s!@q3>7f`!s!@ zsqfQykAN2W5V&6xM}Sc1)5v}QWEuE!hHB)g04~wMOpP)0eKvsA@j~3#i4XV7eRv?_ zeP3;oH~E{=&usyTh0q4T$SQY!FB})yc>5>hNk*cuoI71 z^7oZt3i3to#!n#t+XHcY58pO#3Z@a(V}=cL2wvZVJ1KMH*M>;J-UrFccOoU2Xz-T3 z;w_g9Wyqu@-&H~|=CqO(Tk>t~q?d74GQ1Fl;Q z!)fwxgSY%iRRYP&uVq9wwqwpJIdGHrq;_8K)YnHO>B}=k@Lh)RzG?$+kbQTp z65l%6UM4xP#FV#E%ehxySD`p|iZCf`Yz*Tqy3V?ch( z9mGghE|;9fgp^NZLfKu+Vo0o9jjF&jRc`X0^fs^C^mR9~TV#~4XD-R^LxHEm%cVec zK5WsU@6gx1kS~cPkD1DLGtRGS)J}cf2lNt2CD3LHH<;+H8nsJb_wPvvFJ~7uUiXxt z7fN(bi4_A`FRAINk19hSUV)VWoT(guBf=)2`OvDBFSUo+t)2s4Up!S)RH*(f zzO2_VQ#G;lS!!)n>>d$weIn>ynxXDNKGv?`QY$P z&Ark81is8|?MO%1t$$BwY^w@wRQsJI8C6rW+OObJ2iekj>E4II=IH#fylP78-t@NO zWo?0*!o}M#8>mtdSb>SoGuobblUFQ%y?M@raA0ML#TvG3N#I*sXhe!;cOKqDe)jb+<#C z$ib}H6QRIX$VY|W)`lIWecXZ~usf?WRD2UmARAnsvkZ}%5WbB)`-IL{Lz{#(RJ<(I zauWh!r+Sl@^Bu_f!uZf&T$Xunm3x`wUFKz>g6dBU2ey@jm-8i3qKoJz?-D#*x|aAj zOg$%u+4yw`H|=eA7%lDGhFE*Ae+?~#HOJL9&@g!4UX}II zRFxcAHpBTB)mRq8*9S+6aWl>ri0@5{#u@c9h1LY$S>oeoA1+c(F!~`vsww4KK72qy z^`^CbmdIq5zx3Rt@RTKHeT_@n(zU86e6!=jxgNeExPx7J5!z094jLC55I#O|w+m@N zMZ53~ZUHuTTj!m!5ntlG1+V6}u1#+}l+d^?v`#EHXJLjOX=Tk;aYH;*Ye9ekl=x1_ z3-o3zf{0UjFfG)AxmnBsW1ScpYqC($HK0{~TUru^HS@qe-Vw7c{G%n>i%q=*RMHVR zz{eedgKR_q?Ud|gXh{f7f7%QG=mB9Y7pAUq5s~CTED{-iOX8+TiTfE93fsXGHv2hZ z9CeNeF8rgtVAqkeM6uDvB+93Asv}_W9x$^-MFg=I=_TPG`A{(+*UqdIdC0I1Ak%fs z!#~Of4tXp^paq*Uo!mavjFIcbJC?ICgS<& z6JM0{w?Fu)7blm%j5oSVQD)21K$w=^;YS@8LSZHe*&Y57Cc#gZJe>T69sV&UADVY^ z$s|(CI{XzTbs7lMYDk^k;jc3#G?3a%>cS5HwWNBNwO|?=v3!(06s`|a%~eeVAD&QI z%VqELyQuZz@om(5?M9=%W2uipTsN!VM#)|!As8Dj;?R(NcwPkjdk)mT?Q8$C4~z&>tC@B1xN-4;d;n z$pLeL83-VR>qW|w4+T>x@Jg6fJZJT zq_W!t1y|UGRJqbj&8XEQ0?^l8B@j-)Q-(C)QpYv3C# zG=3U98$KD$E#12sUbF+QJJ2dus3m2J_wx48x1yeX0WXS(JO54P2l~s~9puZ~zrdqy zLh(-N)Y=DF4txQT+rYPYFHid|o>I{h5Av;Da;2fPM6IVWl$|^s5HusTmkN$r@}=}b zXrr>Bk=$T>&U z5tcLRJ9xW~k=*T6^STP59%)4vYVf|&5;DFT4xlAyU6UFhG&_ce)NWB1R25O8Rs0x^ zFFLo@3y;8EnG{~mSwv1-ao_Bz)DEE-YGqHWcv`X3>YUc!EQM_Wv z-)F5hB3UIV*6x|fWvL*PW#A+_V%bn6p%QOCS+#`D1`!|!-fxV}RgGTzDHFi zZ9y8xLfzwgny-<&IOB@zZJcv;bdrgVPBKaPH$eV>QnOU5F=C-KOQjMk%~GkwO0$$V zi|Es__sA$d(SK8zJ186LU4gQuKSE(nQ4B|;S!P0ZG=*6y!B(=ODa`1-)C==brCrDR zqCo{ax@1AW6oz!>Lz*KWP~EM3=u1E9!Z;ASeP=$XRADn&T@+@B@I6YES`wxLJ?xv4 z!DZ?^M`1zi5w%QUlEqO<3cAcdBlF8GKHYw0Dk(IHIoM*FCvT=$s#0)|i z)}`XBY&Vm#fk~+|lLDPO=A<+nZBn3R9z{|XcApfxVreZiRTe)ey^k7PCXN&_v2l_3 zsNeMyALdGo{^ASatTf7>!>9DVUs<$2TQuq+O3ESll$2EH9g3IwrjnO$(I&%pHn1s1 zo8`M7KBal`Cu#L`Cwxlt?13pyMVk+wlDx|Dy=?iuw0xM7MC&nERG);<3@qKnuNmHq zPw>e&arx%!iey>5Z+>EHJ8GlvQXG6SbGdfmL7e;tRK3Kfp>m_OUB8vE5Vs2bM&$-? z#>d`_ovj~xS~iA?Q*&!qDI`S5z7!vAFdIT;NJIj|AoDU-F!JXFoGB z)>UK7dvXXb`MVsZG|CnH5`xXcTt)lU(&Dn}cZTdJ8~lU6U*K6ZWKxgL|GMwG7dKW` zJap&WxtVwT?DW_A^}FTHIeCxwzoqYrEyo$tjve;obwBytD;d}Q=$9Xy{mDyrbOe8K zb>YuHOV7XYqUYaw;He*P+f(%EnHPP2$}=aPf2h}-?RS@rnlNhnp=pKRpL+esLnD5( zVZ&cP`{3pHhh}cBN<3%d*y6$`+iwakDg1odU;bE9cKw67SKaV@QfXbw>sQ=*XK=uU zw|xD_@7?<6{tI6^X65KLcaLBC!hdpg?$gLTx9jIvoyA2Ew)K#jrF$QSmPLu2Hy_wp8M&%ftdlduWAP-;!}VYE4SKNj<4DYLg5laPrfd6|3u_}WSUd(fT=(@o_!=A5 zei?~L5)9XTrNX!G?(t|sl<3Uo69n@i&dim~Up$MElbM^$UpjjQuXHj(OB1|d1mun< zlQLIR?6twI5tucaVsA+CnWos=Mx3joVXqCIsVVjk!0bxtXs(~}H;i4HVy{CUpdL8Z zGheGIcAW2ups=H*v$s<@fmKqR8CFIFB`1PX9znS(g3@MD44sNQT@>ekl)VrGdp+|d z7tMUia<%xf(SWF>bDtU0iWhZvbhA^)t;yjGOBe7uTFi z*P&LMTQ)`rRJO;9bAVYn$=GX0hr#tFgLaHdeMr;flsKs;;`JsdnZf#?-~a z9GQ|`TH91Ry|%8ld66H+#*4-mIhWMSYI;+EFgLc$J+c(!F=Vk2OkTa5{)pkb7P-4Z zFRqr^~)B49dIAzaOq+=`VBGv* zV_kIvto2XQzeKQ%Oe!+fl|hB5YuN++h5UWNe>mI0b+yyyRy8#R2UgLBa8(10(A72t zu~y%HFr&UHD!r*TI^Hd(3V&&|G@=q|i^UK3ZLdG*gPn)&+ccJLMKbW#4OSdHg*^QG%> z(f+6?!t+wRX7Ayv7LIR^Xe<4_h|lA|tmDfSj@qq_TPQT1IPBdI%-MY9!tr%tsZ<1k4>8$K(nw%AXwf1M`>z7wu0D>M~CQ^MV7{oxH8U>~i3u$)g7Q88FB51rK+) z_?-mIxei=3dHj&oADAC%990!NU+ny2xDNyKd{msBf5d%AjEv(CAHU;(In9BK7Qc%j zDjk@q8fV2XN_kuh%uPp-_XOnK4$NpOEpQwcb(h|iz&xsPR=AEa9{ES%coCRhRA=Da zICuW_1*Rw}&d$GykTDCGKWJQc_4HHVJ^<#GREDZXW8I~r4^*Uls!4F}_}Srdgju68 z0>sIdXXBXO9|HGMRC(_7?g1w8G$pOOaA_y^JYXhh(~^g4zsrF6y~cHyFH;cQc3?7l zt8lIM(WTrlJz`u8%%UUUt^uwUm_r)pPKP_ay;1pxu>rujad!SK!?P*Cyd4$imiH|% zCv%x0TzB#kF_DxF%!qV_W4fZ1+X~PhLm^*`aX(#m{b?hfjRmIt2)Ih%wrULJ(M1dQ zCImDf1AnPqpfIcs(Qr+mue}gy>8o(vmD^A8_)=j0q;cJ)0|P|kV~tS~b+}Rbjn9Ge z@C5Wuzt$fH=J8yGv&y4sp<}y2^;zLw$Zb*9DgZ`b)rU*ElQxy5K198;yZiTr_!nbsS%y0s0aR$M_74 z0e2Q~Lt?-w|+BNB$1X$%XL1S@Dzdu;now7XWiI4o#KJhHvgZFAER5r`cQ}wz5-v{K z%>r81-YgagC#S$BU7N41FurnqIMCbiJdFSC@XJndZ*SfUq2y3eyhia;+DaTL2J~m+ zN8*F6u+119J$YXKws+YYT(9iG zHJ1lTlGv@``ve3mL+T8z*DT+>zlQgU^U5CH+_fbFZr$K(2>uCWS`t%~Jo^tp?Eem?w7Hci>2oU%}eNmyYx45>Oxb)(WjO^f~h( zz9YfThJ3zRjnKx9d^Tld1AA;-Qq?6xT__F2G<9L8X-r*Dom|D1_nf&>E{@WTpW*0f zlwN6sK9}6XFL3Lb=QaoDrj+X;98cp09HGxU=f?{R{;==JSG7Y*YpN_{xB)PUr2Jc| z1gIc?E&?LzUg>=Vxhmf0SN1?4&KlObA<-3-EmZj&<-Gq0<$Pk7a*n8* z_d%+wY9eb|tg>>X!c_-1fGI&%E~qqQ;69=b9y~(az7ipJ9Yowv4UeuCeH}>j=$h1g z{FS{+rHD`%Xza9_!J<(4$kI}|cb?@7z_%2K{3LMXy7YM#*8a;YLB(;{b*NG^y=Ud2 z`^rbfT8;f2q+)GE&o2=vfX`r+x-PYG2Ywbt*QctKs{5Vub(J#vJXNLUt15+lowZ8! zj~)3;iune5*wdW$aC}Shl|4!kBdUxN+@8cM(;PYAC_ME8N4z0jc>?f%!{Mxi18}b@ z;Y9dUQ8vP-GVf~mbk(zb>nz+B_*!wK7)MbtPl>FUv6)A4m(zEvz8#3|zg&F}h!9ux zb;qq6l_TqG_C*)2Ji5-P3N*mqj zyl9X5HM{4Stgl0H;o`*3rWD;tjt?237u#AAJ70y;b|zx8yb)>;?5{>>9`Ob&#zvvC z3ht5oI~ixyhvdVjD&9i)*xRKTzrguB>LZ*e?W&J(awtK5YhNo*(c_FSWiFa3!mG$e z*fRJ&+8#^?c$1Iu`uwoSl8XhE*ZI?Cdf&`V3;8qJax;)CuXoN*Rc#vf8N!nfPU!T> zZ&L9F-vcWC2w=%#{A&MNN3OgznosBmNJFmt7#Jg~eOPY%e5h2uw)my~;kogR`$M^j zteu9z?(1}1@4^vd2lcJ0S{HfGGLEit={KFLq+I>|r-+2JyRggZD4IM!RXTN!h<8y` z6}=@fTppjbdDvws&F6 zX2T>?Q)*kwF7A2sW9U4gi7BmzJT0e&jth-SqM{zZB2yvGiP;+KXoGz#nsHz@TKt*=M8Ab!soP$e;@=^Wg-AhB~nd}mAV&X!bjDAGHW z81l!r6{m)a(?nWZpttlH%i3Gc62@&dV|r&xn$5T`)C(27Es!1#q_!2Op%1_hTI}{z zzAnRNO}Qx3(BzcXzsGxT{2u(B>9_HDIB)<1w=@Z7{Py1Ih_}P9)Cry<#%!?75lF?c+mdYB`cMf>Y=d>~QK?y-g>8Y9mB_tt z_R!F%l zfX-2L=iejlQhYo#AV?UwGQbH4xLh)-t+1Inm z?uM4Jyz{!GP~I9;#OvDvdokn;?3KbU@F2%gJ3}L`4+VA=4hy6#_EJ*b(s+UHBXplY z^W&WfU4A*Fq6Rx?&Dk@YB~aM6S1OH4KiRf8 zC6rJIV(Wn(-Wz)&u+H@5j7Mk7-q4Fvl&;j-vTu9kt|_IuP!N12e(mzf2wMKjD}MtK z*DYTeMg_0k@=o1cU{Y&lN0 zdMeA$*mDAC{HAUfE_ubf_%}rUS120?Oa&~t)7bu>m@n_aAbN%V zNA7v#PzAD(CfzIWLnO`d)9`;eelZYx+whm+dD&lZh-rTALV%7D;fzBgs~9U41mI$X zTBftynWF$oP0Ej`NfJFgWwMJ&*1x!`1qYu@jheuHe0^e;ZyQ6UMvr@BS-#&{zSZzOD^j>}SMhE_7x1QpwgtYI z#P=$EuZV9ed@qV`8+;rdB^W#4Qye?tdsS$=;8PsC;Zq!Y;Zq#@;M*#={qVgmz5|x; zpyh*b;|+Nl58t1}2h|G76s9)|QZYqXzhrTe(R@kP*YMB4jOR>_JtnG|kWkVJ`>ojG z%jfLJ`&Cn0H+5b?!%1RtjGk~q=kl)?o(pd8S$?XQQTbnmEz3n8*z6ousv2??d_Tq^ zsx0=OnG#x*y1cXH+$mxG^Eo`~mw0qz(7mC7SLu#F-Uy9PDGgl(btn{nLkLE^{CL;z zZ!6vx%KHOeMmJ2YGKmMl+*S-bVdS^iPeizC6v2r@m z6vQkg)DvRSeH5Z!d#&~Fp82Pv{~aCjgp2S-!-Gn`<*Q1PT0il$e9Wk_A7QVm#6UQd zKNP^?q!82?zI+N%%k|5rbupqR+uRhe8>2CvWbD?kj3&lgH$s!!4Xa4wl%}FzWE>i^ zd*5D}h}VR4($*^u!TKnpq5!=#UYO_$1Gp{cUJQ`C9a@ptiDR&Uo`fvmwE({*b3cMA zzNu9~_Hf-CLtQ2LO-Y)NZv7yX2R_*@dV zF_OMyuqffm1sLk3`x_>ZpTeC9Ujq;c#<}oaA->DtyHb43@NGlP5{!lLZ5JPZ1p2f1 zmRP=J@Vzax74Yp4pLBdO#)oq{hvlbSdqOBbHEwO_WnD~TQ$qPZw$|P&02tnJ ztuHjz7fxAP7&@+Pbo}s+#ryEQt@rBC*u+ju^`XIsjJEinkqN9xD?<5+Q?KZVUxCmJ z?016xl06MGQu;d>{Dncr(6`}<@v2A8mcF>3nma5=nGmfnK0Y6CcE|7T>Ct+qvn4LH zAeD0!y7hCWVsmqv*B6H!o4meJn5M`N%R#hjefzOC(P>p_sIQ(jH?I6N}x&Ylg8r}a==)3GqG#|r2(vR)65 z?L>d)<6KCtr>%JJ@J-$uz5q|CB`KV9=(XKwX@2zD;rIZG(`XCqmc)ni%V5_rJhm@P zhU|2;nNTqdzilf;zp>BV-|d5W%v=P6h9f#U0Bl1zi2_dhM&)Ctu`@x}anPIGlRbzx zxqz9I-y4}zkQT~MZ!5@X?dS`}{A@7V%`%WO|2z;g7=q#*YVsCp-V(*zI(NS()N;VP zd?-h2Etq52i}Z&AyN9oB$qeTon)5>6IqiMpUWp4Ni7?J5p`bXQBn2h&Nhm1HC*@?o zK$nw$T|n@2ilXsx8fg zPqn4_7HzRb*B43ciCC+Wo^bweAu{D?+v7fUKPb8JfSaJ6o!A8 z5h>o61BlGU_xg$W8)d-h#LI7Uj z-Wxu{ZD{e9aPFZ{%huM8_}6x$LhiCE%9Yu^B|6E-3=c`N5# z4OCxjy}T7k%x4`=g6&#lTCSOAxjM^onPcE(TA_LE-P1QDy_qCz4N_|C@pYw)*9uD3 z*ZfGg717e#Nni_FAX*%?1rdN12qFCH?^p<+8Y%_|#x5K%vxT#o?xZrX8b^vzZTa|l zSam7<0HnHmjHp9p%YRc*>LVx($7I8-%`qMT9C)>2C5UC8U

    }@L(fpM45Ezy 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

  • N3)-q6NB*iVK1XME= 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་*o4jKcMxMq!+EP))Gbko7P9_{#s2JC09=( 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�c^mKb^QyR^p^dPK>g0Crz?tludThB#%bfbSF)6 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 zℑ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 z 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ⅇm!8OfB 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