Compare commits

...

584 Commits

Author SHA1 Message Date
gautam 79e53e788a Update 'README.md' 2023-04-13 14:36:49 +02:00
gautam cd5aade200 Update 'README.md' 2023-04-12 16:28:40 +02:00
apoorva 303d8e7742 cleanup tabs 2023-04-05 15:35:07 +05:30
apoorva db318cf66c cleanup 2023-04-05 15:34:19 +05:30
apoorva 7e8d3fb2a8 updated with dependencies 2023-04-05 15:31:08 +05:30
apoorva 3c49096d39 one more update to readme 2023-04-05 15:31:08 +05:30
apoorva 9189153436 final pdf of all the tasks done 2023-03-29 13:27:37 +05:30
apoorva 725909632a more updates to readme 2023-03-29 12:51:33 +05:30
apoorva 9eea08eaaa more updates to readme 2023-03-29 12:38:27 +05:30
apoorva 0ab0bec309 updated readme 2023-03-29 12:11:50 +05:30
apoorva 0e6937828b Add 'ros2_ws/src/perception_pcl/' from commit '6642b7398a4488040c44d48a48308411bcde2228'
git-subtree-dir: ros2_ws/src/perception_pcl
git-subtree-mainline: 0c9504b343
git-subtree-split: 6642b7398a
2023-03-29 11:40:49 +05:30
apoorva 0c9504b343 Add 'rosbags/' from commit 'c80625df279c154c6ec069cbac30faa319755e47'
git-subtree-dir: rosbags
git-subtree-mainline: 48df1fbdf4
git-subtree-split: c80625df27
2023-03-28 18:21:08 +05:30
apoorva 48df1fbdf4 updated to readme wip 2023-03-28 18:06:54 +05:30
apoorva 65415a8355 best weights for detection 2023-03-28 17:22:58 +05:30
apoorva 9069d699be ros package to run yolo detection with ros 2023-03-28 17:22:37 +05:30
apoorva 88944d72c2 custom msgs for bounding box for detetcion 2023-03-28 17:22:12 +05:30
apoorva 42814614e3 updated find pose 2023-03-28 17:21:18 +05:30
apoorva acbddfc828 yolov3 back to its original space 2023-03-28 17:20:15 +05:30
apoorva 12d72479aa updated file extension 2023-03-27 17:11:27 +05:30
apoorva d7ec4d8754 find pose cleanup and final launch file update 2023-03-27 16:51:12 +05:30
apoorva 821e6cc0ba now launch file install properly 2023-03-27 16:45:18 +05:30
apoorva 1467525ec5 added launch file 2023-03-27 16:42:25 +05:30
apoorva 126124c4da tf broadcast for each object 2023-03-27 16:11:52 +05:30
apoorva b3d2fa0ee6 added number to the frame id 2023-03-27 16:11:15 +05:30
apoorva 46177f166a added the best weights for training 2023-03-22 11:27:52 +05:30
apoorva 0e1db823a8 pose estination updated 2023-03-22 11:22:45 +05:30
apoorva 61e7117511 adding synced data for pose estimation 2023-03-22 11:20:49 +05:30
apoorva cf0fdc175b pipeline works but might be slow on runtime 2023-03-21 14:08:41 +05:30
apoorva 987530bbfe msg files and cmakelist to build msg 2023-03-21 12:04:27 +05:30
apoorva fc5dbd85d3 added detection image and bounding boxes to run on bag 2023-03-21 12:03:10 +05:30
apoorva a312c2ae7d script that detects on rostopics 2023-03-20 17:47:04 +05:30
apoorva 0b0b834744 Updated document 2023-03-14 12:10:00 +05:30
apoorva 8fdea465cb updated find pose to read from bag and estimate pose 2023-03-14 10:08:47 +05:30
apoorva 524459ec04 darknet_ros2 with updated code to make the repo work as repo was outdated 2023-03-13 14:33:18 +05:30
apoorva fd4bcdecfd darknet_vendor 2023-03-13 14:32:47 +05:30
apoorva 83ad680cab removing darknet vendor 2023-03-13 12:45:22 +05:30
apoorva e9591d651e Add 'ros2_ws/src/darknet_vendor/' from commit '4d609295280bf9b50cde69bb9a483a8db839ba0b'
git-subtree-dir: ros2_ws/src/darknet_vendor
git-subtree-mainline: 69673fdb02
git-subtree-split: 4d60929528
2023-03-13 12:24:07 +05:30
apoorva 69673fdb02 build was failing so removing vemdor 2023-03-13 12:23:57 +05:30
apoorva d17bf70260 darknet vendor 2023-03-13 12:16:20 +05:30
apoorva 21f381238d Add 'darknet_vendor/' from commit '4d609295280bf9b50cde69bb9a483a8db839ba0b'
git-subtree-dir: darknet_vendor
git-subtree-mainline: a6a4482dd1
git-subtree-split: 4d60929528
2023-03-10 18:45:53 +05:30
apoorva a6a4482dd1 moved darknet ros 2023-03-10 18:45:43 +05:30
apoorva aa265edfb1 Add 'darknet_ros2/' from commit 'be4fd04c0ea8fbed80b3549283701e16145422c6'
git-subtree-dir: darknet_ros2
git-subtree-mainline: f33742e6e8
git-subtree-split: be4fd04c0e
2023-03-10 18:40:03 +05:30
apoorva f33742e6e8 conversion code works as well as pose estimation for two object works(not using topics) 2023-03-10 16:22:58 +05:30
apoorva 7a7f46052b two object pose estimation but failing 2023-03-10 15:46:04 +05:30
apoorva b130ae7c9a code to convert both depth and rgb data to .jpeg in sync 2023-03-09 16:21:28 +05:30
apoorva 241656445f code updated to use 6 points 2023-03-06 14:48:49 +05:30
apoorva 66f57f7011 document updated with weekly update 2023-03-06 14:48:22 +05:30
apoorva cb6fdc66b5 This package converts point cloud to depth image. Also has code to find pose based on depth 2023-03-03 18:59:55 +05:30
apoorva 13c51ae2a2 deleting find0object files 2023-03-03 18:56:16 +05:30
Marko Durkovic c80625df27 Release 0.9.15 2023-03-02 13:35:17 +01:00
Marko Durkovic dff38bdb60 Add rosbag2 mcap storage reader 2023-03-02 12:55:12 +01:00
Marko Durkovic 9830c38fc7 Do not read index if no chunks in rosbag1 2023-03-02 12:25:05 +01:00
Marko Durkovic 967328627c Advertise AnyReader in documentation 2023-03-02 09:37:52 +01:00
Marko Durkovic 56df6c40f6 Update code for current linter 2023-03-01 20:18:38 +01:00
Marko Durkovic 53e3209cd5 Update dependencies 2023-03-01 20:13:08 +01:00
Marko Durkovic df9bf80170 Update tooling 2023-03-01 20:12:57 +01:00
Markus Vieth 6642b7398a Optimize includes (#407) 2023-02-27 10:33:52 -08:00
Andrew Symington 1e544f132e [ros2] lint the pcl_ros code base to try and get a green build :) (#406)
* Lint!

* Fix flake8 errors

* Fix clang-tidy errors

* Remove [[maybe_unused]]
2023-02-24 13:03:08 -08:00
Andrew Symington 3966b71ad6 Move filter() function implementation for all filters (#405) 2023-02-22 11:20:09 -08:00
Andrew Symington b52e7a7ab1 Migrate the ROS1 pcl::VoxelGrid filter to ROS2 pcl_ros::VoxelGrid (#398)
* Add the VoxelGrid filter (squash commit)

* Revert the change that brings in separate leaf sizes
2023-02-21 14:07:04 -08:00
Andrew Symington bb871ac7f0 Migrate the ROS1 pcl_ros::CropBox filter to ROS2 (#401)
* Add squashed commit for CropBox filter

* Lint
2023-02-21 12:51:13 -08:00
Andrew Symington de15639154 Add the StatisticalOutlierRemoval filter. (#400) 2023-02-21 10:35:21 -08:00
Andrew Symington 628aaec1dc Migrate the ROS1 pcl_ros::RadiusOutlierRemoval filter to ROS2 (#399)
* Add the RadiusOutlierRemoval filter.

* Lint

* PLay iit again, Linty Sam.

* Header order

* This is now just getting embarrassing

* Move parameter to class constructor.
2023-02-15 17:32:08 -08:00
Markus Vieth 1868f51160 Avoid copying data in fromROSMsg with PCL >= 1.13.1 (#402)
See also https://github.com/PointCloudLibrary/pcl/pull/5608
2023-02-14 14:38:26 -08:00
Daisuke Sato de09161924 migrate passthrough and project_inliers filters (#395)
* migrate passthrough and project_inliers filters

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* - remove throwing runtime_error (result always true)
- use get_subscription_count()

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* change comparison operator

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

---------

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>
2023-01-30 18:36:12 -08:00
Daisuke Sato 0c8e7dafce Migrate extract_indices filter (#394)
* - migrate extract_indices filter
- add test to check if filter node/component output result

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* add test_depend to package.xml

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* add launch_testing_ros as test_depend too

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* fixed test not to depend on ros2cli

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

---------

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>
2023-01-27 15:50:45 -08:00
Marko Durkovic aa18bec9d1 Improve parsing of string types in idl definitions 2023-01-13 12:16:05 +01:00
Marko Durkovic eaa64002b8 Refactor rosbag2 Reader 2023-01-11 15:26:05 +01:00
Marko Durkovic d7d24c4478 Release 0.9.14 2023-01-12 12:52:59 +01:00
Marko Durkovic f2020fa929 Advertise Python 3.11 compatibility 2023-01-11 13:27:00 +01:00
Marko Durkovic 2732b8876e Flush decompressed files in rosbag2.Reader 2023-01-11 13:22:46 +01:00
Marko Durkovic 51c0b30cbc Update reader example in README 2023-01-11 11:18:49 +01:00
Marko Durkovic ec7cd4a4e5 Update copyright headers 2023-01-11 15:21:14 +01:00
Marcel Zeilinger 3b0cfd8529 Export PCL dependency in pcl_conversions (#392)
Co-authored-by: Marcel Zeilinger <marcel.zeilinger@ait.ac.at>
2023-01-09 10:17:28 -08:00
Daisuke Sato 387f5b158b migrate abstract filter node (#388)
* migrate abstract filter node

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* remove use_frame_params from constructor and make a function for the logic

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>
2022-12-19 11:13:06 -08:00
Daisuke Sato 5c5382eb5c migrate pcl_nodelet.hpp to pcl_node.hpp (#385)
* migrate pcl_nodelet.hpp to pcl_node.hpp
TODOs
- lazy subscription
- cpplint, uncrustify
- type adaptation

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* rename latched_indices to transient_local_indices

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* - remove some TODOs
- change pub_output_ type

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* remove TODOs

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

* use template instead of PublisherBase

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>

Signed-off-by: Daisuke Sato <daisukes@cmu.edu>
2022-12-09 11:12:01 -08:00
Adam Aposhian ca69652eb8 use modular pcl dependencies for bloom (#384) 2022-11-29 10:27:59 -08:00
Markus Vieth 0918531c17 Add logic for missing pcl/point_traits.h in newer PCL versions (#382)
point_traits.h is no longer available, starting with PCL 1.13.0
Since PCL 1.11.0, type_traits.h should be used instead
2022-11-20 11:00:22 -08:00
Aditya Ardiya 7c6a2a5a38 Avoid redundant boost::make_shared copy in pcl_ros::Publisher<PointT> (#380)
`boost make_shared` is actually making a copy. This PR introduces the `sensor_msgs::PointCloud2` as pointer directly so that it doesn't need a `boost::make_shared` convertsion to pointer anymore.
2022-11-18 10:39:32 -08:00
ralwing 389297dfad Fixing implicit conversion warnings #378 (#379) 2022-11-03 05:03:31 -07:00
Marko Durkovic 88bbf1b5e3 Release 0.9.13 2022-09-23 12:45:38 +02:00
Marko Durkovic 219a4d9846 Implement direct ros1 (de)serialization 2022-09-22 21:46:00 +02:00
Marko Durkovic 1309d42b64 Add include filters to rosbag conversion 2022-09-23 12:35:37 +02:00
Marko Durkovic 4437512f05 Change lz4 compression level to 0 2022-09-23 12:19:08 +02:00
Marko Durkovic a0c4516e2f Fix parsing of members starting with string 2022-09-23 12:15:08 +02:00
Marko Durkovic 1de7380138 Fix comment parsing in message definitions 2022-07-28 19:14:39 +02:00
Marko Durkovic 17f4d54449 Release 0.9.12 2022-07-27 17:28:39 +02:00
Marko Durkovic b86cd70ee9 Update dependencies 2022-07-27 16:39:47 +02:00
Marko Durkovic 8333cfb971 Update code for current linters 2022-07-27 16:39:26 +02:00
Marko Durkovic 5257497a6a Add support for rosbag version 6 metadata 2022-07-27 16:14:08 +02:00
Marko Durkovic ff24d7e424 Move metadata to dedicated module 2022-07-27 16:03:22 +02:00
Marko Durkovic b9fd0b014b Add topic filters to rosbag conversion 2022-07-27 15:39:47 +02:00
Marko Durkovic 05df51aa96 Add badge with supported python versions 2022-07-27 14:31:16 +02:00
Marko Durkovic 501f97243c Update python package configuration 2022-07-27 14:30:36 +02:00
Markus Vieth 3eecd4e37b Add boost include, missing in upcoming PCL versions (ros2) (#374)
* Remove name of nonexistent PCL component (core)
Probably, common is meant, which is also requested

* Add boost include, missing in upcoming PCL versions
Was removed in pcl/conversion.h here: https://github.com/PointCloudLibrary/pcl/commit/292593abd3b69af315c7fe3379363bdce7800d5a
2022-07-07 12:22:26 -07:00
Marko Durkovic 0bf94a6238 Add typename guessing to examples 2022-05-25 15:39:47 +02:00
Marko Durkovic abc1acfecb Update gitlab CI config 2022-05-20 11:36:21 +02:00
Marko Durkovic a1fa5c7cfb Release 0.9.11 2022-05-17 23:57:30 +02:00
Marko Durkovic 8cb7a13485 Report start_time and end_time on empty bags 2022-05-17 23:54:10 +02:00
Marko Durkovic a1afc15dfa Release 0.9.10 2022-04-24 16:12:15 +02:00
Marko Durkovic 9f3da0c2be Fix serialization of empty message sequences 2022-05-04 17:40:50 +02:00
Marko Durkovic c2e676a01f Speed up reading of index data records 2022-04-24 10:11:31 +02:00
Marko Durkovic 926813bf17 Speed up index construction 2022-04-23 11:21:47 +02:00
Marko Durkovic d196e8b74e Add support for rosbag2 version 5 metadata 2022-04-21 15:58:09 +02:00
Marko Durkovic 34ffe96692 Convert connections attribute to list 2022-04-21 15:15:10 +02:00
Daisuke Nishimatsu bd7a060e98 use common header instead of io (#361)
Signed-off-by: wep21 <border_goldenmarket@yahoo.co.jp>
2022-04-13 13:17:03 -07:00
Marko Durkovic f7d69e35d5 Add all-in-one reader 2022-04-13 13:12:18 +02:00
Marko Durkovic 657032ce9f Add owner field to connection instances 2022-04-13 11:09:30 +02:00
Marko Durkovic d32742b904 Unify rosbag1 and rosbag2 topic information 2022-04-13 10:42:47 +02:00
Marko Durkovic 16d1758327 Unify rosbag1 and rosbag2 connection class 2022-04-13 09:40:22 +02:00
Marko Durkovic dee7e9c2fc Rename rosbag1 connection cid to id 2022-04-12 17:48:11 +02:00
Marko Durkovic 42243eac2d Move indices to dedicated attribute 2022-04-12 17:03:04 +02:00
Marko Durkovic b924fd4642 Add documentation for included types 2022-04-11 14:10:38 +02:00
Marko Durkovic dd357fa3e4 Allow alternative type stores 2022-04-11 12:47:01 +02:00
Marko Durkovic e88241074e Type message definition parsers 2022-04-11 10:46:12 +02:00
Marko Durkovic 19f0678645 Update lint 2022-04-11 00:07:53 +02:00
Marko Durkovic 7315a4ab4d Update dependencies 2022-04-10 23:47:10 +02:00
Marko Durkovic 24bea31f38 Update project settings 2022-04-10 23:33:44 +02:00
Marko Durkovic 946f2edb42 Update copyright headers 2022-04-10 23:32:25 +02:00
Ivan Santiago Paunovic 27448f7575 Migrate pcd to pointcloud tool (#359)
* Migrate pcl_ros pcd_to_pointcloud tool

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* Remove log used for debugging

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* Undo unnecessary changes

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* Remove commented out code

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* Address peer review comments

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* rename node

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2022-04-04 12:54:29 -07:00
Marko Durkovic f5d3494cbb Add common usage examples to docs 2022-02-11 14:31:06 +01:00
Steve Macenski 2b82545af3 bumping versions to 2.4.1 (#357) 2022-02-08 15:31:32 -08:00
Shane Loretz 8093d5b35d Install headers to include/${PROJECT_NAME} (#354)
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2022-02-03 10:11:55 -08:00
Marko Durkovic af4830c647 Adjust conversion documentation title 2022-01-31 12:01:37 +01:00
Marko Durkovic 25520eab57 Release 0.9.9 2022-01-10 11:51:20 +01:00
Marko Durkovic 2eb3b1c671 Add conversion from rosbag2 to rosbag1 2022-01-09 20:31:51 +01:00
Marko Durkovic ac55fd2f4a Fix handling of padding after empty sequences 2022-01-06 20:35:58 +01:00
Marko Durkovic 8bf8994fbf Fix documentation code samples 2022-01-06 12:50:40 +01:00
Marko Durkovic c9bd6ebbc0 Release 0.9.8 2021-11-25 14:41:31 +01:00
Marko Durkovic 18983868c6 Support bool and float constants in msg files 2021-11-25 14:26:48 +01:00
Marko Durkovic 52480e2bad Type generics and missing return types 2021-11-25 14:26:17 +01:00
Marko Durkovic ac704bd890 Release 0.9.7 2021-11-09 12:34:39 +01:00
Marko Durkovic aaa9969856 Parse msg bounded fields and default values 2021-11-09 10:40:25 +01:00
Marko Durkovic ae13edd221 Make packages PEP561 compliant 2021-11-08 18:48:19 +01:00
Marko Durkovic af848eb3d2 Parse empty msg definitions 2021-11-08 15:11:39 +01:00
Marko Durkovic c55e81f375 Report faulty index on connection or chunk error 2021-10-21 19:13:33 +02:00
Marko Durkovic c6dd2995f6 Use repr on const field values 2021-10-04 22:56:58 +02:00
Marko Durkovic b14085019c Generate style compliant code 2021-10-21 18:53:29 +02:00
Marko Durkovic 4f658378eb Fix lint for updated tools 2021-10-21 18:53:29 +02:00
Marko Durkovic 0e42f941d5 Update dependencies 2021-10-21 18:53:29 +02:00
Florian Friesdorf 2f05cae883 Add pytest-yapf3 2021-10-21 18:53:29 +02:00
Florian Friesdorf 03e82a91ad Exclude venvs for flake8 2021-10-21 18:44:20 +02:00
Florian Friesdorf 634a497dd5 Tweak mypy config to handle namespaces 2021-10-21 17:54:45 +02:00
Marko Durkovic edf9db2724 Ignore typing error in docs config 2021-10-21 17:09:24 +02:00
Marko Durkovic 54a7eca6be Use current APIs 2021-10-21 17:09:24 +02:00
Marko Durkovic fa62876dd8 Release 0.9.6 2021-10-04 16:46:49 +02:00
Marko Durkovic 75d98df4bf Do not match msg separator as constant value 2021-10-04 16:46:22 +02:00
Marko Durkovic 7bbc2914c4 Release 0.9.5 2021-10-04 11:54:39 +02:00
Marko Durkovic 1333cf1168 Add string constant support to msg parser 2021-10-03 06:28:02 +02:00
Rich Mattes 755f566356 pcl_ros: Use vec.data() instead of &vec[0] (#348)
Update pcl_ros to use the data() member function of STL containers to
get the pointer to the underlying storage, instead of dereferencing the
zeroth element and taking its reference.  When a container is of size 0,
dereferencing element 0 with operator[]() is undefined behavior, and
will trigger assertions when features like _GLIBCXX_ASSERTIONS are
enabled.

Fixes #333.
2021-09-27 14:28:26 -07:00
Marko Durkovic 203131b777 Release 0.9.4 2021-09-15 14:47:38 +02:00
Steve Macenski 834eb111e8 bumping rolling from 2.3.1 to 2.4.0 2021-09-14 14:21:14 -07:00
Marko Durkovic be2d5675b3 Fix connection mapping for reader2 messages 2021-09-13 17:30:09 +02:00
Marko Durkovic 885900df39 Make reader1 API match reader2 2021-09-13 10:49:57 +02:00
Kenji Miyake 1a214ccc6e Fix obsolete header (#342)
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
2021-08-30 11:08:25 -07:00
Marko Durkovic 5d0aa8277c Release 0.9.3 2021-08-06 18:13:33 +02:00
Marko Durkovic 4041e882c1 Add issue template 2021-08-06 18:13:33 +02:00
Marko Durkovic 5f99a3be84 Add rosbag1 to rosbag1 comparison 2021-08-06 18:13:33 +02:00
Marko Durkovic cc96973be3 Add rosbag1 writer 2021-08-06 18:13:33 +02:00
Marko Durkovic 5bd1bcbd83 Use built-in collections as generic types 2021-08-06 18:13:33 +02:00
Marko Durkovic f33e65b14a Change to connection oriented reader API 2021-08-06 18:13:33 +02:00
Marko Durkovic ebf357a0c6 Add ROS1 message definition generator 2021-08-06 18:12:51 +02:00
Marko Durkovic ef97081e5a Add CDR to ROS1 bytestream conversion 2021-08-06 18:12:51 +02:00
Marko Durkovic 03b4d7e5c7 Add const fields to type representations 2021-08-06 18:12:51 +02:00
Marko Durkovic fa57b16765 Release 0.9.2 2021-07-08 09:29:44 +02:00
Marko Durkovic 117a4f6348 Support relative type references in msg files 2021-07-08 09:20:31 +02:00
Marko Durkovic 3d694b20f6 Release 0.9.1 2021-07-05 17:48:36 +02:00
Marko Durkovic 44a9c606b2 Update requirements 2021-07-05 17:48:36 +02:00
Marko Durkovic 19e81abef9 Fix sphinx circular imports 2021-07-05 17:48:36 +02:00
Marko Durkovic 12acb677e6 Use half-open intervals for time ranges 2021-07-05 17:48:36 +02:00
Marko Durkovic 5175c349aa Translate latching info to equivalent QoS settings 2021-07-05 17:48:36 +02:00
Marko Durkovic c2bbeec7aa Make optional connection header fields available 2021-07-05 17:48:36 +02:00
Marko Durkovic 77e68e8191 Fix rv tuple order of messages() in docs 2021-07-05 17:48:36 +02:00
Marko Durkovic 24cc3e0c2f Add type hints to message classes 2021-07-05 17:48:36 +02:00
Marko Durkovic aba557c015 Remove non-default ROS2 message types 2021-07-05 17:48:33 +02:00
Marko Durkovic d83e9aaaae Support multi-line comments in idl files 2021-07-05 11:18:46 +02:00
Marko Durkovic 1d00fa317d Fix msg parsing on non-POSIX platforms 2021-07-05 11:18:46 +02:00
Marko Durkovic ea40c74133 Assert importlib specs 2021-07-05 11:18:46 +02:00
Steve Macenski 051c6df956 adding -fPIC compiler flag per warning suggestion (#335) 2021-07-01 16:54:20 -07:00
Steve Macenski 5d63abd06e Revert "shared library bug fix (#331)" (#334)
This reverts commit 35a9f25848.
2021-07-01 16:20:31 -07:00
Markus Vieth 461a66ca08 Use complete namespace for traits members (#332)
This prevents errors like this: error: ‘name’ is not a member of ‘pcl::detail::traits’; did you mean ‘pcl::traits::name’?
The error appears for newer PCL versions (everything after commit https://github.com/PointCloudLibrary/pcl/commit/d39d3d3300746b952997e5bd2742dac7482aa5ab), but this change should also be fully compatible with older PCL versions.
2021-06-30 12:44:28 -07:00
Patrick Musau 35a9f25848 shared library bug fix (#331)
Signed-off-by: Patrick Musau <pmusau13ster@gmail.com>
2021-06-28 09:37:50 -07:00
Steve Macenski d63143da27 bump to 2.3.1 for release updates based on build farm fixes 2021-05-20 15:58:46 -07:00
Steve Macenski 4156c71c02 replace ament_cmake_ros with ament_cmake to build in build farm (#326) 2021-05-20 15:57:37 -07:00
Steve Macenski 487957aebc bumping to 2.3.0 for release 2021-05-20 13:34:08 -07:00
Marko Durkovic a8baffcbd7 Update changes 2021-05-16 17:40:53 +02:00
Marko Durkovic 96c26bca48 Update requirements 2021-05-16 17:40:53 +02:00
Marko Durkovic ea67671f53 Add compare tool 2021-05-16 17:40:53 +02:00
Marko Durkovic bbedf76b98 Add bench tool 2021-05-16 17:40:53 +02:00
Marko Durkovic 5d2d394110 Add rosbag conversion tools 2021-05-16 17:40:53 +02:00
Marko Durkovic 4de0c99274 Add rosbag1 support 2021-05-16 17:40:53 +02:00
Marko Durkovic ffacb7602c Add rosbag2 support 2021-05-16 17:40:53 +02:00
Marko Durkovic abd0c1fa73 Add serde 2021-05-16 17:40:53 +02:00
Marko Durkovic a7461c8ae7 Add type system 2021-05-16 17:40:53 +02:00
Marko Durkovic 3628834c21 Add boilerplate 2021-05-16 17:40:53 +02:00
Markus Vieth 135a2c29e3 Correct conversion of time stamp (#319)
* Add test to verify that stamps are correctly converted

* Fix bug in fromPCL function for headers
The time stamp was not set.
2020-12-04 10:57:37 -08:00
Markus Vieth 2d21467423 Change conversions of Vertices for new PCL versions (#316)
In https://github.com/PointCloudLibrary/pcl/commit/ad00c7bee2fad0391649479d90eee4461a2e74e7, the vertices field of pcl::Vertices changed from std::vector<std::uint32_t> to std::vector<pcl::index_t>, where index_t is an index type with configurable size (currently by default int). This commit makes conversions from and to pcl_msgs::Vertices possible again, moving the vector contents if possible.
2020-11-09 11:09:17 -08:00
Markus Vieth 706c020528 Deprecate use_polynomial_fit (#305)
The pcl function setPolynomialFit is deprecated, setPolynomialOrder should be used instead
2020-08-22 11:04:21 -07:00
Sean Kelly d7a79b927f Port transforms library to ROS2 (#301)
* Port transforms library to ROS2

- Port the transforms library to ROS2
- Update CMakeLists
- Update package.xml
- Enable the package

Signed-off-by: Sean Kelly <sean@seankelly.dev>

* Feedback from PR
2020-08-12 12:12:51 -07:00
Sean Kelly 420f5b032b Make ament_cpplint pass (#298)
Collection of hand-made changes to make ament_cpplint pass consisting of:
- whitespace between comments
- line length
- header ordering
- include guard formats
- remove a couple `using namespace std;`
- using c++ casts instead of c-style casts

Signed-off-by: Sean Kelly <sean@seankelly.dev>
2020-08-09 16:47:21 -07:00
Sean Kelly 9689971aee Make ament_flake8 pass (#299)
Set of hand-made changes to let ament_flake8 pass
2020-08-09 16:47:01 -07:00
Sean Kelly 63cee139f1 Apply ament_uncrustify --reformat (#297)
Signed-off-by: Sean Kelly <sean@seankelly.dev>
2020-08-06 12:28:29 -07:00
Sean Kelly 0ac6810688 Rename headers from .h to .hpp (#296)
* Rename headers from .h to .hpp per ROS2 guidelines

This change is the result of the following command run from pcl_ros dir:

$ find -name *.h | xargs -I {} mv {} {}pp

Signed-off-by: Sean Kelly <sean@seankelly.dev>

* Update internal includes for the renamed headers

This change was the result of the following bash script:

$ find -name *.h -o -name *.cpp -o -name *.hpp | xargs -I {} sed -i 's/\(pcl_ros\/.*\)\(h\)\([">]\)$/\1\2pp\3/g' {}

Signed-off-by: Sean Kelly <sean@seankelly.dev>
2020-08-06 11:13:01 -07:00
Markus Vieth 21cf907c46 Add missing include for new PCL versions (#293)
After this change https://github.com/PointCloudLibrary/pcl/commit/6df3e602a72ea16657f901c9a6911d95b263ba08#diff-24324a084e511502d7f34054ec31b353L50, an explicit include for KdTree is needed.
It was formerly a transitive include via pcl/surface/mls.h - pcl/search/pcl_search.h - pcl/search/kdtree.h - pcl/kdtree/kdtree_flann.h.
2020-07-30 11:52:57 -07:00
Shivam Pandey 4ed0d3ecef link pcl library to targets (#287)
* link pcl library to targets

* changes OS_CODE_NAME to focal in travis config file
2020-07-01 12:13:29 -07:00
Steve Macenski 5e27157ec2 Updating CI and versions for foxy release (#280)
* changing CI to foxy from eloquent

* increment up version
2020-05-13 11:39:16 -07:00
Kunal Tyagi 2b770b15ed Changes in preparation for PCL 1.11 (#273) (#279)
* Deriving typedef from pcl type

* Explicit boost shared_ptr for function parameters

* Use boost::shared_ptr instead of PCL::Ptr

* Implementing boost-std compatibility

* Using the compatibility layer
2020-05-11 18:50:15 -07:00
Ruffin 36eb607be7 Use std::uint* types. (#265) (#266)
Co-authored-by: Mike Purvis <mike@uwmike.com>
2020-03-16 13:08:48 -07:00
Shane Loretz 4d60929528 Include FetchContent on CMake >= 3.11 (#6)
Fixes #5
2020-03-06 13:13:56 -08:00
Shane Loretz 7f9693b325 Ament index marker (#3)
* Add ament_index marker file

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Install ament index marker

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2020-03-06 09:03:17 -08:00
Steven Macenski 1273c7581d changing base version to 2.1.0 for first ros2 sync [eloquent] (#253)
* changing base version to 2.0.0 for first ros2 sync

* changing industrial CI to use eloquent

* increment 2.0.0 to 2.1.0 for eloquent release
2019-12-02 09:39:11 -08:00
Andreas Klintberg a1fd4d2a09 Updated ROS2 PR: pcl_conversion only to ROS2 (dashing) (#244)
* pcl_conversion to ros2

* travis for ros2 and fixed cmakelists

* exporting dependencies

* updated travis

* fixed smaller things

* added colcon ignore to meta package

* merge pcl_conversions.h with version released in Dashing

* merge test script, CMakeListst, package.xml

* append authors, clean up

* PR feedback

* fixed PR comments

* fixed PR comments, cmakelists message_filters, reverted type masq, added maintainer

* removed dashing and made ros_distro matrix env
2019-10-30 07:10:32 +08:00
Shane Loretz c8d68fbe1e Fix cuda build downstream (#4)
* Cuda flags should not be exported to downstream targets

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Fix c linkage with C++ cuda code

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-10-09 11:08:29 -07:00
Shane Loretz 4ad6ed7b0a Initial readme draft (#2)
* Initial readme draft

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Add USING section

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Make it more clear what definitions do

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-10-04 16:05:31 -07:00
Shane Loretz 84cb832919 Initial version of darknet_vendor (#1)
* Initial version of darknet_vendor

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Quote to make tag usable as string

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Add OpenCV option

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Fix include guards

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* First cuda attempt

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Cuda builds and runs

Signed-off-by: Shane Loretz<sloretz@openrobotics.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Avoid -pthread flag

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Combine cuda blocks, trivial cleanup

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Add opencv and cuda dependencies

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Add license for FetchContent

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Add Apache 2.0 license

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* FetchContent uses git

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Add CONTRIBUTING.md

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-10-04 15:42:48 -07:00
Shane Loretz be4fd04c0e Fix size of weights filename (#3)
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-10-04 15:15:02 -07:00
Shane Loretz bcb79e66ab Fix off by one bug (#2)
Signed-off-by: Shane Loretz<sloretz@openrobotics.org>
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-10-04 15:12:45 -07:00
Shane Loretz 9740b6209f Initial package (#1)
* Initial package

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Use latest vision_msgs with string id

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Tiny improvements

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Add parser tests and ignore blank lines in class names

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Test when cfg file does not exist

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Rename test

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* openrobotics_darknet_ros -> openrobotics::darknet_ros

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Added visibility files

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Rename files

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* darknet_node -> detector_node

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Rename files

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Rename files

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* DetectorNetwork and DetectorNode

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Simple readme

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Add Example section

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Example actually works

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Fix link

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Linter tests pass

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-10-04 14:59:05 -07:00
Shane Loretz 9bcd4ff531 initial commit
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-10-03 17:29:42 -07:00
Shane Loretz b71c0ce77a Initial commit
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-09-10 16:02:37 -04:00
James Xu a8ba2c790d use <chrono> and <thread> on Windows (#221)
* Changing from usleep to c++14 style sleep_for for Windows support
2019-04-05 10:50:10 -04:00
Kentaro Wada 12482e555d 1.6.2 2018-05-20 04:14:40 +09:00
Kentaro Wada 99f7caacb9 Update CHANGELOG.rst 2018-05-20 04:14:16 +09:00
Jiri Horner f8fee6128a pcl_ros: fix exported includes in Ubuntu Artful
pcl_ros needs the same fix as pcl_conversions
2018-05-20 04:12:55 +09:00
James Ward cd3720923a Increase limits on CropBox filter parameters
Min and max of CropBox filter was +/- 5m. For a pointcloud from a Velodyne, for example, this is not enough.
Increased to +/- 1000m.
2018-05-08 22:17:42 +09:00
Kentaro Wada 32d3e6a459 1.6.1 2018-05-08 18:56:16 +09:00
Kentaro Wada 283782b420 Update CHANGELOG.rst 2018-05-08 18:56:01 +09:00
Kentaro Wada 9dee4fb36d Add 1.6.0 section to CHANGELOG.rst 2018-05-08 18:54:33 +09:00
Kentaro Wada 80131757e8 Remove no need ROS_PARALLEL_JOBS env in .travis.yml 2018-05-08 17:45:53 +09:00
Kentaro Wada 9b4d31c912 Add NOT_TEST_INSTALL option to .travis.sh 2018-05-08 17:45:53 +09:00
Kentaro Wada 25c86b2115 Update travis badge in README.md 2018-05-08 17:45:53 +09:00
Kentaro Wada 3be6003f1b sudo -E to enable DEBIAN_FRONTEND=noninteractive 2018-05-08 17:45:53 +09:00
Kentaro Wada 090e105e77 Add DEBIAN_FRONTEND=noninteractive 2018-05-08 17:45:53 +09:00
Kentaro Wada cd2a12af43 Use foreach + string regex to implement list(filter on old cmake 2018-05-08 17:45:53 +09:00
Kentaro Wada d61aa376ec Downgrade the required cmake version for backward compatibility
I think 3.7 is not required currently and requiring 2.8 is better.
2018-05-08 17:45:53 +09:00
Kentaro Wada 19cd3cfd75 Test backward compatibility for users who build from source 2018-05-08 17:45:53 +09:00
Kentaro Wada 595067b122 Just update .travis.yml for melodic
To divide the build failure problem to following:

1. current industrial_ci config is bad?
2. perception_pcl cannot be built on stretch, artful, and bionic?
2018-05-08 17:45:53 +09:00
Paul Bovbel a21e3ee28a Merge pull request #198 from mikaelarguedas/fix_pcl_conversions_links
Fix pcl conversions links
2018-05-07 15:00:01 -04:00
Mikael Arguedas 0b4ad1f1d6 update package.xml links to point to new repository 2018-05-07 08:13:36 -07:00
Mikael Arguedas 235612cca9 CMake 3.6.3 is sufficient 2018-05-07 08:13:20 -07:00
Paul Bovbel f335c169df Merge pull request #196 from clalancette/fix-artful
Fix a bug building on artful.
2018-05-02 11:10:24 -04:00
Chris Lalancette 242ce31b32 Fix a bug building on artful.
The comment explains it in more detail.  While we are at it,
fix the link in the README.rst to point to the right repository.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2018-05-02 14:59:26 +00:00
Kentaro Wada 3e97d7ce9c Fix the use of Eigen3 in cmake
(cherry picked from commit 27c02d1f49468f450c4f91992ddaf5f3e8698b56)
2018-05-02 11:09:44 +09:00
Paul Bovbel 2be69aee71 Fixup pcl_conversions test 2018-05-02 11:09:44 +09:00
Paul Bovbel e0a6c06448 1.6.0 2018-04-30 12:10:14 -04:00
Paul Bovbel 371bf7d789 Fix build and update maintainers 2018-04-30 12:03:07 -04:00
Kentaro Wada 118784a4dd Add message_filters to find_package
```
% catkin lint .
pcl_ros: error: nodelet plugin file 'plugins/nodelet/libpcl_ros_features.xml' is not installed to ${CATKIN_PACKAGE_SHARE_DESTINATION}
pcl_ros: error: nodelet plugin file 'plugins/nodelet/libpcl_ros_filters.xml' is not installed to ${CATKIN_PACKAGE_SHARE_DESTINATION}
pcl_ros: error: nodelet plugin file 'plugins/nodelet/libpcl_ros_io.xml' is not installed to ${CATKIN_PACKAGE_SHARE_DESTINATION}
pcl_ros: error: nodelet plugin file 'plugins/nodelet/libpcl_ros_segmentation.xml' is not installed to ${CATKIN_PACKAGE_SHARE_DESTINATION}
pcl_ros: error: nodelet plugin file 'plugins/nodelet/libpcl_ros_surface.xml' is not installed to ${CATKIN_PACKAGE_SHARE_DESTINATION}
pcl_ros: error: unconfigured build_depend on 'message_filters'
catkin_lint: checked 1 packages and found 6 problems
catkin_lint: 40 notices have been ignored. Use -W2 to see them
```
2018-04-30 11:44:37 -04:00
Kentaro Wada 853a8f9164 Remove unnecessary dependency on genmsg 2018-04-30 11:44:37 -04:00
Kentaro Wada 492e4f917e 1.5.4 2018-04-30 11:44:37 -04:00
Kentaro Wada 273b011e4e Update CHANGELOG.rst 2018-04-30 11:44:37 -04:00
Kentaro Wada c8167b0e18 Restrict push build only /.*-devel$/ branches 2018-04-30 11:44:37 -04:00
Kentaro Wada 72e5cbf64f Drop zesty from CI: zesty went EOL
https://github.com/ros/rosdistro/blob/03f2bb4fd0367e1e706cde0745fd52ba52afea74/lunar/distribution.yaml#L11
2018-04-30 11:44:37 -04:00
Kentaro Wada d2792accbf Drop yakkety from CI: Yakkety went EOL in July
Close https://github.com/ros-perception/perception_pcl/issues/166

https://discourse.ros.org/t/suspension-of-debian-packaging-for-eol-ubuntu-yakkety/2444
2018-04-30 11:44:37 -04:00
Mikael Arguedas 08c7c12cff update to use non deprecated pluginlib macro 2018-04-30 11:44:37 -04:00
Kentaro Wada d34cd5eda8 Fix config path of sample_voxel_grid.launch 2018-04-30 11:44:37 -04:00
Kentaro Wada 58c7c8648f Update .travis.yml 2018-04-30 11:44:37 -04:00
Kentaro Wada 271c5e1538 Add services: - docker to .travis.yml 2018-04-30 11:44:37 -04:00
Kentaro Wada 6e96187973 Use ccache for faster testing 2018-04-30 11:44:37 -04:00
Kentaro Wada a243765cc0 sudo: false in .travis.yml 2018-04-30 11:44:37 -04:00
Mikael Arguedas 1d1f9c2b77 remove hack now that upstream pcl has been rebuilt 2018-04-30 11:44:37 -04:00
Kentaro Wada cef8df686c Looser hzerror in test for extract_clusters to make it pass on Travis 2018-04-30 11:44:37 -04:00
Kentaro Wada bb2fa3f936 Add sample & test for surface/convex_hull 2018-04-30 11:44:37 -04:00
Kentaro Wada f16207321b Add sample & test for segmentation/extract_clusters.cpp 2018-04-30 11:44:37 -04:00
Kentaro Wada 419366b5f5 Add sample & test for io/concatenate_data.cpp 2018-04-30 11:44:37 -04:00
Kentaro Wada 3e5c704046 Add sample & test for features/normal_3d.cpp 2018-04-30 11:44:37 -04:00
Kentaro Wada 87e7555655 Organize samples of pcl_ros/features 2018-04-30 11:44:37 -04:00
Kentaro Wada 9a99734362 Add test arg to avoid duplicated testing 2018-04-30 11:44:37 -04:00
Kentaro Wada 9ac65d9d20 LazyNodelet for features/* 2018-04-30 11:44:37 -04:00
Kentaro Wada c4c7f30977 LazyNodelet for filters/ProjectInliers 2018-04-30 11:44:37 -04:00
Kentaro Wada 560fd2cd63 Refactor io/PCDReader and io/PCDWriter as child of PCLNodelet 2018-04-30 11:44:37 -04:00
Kentaro Wada 2d13abfc8e LazyNodelet for io/PointCloudConcatenateFieldsSynchronizer 2018-04-30 11:44:37 -04:00
Kentaro Wada 7124f54462 LazyNodelet for io/PointCloudConcatenateDataSynchronizer 2018-04-30 11:44:37 -04:00
Kentaro Wada 071de1e3b4 LazyNodelet for segmentation/SegmentDifferences 2018-04-30 11:44:37 -04:00
Kentaro Wada 3cab2abb15 LazyNodelet for segmentation/SACSegmentationFromNormals 2018-04-30 11:44:37 -04:00
Kentaro Wada 3ef2b1bf8a LazyNodelet for segmentation/SACSegmentation 2018-04-30 11:44:37 -04:00
Kentaro Wada ebe25b4b89 LazyNodelet for segmentation/ExtractPolygonalPrismData 2018-04-30 11:44:37 -04:00
Kentaro Wada 76ea38194e LazyNodelet for segmentation/EuclideanClusterExtraction 2018-04-30 11:44:37 -04:00
Kentaro Wada 6f2d30996a LazyNodelet for surface/MovingLeastSquares 2018-04-30 11:44:37 -04:00
Kentaro Wada 7c70b159da LazyNodelet for surface/ConvexHull2D 2018-04-30 11:44:37 -04:00
Kentaro Wada f0a28c9338 Limit branch of push build on Travis 2018-04-30 11:44:37 -04:00
Kentaro Wada 1efe3679bb Set branch to show correct badge status 2018-04-30 11:44:37 -04:00
Kentaro Wada 34c4131455 Add missing COMPONENTS of PCL 2018-04-30 11:44:37 -04:00
Kentaro Wada c370da8a48 Inherit NodeletLazy for pipeline with less cpu load 2018-04-30 11:44:37 -04:00
Kentaro Wada fa0813e124 Set leaf_size 0.02 2018-04-30 11:44:37 -04:00
Kentaro Wada a1f56af638 Install samples 2018-04-30 11:44:37 -04:00
Kentaro Wada 443981ed88 Add sample and test for pcl/StatisticalOutlierRemoval
Conflicts:
	pcl_ros/CMakeLists.txt
2018-04-30 11:44:37 -04:00
Kentaro Wada b187fcb854 Add sample and test for pcl/VoxelGrid
Conflicts:
	pcl_ros/CMakeLists.txt
2018-04-30 11:44:37 -04:00
Mikael Arguedas 259cde8833 no need to remove duplicates 2018-04-30 11:44:37 -04:00
Mikael Arguedas 20db374c26 spourious line change 2018-04-30 11:44:37 -04:00
Mikael Arguedas a5aacd7a7b remove now unnecessary build_depend on qtbase5 2018-04-30 11:44:37 -04:00
Mikael Arguedas 157874336c exclude PCL IO libraries exporting Qt flag 2018-04-30 11:44:37 -04:00
Mikael Arguedas 5a8d278fb9 find only PCL components used instead of all PCL 2018-04-30 11:44:37 -04:00
Kentaro Wada 3d23cce807 Add README.md 2018-04-30 11:44:37 -04:00
Kentaro Wada bc99f755bf Remove dependency on vtk/libproj-dev (#145)
* Remove dependency on vtk/libproj-dev

These dependencies were introduced in #124 to temporarily fix
missing / wrong dependencies in upstream vtk. This hack is no longer
necessary, since fixed vtk packages have been uploaded to
packages.ros.org (see #124 and ros-infrastructure/reprepro-updater#32).

* Remove vtk hack from CMakeLists.txt
2018-04-30 11:44:37 -04:00
Kentaro Wada debdde93f7 Add --os option to rosdep for debian 2018-04-30 11:44:37 -04:00
Kentaro Wada 410e6ba650 Install gnupg for debian 2018-04-30 11:44:37 -04:00
Kentaro Wada feb5ca3c54 Add various docker images 2018-04-30 11:44:37 -04:00
Kentaro Wada fc55edf7ad Add travis config
Refering to https://github.com/ros-perception/vision_opencv
2018-04-30 11:44:37 -04:00
Kentaro Wada 4b37e42c6e 1.5.3 2018-04-30 11:44:37 -04:00
Kentaro Wada 3d8e48a27c Update CHANGELOG.rst 2018-04-30 11:44:37 -04:00
Kentaro Wada 075139bff8 Add dependency on qtbase5-dev for find_package(Qt5Widgets)
See https://github.com/ros-perception/perception_pcl/pull/117#issuecomment-298158272 for detail.
2018-04-30 11:44:37 -04:00
Kentaro Wada bd227b5c03 1.5.2 2018-04-30 11:44:37 -04:00
Kentaro Wada c1d493f355 Update CHANGELOG.rst 2018-04-30 11:44:37 -04:00
Kentaro Wada cddbb655bc Find Qt5Widgets to fix -lQt5::Widgets error 2018-04-30 11:44:37 -04:00
Kentaro Wada fb2d0c6955 1.5.1 2018-04-30 11:44:37 -04:00
Kentaro Wada 9c93a02142 Update CHANGELOG 2018-04-30 11:44:37 -04:00
Kentaro Wada ad76ef2efe Add myname as a maintainer 2018-04-30 11:44:37 -04:00
Kentaro Wada 8ebf5d2e0b Remove pointcloud_to_laserscan 2018-04-30 11:44:37 -04:00
Kentaro Wada dbe985e9d4 1.5.0 2018-04-30 11:44:37 -04:00
Kentaro Wada 0a75478fe6 Update CHANGELOG.rst 2018-04-30 11:44:37 -04:00
Kentaro Wada 28711dd491 Fix lib name duplication error 2018-04-30 11:44:37 -04:00
Kentaro Wada a00763f038 Detect automatically the version of PCL 2018-04-30 11:44:37 -04:00
Kentaro Wada 64996ea8d8 Install xml files declaring nodelets
https://github.com/ros-perception/perception_pcl/commit/f81cded18b4f6d398b460a36c953fe6620a02bd6#commitcomment-21871201

@scottnothing Thanks!
2018-04-30 11:44:37 -04:00
Kentaro Wada d1368c0f65 Fix syntax of nodelet manifest file
By splitting files for each library.

Close #131
2018-04-30 11:44:37 -04:00
Paul Bovbel 909b76d773 1.4.1 2018-04-30 11:44:37 -04:00
Paul Bovbel d273c545a7 Add tf2_eigen dependency 2018-04-30 11:44:37 -04:00
Paul Bovbel 9f629d35c9 Switch to package format 2 2018-04-30 11:44:37 -04:00
Martin Guenther b1c6428c83 Copy header in convert_pointcloud_to_image 2018-04-30 11:44:37 -04:00
Martin Guenther 360b87131b Fix handling of unorganized input in convert_pointcloud_to_image
Without this patch, convert_pointcloud_to_image doesn't correctly
recognize unorganized point clouds and outputs garbage that crashes
image_view.
2018-04-30 11:44:37 -04:00
Jochen Sprickerhof aa370cefc8 Add fixed_frame to pointcloud_to_pcd 2018-04-30 11:44:37 -04:00
Paul Bovbel 2aa0495516 1.4.0 2018-04-30 11:44:37 -04:00
Paul Bovbel 6e20601cf1 Update changelogs 2018-04-30 11:44:37 -04:00
Paul Bovbel 20ca7cb16a Fixup libproj-dev rosdep 2018-04-30 11:44:37 -04:00
Jackie Kay eba277ffc0 Add build depend on libproj, since it's not provided by vtk right now 2018-04-30 11:44:37 -04:00
Jackie Kay 7fd1bac676 manually remove dependency on vtkproj from PCL_LIBRARIES 2018-04-30 11:44:37 -04:00
Paul Bovbel 96f6657b23 Remove python-vtk for kinetic-devel, see issue #44 2018-04-30 11:44:37 -04:00
Paul Bovbel 8bb614fc3a 1.3.0 2018-04-30 11:44:37 -04:00
Paul Bovbel 8d457bbd61 Update changelogs 2018-04-30 11:44:37 -04:00
v4hn c40e5afdbd cleanup broken library links
All removed library names are included in ${PCL_LIBRARIES}.
However, the plain library names broke catkin's overlay mechanism:
Where ${PCL_LIBRARIES} could point to a local installation of the PCL,
e.g. pcd_ros_segmentation might still link to the system-wide installed version
of pcl_segmentation.
2018-04-30 11:44:37 -04:00
Paul Bovbel d050db471e Add deprecation notice 2018-04-30 11:44:37 -04:00
Paul Bovbel 5472ff8f8a Remove pointcloud_to_laserscan package 2018-04-30 11:44:37 -04:00
Lucid One 8ffb7a3189 Fixed test for jade-devel. Progress on #92 2018-04-30 11:44:37 -04:00
Brice Rebsamen 76f900c0ca commented out test_tf_message_filter_pcl
Until ros/geometry#80 has been merged the test will fail.
2018-04-30 11:44:37 -04:00
Brice Rebsamen 3a202ced73 fixed indentation and author 2018-04-30 11:44:37 -04:00
Brice Rebsamen 5f276e80b8 Adds a test for tf message filters with pcl pointclouds 2018-04-30 11:44:37 -04:00
Brice Rebsamen a32bff82f7 specialized HasHeader, TimeStamp, FrameId
- HasHeader now returns false
- TimeStamp and FrameId specialed for pcl::PointCloud<T> for any point type T

These changes allow to use pcl::PointCloud with tf::MessageFilter
2018-04-30 11:44:37 -04:00
Lucid One afeb804f30 Sync pcl_nodelets.xml from hydro to indigo
Fixes to pass catkin lint -W1
2018-04-30 11:44:37 -04:00
Lucid One d245f70f4f Fixes #87 for Indigo 2018-04-30 11:44:37 -04:00
Lucid One 04c29ac9cc Fixes #85 for Indigo 2018-04-30 11:44:37 -04:00
Lucid One 0a958f55ce Fixes #77 and #80 for indigo 2018-04-30 11:44:37 -04:00
Mitchell Wills 10727ec650 Added option to save pointclouds in binary and binary compressed format 2018-04-30 11:44:37 -04:00
Paul Bovbel d7adb41971 1.2.6 2018-04-30 11:44:37 -04:00
Paul Bovbel 9b2bd47887 Update changelogs 2018-04-30 11:44:37 -04:00
Paul Bovbel 6dfaf5c596 Fix default value for concurrency 2018-04-30 11:44:37 -04:00
Paul Bovbel 040f68c31f Fix multithreaded lazy pub sub 2018-04-30 11:44:37 -04:00
Paul Bovbel e739e0f297 1.2.5 2018-04-30 11:44:37 -04:00
Paul Bovbel 7ef9fed2b8 Update changelog 2018-04-30 11:44:37 -04:00
Paul Bovbel 1a8e94ddbe Fix regression with pointcloud2 iter double->float 2018-04-30 11:44:37 -04:00
Paul Bovbel a71bb05a7c Remove stray depedency 2018-04-30 11:44:37 -04:00
Paul Bovbel 6aded38494 Switch to tf_sensor_msgs for transform 2018-04-30 11:44:37 -04:00
Paul Bovbel 7295940808 Add proper error checking for tolerance 2018-04-30 11:44:37 -04:00
Paul Bovbel 8a42c9586b Set parameters in sample launch files to default 2018-04-30 11:44:37 -04:00
Paul Bovbel fb5c47982c Add tolerance parameter 2018-04-30 11:44:37 -04:00
Paul Bovbel b9e0b5d213 1.2.4 2018-04-30 11:44:37 -04:00
Paul Bovbel c22d38df09 Update changelogs 2018-04-30 11:44:37 -04:00
Paul Bovbel aa6e728362 Disable travis until trusty support is available 2018-04-30 11:44:37 -04:00
Paul Bovbel f822d6ff6e Remove stray dependencies 2018-04-30 11:44:37 -04:00
Paul Bovbel 55a9ab8f6b Remove stray dependencies 2018-04-30 11:44:37 -04:00
Paul Bovbel 3fb881f8eb Refactor with tf2 and message filters 2018-04-30 11:44:37 -04:00
Paul Bovbel 17db2afd94 Remove roslaunch check 2018-04-30 11:44:37 -04:00
Paul Bovbel de8a0aca3f Fix regressions 2018-04-30 11:44:37 -04:00
Paul Bovbel eafe961c0c Refactor to allow debug messages from node and nodelet 2018-04-30 11:44:37 -04:00
Paul Bovbel d604c43332 1.2.3 2018-04-30 11:44:37 -04:00
Paul Bovbel 0d34c85f13 update changelogs 2018-04-30 11:44:37 -04:00
Paul Bovbel 091682c44a add launch tests 2018-04-30 11:44:37 -04:00
Paul Bovbel a70e770af5 refactor naming and fix nodelet export 2018-04-30 11:44:37 -04:00
Dani Carbonell a41d54b3eb Update common.py
Extended filter limits up to ±100000.0 in order to support intensity channel filtering.
2018-04-30 11:44:37 -04:00
Paul Bovbel e7a67030cb set default target frame to empty 2018-04-30 11:44:37 -04:00
Paul Bovbel 8d7192c120 clean up package.xml 2018-04-30 11:44:37 -04:00
Paul Bovbel 8010ae7ba8 1.2.2 2018-04-30 11:44:37 -04:00
Paul Bovbel 841ce1f77c update changelogs 2018-04-30 11:44:37 -04:00
Paul Bovbel 9537f5f1c4 clean up package.xml 2018-04-30 11:44:37 -04:00
Ruffin ac5593dd7c Adding target_frame
[Ability to specify frame in bag_to_pcd #55](https://github.com/ros-perception/perception_pcl/issues/55)
2018-04-30 11:44:37 -04:00
Matt Derry 155a69e484 Update pcl_nodelets.xml
Included missing closing library tag.  This was causing the pcl/Filter nodelets below the missing nodelet tag to not be exported correctly.
2018-04-30 11:44:37 -04:00
Paul Bovbel 0e73b421c9 Fix header reference 2018-04-30 11:44:37 -04:00
Paul Bovbel 11e2ff0797 Fix flow 2018-04-30 11:44:37 -04:00
Paul Bovbel f44eaf2fa5 Fix pointer assertion 2018-04-30 11:44:37 -04:00
Paul Bovbel dc1cf04b07 Finalize pointcloud to laserscan 2018-04-30 11:44:37 -04:00
Paul Bovbel 85241bcb53 Initial pointcloud to laserscan commit 2018-04-30 11:44:37 -04:00
Paul Bovbel fa30e01255 Fix issue #44 2018-04-30 11:44:37 -04:00
Paul Bovbel c8da9866e4 1.2.1 2018-04-30 11:44:37 -04:00
Paul Bovbel 1b41421471 update changelogs 2018-04-30 11:44:37 -04:00
Paul Bovbel 56c091eb38 clean up merge 2018-04-30 11:44:37 -04:00
Paul Bovbel 08e83a67bf merge pull request #60 2018-04-30 11:44:37 -04:00
Lucid One aac231674a 1.2.0 2018-04-30 11:44:37 -04:00
Lucid One 84e17581ea changelog 2018-04-30 11:44:37 -04:00
Lucid One e89fafe2e7 Updated changelog, maintainership, bugtracker and repository 2018-04-30 11:44:37 -04:00
Lucid One c178c5a08d Fixes #46 on indigo-devel
Tested with velodyne data on indigo on Ubuntu 14.04
2018-04-30 11:44:37 -04:00
Paul Bovbel 8a6fbbd99d remove redundant message files 2018-04-30 11:44:37 -04:00
Paul Bovbel 407f8e4bf7 remove redundant cmake file 2018-04-30 11:44:37 -04:00
Paul Bovbel c9d60b1de9 update maintainer info 2018-04-30 11:44:37 -04:00
Steven Peters 1e6d600c09 Use cmake_modules to help find eigen on indigo 2018-04-30 11:44:37 -04:00
William Woodall e6430884c6 pcl_ros: also run_depend on libpcl-all 2018-04-30 11:44:37 -04:00
Scott K Logan cb8c9c4408 Make pcl_ros run_depend on libpcl-all-dev
When downstream projects build against pcl_ros, they need the pcl headers provided by libpcl-all-dev.
2018-04-30 11:44:37 -04:00
Tully Foote 92c4e3771d 1.1.7 2018-04-30 11:44:37 -04:00
Tully Foote b43d6e18a5 changelog 2018-04-30 11:44:37 -04:00
Tully Foote 5b38aab37e adding more uncaught config dependencies 2018-04-30 11:44:37 -04:00
Tully Foote 9edc4154b6 adding FeatureConfig dependency too 2018-04-30 11:44:37 -04:00
Tully Foote d92092536c 1.1.6 2018-04-30 11:44:37 -04:00
Tully Foote a397fdc267 adding changelogs 2018-04-30 11:44:37 -04:00
Dirk Thomas a68cc1f7b3 add excplicit dependency on gencfg target 2018-04-30 11:44:37 -04:00
William Woodall 2adf6f1d6e 1.1.5 2018-04-30 11:44:37 -04:00
William Woodall f51ccbb0ec Updating changelogs 2018-04-30 11:44:37 -04:00
William Woodall acd12f8132 Updated package.xml's to use new libpcl-all rosdep rules 2018-04-30 11:44:37 -04:00
Lukas Bulwahn 3d35f0f748 package.xml: tuned whitespaces
This commit removes trailing whitespaces and makes the line with the license information in the package.xml bitwise match exactly the common license information line in most ROS packages.
The trailing whitespaces were detected when providing a bitbake recipe in the meta-ros project (github.com/bmwcarit/meta-ros). In the recipe, the hash of the license line is declared and is used to check for changes in the license. For this recipe, it was not matching the common one.
A related already merged commit is https://github.com/ros/std_msgs/pull/3 and a related pending commit is https://github.com/ros-perception/pcl_msgs/pull/1.
2018-04-30 11:44:37 -04:00
William Woodall c13777525f 1.1.4 2018-04-30 11:44:37 -04:00
William Woodall ce64f9450e Updating changelogs 2018-04-30 11:44:37 -04:00
William Woodall 3bc59ab51b Fix a serialization error with point_cloud headers 2018-04-30 11:44:37 -04:00
William Woodall 11d24d0e97 Initialize shared pointers before use
Should address runtime errors reported in #29
2018-04-30 11:44:37 -04:00
William Woodall fd75f3a02c Enable testing 2018-04-30 11:44:37 -04:00
William Woodall 76f48f8b33 Use -j1 and drop clang in .travis.yaml 2018-04-30 11:44:37 -04:00
William Woodall 9384112468 Fixup .travis.yaml 2018-04-30 11:44:37 -04:00
William Woodall 99bfd532c0 Fixup .travis.yaml 2018-04-30 11:44:37 -04:00
Dirk Thomas c9ae3c519f 1.1.3 2018-04-30 11:44:37 -04:00
Dirk Thomas b2b6eba0fc fix missing run_depend and wrong CATKIN_DEPENDS 2018-04-30 11:44:37 -04:00
William Woodall c88a6a1d66 1.1.2 2018-04-30 11:44:37 -04:00
William Woodall f758d4ba80 updating changelogs 2018-04-30 11:44:37 -04:00
William Woodall b6315543bb Fixed missing package exports
also other general CMakeLists.txt cleanup
2018-04-30 11:44:37 -04:00
rlklaser 45c5de6aff Update common.py
filters min max are bounded to only -5,5 when using rosparam load and dynamic reconfigure
2018-04-30 11:44:37 -04:00
William Woodall 716b263d4d Use shadow fixed rather than public 2018-04-30 11:44:37 -04:00
William Woodall d42d6c0be0 Update to travis 2018-04-30 11:44:37 -04:00
William Woodall b6c9ebb319 Updating travis for hydro 2018-04-30 11:44:37 -04:00
William Woodall 585ed21709 Make find_package on Eigen and PCL REQUIRED 2018-04-30 11:44:37 -04:00
William Woodall 7f197fab15 1.1.1 2018-04-30 11:44:37 -04:00
William Woodall 47cc34c7b3 Updating change logs 2018-04-30 11:44:37 -04:00
William Woodall 3a688bcf5f Add missing EIGEN define which caused failures on the farm 2018-04-30 11:44:37 -04:00
William Woodall e0e17d2daa 1.1.0 2018-04-30 11:44:37 -04:00
William Woodall eee71fac20 Adding changelogs 2018-04-30 11:44:37 -04:00
William Woodall edc9fdab85 Add missing include in one of the installed headers 2018-04-30 11:44:37 -04:00
William Woodall a3840127f8 Refactors to use pcl-1.7 2018-04-30 11:44:37 -04:00
William Woodall 4e64cb25e7 Use the PointIndices from pcl_msgs 2018-04-30 11:44:37 -04:00
William Woodall 018bb008d4 Ignore .pyc files 2018-04-30 11:44:37 -04:00
William Woodall 746a8faf65 Experimental changes to point_cloud.h 2018-04-30 11:44:37 -04:00
William Woodall a931106c5b Fixes from converting from pcl-1.7, incomplete 2018-04-30 11:44:37 -04:00
William Woodall 9d08dd5198 Depend on pcl_conversions and pcl_msgs 2018-04-30 11:44:37 -04:00
Martin Günther 1a8f70b099 bag_to_pcd: check return code of transformPointCloud()
This fixes a bug where bag_to_pcd segfaults because of an ignored
tf::ExtrapolationException.
2018-04-30 11:44:37 -04:00
Julius Kammerl fa2baa5248 adding .travis.yml 2018-04-30 11:44:37 -04:00
Davide 5733764621 Changed #include type to lib 2018-04-30 11:44:37 -04:00
Davide d0a5fd4322 Changed some #include types to lib 2018-04-30 11:44:37 -04:00
Davide 8c6b34f6b7 removed a whitespace 2018-04-30 11:44:37 -04:00
Julius Kammerl fdb4fa9bfe 1.0.33 -> 1.0.34 2018-04-30 11:44:37 -04:00
Julius Kammerl 6f256968eb fixing catkin python imports 2018-04-30 11:44:37 -04:00
Julius Kammerl 6e4f23f43c 1.0.32 -> 1.0.33 2018-04-30 11:44:37 -04:00
Julius Kammerl 3327eb6a20 Fixing catkin python imports 2018-04-30 11:44:37 -04:00
Julius Kammerl e6122e2b87 Fixing catkin python import 2018-04-30 11:44:37 -04:00
Julius Kammerl 9244556f9b Fixing catkin python import 2018-04-30 11:44:37 -04:00
Julius Kammerl 3dee819ea9 Fixing catkin python import 2018-04-30 11:44:37 -04:00
Julius Kammerl 0f6ee511da Fixing catkin python import 2018-04-30 11:44:37 -04:00
Julius Kammerl 6038a445d8 Fixing catkin python import 2018-04-30 11:44:37 -04:00
Julius Kammerl 698134ab74 Fixing catkin python import 2018-04-30 11:44:37 -04:00
Julius Kammerl a289400192 1.0.31 -> 1.0.32 2018-04-30 11:44:37 -04:00
Kei Okada b2f9c6e898 fix to compileable 2018-04-30 11:44:37 -04:00
Kei Okada f2553aac6c copy features/segmentation/surface from fuerte-devel 2018-04-30 11:44:37 -04:00
Julius Kammerl 669c2d2b04 1.0.30 -> 1.0.31 2018-04-30 11:44:37 -04:00
Julius Kammerl 7848d6fbec minor 2018-04-30 11:44:37 -04:00
Julius Kammerl 46ceee9f80 adding CMakeLists.txt file for metapackage 2018-04-30 11:44:37 -04:00
Julius Kammerl 16d630573a bumping version to 1.0.30 2018-04-30 11:44:37 -04:00
Julius Kammerl 1ee537f320 adding buildtool_depend to meta package 2018-04-30 11:44:37 -04:00
Julius Kammerl 570269f2e5 deprecating bin install targets 2018-04-30 11:44:37 -04:00
Vincent Rabaud 3b5234cb7f 1.0.29 2018-04-30 11:44:37 -04:00
Vincent Rabaud 12eee07fda Fixes #7 2018-04-30 11:44:37 -04:00
Kai Franke c6a48a583f now also works without specifying publishing interval like described in the wiki. Also renamed rate_ to time_ since it is no rate 2018-04-30 11:44:37 -04:00
Julius Kammerl f7e8a659a9 typo 2018-04-30 11:44:37 -04:00
Julius Kammerl 9410665556 bumping version to 1.0.28 2018-04-30 11:44:37 -04:00
Julius Kammerl 604047b18d reenabling deprecated install targets - comment added 2018-04-30 11:44:37 -04:00
Julius Kammerl 058bed54e1 switching to 1.0.27 2018-04-30 11:44:37 -04:00
Julius Kammerl 418a15560d Update pcl_ros/package.xml 2018-04-30 11:44:37 -04:00
Julius Kammerl 750dc76fe4 Fixing target install directory for pcl tools 2018-04-30 11:44:37 -04:00
jon-weisz 758f23264d update pluginlib macro 2018-04-30 11:44:37 -04:00
Julius Kammerl 8133001c65 1.0.25 -> 1.0.26 2018-04-30 11:44:37 -04:00
Julius Kammerl 23d8010149 fixing catkin export 2018-04-30 11:44:37 -04:00
Julius Kammerl ae3aff7b54 removing build_tool dependency from package.xml 2018-04-30 11:44:37 -04:00
Vincent Rabaud 7bd5038520 1.0.25 2018-04-30 11:44:37 -04:00
Vincent Rabaud 3fc3fa400a fixes #1 2018-04-30 11:44:37 -04:00
Dirk Thomas 20bed7483f 1.0.24 2018-04-30 11:44:37 -04:00
Dirk Thomas c7c4a1fa56 remove obsolete roslib import 2018-04-30 11:44:37 -04:00
Dirk Thomas 95ec2c7171 1.0.23 2018-04-30 11:44:37 -04:00
Dirk Thomas c4aed1cb0c clean up shared parameters 2018-04-30 11:44:37 -04:00
Dirk Thomas ab602d14a1 1.0.22 2018-04-30 11:44:37 -04:00
Dirk Thomas 2da1700056 fix dyn reconf files 2018-04-30 11:44:37 -04:00
Julius Kammerl 54f95ea10f switching to version 1.0.21 2018-04-30 11:44:37 -04:00
Julius Kammerl a0464e15b0 fixing catkin_package debs 2018-04-30 11:44:37 -04:00
Julius Kammerl e0f9f36fec switching to version 1.0.20 2018-04-30 11:44:37 -04:00
Julius Kammerl 19906dc323 adding catkin_project dependencies 2018-04-30 11:44:37 -04:00
Julius Kammerl a2617ff826 switching to version 1.0.19 2018-04-30 11:44:37 -04:00
Julius Kammerl 140a4a3bf9 adding nodelet_topic_tools dependency 2018-04-30 11:44:37 -04:00
Julius Kammerl 077b4f3dea adding pluginlib dependency 2018-04-30 11:44:37 -04:00
Julius Kammerl 993afab40b adding nodelet dependencies 2018-04-30 11:44:37 -04:00
Julius Kammerl 540fcd0604 CMake install fixes 2018-04-30 11:44:37 -04:00
Julius Kammerl baa59c0d00 increasing version to 1.0.18 2018-04-30 11:44:37 -04:00
Julius Kammerl a3701bb3df migrating nodelets and tools from fuerte release to pcl_ros 2018-04-30 11:44:37 -04:00
mirzashah d5d9e3816a Updated for new <buildtool_depend>catkin<...> catkin rule 2018-04-30 11:44:37 -04:00
Vincent Rabaud 25e6d566f1 1.0.17 2018-04-30 11:44:37 -04:00
Vincent Rabaud fe018e3174 remove useless tags 2018-04-30 11:44:37 -04:00
Vincent Rabaud 9694594f7c 1.0.16 2018-04-30 11:44:37 -04:00
Vincent Rabaud f21e5b679a no need to depend on a meta-package 2018-04-30 11:44:37 -04:00
Vincent Rabaud 68459d68d2 1.0.15 2018-04-30 11:44:37 -04:00
Vincent Rabaud 9370244dca do not generrate messages automatically 2018-04-30 11:44:37 -04:00
Vincent Rabaud 6a8696b61f 1.0.14 2018-04-30 11:44:37 -04:00
Vincent Rabaud e677ddf794 bring back the PCL msgs 2018-04-30 11:44:37 -04:00
Vincent Rabaud a5c158904d 1.0.13 2018-04-30 11:44:37 -04:00
Vincent Rabaud a54a518837 install library to the right place 2018-04-30 11:44:37 -04:00
Vincent Rabaud a3726b72cd 1.0.12 2018-04-30 11:44:37 -04:00
Vincent Rabaud c0b5f1030d make sure perception_pcl is a meta package 2018-04-30 11:44:37 -04:00
Vincent Rabaud 52dd24a4af 1.0.11 2018-04-30 11:44:37 -04:00
Vincent Rabaud 70d156a8b1 1.0.11 2018-04-30 11:44:37 -04:00
Vincent Rabaud 03cde871a2 fix a few dependencies 2018-04-30 11:44:37 -04:00
Vincent Rabaud a1b32d4fb6 comply to the new catkin API 2018-04-30 11:44:37 -04:00
jkammerl a29653e9aa fixed pcl_ros manifest 2018-04-30 11:44:37 -04:00
jkammerl fb513120e3 added pcl exports in manifest.xml 2018-04-30 11:44:37 -04:00
jkammerl e7176a5355 fixed rosdeb pcl in pcl_ros/manifest.xml 2018-04-30 11:44:37 -04:00
jkammerl e40bfe91f0 removing common_rosdeps from manifest.xml 2018-04-30 11:44:37 -04:00
jkammerl e6846d72da change perception_pcl version to 1.0.6 in stack.xml (groovy branch) 2018-04-30 11:44:37 -04:00
jkammerl 3c3c86fc37 perception_pcl restructuring in groovy branch 2018-04-30 11:44:37 -04:00
jkammerl bcda3321ad restructuring perception_pcl in groovy branch 2018-04-30 11:44:37 -04:00
jkammerl cb6e2b0529 minor 2018-04-30 11:44:37 -04:00
jkammerl 441319bcee stack.xml: PCL->pcl 2018-04-30 11:44:37 -04:00
jkammerl 4043ed1cde stack.xml: Eigen->eigen 2018-04-30 11:44:37 -04:00
jkammerl eb0ea004b7 fixed stack.xml - common_msgs 2018-04-30 11:44:37 -04:00
jkammerl 8e042cf9d5 tf->geometry in stack.xml 2018-04-30 11:44:37 -04:00
jkammerl 6dcca0ae2e increased stack version to 1.0.5 2018-04-30 11:44:37 -04:00
jkammerl a9f97a0606 added missing tf stack to CMakeList 2018-04-30 11:44:37 -04:00
jkammerl ffb3e9d7eb minor 2018-04-30 11:44:37 -04:00
jkammerl a57e6ab579 moved transforms.cpp to /src 2018-04-30 11:44:37 -04:00
jkammerl dfa5be4f9d added new stack.xml, removed manifest.xml 2018-04-30 11:44:37 -04:00
jkammerl 33ae605cd1 catkinized version of perception_pcl for groovy 2018-04-30 11:44:37 -04:00
jkammerl 73e8aa93ac added perception_pcl_unstable to groovy branch 2018-04-30 11:44:37 -04:00
jkammerl 6d993c0282 removed pcl release from perception_pcl groovy stack 2018-04-30 11:44:37 -04:00
rusu adf647f14d added PCL 1.6 stac for Groovy 2018-04-30 11:44:37 -04:00
Paul Bovbel 693a18feb0 Move to subdirectory 2018-04-30 11:34:36 -04:00
Paul Bovbel bdecc4af0d Make dependencies transitive and test dependencies 2018-04-30 11:11:51 -04:00
Paul Bovbel 4bf3478d04 Fix up PCL libraries 2018-04-30 11:10:34 -04:00
Paul Bovbel 49ccc0599a Drop deprecated Eigen cmake module 2018-04-30 10:58:35 -04:00
Paul Bovbel 686502e1ac Merge pull request #22 from ros-perception/paulbovbel-patch-1
Remove duplicated line
2016-10-27 11:01:20 -04:00
Paul Bovbel 3f25096398 Remove duplicated line 2016-10-27 11:00:13 -04:00
Paul Bovbel 98d99aa91c 0.2.1 2015-06-08 09:03:46 -04:00
Paul Bovbel 6eef12333f Update changelogs 2015-06-08 09:02:46 -04:00
Lucid One 4675fefe36 Merge pull request #15 from bricerebsamen/stamp_rounding_error
🏁 Thanks! 🏁

`catkin build pcl_conversions -v --make-args run_tests`

---
```
[100%] Built target tests
-- run_tests.py: execute commands
  /home/username/rospcl_ws/devel/lib/pcl_conversions/pcl_conversions-test --gtest_output=xml:/home/username/rospcl_ws/build/pcl_conversions/test_results/pcl_conversions/gtest-pcl_conversions-test.xml
[==========] Running 3 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 2 tests from PCLConversionTests
[ RUN      ] PCLConversionTests.imageConversion
[       OK ] PCLConversionTests.imageConversion (0 ms)
[ RUN      ] PCLConversionTests.pointcloud2Conversion
[       OK ] PCLConversionTests.pointcloud2Conversion (0 ms)
[----------] 2 tests from PCLConversionTests (0 ms total)

[----------] 1 test from PCLConversionStamp
[ RUN      ] PCLConversionStamp.Stamps
[       OK ] PCLConversionStamp.Stamps (0 ms)
[----------] 1 test from PCLConversionStamp (0 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 2 test cases ran. (0 ms total)
[  PASSED  ] 3 tests.
```
2015-03-19 16:06:28 -04:00
Brice Rebsamen d1b27af512 Conversion in integral precision
fixes #14
2015-02-11 11:36:56 -08:00
Brice Rebsamen 2c57225370 Added a test for rounding errors in stamp conversion
for some values the test fails. This is because of rounding errors. See #14.
2015-02-11 11:29:33 -08:00
Paul Bovbel 3acde03e8a Merge pull request #13 from mikeferguson/indigo-devel
add pcl::PointCloud to sensor_msgs::Image converter
2014-05-27 20:02:37 -04:00
Michael Ferguson d080cd78ac add pcl::PointCloud to Image msg converter for extracting the rgb component of a cloud 2014-05-27 16:58:40 -07:00
agentx3r 04d919f5bd 0.2.0 2014-04-10 14:37:18 +00:00
agentx3r 6619fbde8f update maintainer info and changelog 2014-04-10 14:37:09 +00:00
Brice Rebsamen 7dc1ae60b0 Added conversions for stamp types 2014-04-08 22:49:22 +00:00
Paul Bovbel e1ba69bfca update maintainer info, add eigen dependency 2014-04-08 22:34:55 +00:00
Paul Bovbel 388c0dc0ff fix Eigen dependency 2014-04-08 22:34:30 +00:00
William Woodall 702f553335 Merge pull request #10 from smd-ros-rpm-release/hydro-devel
Make pcl_conversions run_depend on libpcl-all-dev
2014-02-28 17:19:18 -08:00
Scott K Logan ad560f2626 Make pcl_conversions run_depend on libpcl-all-dev
When downstream projects build against pcl_conversions, they need the pcl headers provided by libpcl-all-dev.
2014-02-28 19:03:17 -06:00
William Woodall 5b52fedea2 0.1.5 2013-08-27 12:20:49 -07:00
William Woodall 85eeb2944d Updating changelog 2013-08-27 12:20:44 -07:00
William Woodall a868e1a16e Use new pcl keys 2013-08-27 12:19:38 -07:00
William Woodall 9e568f8d8b 0.1.4 2013-07-13 13:23:32 -07:00
William Woodall 95c63f9980 Updating changelog 2013-07-13 13:23:04 -07:00
William Woodall b4071f4aa6 Fixup dependencies and CMakeLists.txt
I added a versioned dependency on pcl, fixes #1,
and I added a dependency on pcl_msgs, fixes #2,
and I wrapped the test target in a
CATKIN_ENABLE_TESTING check.
2013-07-13 13:19:22 -07:00
Ioan Sucan cb88b4f66e 0.1.3 2013-07-13 09:21:06 +02:00
Ioan Sucan 93c7b52b82 update changelog 2013-07-13 09:21:02 +02:00
William Woodall 7a46755d94 Add missing dependency on roscpp 2013-07-12 14:10:06 -07:00
William Woodall 2f1a58d442 Fixup tests and pcl usage in CMakeList.txt 2013-07-12 13:59:30 -07:00
Ioan Sucan d4bc987fed 0.1.2 2013-07-12 15:16:20 +02:00
Ioan Sucan bd587dc94a update changelog 2013-07-12 15:16:17 +02:00
Ioan Sucan a369efcaa8 small fix for conversion functions 2013-07-12 15:12:04 +02:00
William Woodall b2eea44781 0.1.1 2013-07-10 13:36:19 -07:00
William Woodall fa4f5876d4 Updating changelog 2013-07-10 13:36:04 -07:00
William Woodall fe71108db7 Ignore build folders 2013-07-10 13:35:23 -07:00
William Woodall 2103cd06af Fix find_package bug with pcl 2013-07-10 13:35:11 -07:00
William Woodall f9b1996498 0.1.0 2013-07-09 22:12:01 -07:00
William Woodall c8e85dbe99 Adding a basic changelog 2013-07-09 22:09:44 -07:00
William Woodall 85d9828cd8 Added more pcl::to/fromROSMsg which went missing in 1.7 2013-07-09 21:49:26 -07:00
William Woodall 4b6240e924 Added converters and destructive move functions 2013-07-09 18:55:42 -07:00
William Woodall 9f685befcb Inlined functions to prevent duplicate symbols 2013-07-08 18:50:55 -07:00
William Woodall 6b77c9163f add conversions for PointIndices 2013-07-08 17:36:58 -07:00
William Woodall 2e89da5996 Custom serializer for PCLPointCloud2 and PCLHeader 2013-07-08 16:34:15 -07:00
William Woodall 5c7d7c3f86 New toPCL and fromPCL functions 2013-07-08 16:33:56 -07:00
William Woodall 2b131448db updating pcl namespaces 2013-07-08 16:33:15 -07:00
William Woodall 9dc59ae6ec Adding include guard 2013-07-08 16:29:37 -07:00
William Woodall 17662604b8 Shorten the names of functions by popular demand. 2013-06-28 12:07:30 -07:00
William Woodall 034680bd5b Update README.rst 2013-06-26 17:15:16 -07:00
William Woodall d6c254cb4e Update README.rst 2013-06-26 17:12:46 -07:00
William Woodall 21ed95ce4e Adding a README 2013-06-26 17:11:54 -07:00
William Woodall f265bb7aa8 Added some simple tests. 2013-06-26 17:08:00 -07:00
William Woodall 06bdd26173 Boost is no longer used. 2013-06-26 15:51:38 -07:00
William Woodall c09b1a25de PCL uses microseconds rather than nanoseconds
Also removed some vestigial code
2013-06-26 15:45:02 -07:00
William Woodall 649d1ca6ce Initial code commit 2013-06-26 15:41:31 -07:00
1761 changed files with 181306 additions and 33631 deletions
Binary file not shown.
Binary file not shown.
+242 -1
View File
@@ -1,3 +1,244 @@
# greenhouse
This repository contains code for detecting heat pipes in the greenhouse as well as estimating the pose of the pipes
This repository contains code for detecting heat pipes in the greenhouse as well as estimating the pose of the pipes.
Platform: ROS 2, Humble, Ubuntu 22.04
## How to install dependencies??
- Install `git`
```
sudo apt install git
```
- Install `ROS 2 Humble` on `Ubuntu 22.04` by following https://docs.ros.org/en/foxy/Installation/Ubuntu-Install-Debians.html
- Install `colcon build` by following https://docs.ros.org/en/foxy/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html
```
sudo apt install python3-colcon-common-extensions
```
- Instal `pip` for python packages
```
sudo apt install python3-pip
```
- Now clone the repository
```
git clone https://tea.der-space.de/apoorva/greenhouse.git
```
- Install `ultralytics` for yolov3 package
```
pip install ultralytics
```
- For `yolov3_ros`, there are a bunch of other requirements. Go to `yolov3` folder and install using following commands:
```
cd ~/greenhouse/yolov3
pip install -r requirements.txt
```
- Go to `ros2_ws` inside `greenhouse`. Make sure you only have `src` folder.
```
cd ~/greenhouse/ros2_ws
ls
src
```
- Inside `ros2_ws` folder, start building individual packages in the below sequence to avoid errors.
```
colcon build --packages-select pipe_msgs
colcon build --packages-select pcl_ros
colcon build --allow-overriding pcl_ros
colcon build --packages-select pcl_conversions
colcon build --allow-overriding pcl_conversions
colcon build --packages-select find-pose
colcon build --packages-select yolov3_ros
. install/setup.bash
```
- The code should be ready to launch as explained in [How to run Live Detection?](#how-to-run-live-detection)
This section explains what each module is responsible for.
## perception_pcl
This module is responsible for providing `pcl_conversions` and `pcl_ros` modules in `ros 2`.
To build, run the following command:
```
cd ros2_ws/
colcon build --packages-select perception_pcl
. install/setup.bash
```
## pipe_msgs
This module contains ros msgs for storing information about the detected object's bounding box.
```
cd ros2_ws/
colcon build --packages-select pipe_msgs
. install/setup.bash
```
To check if msgs are built properly, run following command
```
ros2 interface show pipe_msgs/msg/BoundingBox
```
The output will be:
float64 probability
int64 xmin
int64 ymin
int64 xmax
int64 ymax
int16 id
string class_id
## find-pose
This ROS module is responsible for determining the position of the detected objects.
The following input/ros topics are needed:
- /rgb_img: RGB Image topic
- /camera_info: Camera calibration parameters topic
- /depth_img: Aligned depth image topic (aligned with rgb image)
- /bboxes: Bounding box of each detected object. (Comes from yolov3 detection module)
Output:
- TF: Transform between camera_link and detected_object frame.
How to build and run?
This package is dependent on custom `pcl_conversion` and `pcl_ros` module. Make sure you have built those before building this package.
```
colcon build --packages-select find-pose
. install/setup.bash
ros2 launch find-pose find-pose-node.launch.py
```
All the topics can be remapped in the launch file.
## yolov3_ros
This ROS module is responsible for detecting the pipes from rgb image topic and also syncing the depth, rgb and camera_info topics.
The following input/ros topics are needed:
- /camera/color/image_raw: RGB Image topic
- /camera/aligned_depth_to_color/image_raw: Aligned depth image topic (aligned with rgb image)
- /camera/color/camera_info: Camera calibration parameters topic
ROS Paramater Input:
- best_weights: String that is the path to the best weights file of yolov3 detection
Defaults: `'src/pipe_weights.pt'` inside `ros2_ws` folder
The following are the output topics:
- /detection_image: The RGB Image topic with bounding box drawn on it for visualization and debugging purpose
- /bboxes: Bounding box of each detected object.
- /rgb_img: Time Synced RGB Image topic
- /camera_info: Time Synced Camera calibration parameters topic
- /depth_img: Time Synced Aligned depth image topic (aligned with rgb image)
How to build and run?
```
colcon build --packages-select yolov3_ros
. install/setup.bash
cd greenhouse/ros2_ws/
ros2 launch yolov3_ros pipe_detection.launch.py
```
All the topics can be remapped in the launch file. The path to best_weights can also be changed inside the launch file.
Launch file is stored in `yolov3_ros/launch/`.
## yolov3
This module contains code for yolov3. This method is being used to train the model to detect pipes in the greenhouse.
- Ros bag was converted from ros 1 to ros 2 using rosbags module
- Ros 2 bag was played, convert_2_img was used to subscribe to images and all the images were saved as .jpeg in a folder.
- Images were labeled used labelImg.
- Create a `custom-yolov3.yaml` file that has information about number of classes, location for labels,images.
- Used google colab to run the yolov3 training.
- Upload the label and images to drive and Mount the google drive in python notebook
```
from google.colab import drive
drive.mount("/content/gdrive")
```
- Upload the yolov3 code and cd into the location of code
```
cd /content/gdrive/MyDrive/yolov3
```
- Run the training script
```
!python train.py --img 1280 --batch 16 --epochs 300 --data data/custom-yolov3.yaml --weights '' --cfg yolov3.yaml
```
- Important to note that we are not using any pre-trained weights.
- Once training is finished, a `run` folder is created with exp number that stores the best weights (a .pt file).
- This file is then used by detection to node to detect on new data. Update the image path and weights path to run detection.
```
!python detect.py --img 1280 --source ../pipe-dataset/validate/images/stereo_image103.jpeg --weights runs/train/exp14/weights/best.pt
```
- Once detect.py is finished, it create a new folder called `detect` inside `runs` folder that store the image with bounding box of detected object.
More details: https://github.com/ultralytics/yolov3
## convert_2_img
This ROS module converts the rosbag data to images for yolo training purpose etc.
- Make sure you have this module inside a ros workspace.
- Create folder called `stereo` inside convert_2_img module.
- Run following command to launch the node. Currently, this node listens for `/camera/color/image_raw` topic.
```
cd ros2_ws/src/convert_2_img
python3 convert_2_img/convert_to_img.py
```
- Play the rosbag in another terminal
```
ros2 bag play bag/bag.db
```
- Once bag has finished playing, the images will be stored inside `stereo` folder.
## labelImg
This module is used to label images for yolo. The pre-defined custom classes file was changed to use new labels. This file is stored in `cd labelImg/data/predefined_classes.txt`
To launch the gui, run
```
cd labelImg
python3 labelImg.py
```
More details: https://github.com/heartexlabs/labelImg
## rosbags
This module convert rosbags from ros 1 to ros 2.
```
git clone https://gitlab.com/ternaris/rosbags.git
cd rosbags
python -m venv venv
. venv/bin/activate
pip install -r requirements-dev.txt
pip install -e .
rosbags-convert ../single_depth_color_640x480.bag
```
## flann_based
Module that uses 3D model of the pipe to estimate pose. This method was not successful.
## yolov7
This module contains code for yolov7. This method was too heavy and didn't produce great results for detection.
## darknet_ros2
This module was provides interface to run neural network as rosnodes. The purpose was to use yolo model as ros node but this method was not successful
## darknet_vendor
This module was needed to build darknet_ros2.
# How to run live detection?
Once you have succefully built the ROS Modules specifically, `yolov3_ros` and `find-pose` along with dependencies like `pipe_msgs` and `perception_ros`, `perception_pcl`,you can do the following:
Assumption:
You have the following required data in forms of ros topic:
- /camera/color/image_raw: RGB Image topic
- /camera/aligned_depth_to_color/image_raw: Aligned depth image topic (aligned with rgb image)
- /camera/color/camera_info: Camera calibration parameters topic
How do you get this data?
- This data can come from a pre recorded Rosbag. If this is the case, do following:
```
ros2 bag play bag-folder/bag-name.db3
```
- This data can come directly from camera's (D455/ZED2I) ROS Node: Launch your node in a terminal.
- If your camera topics have different names than the default topic names mentioned above, update/remap ONLY the `pipe_detection.launch.py` script stored in `ros2_ws/src/yolov3_ros/launch` folder.
- Once you have updated the launch file, build the code again using `colcon build --packages-select yolov3_ros` and proceedas mentioned below.
Steps to run:
- Open a terminal.
- Run `$ cd greenhouse/ros2_ws/` and `$ . install/setup.bash`.
- Launch node for object detection:
```
ros2 launch yolov3_ros pipe_detection.launch.py
```
- This node will output two topics: `/bboxes` and `/detection_image`.
- Make sure that you run this launch file from `greenhouse/ros2_ws/` folder since the path of weights is relative (`/src/pipe_weights.pt`) inside the launch file.
- Launch node for pose estimation:
```
ros2 launch find-pose find-pose-node.launch.py
```
- This node will output TF topics between `/camera_link` and `/${detected_object_name}`.
- Open RVIZ by running `$ rviz2`. Change `fixed frame` from `map` to `camera_link`.
- Go to `Add` button. Under `By Display type`, select `tf`. Once tf is added, select required frames like `camera_link` and `l_trail` to see the tfs.
- To see the current image with detected object, Go to `Add` Button. Under `By Topic`, select topci called `detection_image`.
-You can add other topics as per the need and topic names.
- You can open launch files to update/remap topic name if different camera is being used.
- You can also update ros parameter from launch file. Currently, the `pipe_weights.pt` file is the one used. This file can be changed and you can update the parameter name `best_weights` inside the `pipe_detection.launch.py` file.
-55
View File
@@ -1,55 +0,0 @@
branches:
only:
- master
- devel
os: Visual Studio 2015
clone_folder: c:\projects\find-object
platform: x64
configuration: Release
init:
- cmake --version
- call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64
install:
# Qt
- set QTDIR=C:\Qt\5.10.1\msvc2015_64
# make sure Qt bin path is before cmake bin path to avoid copying qt5 dlls from cmake before qt installation
- set PATH=%QTDIR%\bin;%PATH%
# OpenCV
- ps: wget 'https://dl.dropboxusercontent.com/s/o6ofn491bc0jso1/opencv450_vc14.exe?dl=0' -outfile opencv.exe
- cmd: opencv.exe -o"C:\Program Files" -y
- ECHO "Installed OpenCV:"
- ps: "ls \"C:/Program Files/opencv\""
- set PATH=%PATH%;C:\Program Files\opencv\x64\vc14\bin
# zlib
- ps: wget 'https://docs.google.com/uc?authuser=0&id=0B46akLGdg-uaYm9MTTI4MUtUcmc&export=download' -outfile zlib-1.2.8-vc2010-x64.zip
- ps: Expand-Archive zlib-1.2.8-vc2010-x64.zip -DestinationPath 'C:\Program Files'
- ECHO "Installed zlib:"
- ps: "ls \"C:/Program Files/zlib\""
- set PATH=%PATH%;C:\Program Files\zlib\bin
before_build:
- cd c:\projects\find-object\build
- ECHO %PROGRAMFILES%
- ECHO %PATH%
- cmake -G "Visual Studio 14 2015 Win64" -DOpenCV_DIR="C:\Program Files\opencv\build" ..
after_build :
- cmake --build . --config Release --target package
artifacts:
- path: build\Find-Object-*
notifications:
- provider: Email
to:
- matlabbe@email.com
on_build_success: false
on_build_failure: false
on_build_status_changed: true
-221
View File
@@ -1,221 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?>
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1122816744">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1122816744" moduleId="org.eclipse.cdt.core.settings" name="Unix">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.1122816744" name="Unix" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.1122816744.306079558" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1536867206" name="cdt.managedbuild.toolchain.gnu.base" superClass="cdt.managedbuild.toolchain.gnu.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.1135530120" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
<builder arguments="-C ${ProjDirPath}/build VERBOSE=true" command="make" id="cdt.managedbuild.target.gnu.builder.base.673178816" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.881773237" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.2094327183" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.424205109" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.86959710" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1730465962" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.467751471" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.921357809" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.2123576755" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.base.961100725" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.652879249" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
<buildTargets>
<target name="CMake-MinGW-Debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Debug ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-MinGW-Release" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Release ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-Unix-Debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-Unix-Release" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Release ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
</cconfiguration>
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1122816744.759219509">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1122816744.759219509" moduleId="org.eclipse.cdt.core.settings" name="Windows">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.1122816744.759219509" name="Windows" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.1122816744.759219509." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1456803292" name="cdt.managedbuild.toolchain.gnu.base" superClass="cdt.managedbuild.toolchain.gnu.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.2081668986" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
<builder arguments="-j1" buildPath="${workspace_loc:/find-object/build}" command="jom" id="cdt.managedbuild.target.gnu.builder.base.1061057950" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.1544971303" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.2118555748" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.94612230" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.2131826214" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.793991581" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.425208659" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.857190324" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.814112417" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.base.1251214126" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1528092174" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
<buildTargets>
<target name="CMake-MinGW-Debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Debug ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-MinGW-Release" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Release ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-Unix-Debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-Unix-Release" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Release ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="find_object.null.1999159200" name="find_object"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
<buildTargets>
<target name="CMake-MinGW-Debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Debug ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-MinGW-Release" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE=Release ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-Unix-Debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Debug ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="CMake-Unix-Release" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>cmake</buildCommand>
<buildArguments>-E chdir build/ cmake -G "Unix Makefiles" -D CMAKE_BUILD_TYPE=Release ../</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Windows">
<resource resourceType="PROJECT" workspacePath="/find_object"/>
</configuration>
<configuration configurationName="Unix">
<resource resourceType="PROJECT" workspacePath="/find_object"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1122816744;cdt.managedbuild.toolchain.gnu.base.1122816744.306079558;cdt.managedbuild.tool.gnu.cpp.compiler.base.2094327183;cdt.managedbuild.tool.gnu.cpp.compiler.input.424205109">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1122816744;cdt.managedbuild.toolchain.gnu.base.1122816744.306079558;cdt.managedbuild.tool.gnu.c.compiler.base.86959710;cdt.managedbuild.tool.gnu.c.compiler.input.1730465962">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>
-36
View File
@@ -1,36 +0,0 @@
name: CMake
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
BUILD_TYPE: Release
jobs:
build:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04]
steps:
- name: Install dependencies
run: |
DEBIAN_FRONTEND=noninteractive
sudo apt-get update
sudo apt-get -y install libopencv-dev qtbase5-dev git cmake software-properties-common
- uses: actions/checkout@v2
- name: Configure CMake
run: |
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
-59
View File
@@ -1,59 +0,0 @@
name: ros1
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
name: Build on ros ${{ matrix.ros_distro }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-18.04]
include:
- os: ubuntu-20.04
ros_distro: 'noetic'
- os: ubuntu-18.04
ros_distro: 'melodic'
steps:
- uses: ros-tooling/setup-ros@v0.2
with:
required-ros-distributions: ${{ matrix.ros_distro }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install ros-${{ matrix.ros_distro }}-cv-bridge qtbase5-dev
- name: Setup catkin workspace
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
mkdir -p ${{github.workspace}}/catkin_ws/src
cd ${{github.workspace}}/catkin_ws/src
catkin_init_workspace
cd ..
catkin_make
- uses: actions/checkout@v2
with:
path: 'catkin_ws/src/find_object_2d'
- name: caktkin_make
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
source ${{github.workspace}}/catkin_ws/devel/setup.bash
cd ${{github.workspace}}/catkin_ws
catkin_make -DSETUPTOOLS_DEB_LAYOUT=OFF
catkin_make install
-58
View File
@@ -1,58 +0,0 @@
name: ros2
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally
# well on Windows or Mac. You can convert this to a matrix build if you need
# cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
name: Build on ros2 ${{ matrix.ros_distro }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
ros_distro: [foxy, galactic, humble]
include:
- ros_distro: 'foxy'
os: ubuntu-20.04
- ros_distro: 'galactic'
os: ubuntu-20.04
- ros_distro: 'humble'
os: ubuntu-22.04
steps:
- uses: ros-tooling/setup-ros@v0.4
with:
required-ros-distributions: ${{ matrix.ros_distro }}
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install ros-${{ matrix.ros_distro }}-cv-bridge qtbase5-dev
- name: Setup ros2 workspace
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
mkdir -p ${{github.workspace}}/ros2_ws/src
cd ${{github.workspace}}/ros2_ws
colcon build
- uses: actions/checkout@v2
with:
path: 'ros2_ws/src/find_object_2d'
- name: colcon build
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
cd ${{github.workspace}}/ros2_ws
colcon build --event-handlers console_direct+
-79
View File
@@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>find_object</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value>-C ${ProjDirPath}/build VERBOSE=true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>false</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>
-22
View File
@@ -1,22 +0,0 @@
sudo: true
dist: trusty
language: cpp
compiler:
- gcc
- clang
addons:
apt:
packages:
- cmake
- libopencv-dev
- libqt4-dev
script:
- mkdir -p build && cd build
- cmake ..
- make
notifications:
email: false
-472
View File
@@ -1,472 +0,0 @@
cmake_minimum_required(VERSION 3.5)
SET(CATKIN_BUILD FALSE)
SET(COLCON_BUILD FALSE)
# Detect if it is called by catkin (ros1)
IF(CATKIN_TOPLEVEL OR CATKIN_BUILD_BINARY_PACKAGE OR CATKIN_SKIP_TESTING OR CATKIN_ENABLE_TESTING OR CATKIN_DEVEL_PREFIX)
SET(CATKIN_BUILD TRUE)
ELSE()
# Detect if it is called by colcon (ros2)
IF(DEFINED AMENT_PREFIX_PATH) # buildfarm
SET(COLCON_BUILD TRUE)
ELSE() # colcon local build in ros2_ws
string(FIND ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR} POS)
IF(${POS} EQUAL -1)
SET(COLCON_BUILD TRUE)
ENDIF()
ENDIF()
ENDIF()
MESSAGE(STATUS "CATKIN_BUILD=${CATKIN_BUILD}")
MESSAGE(STATUS "COLCON_BUILD=${COLCON_BUILD}")
SET(ROS_BUILD FALSE)
IF(CATKIN_BUILD OR COLCON_BUILD)
SET(ROS_BUILD TRUE)
ENDIF()
IF(NOT ROS_BUILD)
#Standalone build
PROJECT( Find-Object )
ELSE()
#ROS build
PROJECT( find_object_2d )
MESSAGE(STATUS "ROS_DISTRO=$ENV{ROS_DISTRO}")
ENDIF()
# Catkin doesn't support multiarch library path,
# fix to "lib" if not set by user.
IF(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
ENDIF(NOT DEFINED CMAKE_INSTALL_LIBDIR)
INCLUDE(GNUInstallDirs)
####### local cmake modules #######
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
# Policy CMP0043 introduced in cmake version 3.0 IGNORES the use of COMPILE_DEFINITIONS suffixed variables, e.g. COMPILE_DEFINITIONS_DEBUG
# Set to OLD behavior until minimum cmake version >= 2.8.10 (version that COMPILE_DEFINITIONS can be set by generator expressions instead)
if (POLICY CMP0043)
cmake_policy(SET CMP0043 OLD)
endif (POLICY CMP0043)
# Policy CMP0042 introduced in cmake version 3.0 enables the use of @rpath in an install name via MACOSX_RPATH by default
# Set to OLD behavior so that all versions use the same behavior, or until minimum cmake version >= 2.8.12 (version where @rpath is available)
if (POLICY CMP0042)
cmake_policy(SET CMP0042 OLD)
endif (POLICY CMP0042)
#######################
# VERSION
#######################
SET(PROJECT_VERSION "0.7.0")
SET(PROJECT_PREFIX find_object)
STRING(REGEX MATCHALL "[0-9]" PROJECT_VERSION_PARTS "${PROJECT_VERSION}")
LIST(GET PROJECT_VERSION_PARTS 0 PROJECT_VERSION_MAJOR)
LIST(GET PROJECT_VERSION_PARTS 1 PROJECT_VERSION_MINOR)
LIST(GET PROJECT_VERSION_PARTS 2 PROJECT_VERSION_PATCH)
ADD_DEFINITIONS(-DPROJECT_PREFIX="${PROJECT_PREFIX}")
ADD_DEFINITIONS(-DPROJECT_VERSION="${PROJECT_VERSION}")
ADD_DEFINITIONS(-DPROJECT_NAME="${PROJECT_NAME}")
####### DEPENDENCIES #######
FIND_PACKAGE(OpenCV REQUIRED) # tested on 2.3.1
# check if version status is "-dev" (SIFT compatibility issue between 4.3.0 vs 4.3.0-dev)
FIND_FILE(OpenCV_VERSION_HPP opencv2/core/version.hpp
PATHS ${OpenCV_INCLUDE_DIRS}
NO_DEFAULT_PATH)
FILE(READ ${OpenCV_VERSION_HPP} TMPTXT)
STRING(FIND "${TMPTXT}" "-dev" matchres)
IF(NOT ${matchres} EQUAL -1)
add_definitions(-DOPENCV_DEV)
ENDIF(NOT ${matchres} EQUAL -1)
# For SuperPoint
SET(TORCH 0)
FIND_PACKAGE(Torch QUIET)
IF(TORCH_FOUND)
MESSAGE(STATUS "Found Torch: ${TORCH_INCLUDE_DIRS}")
SET(TORCH 1)
ENDIF(TORCH_FOUND)
IF(NOT MSVC)
IF(TORCH_FOUND)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
IF(COMPILER_SUPPORTS_CXX14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(CMAKE_CXX_STANDARD 14)
ELSE()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler if you want to use Torch.")
ENDIF()
ENDIF(TORCH_FOUND)
IF( NOT CMAKE_CXX_STANDARD AND OpenCV_VERSION_MAJOR EQUAL 4)
#Newest versions require std11
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
IF(COMPILER_SUPPORTS_CXX17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
ELSEIF(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
ELSEIF(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
ELSE()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
ENDIF()
ENDIF()
ENDIF()
# look for Qt5 before Qt4
FIND_PACKAGE(Qt5 COMPONENTS Widgets Core Gui Network QUIET)
IF(NOT Qt5_FOUND)
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
ENDIF(NOT Qt5_FOUND)
ADD_DEFINITIONS(-DQT_NO_KEYWORDS) # To avoid conflicts with boost signals used in ROS
FIND_PACKAGE(Tcmalloc QUIET)
FIND_PACKAGE(ZLIB REQUIRED QUIET)
SET(NONFREE 1)
IF(NOT (OPENCV_NONFREE_FOUND OR OPENCV_XFEATURES2D_FOUND))
SET(NONFREE 0)
ELSEIF(OpenCV_VERSION VERSION_GREATER "3.4.2")
FIND_FILE(OpenCV_MODULES_HPP opencv2/opencv_modules.hpp
PATHS ${OpenCV_INCLUDE_DIRS}
NO_DEFAULT_PATH)
FILE(READ ${OpenCV_MODULES_HPP} TMPTXT)
STRING(FIND "${TMPTXT}" "#define OPENCV_ENABLE_NONFREE" matchres)
IF(${matchres} EQUAL -1)
SET(NONFREE 0)
ENDIF(${matchres} EQUAL -1)
ENDIF()
CONFIGURE_FILE(Version.h.in ${PROJECT_SOURCE_DIR}/include/${PROJECT_PREFIX}/Version.h)
IF(NOT ROS_BUILD)
#Standalone build
IF(WIN32 AND NOT MINGW)
ADD_DEFINITIONS("-wd4251")
ELSE ()
ADD_DEFINITIONS( "-Wall" )
ENDIF()
#ADD_DEFINITIONS("-DUNICODE") # to test with UNICODE projects
####### COMPILATION PARAMS #######
# In case of Makefiles if the user does not setup CMAKE_BUILD_TYPE, assume it's Release:
IF(${CMAKE_GENERATOR} MATCHES ".*Makefiles")
IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE Release)
ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
ENDIF(${CMAKE_GENERATOR} MATCHES ".*Makefiles")
SET(CMAKE_DEBUG_POSTFIX "d")
####### Build libraries as shared or static #######
OPTION( BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON )
####### OUTPUT DIR #######
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
####### INSTALL DIR #######
# Offer the user the choice of overriding the installation directories
set(INSTALL_INCLUDE_DIR include/${PROJECT_PREFIX}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} CACHE PATH
"Installation directory for header files")
if(WIN32 AND NOT CYGWIN)
set(DEF_INSTALL_CMAKE_DIR CMake)
else()
set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_PREFIX}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR})
endif()
set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH
"Installation directory for CMake files")
####### OSX BUNDLE CMAKE_INSTALL_PREFIX #######
IF(APPLE)
OPTION(BUILD_AS_BUNDLE "Set to ON to build as bundle (DragNDrop)" OFF)
ENDIF(APPLE)
IF(APPLE AND BUILD_AS_BUNDLE)
# Required when packaging, and set CMAKE_INSTALL_PREFIX to "/".
SET(CPACK_SET_DESTDIR TRUE)
SET(CMAKE_BUNDLE_NAME
"${PROJECT_NAME}")
SET(CMAKE_BUNDLE_LOCATION "/")
# make sure CMAKE_INSTALL_PREFIX ends in /
SET(CMAKE_INSTALL_PREFIX
"/${CMAKE_BUNDLE_NAME}.app/Contents")
ENDIF(APPLE AND BUILD_AS_BUNDLE)
####### SOURCES (Projects) #######
ADD_SUBDIRECTORY( src )
ADD_SUBDIRECTORY( app )
ADD_SUBDIRECTORY( tools )
IF(NONFREE OR OpenCV_VERSION VERSION_GREATER "4.2.0") # SIFT is free from 4.3.0
ADD_SUBDIRECTORY( example )
ENDIF(NONFREE OR OpenCV_VERSION VERSION_GREATER "4.2.0")
#######################
# Uninstall target, for "make uninstall"
#######################
CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
ADD_CUSTOM_TARGET(uninstall
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
#######################
# Setup FindObjectConfig.cmake
#######################
# Create the FindObjectConfig.cmake and FindObjectConfigVersion files
file(RELATIVE_PATH REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}")
file(RELATIVE_PATH REL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
# ... for the build tree
set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include")
set(CONF_LIB_DIR "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}")
configure_file(FindObjectConfig.cmake.in
"${PROJECT_BINARY_DIR}/FindObjectConfig.cmake" @ONLY)
# ... for the install tree
set(CONF_INCLUDE_DIRS "\${FindObject_CMAKE_DIR}/${REL_INCLUDE_DIR}")
set(CONF_LIB_DIR "\${FindObject_CMAKE_DIR}/${REL_LIB_DIR}")
configure_file(FindObjectConfig.cmake.in
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindObjectConfig.cmake" @ONLY)
# ... for both
configure_file(FindObjectConfigVersion.cmake.in
"${PROJECT_BINARY_DIR}/FindObjectConfigVersion.cmake" @ONLY)
# Install the FindObjectConfig.cmake and FindObjectConfigVersion.cmake
install(FILES
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindObjectConfig.cmake"
"${PROJECT_BINARY_DIR}/FindObjectConfigVersion.cmake"
DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT devel)
####
#######################
# CPACK (Packaging)
#######################
INCLUDE(InstallRequiredSystemLibraries)
SET(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
SET(CPACK_PACKAGE_VENDOR "${PROJECT_NAME} project")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Find-Object")
SET(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
SET(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
SET(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
SET(CPACK_PACKAGE_CONTACT "matlabbe@gmail.com")
set(CPACK_SOURCE_IGNORE_FILES
"\\\\.svn/"
"${PROJECT_SOURCE_DIR}/build/[a-zA-Z0-9_]+"
"~$"
"${PROJECT_SOURCE_DIR}/bin/.*${PROJECT_PREFIX}"
"${PROJECT_SOURCE_DIR}/bin/.*${PROJECT_NAME}"
"\\\\.DS_Store"
)
IF(WIN32)
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
IF(CMAKE_CL_64)
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
ELSE()
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
ENDIF()
SET(CPACK_GENERATOR "ZIP;NSIS")
SET(CPACK_SOURCE_GENERATOR "ZIP")
SET(CPACK_NSIS_PACKAGE_NAME "${PROJECT_NAME}")
SET(ICON_PATH "${PROJECT_SOURCE_DIR}/app/${PROJECT_NAME}.ico")
SET(CPACK_NSIS_MUI_ICON ${ICON_PATH})
SET(CPACK_NSIS_MUI_UNIICON ${ICON_PATH})
SET(CPACK_NSIS_DISPLAY_NAME "${PROJECT_NAME}")
SET(CPACK_NSIS_CONTACT ${CPACK_PACKAGE_CONTACT})
# Set the icon used for the Windows "Add or Remove Programs" tool.
SET(CPACK_NSIS_INSTALLED_ICON_NAME bin\\\\${PROJECT_NAME}.exe)
SET(CPACK_PACKAGE_EXECUTABLES "${PROJECT_NAME}" "${PROJECT_NAME}" ${CPACK_PACKAGE_EXECUTABLES})
SET(CPACK_CREATE_DESKTOP_LINKS "${PROJECT_NAME}" ${CPACK_CREATE_DESKTOP_LINKS})
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}")
ELSEIF(APPLE)
IF(BUILD_AS_BUNDLE)
# On APPLE and if BUILD_AS_BUNDLE=ON, the project is created as a bundle
# over the main app (see ./src).Here we package only this bundle. Note
# that we set CMAKE_INSTALL_PREFIX to "/" when packaging to DragNDrop...
SET(CPACK_GENERATOR "DragNDrop")
ELSE()
SET(CPACK_GENERATOR "PackageMaker;TBZ2")
ENDIF()
SET(CPACK_SOURCE_GENERATOR "TBZ2")
SET(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/app/${PROJECT_NAME}.icns")
ELSE()
SET(CPACK_SOURCE_GENERATOR "ZIP")
ENDIF()
INCLUDE(CPack)
#######################
# OUTPUT INFO
#######################
MESSAGE(STATUS "--------------------------------------------")
MESSAGE(STATUS "Info :")
MESSAGE(STATUS " CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
MESSAGE(STATUS " CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
MESSAGE(STATUS " PROJECT_VERSION = ${PROJECT_VERSION}")
IF(OpenCV_VERSION_MAJOR EQUAL 2)
IF(OPENCV_NONFREE_FOUND)
MESSAGE(STATUS " With OpenCV 2 nonfree module (SIFT/SURF) = YES")
ELSE()
MESSAGE(STATUS " With OpenCV 2 nonfree module (SIFT/SURF) = NO (not found)")
ENDIF()
ELSE()
IF(OPENCV_XFEATURES2D_FOUND)
MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} xfeatures2d module (BRIEF/FREAK/KAZE) = YES")
ELSE()
MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} xfeatures2d module (BRIEF/FREAK/KAZE) = NO (not found)")
ENDIF()
IF(OpenCV_VERSION VERSION_GREATER "4.2.0")
IF(NONFREE)
MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} nonfree module (SURF) = YES")
ELSE()
MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} nonfree module (SURF) = NO")
ENDIF()
ELSEIF()
IF(NONFREE)
MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} nonfree module (SIFT/SURF) = YES")
ELSE()
MESSAGE(STATUS " With OpenCV ${OpenCV_VERSION} nonfree module (SIFT/SURF) = NO")
ENDIF()
ENDIF()
ENDIF()
IF(QT4_FOUND)
MESSAGE(STATUS " With Qt4 = YES")
ELSEIF(Qt5_FOUND)
MESSAGE(STATUS " With Qt5 = YES")
ELSE()
MESSAGE(STATUS " With Qt = NO (Qt not found)")
ENDIF()
IF(Tcmalloc_FOUND)
MESSAGE(STATUS " With tcmalloc = YES")
ELSE()
MESSAGE(STATUS " With tcmalloc = NO (tcmalloc not found)")
ENDIF(Tcmalloc_FOUND)
IF(TORCH_FOUND)
MESSAGE(STATUS " With Torch = YES")
ELSE()
MESSAGE(STATUS " With Torch = NO (libtorch not found)")
ENDIF(TORCH_FOUND)
IF(APPLE)
MESSAGE(STATUS " BUILD_AS_BUNDLE = ${BUILD_AS_BUNDLE}")
ENDIF(APPLE)
MESSAGE(STATUS "--------------------------------------------")
ELSEIF(CATKIN_BUILD)
#ROS Catkin build
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
cv_bridge roscpp sensor_msgs std_msgs image_transport message_filters tf message_generation
)
## Generate messages in the 'msg' folder
add_message_files(
FILES
ObjectsStamped.msg
DetectionInfo.msg
)
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
std_msgs
sensor_msgs
)
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if you package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
CATKIN_DEPENDS cv_bridge roscpp sensor_msgs std_msgs image_transport message_filters tf message_runtime
DEPENDS OpenCV
)
###########
## Build ##
###########
ADD_SUBDIRECTORY( src )
#############
## Install ##
#############
## Mark other files for installation (e.g. launch and bag files, etc.)
install(DIRECTORY
launch/ros1
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
)
ELSE() # COLCON_BUILD
#ROS Colcon build
find_package(ament_cmake REQUIRED)
find_package(builtin_interfaces REQUIRED)
find_package(rosidl_default_generators REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(cv_bridge REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(std_msgs REQUIRED)
find_package(image_transport REQUIRED)
find_package(message_filters REQUIRED)
find_package(tf2 REQUIRED)
find_package(tf2_ros REQUIRED)
find_package(tf2_geometry_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
## Generate messages and services
rosidl_generate_interfaces(${PROJECT_NAME}
msg/ObjectsStamped.msg
msg/DetectionInfo.msg
DEPENDENCIES std_msgs sensor_msgs
)
ament_export_dependencies(rosidl_default_runtime)
###########
## Build ##
###########
ADD_SUBDIRECTORY( src )
#############
## Install ##
#############
install(DIRECTORY
launch/ros2/.
DESTINATION share/${PROJECT_NAME}/launch
)
ament_package()
ENDIF()
-10
View File
@@ -1,10 +0,0 @@
# - Config file for the FindObject package
# It defines the following variables
# FindObject_INCLUDE_DIRS - include directories for FindObject
# FindObject_LIBRARIES - libraries to link against
# Compute paths
get_filename_component(FindObject_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(FindObject_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@")
find_library(FindObject_LIBRARIES NAMES find_object NO_DEFAULT_PATH HINTS "@CONF_LIB_DIR@")
@@ -1,11 +0,0 @@
set(PACKAGE_VERSION "@PROJECT_VERSION@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
-27
View File
@@ -1,27 +0,0 @@
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
-92
View File
@@ -1,92 +0,0 @@
# find-object
<table>
<tbody>
<tr>
<td>Linux</td>
<td><a href="https://github.com/introlab/find-object/actions/workflows/cmake.yml"><img src="https://github.com/introlab/find-object/actions/workflows/cmake.yml/badge.svg" alt="Build Status"/> <br> <a href="https://github.com/introlab/find-object/actions/workflows/ros1.yml"><img src="https://github.com/introlab/find-object/actions/workflows/ros1.yml/badge.svg" alt="Build Status"/> <br> <a href="https://github.com/introlab/find-object/actions/workflows/ros2.yml"><img src="https://github.com/introlab/find-object/actions/workflows/ros2.yml/badge.svg" alt="Build Status"/>
</td>
</tr>
<tr>
<td>Windows</td>
<td><a href="https://ci.appveyor.com/project/matlabbe/find-object/branch/master"><img src="https://ci.appveyor.com/api/projects/status/hn51r6p5c0peqctb/branch/master?svg=true" alt="Build Status"/>
</td>
</tr>
</tbody>
</table>
## Standalone
Find-Object project, visit the [home page](http://introlab.github.io/find-object/) for more information.
## ROS1
### Install
Binaries:
```bash
sudo apt-get install ros-$ROS_DISTRO-find-object-2d
```
Source:
* To include `xfeatures2d` and/or `nonfree` modules of OpenCV, to avoid conflicts with `cv_bridge`, build same OpenCV version that is used by `cv_bridge`. Install it in `/usr/local` (default).
```bash
cd ~/catkin_ws
git clone https://github.com/introlab/find-object.git src/find_object_2d
catkin_make
```
### Run
```bash
roscore
# Launch your preferred usb camera driver
rosrun uvc_camera uvc_camera_node
rosrun find_object_2d find_object_2d image:=image_raw
```
See [find_object_2d](http://wiki.ros.org/find_object_2d) for more information.
## ROS2
### Install
Binaries:
```bash
To come...
```
Source:
```bash
cd ~/ros2_ws
git clone https://github.com/introlab/find-object.git src/find_object_2d
colcon build
```
### Run
```bash
# Launch your preferred usb camera driver
ros2 launch realsense2_camera rs_launch.py
# Launch find_object_2d node:
ros2 launch find_object_2d find_object_2d.launch.py image:=/camera/color/image_raw
# Draw objects detected on an image:
ros2 run find_object_2d print_objects_detected --ros-args -r image:=/camera/color/image_raw
```
#### 3D Pose (TF)
A RGB-D camera is required. Example with Realsense D400 camera:
```bash
# Launch your preferred usb camera driver
ros2 launch realsense2_camera rs_launch.py align_depth.enable:=true
# Launch find_object_2d node:
ros2 launch find_object_2d find_object_3d.launch.py \
rgb_topic:=/camera/color/image_raw \
depth_topic:=/camera/aligned_depth_to_color/image_raw \
camera_info_topic:=/camera/color/camera_info
# Show 3D pose in camera frame:
ros2 run find_object_2d tf_example
```
See [find_object_2d](http://wiki.ros.org/find_object_2d) for more information (same parameters/topics are used between ROS1 and ROS2 versions).
-44
View File
@@ -1,44 +0,0 @@
/*
Copyright (c) 2010-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 VERSION_H_
#define VERSION_H_
// This is auto-generated!
#define FINDOBJECT_VERSION "@PROJECT_VERSION@"
#define FINDOBJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define FINDOBJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define FINDOBJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define FINDOBJECT_VERSION_COMPARE(major, minor, patch) (major>=@PROJECT_VERSION_MAJOR@ || (major==@PROJECT_VERSION_MAJOR@ && minor>=@PROJECT_VERSION_MINOR@) || (major==@PROJECT_VERSION_MAJOR@ && minor==@PROJECT_VERSION_MINOR@ && patch >=@PROJECT_VERSION_PATCH@))
#define FINDOBJECT_NONFREE @NONFREE@
#define FINDOBJECT_TORCH @TORCH@
#endif /* VERSION_H_ */
-164
View File
@@ -1,164 +0,0 @@
SET(headers_ui
TcpServerPool.h
)
IF(QT4_FOUND)
QT4_WRAP_CPP(moc_srcs ${headers_ui})
ELSE()
QT5_WRAP_CPP(moc_srcs ${headers_ui})
ENDIF()
SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../include
${CMAKE_CURRENT_SOURCE_DIR}
${OpenCV_INCLUDE_DIRS}
)
IF(QT4_FOUND)
INCLUDE(${QT_USE_FILE})
ENDIF(QT4_FOUND)
SET(LIBRARIES
${QT_LIBRARIES}
${OpenCV_LIBS}
)
if(Tcmalloc_FOUND)
SET(LIBRARIES
${LIBARIES}
${Tcmalloc_LIBRARIES}
)
endif(Tcmalloc_FOUND)
#include files
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
SET(SRC_FILES main.cpp ${moc_srcs} )
# For Apple set the icns file containing icons
IF(APPLE AND BUILD_AS_BUNDLE)
# set how it shows up in the Info.plist file
SET(MACOSX_BUNDLE_ICON_FILE ${PROJECT_NAME}.icns)
# set where in the bundle to put the icns file
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
# include the icns file in the target
SET(SRC_FILES ${SRC_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.icns)
ENDIF(APPLE AND BUILD_AS_BUNDLE)
# Add exe icon resource
IF(WIN32)
IF( MINGW )
# resource compilation for MinGW
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o
COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR} -i${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.rc
-o ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o )
SET(SRC_FILES ${SRC_FILES} ${CMAKE_CURRENT_BINARY_DIR}/AppIco.o)
ELSE( MINGW )
SET(SRC_FILES ${SRC_FILES} ${PROJECT_NAME}.rc) # Error on visual studio 2008
ENDIF( MINGW )
ENDIF(WIN32)
# create an executable file
IF(APPLE AND BUILD_AS_BUNDLE)
ADD_EXECUTABLE(find_object_app MACOSX_BUNDLE ${SRC_FILES})
ELSEIF(MINGW)
ADD_EXECUTABLE(find_object_app WIN32 ${SRC_FILES})
ELSE()
ADD_EXECUTABLE(find_object_app ${SRC_FILES})
ENDIF()
# Linking with Qt libraries
TARGET_LINK_LIBRARIES(find_object_app find_object ${LIBRARIES})
IF(Qt5_FOUND)
QT5_USE_MODULES(find_object_app Widgets Core Gui Network PrintSupport)
ENDIF(Qt5_FOUND)
IF(APPLE AND BUILD_AS_BUNDLE)
SET_TARGET_PROPERTIES(find_object_app PROPERTIES
OUTPUT_NAME ${CMAKE_BUNDLE_NAME})
ELSEIF(WIN32)
SET_TARGET_PROPERTIES(find_object_app PROPERTIES
OUTPUT_NAME ${PROJECT_NAME})
ELSE()
SET_TARGET_PROPERTIES(find_object_app PROPERTIES
OUTPUT_NAME ${PROJECT_PREFIX})
ENDIF()
#---------------------------
# Installation stuff
#---------------------------
INSTALL(TARGETS find_object_app
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
#---------------------------
# Dependencies packaging
#---------------------------
IF(APPLE AND BUILD_AS_BUNDLE)
INSTALL(CODE "execute_process(COMMAND ln -s \"../MacOS/${CMAKE_BUNDLE_NAME}\" ${PROJECT_NAME}
WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)")
ENDIF(APPLE AND BUILD_AS_BUNDLE)
IF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
SET(plugin_dest_dir bin)
SET(qtconf_dest_dir bin)
IF(APPLE)
SET(plugin_dest_dir MacOS)
SET(qtconf_dest_dir Resources)
SET(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/${CMAKE_BUNDLE_NAME}")
ENDIF(APPLE)
# Install needed Qt plugins by copying directories from the qt installation
# One can cull what gets copied by using 'REGEX "..." EXCLUDE'
# Exclude debug libraries
IF(QT_PLUGINS_DIR)
INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats"
DESTINATION ${plugin_dest_dir}/plugins
COMPONENT runtime
REGEX ".*d4.dll" EXCLUDE
REGEX ".*d4.a" EXCLUDE)
ELSE()
#Qt5
foreach(plugin ${Qt5Gui_PLUGINS})
get_target_property(plugin_loc ${plugin} LOCATION)
get_filename_component(plugin_dir ${plugin_loc} DIRECTORY)
string(REPLACE "plugins" ";" loc_list ${plugin_dir})
list(GET loc_list 1 plugin_type)
#MESSAGE(STATUS "Qt5 plugin \"${plugin_loc}\" installed in \"${plugin_dest_dir}/plugins${plugin_type}\"")
INSTALL(FILES ${plugin_loc}
DESTINATION ${plugin_dest_dir}/plugins${plugin_type}
COMPONENT runtime)
endforeach()
ENDIF()
# install a qt.conf file
# this inserts some cmake code into the install script to write the file
SET(QT_CONF_FILE [Paths]\nPlugins=plugins)
IF(APPLE)
SET(QT_CONF_FILE [Paths]\nPlugins=MacOS/plugins)
ENDIF(APPLE)
INSTALL(CODE "
file(WRITE \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"${QT_CONF_FILE}\")
" COMPONENT runtime)
# directories to look for dependencies
SET(DIRS ${QT_LIBRARY_DIRS} ${PROJECT_SOURCE_DIR}/bin)
IF(APPLE)
SET(DIRS ${DIRS} /usr/local /usr/local/lib)
ENDIF(APPLE)
# Now the work of copying dependencies into the bundle/package
# The quotes are escaped and variables to use at install time have their $ escaped
# An alternative is the do a configure_file() on a script and use install(SCRIPT ...).
# Note that the image plugins depend on QtSvg and QtXml, and it got those copied
# over.
# To find dependencies, cmake use "otool" on Apple and "dumpbin" on Windows (make sure you have one of them).
install(CODE "
file(GLOB_RECURSE QTPLUGINS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/plugins/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
include(\"BundleUtilities\")
fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
" COMPONENT runtime)
ENDIF((APPLE AND BUILD_AS_BUNDLE) OR WIN32)
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.
-1
View File
@@ -1 +0,0 @@
IDI_ICON1 ICON DISCARDABLE "Find-Object.ico"
-127
View File
@@ -1,127 +0,0 @@
/*
* TcpServerPool.h
*
* Created on: Nov 29, 2015
* Author: mathieu
*/
#ifndef TCPSERVERPOOL_H_
#define TCPSERVERPOOL_H_
#include <find_object/FindObject.h>
#include <find_object/TcpServer.h>
#include <find_object/utilite/ULogger.h>
#include <QtCore/QThread>
#include <QtCore/QSemaphore>
class FindObjectWorker : public QObject
{
Q_OBJECT;
public:
FindObjectWorker(
find_object::FindObject * sharedFindObject,
QSemaphore * sharedSemaphore,
int maxSemaphoreResources,
QObject * parent = 0) :
QObject(parent),
sharedFindObject_(sharedFindObject),
sharedSemaphore_(sharedSemaphore),
maxSemaphoreResources_(maxSemaphoreResources)
{
UASSERT(sharedFindObject != 0);
UASSERT(sharedSemaphore != 0);
UASSERT(maxSemaphoreResources > 0);
}
public Q_SLOTS:
void detect(const cv::Mat & image)
{
sharedSemaphore_->acquire(1);
UINFO("Thread %p detecting...", (void *)this->thread());
find_object::DetectionInfo info;
sharedFindObject_->detect(image, info);
Q_EMIT objectsFound(info);
sharedSemaphore_->release(1);
}
void addObjectAndUpdate(const cv::Mat & image, int id, const QString & filePath)
{
//block everyone!
sharedSemaphore_->acquire(maxSemaphoreResources_);
UINFO("Thread %p adding object %d (%s)...", (void *)this->thread(), id, filePath.toStdString().c_str());
sharedFindObject_->addObjectAndUpdate(image, id, filePath);
sharedSemaphore_->release(maxSemaphoreResources_);
}
void removeObjectAndUpdate(int id)
{
//block everyone!
sharedSemaphore_->acquire(maxSemaphoreResources_);
UINFO("Thread %p removing object %d...", (void *)this->thread(), id);
sharedFindObject_->removeObjectAndUpdate(id);
sharedSemaphore_->release(maxSemaphoreResources_);
}
Q_SIGNALS:
void objectsFound(const find_object::DetectionInfo &);
private:
find_object::FindObject * sharedFindObject_; //shared findobject
QSemaphore * sharedSemaphore_;
int maxSemaphoreResources_;
};
class TcpServerPool : public QObject
{
Q_OBJECT;
public:
TcpServerPool(find_object::FindObject * sharedFindObject, int threads, int port) :
sharedSemaphore_(threads)
{
UASSERT(sharedFindObject != 0);
UASSERT(threads>=1);
qRegisterMetaType<cv::Mat>("cv::Mat");
threadPool_.resize(threads);
for(int i=0; i<threads; ++i)
{
find_object::TcpServer * tcpServer = new find_object::TcpServer(port!=0?port++:0);
UINFO("TcpServer set on port: %d (IP=%s)",
tcpServer->getPort(),
tcpServer->getHostAddress().toString().toStdString().c_str());
threadPool_[i] = new QThread(this);
FindObjectWorker * worker = new FindObjectWorker(sharedFindObject, &sharedSemaphore_, threads);
tcpServer->moveToThread(threadPool_[i]);
worker->moveToThread(threadPool_[i]);
connect(threadPool_[i], SIGNAL(finished()), tcpServer, SLOT(deleteLater()));
connect(threadPool_[i], SIGNAL(finished()), worker, SLOT(deleteLater()));
// connect stuff:
QObject::connect(worker, SIGNAL(objectsFound(find_object::DetectionInfo)), tcpServer, SLOT(publishDetectionInfo(find_object::DetectionInfo)));
QObject::connect(tcpServer, SIGNAL(detectObject(const cv::Mat &)), worker, SLOT(detect(const cv::Mat &)));
QObject::connect(tcpServer, SIGNAL(addObject(const cv::Mat &, int, const QString &)), worker, SLOT(addObjectAndUpdate(const cv::Mat &, int, const QString &)));
QObject::connect(tcpServer, SIGNAL(removeObject(int)), worker, SLOT(removeObjectAndUpdate(int)));
threadPool_[i]->start();
}
}
virtual ~TcpServerPool()
{
for(int i=0; i<threadPool_.size(); ++i)
{
threadPool_[i]->quit();
threadPool_[i]->wait();
}
}
private:
QVector<QThread*> threadPool_;
QSemaphore sharedSemaphore_;
};
#endif /* TCPSERVERPOOL_H_ */
-685
View File
@@ -1,685 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include <QApplication>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <iostream>
#include <iomanip>
#include "find_object/MainWindow.h"
#include "find_object/Settings.h"
#include "find_object/FindObject.h"
#include "find_object/Camera.h"
#include "find_object/TcpServer.h"
#include "find_object/JsonWriter.h"
#include "find_object/utilite/ULogger.h"
#include "TcpServerPool.h"
bool running = true;
#ifdef WIN32
#include <windows.h>
BOOL WINAPI my_handler(DWORD signal)
{
if (signal == CTRL_C_EVENT)
{
printf("\nCtrl-C caught! Quitting application...\n");
QCoreApplication::quit();
}
return TRUE;
running = false;
}
#else
#include <signal.h>
void my_handler(int s)
{
printf("\nCtrl-C caught! Quitting application...\n");
QCoreApplication::quit();
running = false;
}
inline void Sleep(unsigned int ms)
{
struct timespec req;
struct timespec rem;
req.tv_sec = ms / 1000;
req.tv_nsec = (ms - req.tv_sec * 1000) * 1000 * 1000;
nanosleep (&req, &rem);
}
#endif
void setupQuitSignal()
{
// Catch ctrl-c to close Qt
#ifdef WIN32
if (!SetConsoleCtrlHandler(my_handler, TRUE))
{
UERROR("Could not set control (ctrl-c) handler");
}
#else
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
#endif
}
void showUsage()
{
printf("\nUsage:\n"
#ifdef WIN32
" Find-Object.exe [options]\n"
#else
" find_object [options]\n"
#endif
"Options:\n"
" --console Don't use the GUI (by default the camera will be\n"
" started automatically). Option --objects must also be\n"
" used with valid objects.\n"
" --session \"path\" Path to a session to load (*.bin). Use \"--session_new\" to\n"
" create a session instead (will be saved to \"path\" on exit, only\n"
" on console mode).\n"
" --object \"path\" Path to an object to detect.\n"
" --objects \"path\" Directory of the objects to detect (--object is ignored).\n"
" --config \"path\" Path to configuration file (default: %s).\n"
" If set to \"\", default parameters are used\n"
" without saving modified parameters on closing.\n"
" --scene \"path\" Path to a scene image file.\n"
" --vocabulary \"path\" Path to a vocabulary file (*.yaml *.xml). Parameters \"General/invertedSearch\"\n"
" and \"General/vocabularyFixed\" will be also enabled. Ignored if \"--session\" is set.\n"
" --images_not_saved Don't keep images in RAM after the features are extracted (only\n"
" in console mode). Images won't be saved if an output session is set.\n"
" --tcp_threads # Number of TCP threads (default 1, only in --console mode). \"--General/port\" parameter should not be 0.\n"
" Port numbers start from \"General/port\" value. \"Detect\" TCP service can be\n"
" executed at the same time by multiple threads. \"Add/Remove\" TCP services\n"
" cannot be called by multiple threads, so calling these services on a port\n "
" will block all other threads on the other ports.\n"
" --debug Show debug log.\n"
" --log-time Show log with time.\n"
" --params Show all parameters.\n"
" --defaults Use default parameters (--config is ignored).\n"
" --My/Parameter \"value\" Set find-Object's parameter (look --params for parameters' name).\n"
" It will override the one in --config. Example to set 4 threads:\n"
" $ find_object --General/threads 4\n"
" --json \"path\" Path to an output JSON file (only in --console mode with --scene).\n"
" --help Show usage.\n"
, find_object::Settings::iniDefaultPath().toStdString().c_str());
exit(-1);
}
int main(int argc, char* argv[])
{
ULogger::setType(ULogger::kTypeConsole);
ULogger::setLevel(ULogger::kInfo);
ULogger::setPrintWhere(false);
ULogger::setPrintTime(false);
//////////////////////////
// parse options BEGIN
//////////////////////////
bool guiMode = true;
QString sessionPath = "";
bool sessionNew = false;
QString objectsPath = "";
QString objectPath = "";
QString scenePath = "";
QString configPath = "";
QString vocabularyPath = "";
QString jsonPath;
find_object::ParametersMap customParameters;
bool imagesSaved = true;
int tcpThreads = 1;
for(int i=1; i<argc; ++i)
{
#ifdef __APPLE__
if(QString(argv[i]).startsWith("-psn"))
{
//safely ignore
continue;
}
#endif
if(strcmp(argv[i], "-objs") == 0 ||
strcmp(argv[i], "--objs") == 0 ||
strcmp(argv[i], "-objects") == 0 ||
strcmp(argv[i], "--objects") == 0)
{
++i;
if(i < argc)
{
objectsPath = argv[i];
if(objectsPath.contains('~'))
{
objectsPath.replace('~', QDir::homePath());
}
if(!QDir(objectsPath).exists())
{
UERROR("Objects path not valid : %s", objectsPath.toStdString().c_str());
showUsage();
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-session") == 0 ||
strcmp(argv[i], "--session") == 0 ||
strcmp(argv[i], "-session_new") == 0 ||
strcmp(argv[i], "--session_new") == 0)
{
if(strcmp(argv[i], "-session_new") == 0 ||
strcmp(argv[i], "--session_new") == 0)
{
sessionNew = true;
}
++i;
if(i < argc)
{
sessionPath = argv[i];
if(sessionPath.contains('~'))
{
sessionPath.replace('~', QDir::homePath());
}
if(!sessionNew && !QFile(sessionPath).exists())
{
UERROR("Session path not valid : %s (if you want to create a new session, use \"--session_new\")", sessionPath.toStdString().c_str());
showUsage();
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-object") == 0 ||
strcmp(argv[i], "--object") == 0)
{
++i;
if(i < argc)
{
objectPath = argv[i];
if(objectPath.contains('~'))
{
objectPath.replace('~', QDir::homePath());
}
if(!QFile(objectPath).exists())
{
UERROR("Object path not valid : %s", objectPath.toStdString().c_str());
showUsage();
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-scene") == 0 ||
strcmp(argv[i], "--scene") == 0)
{
++i;
if(i < argc)
{
scenePath = argv[i];
if(scenePath.contains('~'))
{
scenePath.replace('~', QDir::homePath());
}
if(!QFile(scenePath).exists())
{
UERROR("Scene path not valid : %s", scenePath.toStdString().c_str());
showUsage();
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-vocabulary") == 0 ||
strcmp(argv[i], "--vocabulary") == 0)
{
++i;
if(i < argc)
{
vocabularyPath = argv[i];
if(vocabularyPath.contains('~'))
{
vocabularyPath.replace('~', QDir::homePath());
}
if(!QFile(vocabularyPath).exists())
{
UERROR("Vocabulary path not valid : %s", vocabularyPath.toStdString().c_str());
showUsage();
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-config") == 0 ||
strcmp(argv[i], "--config") == 0)
{
++i;
if(i < argc)
{
configPath = argv[i];
if(configPath.contains('~'))
{
configPath.replace('~', QDir::homePath());
}
if(!configPath.isEmpty() && !QFile::exists(configPath))
{
UWARN("Configuration file \"%s\" doesn't exist, it will be created with default values...", configPath.toStdString().c_str());
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-console") == 0 ||
strcmp(argv[i], "--console") == 0)
{
guiMode = false;
continue;
}
if(strcmp(argv[i], "-images_not_saved") == 0 ||
strcmp(argv[i], "--images_not_saved") == 0)
{
imagesSaved = false;
continue;
}
if(strcmp(argv[i], "-debug") == 0 ||
strcmp(argv[i], "--debug") == 0)
{
customParameters.insert(find_object::Settings::kGeneral_debug(), true);
continue;
}
if(strcmp(argv[i], "-log-time") == 0 ||
strcmp(argv[i], "--log-time") == 0)
{
ULogger::setPrintWhere(true);
ULogger::setPrintTime(true);
continue;
}
if(strcmp(argv[i], "-help") == 0 ||
strcmp(argv[i], "--help") == 0)
{
showUsage();
}
if(strcmp(argv[i], "-json") == 0 ||
strcmp(argv[i], "--json") == 0)
{
++i;
if(i < argc)
{
jsonPath = argv[i];
if(jsonPath.contains('~'))
{
jsonPath.replace('~', QDir::homePath());
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "-tcp_threads") == 0 ||
strcmp(argv[i], "--tcp_threads") == 0)
{
++i;
if(i < argc)
{
tcpThreads = atoi(argv[i]);
if(tcpThreads < 1)
{
printf("tcp_threads should be >= 1!\n");
showUsage();
}
}
else
{
showUsage();
}
continue;
}
if(strcmp(argv[i], "--params") == 0)
{
find_object::ParametersMap parameters = find_object::Settings::getDefaultParameters();
for(find_object::ParametersMap::iterator iter=parameters.begin(); iter!=parameters.end(); ++iter)
{
std::string str = "Param: " + iter.key().toStdString() + " = \"" + iter.value().toString().toStdString() + "\"";
std::cout <<
str <<
std::setw(60 - str.size()) <<
" [" <<
find_object::Settings::getDescriptions().value(iter.key()).toStdString().c_str() <<
"]" <<
std::endl;
}
UINFO("Node will now exit after showing default Find-Object's parameters because "
"argument \"--params\" is detected!");
exit(0);
}
// Check for custom parameters:
find_object::ParametersMap parameters = find_object::Settings::getDefaultParameters();
QString name = argv[i];
if(name.size() > 2)
{
//strip the "--"
name.remove(0, 2);
if(parameters.contains(name))
{
++i;
if(i < argc)
{
customParameters.insert(name, argv[i]);
}
else
{
showUsage();
}
continue;
}
}
UERROR("Unrecognized option : %s", argv[i]);
showUsage();
}
UINFO("Options:");
UINFO(" GUI mode = %s", guiMode?"true":"false");
if(!sessionPath.isEmpty())
{
if(sessionNew)
{
UINFO(" Session path: \"%s\" [NEW]", sessionPath.toStdString().c_str());
if(configPath.isEmpty() && guiMode)
{
configPath = find_object::Settings::iniDefaultPath();
}
}
else
{
UINFO(" Session path: \"%s\"", sessionPath.toStdString().c_str());
if(!vocabularyPath.isEmpty())
{
UWARN("Vocabulary \"%s\" is not loaded as a session \"%s\" is already "
"loaded, ignoring vocabulary file...",
vocabularyPath.toStdString().c_str(),
sessionPath.toStdString().c_str());
vocabularyPath.clear();
}
if(!configPath.isEmpty())
{
UWARN("A session \"%s\" is loaded and a config file is also used, "
"the parameters of the session will be overwritten by "
"those in the config file \"%s\".",
sessionPath.toStdString().c_str(),
configPath.toStdString().c_str());
}
}
}
else if(configPath.isEmpty() && guiMode)
{
configPath = find_object::Settings::iniDefaultPath();
}
if(!objectsPath.isEmpty())
{
UINFO(" Objects path: \"%s\"", objectsPath.toStdString().c_str());
}
else if(!objectPath.isEmpty())
{
UINFO(" Object path: \"%s\"", objectPath.toStdString().c_str());
}
UINFO(" Scene path: \"%s\"", scenePath.toStdString().c_str());
if(!guiMode)
{
UINFO(" JSON path: \"%s\"", jsonPath.toStdString().c_str());
}
UINFO(" Settings path: \"%s\"", configPath.toStdString().c_str());
UINFO(" Vocabulary path: \"%s\"", vocabularyPath.toStdString().c_str());
if(!vocabularyPath.isEmpty())
{
if(customParameters.contains(find_object::Settings::kGeneral_vocabularyFixed()))
{
UWARN("\"General/vocabularyFixed\" custom parameter overwritten as a fixed vocabulary is used.");
}
if(customParameters.contains(find_object::Settings::kGeneral_invertedSearch()))
{
UWARN("\"General/invertedSearch\" custom parameter overwritten as a fixed vocabulary is used.");
}
customParameters[find_object::Settings::kGeneral_vocabularyFixed()] = true;
customParameters[find_object::Settings::kGeneral_invertedSearch()] = true;
}
for(find_object::ParametersMap::iterator iter= customParameters.begin(); iter!=customParameters.end(); ++iter)
{
UINFO(" Param \"%s\"=\"%s\"", iter.key().toStdString().c_str(), iter.value().toString().toStdString().c_str());
}
//////////////////////////
// parse options END
//////////////////////////
// Load settings, should be loaded before creating other objects
find_object::ParametersMap parameters;
if(!configPath.isEmpty())
{
parameters = find_object::Settings::init(configPath);
}
// Override custom parameters:
for(find_object::ParametersMap::iterator iter= customParameters.begin(); iter!=customParameters.end(); ++iter)
{
find_object::Settings::setParameter(iter.key(), iter.value());
parameters.insert(iter.key(), iter.value());
}
// Create FindObject
find_object::FindObject * findObject = new find_object::FindObject(guiMode || imagesSaved);
// Load objects if path is set
int objectsLoaded = 0;
if(!sessionPath.isEmpty() && !sessionNew)
{
if(!findObject->loadSession(sessionPath, parameters))
{
UERROR("Could not load session \"%s\"", sessionPath.toStdString().c_str());
}
else
{
objectsLoaded = findObject->objects().size();
}
}
else if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath))
{
UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str());
}
if(!objectsPath.isEmpty())
{
if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath))
{
UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str());
}
objectsLoaded = findObject->loadObjects(objectsPath);
if(!objectsLoaded)
{
UWARN("No objects loaded from \"%s\"", objectsPath.toStdString().c_str());
}
}
else if(!objectPath.isEmpty())
{
if(!vocabularyPath.isEmpty() && !findObject->loadVocabulary(vocabularyPath))
{
UERROR("Failed to load vocabulary \"%s\"", vocabularyPath.toStdString().c_str());
}
const find_object::ObjSignature * obj = findObject->addObject(objectPath);
if(obj)
{
++objectsLoaded;
findObject->updateObjects();
findObject->updateVocabulary();
}
else
{
UWARN("No object loaded from \"%s\"", objectsPath.toStdString().c_str());
}
}
cv::Mat scene;
if(!scenePath.isEmpty())
{
scene = cv::imread(scenePath.toStdString());
if(scene.empty())
{
UERROR("Failed to load scene \"%s\"", scenePath.toStdString().c_str());
}
}
if(guiMode)
{
QApplication app(argc, argv);
find_object::MainWindow mainWindow(findObject, 0); // ownership transfered
app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) );
mainWindow.show();
if(!scene.empty())
{
mainWindow.update(scene);
}
app.exec();
// Save settings
find_object::Settings::saveSettings();
}
else
{
QCoreApplication app(argc, argv);
if(!scene.empty())
{
// process the scene and exit
QTime time;
time.start();
find_object::DetectionInfo info;
findObject->detect(scene, info);
if(info.objDetected_.size() > 1)
{
UINFO("%d objects detected! (%d ms)", (int)info.objDetected_.size(), time.elapsed());
}
else if(info.objDetected_.size() == 1)
{
UINFO("Object %d detected! (%d ms)", (int)info.objDetected_.begin().key(), time.elapsed());
}
else if(find_object::Settings::getGeneral_sendNoObjDetectedEvents())
{
UINFO("No objects detected. (%d ms)", time.elapsed());
}
if(!jsonPath.isEmpty())
{
find_object::JsonWriter::write(info, jsonPath);
UINFO("JSON written to \"%s\"", jsonPath.toStdString().c_str());
}
}
else
{
TcpServerPool tcpServerPool(findObject, tcpThreads, find_object::Settings::getGeneral_port());
setupQuitSignal();
//If TCP camera is used
find_object::Camera * camera = 0;
if(find_object::Settings::getCamera_6useTcpCamera())
{
camera = new find_object::Camera();
// [Camera] ---Image---> [FindObject]
QObject::connect(camera, SIGNAL(imageReceived(const cv::Mat &)), findObject, SLOT(detect(const cv::Mat &)));
QObject::connect(camera, SIGNAL(finished()), &app, SLOT(quit()));
if(!camera->start())
{
UERROR("Camera initialization failed!");
running = false;
}
}
// start processing!
if(running)
{
app.exec();
if(!sessionPath.isEmpty())
{
if(findObject->isSessionModified())
{
UINFO("The session has been modified, updating the session file...");
if(findObject->saveSession(sessionPath))
{
UINFO("Session \"%s\" successfully saved (%d objects)!",
sessionPath.toStdString().c_str(), findObject->objects().size());
}
}
else if(sessionNew)
{
UINFO("The session has not been modified, session file not created...");
}
}
}
// cleanup
if(camera)
{
camera->stop();
delete camera;
}
}
delete findObject;
}
return 0;
}
-8
View File
@@ -1,8 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
!box_in_scene.png
!box.png
!multi-objs
!multi-scene.jpg
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

-4
View File
@@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
@@ -1,34 +0,0 @@
# - Find Tcmalloc
# Find the native Tcmalloc library
#
# Tcmalloc_LIBRARIES - List of libraries when using Tcmalloc.
# Tcmalloc_FOUND - True if Tcmalloc found.
if (USE_TCMALLOC)
set(Tcmalloc_NAMES tcmalloc)
else ()
set(Tcmalloc_NAMES tcmalloc_minimal tcmalloc)
endif ()
find_library(Tcmalloc_LIBRARY NAMES ${Tcmalloc_NAMES})
if (Tcmalloc_LIBRARY)
set(Tcmalloc_FOUND TRUE)
set( Tcmalloc_LIBRARIES ${Tcmalloc_LIBRARY} )
else ()
set(Tcmalloc_FOUND FALSE)
set( Tcmalloc_LIBRARIES )
endif ()
if (Tcmalloc_FOUND)
message(STATUS "Found Tcmalloc: ${Tcmalloc_LIBRARY}")
else ()
message(STATUS "Not Found Tcmalloc: ${Tcmalloc_LIBRARY}")
if (Tcmalloc_FIND_REQUIRED)
message(STATUS "Looked for Tcmalloc libraries named ${Tcmalloc_NAMES}.")
message(FATAL_ERROR "Could NOT find Tcmalloc library")
endif ()
endif ()
mark_as_advanced(Tcmalloc_LIBRARY)
-27
View File
@@ -1,27 +0,0 @@
# -----------------------------------------------
# File that provides "make uninstall" target
# We use the file 'install_manifest.txt'
# -----------------------------------------------
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
STRING(REGEX REPLACE "\n" ";" files "${files}")
FOREACH(file ${files})
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
IF(EXISTS "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSE(EXISTS "$ENV{DESTDIR}${file}")
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
ENDFOREACH(file)
-38
View File
@@ -1,38 +0,0 @@
SET(SRC_FILES
main.cpp
)
SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}
${OpenCV_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../include
)
IF(QT4_FOUND)
INCLUDE(${QT_USE_FILE})
ENDIF(QT4_FOUND)
SET(LIBRARIES
${OpenCV_LIBS}
${QT_LIBRARIES}
)
# Make sure the compiler can find include files from our library.
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
# Add binary called "example" that is built from the source file "main.cpp".
# The extension is automatically found.
ADD_EXECUTABLE(example ${SRC_FILES})
TARGET_LINK_LIBRARIES(example find_object ${LIBRARIES})
IF(Qt5_FOUND)
QT5_USE_MODULES(example Widgets Core Gui Network PrintSupport)
ENDIF(Qt5_FOUND)
SET_TARGET_PROPERTIES( example
PROPERTIES OUTPUT_NAME ${PROJECT_PREFIX}-example)
INSTALL(TARGETS example
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" COMPONENT runtime)
-346
View File
@@ -1,346 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include <stdio.h>
// Qt stuff
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QApplication>
#include <QGraphicsRectItem>
#include <QPen>
#include <QColor>
// OpenCV stuff
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/calib3d/calib3d.hpp> // for homography
#include <opencv2/opencv_modules.hpp>
#ifdef HAVE_OPENCV_NONFREE
#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4
#include <opencv2/nonfree/gpu.hpp>
#include <opencv2/nonfree/features2d.hpp>
#endif
#endif
#ifdef HAVE_OPENCV_XFEATURES2D
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/xfeatures2d/cuda.hpp>
#endif
// From this project
#include "find_object/ObjWidget.h"
#include "find_object/QtOpenCV.h"
using namespace find_object;
void showUsage()
{
printf("\n");
printf("Usage :\n");
printf(" ./example object.png scene.png\n");
exit(1);
}
int main(int argc, char * argv[])
{
if(argc<3)
{
showUsage();
}
QTime time;
// GUI stuff
QApplication app(argc, argv);
time.start();
//Load as grayscale
cv::Mat objectImg = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);
cv::Mat sceneImg = cv::imread(argv[2], cv::IMREAD_GRAYSCALE);
if(!objectImg.empty() && !sceneImg.empty())
{
printf("Loading images: %d ms\n", time.restart());
std::vector<cv::KeyPoint> objectKeypoints;
std::vector<cv::KeyPoint> sceneKeypoints;
cv::Mat objectDescriptors;
cv::Mat sceneDescriptors;
////////////////////////////
// EXTRACT KEYPOINTS
////////////////////////////
cv::Ptr<cv::FeatureDetector> detector;
// The detector can be any of (see OpenCV features2d.hpp):
#if CV_MAJOR_VERSION == 2
// detector = cv::Ptr(new cv::DenseFeatureDetector());
// detector = cv::Ptr(new cv::FastFeatureDetector());
// detector = cv::Ptr(new cv::GFTTDetector());
// detector = cv::Ptr(new cv::MSER());
// detector = cv::Ptr(new cv::ORB());
detector = cv::Ptr<cv::FeatureDetector>(new cv::SIFT());
// detector = cv::Ptr(new cv::StarFeatureDetector());
// detector = cv::Ptr(new cv::SURF(600.0));
// detector = cv::Ptr(new cv::BRISK());
#elif CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION < 3)
detector = cv::xfeatures2d::SIFT::create();
#else // >= 4.3.0
detector = cv::SIFT::create();
#endif
detector->detect(objectImg, objectKeypoints);
printf("Object: %d keypoints detected in %d ms\n", (int)objectKeypoints.size(), time.restart());
detector->detect(sceneImg, sceneKeypoints);
printf("Scene: %d keypoints detected in %d ms\n", (int)sceneKeypoints.size(), time.restart());
////////////////////////////
// EXTRACT DESCRIPTORS
////////////////////////////
cv::Ptr<cv::DescriptorExtractor> extractor;
#if CV_MAJOR_VERSION == 2
// The extractor can be any of (see OpenCV features2d.hpp):
// extractor = cv::Ptr(new cv::BriefDescriptorExtractor());
// extractor = cv::Ptr(new cv::ORB());
extractor = cv::Ptr<cv::DescriptorExtractor>(new cv::SIFT());
// extractor = cv::Ptr(new cv::SURF(600.0));
// extractor = cv::Ptr(new cv::BRISK());
// extractor = cv::Ptr(new cv::FREAK());
#elif CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION < 3)
extractor = cv::xfeatures2d::SIFT::create();
#else // >= 4.3.0
extractor = cv::SIFT::create();
#endif
extractor->compute(objectImg, objectKeypoints, objectDescriptors);
printf("Object: %d descriptors extracted in %d ms\n", objectDescriptors.rows, time.restart());
extractor->compute(sceneImg, sceneKeypoints, sceneDescriptors);
printf("Scene: %d descriptors extracted in %d ms\n", sceneDescriptors.rows, time.restart());
////////////////////////////
// NEAREST NEIGHBOR MATCHING USING FLANN LIBRARY (included in OpenCV)
////////////////////////////
cv::Mat results;
cv::Mat dists;
std::vector<std::vector<cv::DMatch> > matches;
int k=2; // find the 2 nearest neighbors
bool useBFMatcher = false; // SET TO TRUE TO USE BRUTE FORCE MATCHER
if(objectDescriptors.type()==CV_8U)
{
// Binary descriptors detected (from ORB, Brief, BRISK, FREAK)
printf("Binary descriptors detected...\n");
if(useBFMatcher)
{
cv::BFMatcher matcher(cv::NORM_HAMMING); // use cv::NORM_HAMMING2 for ORB descriptor with WTA_K == 3 or 4 (see ORB constructor)
matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k);
}
else
{
// Create Flann LSH index
cv::flann::Index flannIndex(sceneDescriptors, cv::flann::LshIndexParams(12, 20, 2), cvflann::FLANN_DIST_HAMMING);
printf("Time creating FLANN LSH index = %d ms\n", time.restart());
// search (nearest neighbor)
flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
}
}
else
{
// assume it is CV_32F
printf("Float descriptors detected...\n");
if(useBFMatcher)
{
cv::BFMatcher matcher(cv::NORM_L2);
matcher.knnMatch(objectDescriptors, sceneDescriptors, matches, k);
}
else
{
// Create Flann KDTree index
cv::flann::Index flannIndex(sceneDescriptors, cv::flann::KDTreeIndexParams(), cvflann::FLANN_DIST_EUCLIDEAN);
printf("Time creating FLANN KDTree index = %d ms\n", time.restart());
// search (nearest neighbor)
flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
}
}
printf("Time nearest neighbor search = %d ms\n", time.restart());
// Conversion to CV_32F if needed
if(dists.type() == CV_32S)
{
cv::Mat temp;
dists.convertTo(temp, CV_32F);
dists = temp;
}
////////////////////////////
// PROCESS NEAREST NEIGHBOR RESULTS
////////////////////////////
// Set gui data
ObjWidget objWidget(0, objectKeypoints, QMultiMap<int,int>(), cvtCvMat2QImage(objectImg));
ObjWidget sceneWidget(0, sceneKeypoints, QMultiMap<int,int>(), cvtCvMat2QImage(sceneImg));
// Find correspondences by NNDR (Nearest Neighbor Distance Ratio)
float nndrRatio = 0.8f;
std::vector<cv::Point2f> mpts_1, mpts_2; // Used for homography
std::vector<int> indexes_1, indexes_2; // Used for homography
std::vector<uchar> outlier_mask; // Used for homography
// Check if this descriptor matches with those of the objects
if(!useBFMatcher)
{
for(int i=0; i<objectDescriptors.rows; ++i)
{
// Apply NNDR
//printf("q=%d dist1=%f dist2=%f\n", i, dists.at<float>(i,0), dists.at<float>(i,1));
if(results.at<int>(i,0) >= 0 && results.at<int>(i,1) >= 0 &&
dists.at<float>(i,0) <= nndrRatio * dists.at<float>(i,1))
{
mpts_1.push_back(objectKeypoints.at(i).pt);
indexes_1.push_back(i);
mpts_2.push_back(sceneKeypoints.at(results.at<int>(i,0)).pt);
indexes_2.push_back(results.at<int>(i,0));
}
}
}
else
{
for(unsigned int i=0; i<matches.size(); ++i)
{
// Apply NNDR
//printf("q=%d dist1=%f dist2=%f\n", matches.at(i).at(0).queryIdx, matches.at(i).at(0).distance, matches.at(i).at(1).distance);
if(matches.at(i).size() == 2 &&
matches.at(i).at(0).distance <= nndrRatio * matches.at(i).at(1).distance)
{
mpts_1.push_back(objectKeypoints.at(matches.at(i).at(0).queryIdx).pt);
indexes_1.push_back(matches.at(i).at(0).queryIdx);
mpts_2.push_back(sceneKeypoints.at(matches.at(i).at(0).trainIdx).pt);
indexes_2.push_back(matches.at(i).at(0).trainIdx);
}
}
}
// FIND HOMOGRAPHY
unsigned int minInliers = 8;
if(mpts_1.size() >= minInliers)
{
time.start();
cv::Mat H = findHomography(mpts_1,
mpts_2,
cv::RANSAC,
1.0,
outlier_mask);
printf("Time finding homography = %d ms\n", time.restart());
int inliers=0, outliers=0;
for(unsigned int k=0; k<mpts_1.size();++k)
{
if(outlier_mask.at(k))
{
++inliers;
}
else
{
++outliers;
}
}
QTransform hTransform(
H.at<double>(0,0), H.at<double>(1,0), H.at<double>(2,0),
H.at<double>(0,1), H.at<double>(1,1), H.at<double>(2,1),
H.at<double>(0,2), H.at<double>(1,2), H.at<double>(2,2));
// GUI : Change color and add homography rectangle
QColor color(Qt::green);
int alpha = 130;
color.setAlpha(alpha);
for(unsigned int k=0; k<mpts_1.size();++k)
{
if(outlier_mask.at(k))
{
objWidget.setKptColor(indexes_1.at(k), color);
sceneWidget.setKptColor(indexes_2.at(k), color);
}
else
{
objWidget.setKptColor(indexes_1.at(k), QColor(255,0,0,alpha));
sceneWidget.setKptColor(indexes_2.at(k), QColor(255,0,0,alpha));
}
}
QPen rectPen(color);
rectPen.setWidth(4);
QGraphicsRectItem * rectItem = new QGraphicsRectItem(objWidget.pixmap().rect());
rectItem->setPen(rectPen);
rectItem->setTransform(hTransform);
sceneWidget.addRect(rectItem);
printf("Inliers=%d Outliers=%d\n", inliers, outliers);
}
else
{
printf("Not enough matches (%d) for homography...\n", (int)mpts_1.size());
}
// Wait for gui
objWidget.setGraphicsViewMode(false);
objWidget.setWindowTitle("Object");
if(objWidget.pixmap().width() <= 800)
{
objWidget.setMinimumSize(objWidget.pixmap().width(), objWidget.pixmap().height());
}
else
{
objWidget.setMinimumSize(800, 600);
objWidget.setAutoScale(false);
}
sceneWidget.setGraphicsViewMode(false);
sceneWidget.setWindowTitle("Scene");
if(sceneWidget.pixmap().width() <= 800)
{
sceneWidget.setMinimumSize(sceneWidget.pixmap().width(), sceneWidget.pixmap().height());
}
else
{
sceneWidget.setMinimumSize(800, 600);
sceneWidget.setAutoScale(false);
}
sceneWidget.show();
objWidget.show();
int r = app.exec();
printf("Closing...\n");
return r;
}
else
{
printf("Images are not valid!\n");
showUsage();
}
return 1;
}
@@ -1 +0,0 @@
/Version.h
-81
View File
@@ -1,81 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 CAMERA_H_
#define CAMERA_H_
#include <find_object/Header.h>
#include "find_object/FindObjectExp.h" // DLL export/import defines
#include <opencv2/highgui/highgui.hpp>
#include <QtCore/QObject>
#include <QtCore/QTimer>
#include <QtGui/QImage>
namespace find_object {
class CameraTcpServer;
class FINDOBJECT_EXP Camera : public QObject {
Q_OBJECT
public:
Camera(QObject * parent = 0);
virtual ~Camera();
virtual bool start();
virtual void stop();
virtual bool isRunning() {return cameraTimer_.isActive();}
void pause();
int getTotalFrames();
int getCurrentFrameIndex();
int getPort();
void moveToFrame(int frame);
Q_SIGNALS:
void imageReceived(const cv::Mat & image);
void imageReceived(const cv::Mat & image, const find_object::Header & header, const cv::Mat & depth, float depthConstant);
void finished();
public Q_SLOTS:
virtual void updateImageRate();
virtual void takeImage();
protected:
void startTimer();
void stopTimer();
private:
cv::VideoCapture capture_;
QTimer cameraTimer_;
QList<std::string> images_;
unsigned int currentImageIndex_;
CameraTcpServer * cameraTcpServer_;
};
} // namespace find_object
#endif /* CAMERA_H_ */
@@ -1,164 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 DETECTIONINFO_H_
#define DETECTIONINFO_H_
#include <QtCore/QMultiMap>
#include <QtGui/QTransform>
#include <QtCore/QSize>
#include <QtCore/QString>
#include <opencv2/features2d/features2d.hpp>
#include <vector>
namespace find_object {
class DetectionInfo
{
public:
enum TimeStamp{
kTimeKeypointDetection,
kTimeDescriptorExtraction,
kTimeSubPixelRefining,
kTimeSkewAffine,
kTimeIndexing,
kTimeMatching,
kTimeHomography,
kTimeTotal
};
enum RejectedCode{
kRejectedUndef,
kRejectedLowMatches,
kRejectedLowInliers,
kRejectedSuperposed,
kRejectedAllInliers,
kRejectedNotValid,
kRejectedCornersOutside,
kRejectedByAngle
};
public:
DetectionInfo() :
minMatchedDistance_(-1),
maxMatchedDistance_(-1)
{}
public:
// Those maps have the same size
QMultiMap<int, QTransform> objDetected_;
QMultiMap<int, QSize> objDetectedSizes_; // Object ID <width, height> match the number of detected objects
QMultiMap<int, QString > objDetectedFilePaths_; // Object ID <filename> match the number of detected objects
QMultiMap<int, int> objDetectedInliersCount_; // ObjectID <count> match the number of detected objects
QMultiMap<int, int> objDetectedOutliersCount_; // ObjectID <count> match the number of detected objects
QMultiMap<int, QMultiMap<int, int> > objDetectedInliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of detected objects
QMultiMap<int, QMultiMap<int, int> > objDetectedOutliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of detected objects
QMap<TimeStamp, float> timeStamps_;
std::vector<cv::KeyPoint> sceneKeypoints_;
cv::Mat sceneDescriptors_;
QMultiMap<int, int> sceneWords_;
QMap<int, QMultiMap<int, int> > matches_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >, match the number of objects
// Those maps have the same size
QMultiMap<int, QMultiMap<int, int> > rejectedInliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >
QMultiMap<int, QMultiMap<int, int> > rejectedOutliers_; // ObjectID Map< ObjectDescriptorIndex, SceneDescriptorIndex >
QMultiMap<int, RejectedCode> rejectedCodes_; // ObjectID rejected code
float minMatchedDistance_;
float maxMatchedDistance_;
};
inline QDataStream & operator<<(QDataStream &out, const DetectionInfo & info)
{
out << quint32(info.objDetected_.size());
QMultiMap<int, int>::const_iterator iterInliers = info.objDetectedInliersCount_.constBegin();
QMultiMap<int, int>::const_iterator iterOutliers = info.objDetectedOutliersCount_.constBegin();
QMultiMap<int, QSize>::const_iterator iterSizes = info.objDetectedSizes_.constBegin();
QMultiMap<int, QString>::const_iterator iterFilenames = info.objDetectedFilePaths_.constBegin();
for(QMultiMap<int, QTransform>::const_iterator iter=info.objDetected_.constBegin();
iter!=info.objDetected_.constEnd();
++iter)
{
// ID
out << iter.key();
// Size
out << iterSizes.value();
// Transform
out << iter.value();
// Filename
out << iterFilenames.value();
// inliers and outliers count
out << iterInliers.value();
out << iterOutliers.value();
++iterInliers;
++iterOutliers;
++iterSizes;
++iterFilenames;
}
return out;
}
inline QDataStream & operator>>(QDataStream &in, DetectionInfo & info)
{
QDataStream::Status oldStatus = in.status();
in.resetStatus();
info = DetectionInfo();
quint32 n;
in >> n;
for (quint32 i = 0; i < n; ++i) {
if (in.status() != QDataStream::Ok)
break;
int id;
QSize size;
QTransform homography;
QString filename;
int inliers, outliers;
in >> id >> size >> homography >> filename >> inliers >> outliers;
info.objDetected_.insert(id, homography);
info.objDetectedSizes_.insert(id, size);
info.objDetectedFilePaths_.insert(id, filename);
info.objDetectedInliersCount_.insert(id, inliers);
info.objDetectedOutliersCount_.insert(id, outliers);
}
if (in.status() != QDataStream::Ok)
info = DetectionInfo();
if (oldStatus != QDataStream::Ok)
in.setStatus(oldStatus);
return in;
}
} // namespace find_object
#endif /* DETECTIONINFO_H_ */
@@ -1,116 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 FINDOBJECT_H_
#define FINDOBJECT_H_
#include <find_object/Header.h>
#include "find_object/FindObjectExp.h" // DLL export/import defines
#include "find_object/DetectionInfo.h"
#include "find_object/Settings.h"
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QMap>
#include <QtCore/QMultiMap>
#include <QtCore/QPair>
#include <QtCore/QVector>
#include <QtGui/QTransform>
#include <QtCore/QRect>
#include <opencv2/opencv.hpp>
#include <vector>
namespace find_object {
class ObjSignature;
class Vocabulary;
class Feature2D;
class FINDOBJECT_EXP FindObject : public QObject
{
Q_OBJECT;
public:
static void affineSkew(float tilt,
float phi,
const cv::Mat & image,
cv::Mat & skewImage,
cv::Mat & skewMask,
cv::Mat & Ai);
public:
FindObject(bool keepImagesInRAM_ = true, QObject * parent = 0);
virtual ~FindObject();
bool loadSession(const QString & path, const ParametersMap & customParameters = ParametersMap());
bool saveSession(const QString & path);
bool isSessionModified() const {return sessionModified_;}
bool saveVocabulary(const QString & filePath) const;
bool loadVocabulary(const QString & filePath);
int loadObjects(const QString & dirPath, bool recursive = false); // call updateObjects()
const ObjSignature * addObject(const QString & filePath);
const ObjSignature * addObject(const cv::Mat & image, int id=0, const QString & filePath = QString());
bool addObject(ObjSignature * obj); // take ownership when true is returned
void removeObject(int id);
void removeAllObjects();
bool detect(const cv::Mat & image, find_object::DetectionInfo & info) const;
void updateDetectorExtractor();
void updateObjects(const QList<int> & ids = QList<int>());
void updateVocabulary(const QList<int> & ids = QList<int>());
const QMap<int, ObjSignature*> & objects() const {return objects_;}
const Vocabulary * vocabulary() const {return vocabulary_;}
public Q_SLOTS:
void addObjectAndUpdate(const cv::Mat & image, int id=0, const QString & filePath = QString());
void removeObjectAndUpdate(int id);
void detect(const cv::Mat & image); // emit objectsFound()
void detect(const cv::Mat & image, const find_object::Header & header, const cv::Mat & depth, float depthConstant); // emit objectsFound()
Q_SIGNALS:
void objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float);
private:
void clearVocabulary();
private:
QMap<int, ObjSignature*> objects_;
Vocabulary * vocabulary_;
QMap<int, cv::Mat> objectsDescriptors_;
QMap<int, int> dataRange_; // <last id of object's descriptor, id>
Feature2D * detector_;
Feature2D * extractor_;
bool sessionModified_;
bool keepImagesInRAM_;
};
} // namespace find_object
#endif /* FINDOBJECT_H_ */
@@ -1,41 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 FINDOBJECTEXP_H
#define FINDOBJECTEXP_H
#if defined(_WIN32)
#if defined(find_object_EXPORTS)
#define FINDOBJECT_EXP __declspec( dllexport )
#else
#define FINDOBJECT_EXP __declspec( dllimport )
#endif
#else
#define FINDOBJECT_EXP
#endif
#endif // RTABMAPEXP_H
-56
View File
@@ -1,56 +0,0 @@
/*
Copyright (c) 2011-2021, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 INCLUDE_FIND_OBJECT_HEADER_H_
#define INCLUDE_FIND_OBJECT_HEADER_H_
#include <stdint.h>
#include <QString>
namespace find_object {
class Header {
public:
Header() :
sec_(0),
nsec_(0)
{
}
Header(const char * frameId, uint64_t sec, uint64_t nsec) :
frameId_(frameId),
sec_(sec),
nsec_(nsec)
{
}
QString frameId_;
uint64_t sec_;
uint64_t nsec_;
};
}
#endif /* INCLUDE_FIND_OBJECT_HEADER_H_ */
@@ -1,152 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 MAINWINDOW_H_
#define MAINWINDOW_H_
#include "find_object/FindObjectExp.h" // DLL export/import defines
#include "find_object/DetectionInfo.h"
#include "find_object/Header.h"
#include <QMainWindow>
#include <QtCore/QSet>
#include <QtCore/QTimer>
#include <QtCore/QTime>
#include <QtCore/QMap>
#include <QtCore/QByteArray>
#include <opencv2/opencv.hpp>
namespace rtabmap
{
class PdfPlotCurve;
}
class Ui_mainWindow;
class QLabel;
namespace find_object {
class ObjWidget;
class Camera;
class ParametersToolBox;
class AboutDialog;
class TcpServer;
class KeypointDetector;
class DescriptorExtractor;
class Vocabulary;
class FindObject;
class FINDOBJECT_EXP MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(find_object::FindObject * findObject, find_object::Camera * camera = 0, QWidget * parent = 0);
virtual ~MainWindow();
void setSourceImageText(const QString & text);
protected:
virtual void closeEvent(QCloseEvent * event);
virtual void keyPressEvent(QKeyEvent *event);
public Q_SLOTS:
void startProcessing();
void stopProcessing();
void pauseProcessing();
void update(const cv::Mat & image);
void update(const cv::Mat & image, const find_object::Header & header, const cv::Mat & depth, float depthConstant);
private Q_SLOTS:
void loadSession();
void saveSession();
void loadSettings();
void saveSettings();
void loadObjects();
bool saveObjects();
void loadVocabulary();
void saveVocabulary();
void addObjectFromScene();
void addObjectsFromFiles(const QStringList & fileNames);
void addObjectsFromFiles();
void addObjectFromTcp(const cv::Mat & image, int id, const QString & filePath);
void loadSceneFromFile(const QStringList & fileNames);
void loadSceneFromFile();
void setupCameraFromVideoFile();
void setupCameraFromImagesDirectory();
void setupCameraFromTcpIp();
void removeObject(find_object::ObjWidget * object);
void removeObject(int id);
void removeAllObjects();
void updateObjectsSize();
void updateMirrorView();
void showHideControls();
void showObjectsFeatures();
void hideObjectsFeatures();
void updateObjects();
void notifyParametersChanged(const QStringList & param);
void moveCameraFrame(int frame);
void rectHovered(int objId);
Q_SIGNALS:
void objectsFound(const find_object::DetectionInfo &, const find_object::Header & header, const cv::Mat & depth, float depthConstant);
private:
bool loadSettings(const QString & path);
bool saveSettings(const QString & path) const;
int loadObjects(const QString & dirPath, bool recursive = false);
int saveObjects(const QString & dirPath);
void setupTCPServer();
int addObjectFromFile(const QString & filePath);
void showObject(find_object::ObjWidget * obj);
void updateObjectSize(find_object::ObjWidget * obj);
void updateVocabulary(const QList<int> & ids = QList<int>());
void updateObjects(const QList<int> & ids);
private:
Ui_mainWindow * ui_;
Camera * camera_;
FindObject * findObject_;
rtabmap::PdfPlotCurve * likelihoodCurve_;
rtabmap::PdfPlotCurve * inliersCurve_;
AboutDialog * aboutDialog_;
QMap<int, find_object::ObjWidget*> objWidgets_;
QTime updateRate_;
QTime refreshStartTime_;
int lowestRefreshRate_;
bool objectsModified_;
QMap<int, QByteArray> imagesMap_;
QMap<QString, QVariant> lastObjectsUpdateParameters_; // ParametersMap
TcpServer * tcpServer_;
cv::Mat sceneImage_;
};
} // namespace find_object
#endif /* MainWindow_H_ */
-151
View File
@@ -1,151 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 OBJWIDGET_H_
#define OBJWIDGET_H_
#include "find_object/FindObjectExp.h" // DLL export/import defines
#include <opencv2/features2d/features2d.hpp>
#include <QWidget>
#include <QtCore/QMultiMap>
class QAction;
class QMenu;
class QGraphicsView;
class QGraphicsScene;
class QGraphicsRectItem;
class QGraphicsItem;
class QLabel;
namespace find_object {
class KeypointItem;
class ImageKptsView;
class FINDOBJECT_EXP ObjWidget : public QWidget
{
Q_OBJECT
public:
ObjWidget(QWidget * parent = 0);
ObjWidget(int id, const std::vector<cv::KeyPoint> & keypoints, const QMultiMap<int,int> & words, const QImage & image, QWidget * parent = 0);
virtual ~ObjWidget();
void setId(int id);
void updateImage(const QImage & image);
void updateData(const std::vector<cv::KeyPoint> & keypoints, const QMultiMap<int, int> & words=QMultiMap<int, int>());
void updateWords(const QMultiMap<int,int> & words);
void setTextLabel(const QString & text);
void resetKptsColor();
void resetKptsWordID();
void setKptColor(int index, const QColor & color);
void setKptWordID(int index, int wordId);
void setGraphicsViewMode(bool on);
void setAutoScale(bool autoScale);
void setSizedFeatures(bool on);
void setMirrorView(bool on);
void setAlpha(int alpha);
void setDeletable(bool deletable);
void setImageShown(bool shown);
void setFeaturesShown(bool shown);
void addRect(QGraphicsRectItem * rect);
void clearRoiSelection() {mousePressedPos_ = mouseCurrentPos_ = QPoint();update();}
int id() const {return id_;}
const QColor & color() const {return color_;}
const std::vector<cv::KeyPoint> keypoints() const {return keypoints_;}
const QMap<int,int> & words() const {return words_;}
const QPixmap & pixmap() const {return pixmap_;}
QColor defaultColor(int id) const;
bool isImageShown() const;
bool isFeaturesShown() const;
bool isSizedFeatures() const;
bool isMirrorView() const;
//QGraphicsScene * scene() const;
std::vector<cv::KeyPoint> selectedKeypoints() const;
QList<QGraphicsItem*> selectedItems() const;
QPixmap getSceneAsPixmap();
protected:
virtual void paintEvent(QPaintEvent *event);
virtual void contextMenuEvent(QContextMenuEvent * event);
virtual void resizeEvent(QResizeEvent* event);
virtual void mousePressEvent(QMouseEvent * event);
virtual void mouseMoveEvent(QMouseEvent * event);
virtual void mouseReleaseEvent(QMouseEvent * event);
Q_SIGNALS:
void removalTriggered(find_object::ObjWidget *);
void selectionChanged();
void roiChanged(const cv::Rect &);
private:
void setupGraphicsView();
void drawKeypoints(QPainter * painter = 0);
void setupUi();
void updateItemsShown();
void computeScaleOffsets(float & scale, float & offsetX, float & offsetY);
private:
int id_;
std::vector<cv::KeyPoint> keypoints_;
QMap<int,int> words_; //<keypoint, word>
QPixmap pixmap_;
QRect rect_;
QList<KeypointItem*> keypointItems_;
QGraphicsView * graphicsView_;
QVector<QColor> kptColors_;
QList<QGraphicsRectItem*> rectItems_;
bool graphicsViewInitialized_;
int alpha_;
QLabel * label_;
QColor color_;
// menu stuff
QString savedFileName_;
QMenu * menu_;
QAction * showImage_;
QAction * showFeatures_;
QAction * saveImage_;
QAction * mirrorView_;
QAction * delete_;
QAction * graphicsViewMode_;
QAction * autoScale_;
QAction * sizedFeatures_;
QAction * setAlpha_;
QAction * setColor_;
// selection stuff
QPoint mousePressedPos_;
QPoint mouseCurrentPos_;
};
} // namespace find_object
#endif /* OBJWIDGET_H_ */
@@ -1,54 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 QTOPENCV_H
#define QTOPENCV_H
#include "find_object/FindObjectExp.h" // DLL export/import defines
#include <QtGui/QImage>
#include <opencv2/core/core.hpp>
namespace find_object {
// Convert OpenCV matrix to QImage
FINDOBJECT_EXP QImage cvtCvMat2QImage(const cv::Mat & image, bool isBgr = true);
// Convert QImage to OpenCV matrix
FINDOBJECT_EXP cv::Mat cvtQImage2CvMat(const QImage & image);
#if CV_MAJOR_VERSION < 3
// Convert IplImage to QImage
FINDOBJECT_EXP QImage cvtIplImage2QImage(const IplImage * image);
// Convert QImage to IplImage
FINDOBJECT_EXP IplImage * cvtQImage2IplImage(const QImage & image);
#endif
} // namespace find_object
#endif // QTOPENCV_H
-404
View File
@@ -1,404 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 SETTINGS_H_
#define SETTINGS_H_
#include "find_object/FindObjectExp.h" // DLL export/import defines
#include "find_object/Version.h" // DLL export/import defines
#include <QtCore/QMap>
#include <QtCore/QVariant>
#include <QtCore/QByteArray>
#include <opencv2/features2d/features2d.hpp>
namespace find_object {
class Feature2D;
typedef QMap<QString, QVariant> ParametersMap; // Key, value
typedef QMap<QString, QString> ParametersType; // Key, type
typedef QMap<QString, QString> DescriptionsMap; // Key, description
typedef unsigned int uint;
// MACRO BEGIN
#define PARAMETER_GETTER_bool(PREFIX, NAME) \
static bool get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toBool();}
#define PARAMETER_GETTER_int(PREFIX, NAME) \
static int get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toInt();}
#define PARAMETER_GETTER_uint(PREFIX, NAME) \
static uint get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toUInt();}
#define PARAMETER_GETTER_float(PREFIX, NAME) \
static float get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toFloat();}
#define PARAMETER_GETTER_double(PREFIX, NAME) \
static double get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toDouble();}
#define PARAMETER_GETTER_QString(PREFIX, NAME) \
static QString get##PREFIX##_##NAME() {return parameters_.value(#PREFIX "/" #NAME).toString();}
#define PARAMETER(PREFIX, NAME, TYPE, DEFAULT_VALUE, DESCRIPTION) \
public: \
static QString k##PREFIX##_##NAME() {return QString(#PREFIX "/" #NAME);} \
static TYPE default##PREFIX##_##NAME() {return DEFAULT_VALUE;} \
static QString type##PREFIX##_##NAME() {return QString(#TYPE);} \
static QString description##PREFIX##_##NAME() {return QString(DESCRIPTION);} \
PARAMETER_GETTER_##TYPE(PREFIX, NAME) \
static void set##PREFIX##_##NAME(const TYPE & value) {parameters_[#PREFIX "/" #NAME] = value;} \
private: \
class Dummy##PREFIX##_##NAME { \
public: \
Dummy##PREFIX##_##NAME() { \
defaultParameters_.insert(#PREFIX "/" #NAME, QVariant(DEFAULT_VALUE)); \
parameters_.insert(#PREFIX "/" #NAME, DEFAULT_VALUE); \
parametersType_.insert(#PREFIX "/" #NAME, #TYPE); \
descriptions_.insert(#PREFIX "/" #NAME, DESCRIPTION);} \
}; \
Dummy##PREFIX##_##NAME dummy##PREFIX##_##NAME;
#define PARAMETER_COND(PREFIX, NAME, TYPE, COND, DEFAULT_VALUE1, DEFAULT_VALUE2, DESCRIPTION) \
public: \
static QString k##PREFIX##_##NAME() {return QString(#PREFIX "/" #NAME);} \
static TYPE default##PREFIX##_##NAME() {return COND?DEFAULT_VALUE1:DEFAULT_VALUE2;} \
static QString type##PREFIX##_##NAME() {return QString(#TYPE);} \
static QString description##PREFIX##_##NAME() {return QString(DESCRIPTION);} \
PARAMETER_GETTER_##TYPE(PREFIX, NAME) \
static void set##PREFIX##_##NAME(const TYPE & value) {parameters_[#PREFIX "/" #NAME] = value;} \
private: \
class Dummy##PREFIX##_##NAME { \
public: \
Dummy##PREFIX##_##NAME() { \
defaultParameters_.insert(#PREFIX "/" #NAME, QVariant(COND?DEFAULT_VALUE1:DEFAULT_VALUE2)); \
parameters_.insert(#PREFIX "/" #NAME, COND?DEFAULT_VALUE1:DEFAULT_VALUE2); \
parametersType_.insert(#PREFIX "/" #NAME, #TYPE); \
descriptions_.insert(#PREFIX "/" #NAME, DESCRIPTION);} \
}; \
Dummy##PREFIX##_##NAME dummy##PREFIX##_##NAME;
// MACRO END
class FINDOBJECT_EXP Settings
{
PARAMETER(Camera, 1deviceId, int, 0, "Device ID (default 0).");
PARAMETER(Camera, 2imageWidth, int, 0, "Image width (0 means default width from camera).");
PARAMETER(Camera, 3imageHeight, int, 0, "Image height (0 means default height from camera).");
PARAMETER(Camera, 4imageRate, double, 10.0, "Image rate in Hz (0 Hz means as fast as possible)."); // Hz
PARAMETER(Camera, 5mediaPath, QString, "", "Video file or directory of images. If set, the camera is not used. See General->videoFormats and General->imageFormats for available formats.");
PARAMETER(Camera, 6useTcpCamera, bool, false, "Use TCP/IP input camera.");
PARAMETER(Camera, 8port, int, 0, "The images server's port when useTcpCamera is checked. Only one client at the same time is allowed.");
PARAMETER(Camera, 9queueSize, int, 1, "Maximum images buffered from TCP. If 0, all images are buffered.");
//List format : [Index:item0;item1;item3;...]
#if CV_MAJOR_VERSION < 3 || (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
#if CV_MAJOR_VERSION >= 3 // NONFREE=SURF, DEFAULT=KAZE
PARAMETER_COND(Feature2D, 1Detector, QString, FINDOBJECT_NONFREE, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch" , "10:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch", "Keypoint detector.");
PARAMETER_COND(Feature2D, 2Descriptor, QString, FINDOBJECT_NONFREE, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "6:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "Keypoint descriptor.");
#else // NONFREE=SURF, DEFAULT=ORB
PARAMETER_COND(Feature2D, 1Detector, QString, FINDOBJECT_NONFREE, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch" , "4:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch", "Keypoint detector.");
PARAMETER_COND(Feature2D, 2Descriptor, QString, FINDOBJECT_NONFREE, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "1:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "Keypoint descriptor.");
#endif
#else // >=4.4 >=3.4.11: NONFREE=SURF, DEFAULT=SIFT
PARAMETER_COND(Feature2D, 1Detector, QString, FINDOBJECT_NONFREE, "7:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch" , "5:Dense;Fast;GFTT;MSER;ORB;SIFT;Star;SURF;BRISK;AGAST;KAZE;AKAZE;SuperPointTorch", "Keypoint detector.");
PARAMETER_COND(Feature2D, 2Descriptor, QString, FINDOBJECT_NONFREE, "3:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "2:Brief;ORB;SIFT;SURF;BRISK;FREAK;KAZE;AKAZE;LUCID;LATCH;DAISY;SuperPointTorch", "Keypoint descriptor.");
#endif
PARAMETER(Feature2D, 3MaxFeatures, int, 0, "Maximum features per image. If the number of features extracted is over this threshold, only X features with the highest response are kept. 0 means all features are kept.");
PARAMETER(Feature2D, 4Affine, bool, false, "(ASIFT) Extract features on multiple affine transformations of the image.");
PARAMETER(Feature2D, 5AffineCount, int, 6, "(ASIFT) Higher the value, more affine transformations will be done.");
PARAMETER(Feature2D, 6SubPix, bool, false, "Refines the corner locations. With SIFT/SURF, features are already subpixel, so no need to activate this.");
PARAMETER(Feature2D, 7SubPixWinSize, int, 3, "Half of the side length of the search window. For example, if winSize=Size(5,5) , then a 5*2+1 x 5*2+1 = 11 x 11 search window is used.");
PARAMETER(Feature2D, 8SubPixIterations, int, 30, "The process of corner position refinement stops after X iterations.");
PARAMETER(Feature2D, 9SubPixEps, float, 0.02f, "The process of corner position refinement stops when the corner position moves by less than epsilon on some iteration.");
PARAMETER(Feature2D, Brief_bytes, int, 32, "Bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.");
#if CV_MAJOR_VERSION < 3
PARAMETER(Feature2D, Dense_initFeatureScale, float, 1.f, "");
PARAMETER(Feature2D, Dense_featureScaleLevels, int, 1, "");
PARAMETER(Feature2D, Dense_featureScaleMul, float, 0.1f, "");
PARAMETER(Feature2D, Dense_initXyStep, int, 6, "");
PARAMETER(Feature2D, Dense_initImgBound, int, 0, "");
PARAMETER(Feature2D, Dense_varyXyStepWithScale, bool, true, "");
PARAMETER(Feature2D, Dense_varyImgBoundWithScale, bool, false, "");
#endif
PARAMETER(Feature2D, Fast_threshold, int, 10, "Threshold on difference between intensity of the central pixel and pixels of a circle around this pixel.");
PARAMETER(Feature2D, Fast_nonmaxSuppression, bool, true, "If true, non-maximum suppression is applied to detected corners (keypoints).");
PARAMETER(Feature2D, Fast_gpu, bool, false, "GPU-FAST: Use GPU version of FAST. This option is enabled only if OpenCV is built with CUDA and GPUs are detected.");
PARAMETER(Feature2D, Fast_keypointsRatio, double, 0.05, "Used with FAST GPU (OpenCV 2).");
PARAMETER(Feature2D, Fast_maxNpoints, int, 5000, "Used with FAST GPU (OpenCV 3).");
PARAMETER(Feature2D, AGAST_threshold, int, 10, "Threshold on difference between intensity of the central pixel and pixels of a circle around this pixel.");
PARAMETER(Feature2D, AGAST_nonmaxSuppression, bool, true, "If true, non-maximum suppression is applied to detected corners (keypoints).");
PARAMETER(Feature2D, KAZE_extended, bool, false, "Set to enable extraction of extended (128-byte) descriptor.");
PARAMETER(Feature2D, KAZE_upright, bool, false, "Set to enable use of upright descriptors (non rotation-invariant).");
PARAMETER(Feature2D, KAZE_threshold, float, 0.001f, "Detector response threshold to accept point");
PARAMETER(Feature2D, KAZE_nOctaves, int, 4, "Maximum octave evolution of the image.");
PARAMETER(Feature2D, KAZE_nOctaveLayers, int, 4, "Default number of sublevels per scale level.");
PARAMETER(Feature2D, AKAZE_descriptorSize, int, 0, "Size of the descriptor in bits. 0 -> Full size.");
PARAMETER(Feature2D, AKAZE_descriptorChannels, int, 3, "Number of channels in the descriptor (1, 2, 3).");
PARAMETER(Feature2D, AKAZE_threshold, float, 0.001f, "Detector response threshold to accept point.");
PARAMETER(Feature2D, AKAZE_nOctaves, int, 4, "Maximum octave evolution of the image.");
PARAMETER(Feature2D, AKAZE_nOctaveLayers, int, 4, "Default number of sublevels per scale level.");
PARAMETER(Feature2D, GFTT_maxCorners, int, 1000, "Maximum number of corners to return. If there are more corners than are found, the strongest of them is returned.");
PARAMETER(Feature2D, GFTT_qualityLevel, double, 0.01, "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.");
PARAMETER(Feature2D, GFTT_minDistance, double, 1, "Minimum possible Euclidean distance between the returned corners.");
PARAMETER(Feature2D, GFTT_blockSize, int, 3, "Size of an average block for computing a derivative covariation matrix over each pixel neighborhood. See cornerEigenValsAndVecs.");
PARAMETER(Feature2D, GFTT_useHarrisDetector, bool, false, "Parameter indicating whether to use a Harris detector (see cornerHarris) or cornerMinEigenVal.");
PARAMETER(Feature2D, GFTT_k, double, 0.04, "Free parameter of the Harris detector.");
PARAMETER(Feature2D, ORB_nFeatures, int, 500, "The maximum number of features to retain.");
PARAMETER(Feature2D, ORB_scaleFactor, float, 1.2f, "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.");
PARAMETER(Feature2D, ORB_nLevels, int, 8, "The number of pyramid levels. The smallest level will have linear size equal to input_image_linear_size/pow(scaleFactor, nlevels).");
PARAMETER(Feature2D, ORB_edgeThreshold, int, 31, "This is size of the border where the features are not detected. It should roughly match the patchSize parameter.");
PARAMETER(Feature2D, ORB_firstLevel, int, 0, "It should be 0 in the current implementation.");
PARAMETER(Feature2D, ORB_WTA_K, int, 2, "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).");
PARAMETER(Feature2D, ORB_scoreType, int, 0, "The default HARRIS_SCORE=0 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=1 is alternative value of the parameter that produces slightly less stable keypoints, but it is a little faster to compute.");
PARAMETER(Feature2D, ORB_patchSize, int, 31, "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.");
PARAMETER(Feature2D, ORB_gpu, bool, false, "GPU-ORB: Use GPU version of ORB. This option is enabled only if OpenCV is built with CUDA and GPUs are detected.");
PARAMETER(Feature2D, ORB_blurForDescriptor, bool, false, "GPU-ORB: blurForDescriptor parameter (OpenCV 3).");
PARAMETER(Feature2D, MSER_delta, int, 5, "");
PARAMETER(Feature2D, MSER_minArea, int, 60, "");
PARAMETER(Feature2D, MSER_maxArea, int, 14400, "");
PARAMETER(Feature2D, MSER_maxVariation, double, 0.25, "");
PARAMETER(Feature2D, MSER_minDiversity, double, 0.2, "");
PARAMETER(Feature2D, MSER_maxEvolution, int, 200, "");
PARAMETER(Feature2D, MSER_areaThreshold, double, 1.01, "");
PARAMETER(Feature2D, MSER_minMargin, double, 0.003, "");
PARAMETER(Feature2D, MSER_edgeBlurSize, int, 5, "");
PARAMETER(Feature2D, SIFT_nfeatures, int, 0, "The number of best features to retain. The features are ranked by their scores (measured in SIFT algorithm as the local contrast).");
PARAMETER(Feature2D, SIFT_nOctaveLayers, int, 3, "The number of layers in each octave. 3 is the value used in D. Lowe paper. The number of octaves is computed automatically from the image resolution.");
PARAMETER(Feature2D, SIFT_contrastThreshold, double, 0.04, "The contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions. The larger the threshold, the less features are produced by the detector.");
PARAMETER(Feature2D, SIFT_edgeThreshold, double, 10, "The threshold used to filter out edge-like features. Note that the its meaning is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are filtered out (more features are retained).");
PARAMETER(Feature2D, SIFT_sigma, double, 1.6, "The sigma of the Gaussian applied to the input image at the octave #0. If your image is captured with a weak camera with soft lenses, you might want to reduce the number.");
PARAMETER(Feature2D, SIFT_rootSIFT, bool, false, "RootSIFT descriptors.");
PARAMETER(Feature2D, SURF_hessianThreshold, double, 600.0, "Threshold for hessian keypoint detector used in SURF.");
PARAMETER(Feature2D, SURF_nOctaves, int, 4, "Number of pyramid octaves the keypoint detector will use.");
PARAMETER(Feature2D, SURF_nOctaveLayers, int, 2, "Number of octave layers within each octave.");
PARAMETER(Feature2D, SURF_extended, bool, true, "Extended descriptor flag (true - use extended 128-element descriptors; false - use 64-element descriptors).");
PARAMETER(Feature2D, SURF_upright, bool, false, "Up-right or rotated features flag (true - do not compute orientation of features; false - compute orientation).");
PARAMETER(Feature2D, SURF_gpu, bool, false, "GPU-SURF: Use GPU version of SURF. This option is enabled only if OpenCV is built with CUDA and GPUs are detected.");
PARAMETER(Feature2D, SURF_keypointsRatio, float, 0.01f, "Used with SURF GPU.");
PARAMETER(Feature2D, Star_maxSize, int, 45, "");
PARAMETER(Feature2D, Star_responseThreshold, int, 30, "");
PARAMETER(Feature2D, Star_lineThresholdProjected, int, 10, "");
PARAMETER(Feature2D, Star_lineThresholdBinarized, int, 8, "");
PARAMETER(Feature2D, Star_suppressNonmaxSize, int, 5, "");
PARAMETER(Feature2D, BRISK_thresh, int, 30, "FAST/AGAST detection threshold score.");
PARAMETER(Feature2D, BRISK_octaves, int, 3, "Detection octaves. Use 0 to do single scale.");
PARAMETER(Feature2D, BRISK_patternScale, float, 1.0f, "Apply this scale to the pattern used for sampling the neighbourhood of a keypoint.");
PARAMETER(Feature2D, FREAK_orientationNormalized, bool, true, "Enable orientation normalization.");
PARAMETER(Feature2D, FREAK_scaleNormalized, bool, true, "Enable scale normalization.");
PARAMETER(Feature2D, FREAK_patternScale, float, 22.0f, "Scaling of the description pattern.");
PARAMETER(Feature2D, FREAK_nOctaves, int, 4, "Number of octaves covered by the detected keypoints.");
PARAMETER(Feature2D, LUCID_kernel, int, 1, "Kernel for descriptor construction, where 1=3x3, 2=5x5, 3=7x7 and so forth.");
PARAMETER(Feature2D, LUCID_blur_kernel, int, 2, "Kernel for blurring image prior to descriptor construction, where 1=3x3, 2=5x5, 3=7x7 and so forth.");
PARAMETER(Feature2D, LATCH_bytes, int, 32, "Size of the descriptor - can be 64, 32, 16, 8, 4, 2 or 1.");
PARAMETER(Feature2D, LATCH_rotationInvariance, bool, true, "Whether or not the descriptor should compansate for orientation changes.");
PARAMETER(Feature2D, LATCH_half_ssd_size, int, 3, "The size of half of the mini-patches size. For example, if we would like to compare triplets of patches of size 7x7x then the half_ssd_size should be (7-1)/2 = 3.");
PARAMETER(Feature2D, DAISY_radius, float, 15, "Radius of the descriptor at the initial scale.");
PARAMETER(Feature2D, DAISY_q_radius, int, 3, "Amount of radial range division quantity.");
PARAMETER(Feature2D, DAISY_q_theta, int, 8, "Amount of angular range division quantity.");
PARAMETER(Feature2D, DAISY_q_hist, int, 8, "Amount of gradient orientations range division quantity.");
PARAMETER(Feature2D, DAISY_interpolation, bool, true, "Switch to disable interpolation for speed improvement at minor quality loss.");
PARAMETER(Feature2D, DAISY_use_orientation, bool, false, "Sample patterns using keypoints orientation, disabled by default.");
PARAMETER(Feature2D, SuperPointTorch_modelPath, QString, "", "[Required] Path to pre-trained weights Torch file of SuperPoint (*.pt).");
PARAMETER(Feature2D, SuperPointTorch_threshold, float, 0.2, "Detector response threshold to accept keypoint.");
PARAMETER(Feature2D, SuperPointTorch_NMS, bool, true, "If true, non-maximum suppression is applied to detected keypoints.");
PARAMETER(Feature2D, SuperPointTorch_NMS_radius, int, 4, "[%s=true] Minimum distance (pixels) between keypoints");
PARAMETER(Feature2D, SuperPointTorch_cuda, bool, false, "Use Cuda device for Torch, otherwise CPU device is used by default.");
PARAMETER_COND(NearestNeighbor, 1Strategy, QString, FINDOBJECT_NONFREE || CV_MAJOR_VERSION >= 3, "1:Linear;KDTree;KMeans;Composite;Autotuned;Lsh;BruteForce", "6:Linear;KDTree;KMeans;Composite;Autotuned;Lsh;BruteForce", "Nearest neighbor strategy.");
PARAMETER_COND(NearestNeighbor, 2Distance_type, QString, FINDOBJECT_NONFREE || CV_MAJOR_VERSION >= 3, "0:EUCLIDEAN_L2;MANHATTAN_L1;MINKOWSKI;MAX;HIST_INTERSECT;HELLINGER;CHI_SQUARE_CS;KULLBACK_LEIBLER_KL;HAMMING", "1:EUCLIDEAN_L2;MANHATTAN_L1;MINKOWSKI;MAX;HIST_INTERSECT;HELLINGER;CHI_SQUARE_CS;KULLBACK_LEIBLER_KL;HAMMING", "Distance type.");
PARAMETER(NearestNeighbor, 3nndrRatioUsed, bool, true, "Nearest neighbor distance ratio approach to accept the best match.");
PARAMETER(NearestNeighbor, 4nndrRatio, float, 0.8f, "Nearest neighbor distance ratio.");
PARAMETER(NearestNeighbor, 5minDistanceUsed, bool, false, "Minimum distance with the nearest descriptor to accept a match.");
PARAMETER(NearestNeighbor, 6minDistance, float, 1.6f, "Minimum distance. You can look at top of this panel where minimum and maximum distances are shown to properly set this parameter depending of the descriptor used.");
PARAMETER(NearestNeighbor, 7ConvertBinToFloat, bool, false, "Convert binary descriptor to float before quantization, so you can use FLANN strategies with them.");
PARAMETER(NearestNeighbor, BruteForce_gpu, bool, false, "Brute force GPU");
PARAMETER(NearestNeighbor, search_checks, int, 32, "The number of times the tree(s) in the index should be recursively traversed. A higher value for this parameter would give better search precision, but also take more time. If automatic configuration was used when the index was created, the number of checks required to achieve the specified precision was also computed, in which case this parameter is ignored.");
PARAMETER(NearestNeighbor, search_eps, float, 0, "");
PARAMETER(NearestNeighbor, search_sorted, bool, true, "");
PARAMETER(NearestNeighbor, KDTree_trees, int, 4, "The number of parallel kd-trees to use. Good values are in the range [1..16].");
PARAMETER(NearestNeighbor, Composite_trees, int, 4, "The number of parallel kd-trees to use. Good values are in the range [1..16].");
PARAMETER(NearestNeighbor, Composite_branching, int, 32, "The branching factor to use for the hierarchical k-means tree.");
PARAMETER(NearestNeighbor, Composite_iterations, int, 11, "The maximum number of iterations to use in the k-means clustering stage when building the k-means tree. A value of -1 used here means that the k-means clustering should be iterated until convergence.");
PARAMETER(NearestNeighbor, Composite_centers_init, QString, "0:RANDOM;GONZALES;KMEANSPP", "The algorithm to use for selecting the initial centers when performing a k-means clustering step. The possible values are CENTERS_RANDOM (picks the initial cluster centers randomly), CENTERS_GONZALES (picks the initial centers using Gonzales algorithm) and CENTERS_KMEANSPP (picks the initial centers using the algorithm suggested in arthur_kmeanspp_2007 ).");
PARAMETER(NearestNeighbor, Composite_cb_index, double, 0.2, "This parameter (cluster boundary index) influences the way exploration is performed in the hierarchical kmeans tree. When cb_index is zero the next kmeans domain to be explored is chosen to be the one with the closest center. A value greater then zero also takes into account the size of the domain.");
PARAMETER(NearestNeighbor, Autotuned_target_precision, double, 0.8, "Is a number between 0 and 1 specifying the percentage of the approximate nearest-neighbor searches that return the exact nearest-neighbor. Using a higher value for this parameter gives more accurate results, but the search takes longer. The optimum value usually depends on the application.");
PARAMETER(NearestNeighbor, Autotuned_build_weight, double, 0.01, "Specifies the importance of the index build time raported to the nearest-neighbor search time. In some applications its acceptable for the index build step to take a long time if the subsequent searches in the index can be performed very fast. In other applications its required that the index be build as fast as possible even if that leads to slightly longer search times.");
PARAMETER(NearestNeighbor, Autotuned_memory_weight, double, 0, "Is used to specify the tradeoff between time (index build time and search time) and memory used by the index. A value less than 1 gives more importance to the time spent and a value greater than 1 gives more importance to the memory usage.");
PARAMETER(NearestNeighbor, Autotuned_sample_fraction, double, 0.1, "Is a number between 0 and 1 indicating what fraction of the dataset to use in the automatic parameter configuration algorithm. Running the algorithm on the full dataset gives the most accurate results, but for very large datasets can take longer than desired. In such case using just a fraction of the data helps speeding up this algorithm while still giving good approximations of the optimum parameters.");
PARAMETER(NearestNeighbor, KMeans_branching, int, 32, "The branching factor to use for the hierarchical k-means tree.");
PARAMETER(NearestNeighbor, KMeans_iterations, int, 11, "The maximum number of iterations to use in the k-means clustering stage when building the k-means tree. A value of -1 used here means that the k-means clustering should be iterated until convergence.");
PARAMETER(NearestNeighbor, KMeans_centers_init, QString, "0:RANDOM;GONZALES;KMEANSPP", "The algorithm to use for selecting the initial centers when performing a k-means clustering step. The possible values are CENTERS_RANDOM (picks the initial cluster centers randomly), CENTERS_GONZALES (picks the initial centers using Gonzales algorithm) and CENTERS_KMEANSPP (picks the initial centers using the algorithm suggested in arthur_kmeanspp_2007 ).");
PARAMETER(NearestNeighbor, KMeans_cb_index, double, 0.2, "This parameter (cluster boundary index) influences the way exploration is performed in the hierarchical kmeans tree. When cb_index is zero the next kmeans domain to be explored is chosen to be the one with the closest center. A value greater then zero also takes into account the size of the domain.");
PARAMETER(NearestNeighbor, Lsh_table_number, int, 12, "The number of hash tables to use (between 10 and 30 usually).");
PARAMETER(NearestNeighbor, Lsh_key_size, int, 20, "The size of the hash key in bits (between 10 and 20 usually).");
PARAMETER(NearestNeighbor, Lsh_multi_probe_level, int, 2, "The number of bits to shift to check for neighboring buckets (0 is regular LSH, 2 is recommended).");
PARAMETER(General, autoStartCamera, bool, false, "Automatically start the camera when the application is opened.");
PARAMETER(General, autoUpdateObjects, bool, true, "Automatically update objects on every parameter changes, otherwise you would need to press \"Update objects\" on the objects panel.");
PARAMETER(General, nextObjID, uint, 1, "Next object ID to use.");
PARAMETER(General, imageFormats, QString, "*.png *.jpg *.bmp *.tiff *.ppm *.pgm", "Image formats supported.");
PARAMETER(General, videoFormats, QString, "*.avi *.m4v *.mp4", "Video formats supported.");
PARAMETER(General, mirrorView, bool, false, "Flip the camera image horizontally (like all webcam applications).");
PARAMETER(General, invertedSearch, bool, true, "Instead of matching descriptors from the objects to those in a vocabulary created with descriptors extracted from the scene, we create a vocabulary from all the objects' descriptors and we match scene's descriptors to this vocabulary. It is the inverted search mode.");
PARAMETER(General, controlsShown, bool, false, "Show play/image seek controls (useful with video file and directory of images modes).");
PARAMETER(General, threads, int, 1, "Number of threads used for objects matching and homography computation. 0 means as many threads as objects. On InvertedSearch mode, multi-threading has only effect on homography computation.");
PARAMETER(General, multiDetection, bool, false, "Multiple detection of the same object.");
PARAMETER(General, multiDetectionRadius, int, 30, "Ignore detection of the same object in X pixels radius of the previous detections.");
PARAMETER(General, port, int, 0, "Port on objects detected are published. If port=0, a port is chosen automatically.")
PARAMETER(General, autoScroll, bool, true, "Auto scroll to detected object in Objects panel.");
PARAMETER(General, vocabularyFixed, bool, false, "If the vocabulary is fixed, no new words will be added to it when adding new objects.");
PARAMETER(General, vocabularyIncremental, bool, false, "The vocabulary is created incrementally. When new objects are added, their descriptors are compared to those already in vocabulary to find if the visual word already exist or not. \"NearestNeighbor/nndrRatio\" and \"NearestNeighbor/minDistance\" are used to compare descriptors.");
PARAMETER(General, vocabularyUpdateMinWords, int, 2000, "When the vocabulary is incremental (see \"General/vocabularyIncremental\"), after X words added to vocabulary, the internal index is updated with new words. This parameter lets avoiding to reconstruct the whole nearest neighbor index after each time descriptors of an object are added to vocabulary. 0 means no incremental update.");
PARAMETER(General, sendNoObjDetectedEvents, bool, true, "When there are no objects detected, send an empty object detection event.");
PARAMETER(General, autoPauseOnDetection, bool, false, "Auto pause the camera when an object is detected.");
PARAMETER(General, autoScreenshotPath, QString, "", "Path to a directory to save screenshot of the current camera view when there is a detection.");
PARAMETER(General, debug, bool, false, "Show debug logs on terminal.");
PARAMETER(Homography, homographyComputed, bool, true, "Compute homography? On ROS, this is required to publish objects detected.");
PARAMETER(Homography, method, QString, "1:LMEDS;RANSAC;RHO", "Type of the robust estimation algorithm: least-median algorithm or RANSAC algorithm.");
PARAMETER(Homography, ransacReprojThr, double, 3.0, "Maximum allowed reprojection error to treat a point pair as an inlier (used in the RANSAC method only). It usually makes sense to set this parameter somewhere in the range of 1 to 10.");
#if CV_MAJOR_VERSION >= 3
PARAMETER(Homography, maxIterations, int, 2000, "The maximum number of RANSAC iterations, 2000 is the maximum it can be.");
PARAMETER(Homography, confidence, double, 0.995, "Confidence level, between 0 and 1.");
#endif
PARAMETER(Homography, minimumInliers, int, 10, "Minimum inliers to accept the homography. Value must be >= 4.");
PARAMETER(Homography, ignoreWhenAllInliers, bool, false, "Ignore homography when all features are inliers (sometimes when the homography doesn't converge, it returns the best homography with all features as inliers).");
PARAMETER(Homography, rectBorderWidth, int, 4, "Homography rectangle border width.");
PARAMETER(Homography, allCornersVisible, bool, false, "All corners of the detected object must be visible in the scene.");
PARAMETER(Homography, minAngle, int, 0, "(Degrees) Homography minimum angle. Set 0 to disable. When the angle is very small, this is a good indication that the homography is wrong. A good value is over 60 degrees.");
PARAMETER(Homography, opticalFlow, bool, false, "Activate optical flow to refine matched features before computing the homography.");
PARAMETER(Homography, opticalFlowWinSize, int, 16, "Size of the search window at each pyramid level.");
PARAMETER(Homography, opticalFlowMaxLevel, int, 3, "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.");
PARAMETER(Homography, opticalFlowIterations, int, 30, "Specifying the termination criteria of the iterative search algorithm (after the specified maximum number of iterations).");
PARAMETER(Homography, opticalFlowEps, float, 0.01f, "Specifying the termination criteria of the iterative search algorithm (when the search window moves by less than epsilon).");
public:
virtual ~Settings(){}
static QString workingDirectory();
static QString iniDefaultPath();
static QString iniDefaultFileName() {return "config.ini";}
static QString iniPath();
static ParametersMap init(const QString & fileName);
static ParametersMap loadSettings(const QString & fileName = QString());
static void loadWindowSettings(QByteArray & windowGeometry, QByteArray & windowState, const QString & fileName = QString());
static void saveSettings(const QString & fileName = QString());
static void saveWindowSettings(const QByteArray & windowGeometry, const QByteArray & windowState, const QString & fileName = QString());
static const ParametersMap & getDefaultParameters() {return defaultParameters_;}
static const ParametersMap & getParameters() {return parameters_;}
static const ParametersType & getParametersType() {return parametersType_;}
static const DescriptionsMap & getDescriptions() {return descriptions_;}
static void setParameter(const QString & key, const QVariant & value) {if(parameters_.contains(key))parameters_[key] = value;}
static void resetParameter(const QString & key) {if(defaultParameters_.contains(key)) parameters_.insert(key, defaultParameters_.value(key));}
static QVariant getParameter(const QString & key) {return parameters_.value(key, QVariant());}
static Feature2D * createKeypointDetector();
static Feature2D * createDescriptorExtractor();
static QString currentDescriptorType();
static QString currentDetectorType();
static QString currentNearestNeighborType();
static bool isBruteForceNearestNeighbor();
static cv::flann::IndexParams * createFlannIndexParams();
static cvflann::flann_distance_t getFlannDistanceType();
static int getHomographyMethod();
private:
Settings(){}
private:
static ParametersMap defaultParameters_;
static ParametersMap parameters_;
static ParametersType parametersType_;
static DescriptionsMap descriptions_;
static Settings dummyInit_;
static QString iniPath_;
};
class Feature2D
{
public:
#if CV_MAJOR_VERSION < 3
Feature2D(cv::Ptr<cv::FeatureDetector> featureDetector);
Feature2D(cv::Ptr<cv::DescriptorExtractor> descriptorExtractor);
#endif
Feature2D(cv::Ptr<cv::Feature2D> feature2D);
Feature2D() {}
virtual ~Feature2D() {}
virtual void detect(const cv::Mat & image,
std::vector<cv::KeyPoint> & keypoints,
const cv::Mat & mask = cv::Mat());
virtual void compute(const cv::Mat & image,
std::vector<cv::KeyPoint> & keypoints,
cv::Mat & descriptors);
virtual void detectAndCompute(const cv::Mat & image,
std::vector<cv::KeyPoint> & keypoints,
cv::Mat & descriptors,
const cv::Mat & mask = cv::Mat());
private:
#if CV_MAJOR_VERSION < 3
cv::Ptr<cv::FeatureDetector> featureDetector_;
cv::Ptr<cv::DescriptorExtractor> descriptorExtractor_;
#endif
cv::Ptr<cv::Feature2D> feature2D_;
};
} // namespace find_object
#endif /* SETTINGS_H_ */
@@ -1,79 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 TCPSERVER_H_
#define TCPSERVER_H_
#include "find_object/FindObjectExp.h" // DLL export/import defines
#include "find_object/DetectionInfo.h"
#include <opencv2/opencv.hpp>
#include <QtNetwork/QTcpServer>
namespace find_object {
class QNetworkSession;
class FINDOBJECT_EXP TcpServer : public QTcpServer
{
Q_OBJECT
public:
enum Service {
kAddObject, // id fileName imageSize image
kRemoveObject, // id
kDetectObject // image
};
public:
TcpServer(quint16 port = 0, QObject * parent = 0);
QHostAddress getHostAddress() const;
quint16 getPort() const;
public Q_SLOTS:
void publishDetectionInfo(const find_object::DetectionInfo & info);
private Q_SLOTS:
void addClient();
void readReceivedData();
void displayError(QAbstractSocket::SocketError socketError);
void connectionLost();
Q_SIGNALS:
void addObject(const cv::Mat &, int, const QString &);
void removeObject(int);
void detectObject(const cv::Mat &);
private:
QMap<int, quint64> blockSizes_;
};
} // namespace find_object
#endif /* TCPSERVER_H_ */
@@ -1,77 +0,0 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UDESTROYER_H
#define UDESTROYER_H
//#include "utilite/UtiLiteExp.h" // DLL export/import defines
/**
* This class is used to delete a dynamically created
* objects. It was mainly designed to remove dynamically created Singleton.
* Created on the stack of a Singleton, when the
* application is finished, his destructor make sure that the
* Singleton is deleted.
*
*/
template <class T>
class UDestroyer
{
public:
/**
* The constructor. Set the doomed object (take ownership of the object). The object is deleted
* when this object is deleted.
*/
UDestroyer(T* doomed = 0) : doomed_(doomed) {}
~UDestroyer()
{
if(doomed_)
{
delete doomed_;
doomed_ = 0;
}
}
/**
* Set the doomed object. If a doomed object is already set, the function returns false.
* @param doomed the doomed object
* @return false if an object is already set and the new object is not null, otherwise true
*/
bool setDoomed(T* doomed)
{
if(doomed_ && doomed)
{
return false;
}
doomed_ = doomed;
return true;
}
private:
// Prevent users from making copies of a
// Destroyer to avoid double deletion:
UDestroyer(const UDestroyer<T>&);
void operator=(const UDestroyer<T>&);
private:
T* doomed_;
};
#endif // UDESTROYER_H
@@ -1,536 +0,0 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ULOGGER_H
#define ULOGGER_H
#include "find_object/FindObjectExp.h" // DLL export/import defines
#include "find_object/utilite/UMutex.h"
#include "find_object/utilite/UDestroyer.h"
#include <stdio.h>
#include <time.h>
#include <string>
#include <vector>
#include <stdarg.h>
#if _MSC_VER
#undef min
#undef max
#endif
/**
* \file ULogger.h
* \brief ULogger class and convenient macros
*
* This contains macros useful for logging a message anywhere in the
* application. Once the ULogger is set, use these macros like a printf to
* print debug messages.
*/
/*
* Convenient macros for logging...
*/
#define ULOGGER_LOG(level, ...) ULogger::write(level, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define ULOGGER_DEBUG(...) ULOGGER_LOG(ULogger::kDebug, __VA_ARGS__)
#define ULOGGER_INFO(...) ULOGGER_LOG(ULogger::kInfo, __VA_ARGS__)
#define ULOGGER_WARN(...) ULOGGER_LOG(ULogger::kWarning, __VA_ARGS__)
#define ULOGGER_ERROR(...) ULOGGER_LOG(ULogger::kError, __VA_ARGS__)
#define ULOGGER_FATAL(...) ULOGGER_LOG(ULogger::kFatal, __VA_ARGS__)
#define UDEBUG(...) ULOGGER_DEBUG(__VA_ARGS__)
#define UINFO(...) ULOGGER_INFO(__VA_ARGS__)
#define UWARN(...) ULOGGER_WARN(__VA_ARGS__)
#define UERROR(...) ULOGGER_ERROR(__VA_ARGS__)
#define UFATAL(...) ULOGGER_FATAL(__VA_ARGS__)
#define UASSERT(condition) if(!(condition)) ULogger::write(ULogger::kFatal, __FILE__, __LINE__, __FUNCTION__, "Condition (%s) not met!", #condition)
#define UASSERT_MSG(condition, msg_str) if(!(condition)) ULogger::write(ULogger::kFatal, __FILE__, __LINE__, __FUNCTION__, "Condition (%s) not met! [%s]", #condition, msg_str)
/**
* \def UDEBUG(...)
* Print a debug level message in the logger. Format is the same as a printf:
* @code
* UDEBUG("This is a debug message with the number %d", 42);
* @endcode
*/
/**
* \def UINFO(...)
* Print a information level message in the logger. Format is the same as a printf:
* @code
* UINFO("This is a information message with the number %d", 42);
* @endcode
*/
/**
* \def UWARN(...)
* Print a warning level message in the logger. Format is the same as a printf:
* @code
* UWARN("This is a warning message with the number %d", 42);
* @endcode
*/
/**
* \def UERROR(...)
* Print an error level message in the logger. Format is the same as a printf:
* @code
* UERROR("This is an error message with the number %d", 42);
* @endcode
*/
/**
* \def UFATAL(...)
* Print a fatal error level message in the logger. The application will exit on
* fatal error. Format is the same as a printf:
* @code
* UFATAL("This is a fatal error message with the number %d", 42);
* @endcode
*/
/**
* \def UASSERT(condition, ...)
* Print a fatal error level message in the logger if condition is not met. The application will exit on
* fatal error. Format is the same as a printf:
* @code
* UASSERT(a!=42, "This is a fatal error message with the number %d", 42);
* @endcode
*/
/**
* This class is used to log messages with time on a console, in a file
* and/or with an event. At the start of the application, call
* ULogger::setType() with the type of the logger you want (see ULogger::Type, the type of the output
* can be changed at the run-time.). To use it,
* simply call the convenient macros UDEBUG(), UINFO(), UWARN(), UERROR(), UFATAL() depending of
* the severity of the message. You can disable some messages by setting the logger
* level ULogger::setLevel() to severity you want, defined by ULogger::Level. A fatal message
* will make the application to exit, printing the message on console (whatever the logger type) and
* posting a ULogEvent (synchronously... see UEventsManager::post()) before exiting.
*
* The display of the logged messages can be modified:
* - If you don't want the level label, set ULogger::setPrintLevel() to false.
* - If you don't want the time label, set ULogger::setPrintTime() to false.
* - If you don't want the end of line added, set ULogger::setPrintEndline() to false.
* - If you don't the full path of the message, set ULogger::setPrintWhereFullPath() to false.
* - If you don't the path of the message, set ULogger::setPrintWhere() to false.
*
* When using a file logger (kTypeLogger), it can be useful in some
* application to buffer messages before writing them to hard drive (avoiding
* hard drive latencies). You can set ULogger::setBuffered() to true to do that. When the
* buffered messages will be written to file on appllciation exit (ULogger destructor) or when
* ULogger::flush() is called.
*
* If you want the application to exit on a lower severity level than kFatal,
* you can set ULogger::setExitLevel() to any ULogger::Type you want.
*
* Example:
* @code
* #include <utilite/ULogger.h>
* int main(int argc, char * argv[])
* {
* // Set the logger type. The choices are kTypeConsole,
* // kTypeFile or kTypeNoLog (nothing is logged).
* ULogger::setType(ULogger::kTypeConsole);
*
* // Set the logger severity level (kDebug, kInfo, kWarning, kError, kFatal).
* // All log entries under the severity level are not logged. Here,
* // only debug messages are not logged.
* ULogger::setLevel(ULogger::kInfo);
*
* // Use a predefined Macro to easy logging. It can be
* // called anywhere in the application as the logger is
* // a Singleton.
* UDEBUG("This message won't be logged because the "
* "severity level of the logger is set to kInfo.");
*
* UINFO("This message is logged.");
*
* UWARN("A warning message...");
*
* UERROR("An error message with code %d.", 42);
*
* return 0;
* }
* @endcode
* Output:
* @code
* [ INFO] (2010-09-25 18:08:20) main.cpp:18::main() This message is logged.
* [ WARN] (2010-09-25 18:08:20) main.cpp:20::main() A warning message...
* [ERROR] (2010-09-25 18:08:20) main.cpp:22::main() An error message with code 42.
* @endcode
*
* Another useful form of the ULogger is to use it with the UTimer class. Here an example:
* @code
* #include <utilite/ULogger.h>
* #include <utilite/UTimer.h>
* ...
* UTimer timer; // automatically starts
* // do some works for part A
* UINFO("Time for part A = %f s", timer.ticks());
* // do some works for part B
* UINFO("Time for part B = %f s", timer.ticks());
* // do some works for part C
* UINFO("Time for part C = %f s", timer.ticks());
* ...
* @endcode
*
* @see setType()
* @see setLevel()
* @see UDEBUG(), UINFO(), UWARN(), UERROR(), UFATAL()
*
*/
class FINDOBJECT_EXP ULogger
{
public:
/**
* The default log file name.
*/
static const std::string kDefaultLogFileName;
/**
* Loggers available:
* @code
* kTypeNoLog, kTypeConsole, kTypeFile
* @endcode
*/
enum Type{kTypeNoLog, kTypeConsole, kTypeFile};
/**
* Logger levels, from lowest severity to highest:
* @code
* kDebug, kInfo, kWarning, kError, kFatal
* @endcode
*/
enum Level{kDebug, kInfo, kWarning, kError, kFatal};
/**
* Set the type of the logger. When using kTypeFile, the parameter "fileName" would be
* changed (default is "./ULog.txt"), and optionally "append" if we want the
* logger to append messages to file or to overwrite the file.
* @param type the ULogger::Type of the logger.
* @param fileName file name used with a file logger type.
* @param append if true, the file isn't overwritten, otherwise it is.
*
* TODO : Can it be useful to have 2 or more types at the same time ? Print
* in console and file at the same time.
*/
static void setType(Type type, const std::string &fileName = kDefaultLogFileName, bool append = true);
static Type type() {return type_;}
// Setters
/**
* Print time: default true.
* @param printTime true to print time, otherwise set to false.
*/
static void setPrintTime(bool printTime) {printTime_ = printTime;}
static bool isPrintTime() {return printTime_;}
/**
* Print level: default true.
* @param printLevel true to print level, otherwise set to false.
*/
static void setPrintLevel(bool printLevel) {printLevel_ = printLevel;}
static bool isPrintLevel() {return printLevel_;}
/**
* Print end of line: default true.
* @param printLevel true to print end of line, otherwise set to false.
*/
static void setPrintEndline(bool printEndline) {printEndline_ = printEndline;}
static bool isPrintEndLine() {return printEndline_;}
/**
* Print text with color: default true.
* Dark green for Debug, white for Info, yellow for Warning, red for Error and Fatal.
* @param printColored true to print text with color, otherwise set to false.
*/
static void setPrintColored(bool printColored) {printColored_ = printColored;}
static bool isPrintColored() {return printColored_;}
/**
* Print where is this message in source code: default true.
* @param printWhere true to print where, otherwise set to false.
*/
static void setPrintWhere(bool printWhere) {printWhere_ = printWhere;}
static bool isPrintWhere() {return printWhere_;}
/**
* Print the full path: default true. ULogger::setPrintWhere() must be true to have path printed.
* @param printWhereFullPath true to print the full path, otherwise set to false.
*/
static void setPrintWhereFullPath(bool printWhereFullPath) {printWhereFullPath_ = printWhereFullPath;}
static bool isPrintWhereFullPath() {return printWhereFullPath_;}
/**
* Set is the logger buffers messages, default false. When true, the messages are
* buffered until the application is closed or ULogger::flush() is called.
* @see ULogger::flush()
* @param buffered true to buffer messages, otherwise set to false.
*/
static void setBuffered(bool buffered);
static bool isBuffered() {return buffered_;}
/**
* Set logger level: default kInfo. All messages over the severity set
* are printed, other are ignored. The severity is from the lowest to
* highest:
* - kDebug
* - kInfo
* - kWarning
* - kError
* - kFatal
* @param level the minimum level of the messages printed.
*/
static void setLevel(ULogger::Level level) {level_ = level;}
static ULogger::Level level() {return level_;}
/**
* Make application to exit when a log with level is written (useful for debugging). The message is printed to
* console (whatever the logger type) and an ULogEvent is sent (synchronously... see UEventsManager::post()) before exiting.
*
* Note : A kFatal level will always exit whatever the level specified here.
*/
static void setExitLevel(ULogger::Level exitLevel) {exitLevel_ = exitLevel;}
static ULogger::Level exitLevel() {return exitLevel_;}
/**
* An ULogEvent is sent on each message logged at the specified level.
* Note : On message with level >= exitLevel, the event is sent synchronously (see UEventsManager::post()).
* @see ULogEvent
* @see setExitLevel()
*/
static void setEventLevel(ULogger::Level eventSentLevel) {eventLevel_ = eventSentLevel;}
static ULogger::Level eventLevel() {return eventLevel_;}
/**
* Reset to default parameters.
*/
static void reset();
/**
* Flush buffered messages.
* @see setBuffered()
*/
static void flush();
/**
* Write a message directly to logger without level handling.
* @param msg the message to write.
* @param ... the variable arguments
* @deprecated use UDEBUG(), UINFO(), UWARN(), UERROR() or UFATAL()
*/
static void write(const char* msg, ...);
/*
* Write a message to logger: use UDEBUG(), UINFO(), UWARN(), UERROR() or UFATAL() instead.
* @param level the log level of this message
* @param file the file path
* @param line the line in the file
* @param function the function name in which the message is logged
* @param msg the message to write
* @param ... the variable arguments
*/
static void write(ULogger::Level level,
const char * file,
int line,
const char *function,
const char* msg,
...);
/**
* Get the time in the format "2008-7-13 12:23:44".
* @param timeStr string were the time will be copied.
* @return the number of characters written, or 0 if an error occurred.
*/
static int getTime(std::string &timeStr);
protected:
/*
* This method is used to have a reference on the
* Logger. When no Logger exists, one is
* created. There is only one instance in the application.
* Must be protected by loggerMutex_.
* See the Singleton pattern for further explanation.
*
* @return the reference on the Logger
*/
static ULogger* getInstance();
/*
* Called only once in getInstance(). It can't be instanciated
* by the user.
*
* @see getInstance()
*/
ULogger() {}
/*
* Only called by a Destroyer.
* @see Destroyer
*/
virtual ~ULogger();
/*
* Flush buffered messages
*/
void _flush();
/*
* A Destroyer is used to remove a dynamicaly created
* Singleton. It is friend here to have access to the
* destructor.
*
* @see Destroyer
*/
friend class UDestroyer<ULogger>;
/*
* The log file name.
*/
static std::string logFileName_;
/*
* Default true, it doesn't overwrite the file.
*/
static bool append_;
private:
/*
* Create an instance according to type. See the Abstract factory
* pattern for further explanation.
* @see type_
* @return the reference on the new logger
*/
static ULogger* createInstance();
/*
* Write a message on the output with the format :
* "A message". Inherited class
* must override this method to output the message. It
* does nothing by default.
* @param msg the message to write.
* @param arg the variable arguments
*/
virtual void _write(const char* msg, va_list arg) {} // Do nothing by default
virtual void _writeStr(const char* msg) {} // Do nothing by default
private:
/*
* The Logger instance pointer.
*/
static ULogger* instance_;
/*
* The Logger's destroyer
*/
static UDestroyer<ULogger> destroyer_;
/*
* If the logger prints the time for each message.
* Default is true.
*/
static bool printTime_;
/*
* If the logger prints the level for each message.
* Default is true.
*/
static bool printLevel_;
/*
* If the logger prints the end line for each message.
* Default is true.
*/
static bool printEndline_;
/*
* If the logger prints text with color.
* Default is true.
*/
static bool printColored_;
/*
* If the logger prints where the message is logged (fileName::function():line).
* Default is true.
*/
static bool printWhere_;
/*
* If the logger prints the full path of the source file
* where the message is written. Only works when
* "printWhere_" is true.
* Default is false.
*/
static bool printWhereFullPath_;
/*
* If the logger limit the size of the "where" path to
* characters. If the path is over 8 characters, a "~"
* is added. Only works when "printWhereFullPath_" is false.
* Default is false.
*/
static bool limitWhereLength_;
/*
* The type of the logger.
*/
static Type type_;
/*
* The severity of the log.
*/
static Level level_;
/*
* The severity at which the application exits.
* Note : A FATAL level will always exit whatever the level specified here.
*/
static Level exitLevel_;
/*
* The severity at which the message is also sent in a ULogEvent.
*/
static Level eventLevel_;
static const char * levelName_[5];
/*
* Mutex used when accessing public functions.
*/
static UMutex loggerMutex_;
/*
* If the logger prints messages only when ULogger::flush() is called.
* Default is false.
*/
static bool buffered_;
static std::string bufferedMsgs_;
/*
* State attribute. This state happens when an exit level
* message is received.
* Messages received during this state are not logged.
* @see exitLevel_
*/
static bool exitingState_;
};
#endif // ULOGGER_H
@@ -1,179 +0,0 @@
/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* utilite is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UMUTEX_H
#define UMUTEX_H
#include <errno.h>
#ifdef WIN32
#include "find_object/utilite/UWin32.h"
#else
#include <pthread.h>
#endif
/**
* A mutex class.
*
* On a lock() call, the calling thread is blocked if the
* UMutex was previously locked by another thread. It is unblocked when unlock() is called.
*
* On Unix (not yet tested on Windows), UMutex is recursive: the same thread can
* call multiple times lock() without being blocked.
*
* Example:
* @code
* UMutex m; // Mutex shared with another thread(s).
* ...
* m.lock();
* // Data is protected here from the second thread
* //(assuming the second one protects also with the same mutex the same data).
* m.unlock();
*
* @endcode
*
* @see USemaphore
*/
class UMutex
{
public:
/**
* The constructor.
*/
UMutex()
{
#ifdef WIN32
InitializeCriticalSection(&C);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&M,&attr);
pthread_mutexattr_destroy(&attr);
#endif
}
virtual ~UMutex()
{
#ifdef WIN32
DeleteCriticalSection(&C);
#else
pthread_mutex_unlock(&M); pthread_mutex_destroy(&M);
#endif
}
/**
* Lock the mutex.
*/
int lock() const
{
#ifdef WIN32
EnterCriticalSection(&C); return 0;
#else
return pthread_mutex_lock(&M);
#endif
}
#ifdef WIN32
#if(_WIN32_WINNT >= 0x0400)
int lockTry() const
{
return (TryEnterCriticalSection(&C)?0:EBUSY);
}
#endif
#else
int lockTry() const
{
return pthread_mutex_trylock(&M);
}
#endif
/**
* Unlock the mutex.
*/
int unlock() const
{
#ifdef WIN32
LeaveCriticalSection(&C); return 0;
#else
return pthread_mutex_unlock(&M);
#endif
}
private:
#ifdef WIN32
mutable CRITICAL_SECTION C;
#else
mutable pthread_mutex_t M;
#endif
void operator=(UMutex &M) {}
UMutex( const UMutex &M ) {}
};
/**
* Automatically lock the referenced mutex on constructor and unlock mutex on destructor.
*
* Example:
* @code
* UMutex m; // Mutex shared with another thread(s).
* ...
* int myMethod()
* {
* UScopeMutex sm(m); // automatically lock the mutex m
* if(cond1)
* {
* return 1; // automatically unlock the mutex m
* }
* else if(cond2)
* {
* return 2; // automatically unlock the mutex m
* }
* return 0; // automatically unlock the mutex m
* }
*
* @endcode
*
* @see UMutex
*/
class UScopeMutex
{
public:
UScopeMutex(const UMutex & mutex) :
mutex_(mutex)
{
mutex_.lock();
}
// backward compatibility
UScopeMutex(UMutex * mutex) :
mutex_(*mutex)
{
mutex_.lock();
}
~UScopeMutex()
{
mutex_.unlock();
}
private:
const UMutex & mutex_;
};
#endif // UMUTEX_H
@@ -1,62 +0,0 @@
/////////////////////////////////////////////////////////////////////
// Written by Phillip Sitbon
// Copyright 2003
//
// Win32.h
// - Windows includes
//
/////////////////////////////////////////////////////////////////////
#ifndef _U_Win32_
#define _U_Win32_
#if !defined(_WINDOWS_)
// WIN32 Excludes
#ifdef WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
# define WIN32_LEAN_AND_MEAN
# define _PRSHT_H_
# define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
# define NOVIRTUALKEYCODES // VK_*
# define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_*
# define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
# define NOSYSMETRICS // SM_*
# define NOMENUS // MF_*
# define NOICONS // IDI_*
# define NOKEYSTATES // MK_*
# define NOSYSCOMMANDS // SC_*
# define NORASTEROPS // Binary and Tertiary raster ops
# define NOSHOWWINDOW // SW_*
# define OEMRESOURCE // OEM Resource values
# define NOATOM // Atom Manager routines
# define NOCLIPBOARD // Clipboard routines
# define NOCOLOR // Screen colors
# define NOCTLMGR // Control and Dialog routines
# define NODRAWTEXT // DrawText() and DT_*
# define NOGDI // All GDI defines and routines
# define NOKERNEL // All KERNEL defines and routines
# define NOUSER // All USER defines and routines
# define NONLS // All NLS defines and routines
# define NOMB // MB_* and MessageBox()
# define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines
# define NOMETAFILE // typedef METAFILEPICT
# define NOMINMAX // Macros min(a,b) and max(a,b)
# define NOMSG // typedef MSG and associated routines
# define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
# define NOSCROLL // SB_* and scrolling routines
# define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc.
# define NOSOUND // Sound driver routines
# define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines
# define NOWH // SetWindowsHook and WH_*
# define NOWINOFFSETS // GWL_*, GCL_*, associated routines
# define NOCOMM // COMM driver routines
# define NOKANJI // Kanji support stuff.
# define NOHELP // Help engine interface.
# define NOPROFILER // Profiler interface.
# define NODEFERWINDOWPOS // DeferWindowPos routines
# define NOMCX // Modem Configuration Extensions
#endif // WIN32_LEAN_AND_MEAN
//
# include <windows.h>
#endif
#endif // !_U_Win32_
@@ -1,14 +0,0 @@
<launch>
<arg name="gui" default="true"/>
<arg name="image_topic" default="image"/>
<arg name="objects_path" default="~/objects"/>
<arg name="settings_path" default="~/.ros/find_object_2d.ini"/>
<!-- Nodes -->
<node name="find_object_2d" pkg="find_object_2d" type="find_object_2d" output="screen">
<remap from="image" to="$(arg image_topic)"/>
<param name="gui" value="$(arg gui)" type="bool"/>
<param name="objects_path" value="$(arg objects_path)" type="str"/>
<param name="settings_path" value="$(arg settings_path)" type="str"/>
</node>
</launch>
@@ -1,35 +0,0 @@
<launch>
<!-- Example finding 3D poses of the objects detected -->
<!-- $roslaunch openni_launch openni.launch depth_registration:=true -->
<arg name="object_prefix" default="object"/>
<arg name="objects_path" default=""/>
<arg name="gui" default="true"/>
<arg name="approx_sync" default="true"/>
<arg name="pnp" default="true"/>
<arg name="tf_example" default="true"/>
<arg name="settings_path" default="~/.ros/find_object_2d.ini"/>
<arg name="rgb_topic" default="camera/rgb/image_rect_color"/>
<arg name="depth_topic" default="camera/depth_registered/image_raw"/>
<arg name="camera_info_topic" default="camera/rgb/camera_info"/>
<node name="find_object_3d" pkg="find_object_2d" type="find_object_2d" output="screen">
<param name="gui" value="$(arg gui)" type="bool"/>
<param name="settings_path" value="$(arg settings_path)" type="str"/>
<param name="subscribe_depth" value="true" type="bool"/>
<param name="objects_path" value="$(arg objects_path)" type="str"/>
<param name="object_prefix" value="$(arg object_prefix)" type="str"/>
<param name="approx_sync" value="$(arg approx_sync)" type="bool"/>
<param name="pnp" value="$(arg pnp)" type="bool"/>
<remap from="rgb/image_rect_color" to="$(arg rgb_topic)"/>
<remap from="depth_registered/image_raw" to="$(arg depth_topic)"/>
<remap from="depth_registered/camera_info" to="$(arg camera_info_topic)"/>
</node>
<!-- Example of tf synchronisation with the objectsStamped message -->
<node if="$(arg tf_example)" name="tf_example" pkg="find_object_2d" type="tf_example" output="screen">
<param name="object_prefix" value="$(arg object_prefix)" type="str"/>
</node>
</launch>
@@ -1,24 +0,0 @@
<launch>
<!-- Example finding 3D poses of the objects detected -->
<!-- $ roslaunch kinect2_bridge kinect2_bridge.launch publish_tf:=true -->
<!-- Which image resolution: sd, qhd, hd -->
<arg name="resolution" default="qhd" />
<arg name="object_prefix" default="object"/>
<arg name="objects_path" default=""/>
<arg name="gui" default="true"/>
<arg name="settings_path" default="~/.ros/find_object_2d.ini"/>
<node name="find_object_3d" pkg="find_object_2d" type="find_object_2d" output="screen">
<param name="gui" value="$(arg gui)" type="bool"/>
<param name="settings_path" value="$(arg settings_path)" type="str"/>
<param name="subscribe_depth" value="true" type="bool"/>
<param name="objects_path" value="$(arg objects_path)" type="str"/>
<param name="object_prefix" value="$(arg object_prefix)" type="str"/>
<param name="approx_sync" value="false" type="bool"/>
<remap from="rgb/image_rect_color" to="/kinect2/$(arg resolution)/image_color_rect"/>
<remap from="depth_registered/image_raw" to="/kinect2/$(arg resolution)/image_depth_rect"/>
<remap from="depth_registered/camera_info" to="/kinect2/$(arg resolution)/camera_info"/>
</node>
</launch>
@@ -1,23 +0,0 @@
<launch>
<!-- Example finding 3D poses of the objects detected -->
<!-- $ roslaunch zed_wrapper zed.launch -->
<arg name="zed_prefix" default="/zed/zed_node"/>
<arg name="object_prefix" default="object"/>
<arg name="objects_path" default=""/>
<arg name="gui" default="true"/>
<arg name="settings_path" default="~/.ros/find_object_2d.ini"/>
<node name="find_object_3d" pkg="find_object_2d" type="find_object_2d" output="screen">
<param name="gui" value="$(arg gui)" type="bool"/>
<param name="settings_path" value="$(arg settings_path)" type="str"/>
<param name="subscribe_depth" value="true" type="bool"/>
<param name="objects_path" value="$(arg objects_path)" type="str"/>
<param name="object_prefix" value="$(arg object_prefix)" type="str"/>
<param name="approx_sync" value="false" type="bool"/>
<remap from="rgb/image_rect_color" to="$(arg zed_prefix)/rgb/image_rect_color"/>
<remap from="depth_registered/image_raw" to="$(arg zed_prefix)/depth/depth_registered"/>
<remap from="depth_registered/camera_info" to="$(arg zed_prefix)/rgb/camera_info"/>
</node>
</launch>
@@ -1,30 +0,0 @@
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, SetEnvironmentVariable
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
SetEnvironmentVariable('RCUTILS_LOGGING_USE_STDOUT', '1'),
SetEnvironmentVariable('RCUTILS_LOGGING_BUFFERED_STREAM', '0'),
# Launch arguments
DeclareLaunchArgument('gui', default_value='true', description='Launch GUI.'),
DeclareLaunchArgument('image_topic', default_value='image', description='Image topic to subscribe to.'),
DeclareLaunchArgument('objects_path', default_value='~/objects', description='Directory containing objects to load on initialization.'),
DeclareLaunchArgument('settings_path', default_value='~/.ros/find_object_2d.ini', description='Config file.'),
# Nodes to launch
Node(
package='find_object_2d', executable='find_object_2d', output='screen',
parameters=[{
'gui':LaunchConfiguration('gui'),
'objects_path':LaunchConfiguration('objects_path'),
'settings_path':LaunchConfiguration('settings_path')
}],
remappings=[
('image', LaunchConfiguration('image_topic'))]),
])
@@ -1,42 +0,0 @@
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, SetEnvironmentVariable
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
SetEnvironmentVariable('RCUTILS_LOGGING_USE_STDOUT', '1'),
SetEnvironmentVariable('RCUTILS_LOGGING_BUFFERED_STREAM', '0'),
# Launch arguments
DeclareLaunchArgument('gui', default_value='true', description='Launch GUI.'),
DeclareLaunchArgument('approx_sync', default_value='true', description=''),
DeclareLaunchArgument('pnp', default_value='true', description=''),
DeclareLaunchArgument('object_prefix', default_value='object', description='TF prefix of objects.'),
DeclareLaunchArgument('objects_path', default_value='~/objects', description='Directory containing objects to load on initialization.'),
DeclareLaunchArgument('settings_path', default_value='~/.ros/find_object_2d.ini', description='Config file.'),
DeclareLaunchArgument('rgb_topic', default_value='camera/rgb/image_rect_color', description='Image topic.'),
DeclareLaunchArgument('depth_topic', default_value='camera/depth_registered/image_raw', description='Registered depth topic.'),
DeclareLaunchArgument('camera_info_topic', default_value='camera/rgb/camera_info', description='Camera info topic.'),
# Nodes to launch
Node(
package='find_object_2d', executable='find_object_2d', output='screen',
parameters=[{
'subscribe_depth':True,
'gui':LaunchConfiguration('gui'),
'approx_sync':LaunchConfiguration('approx_sync'),
'pnp':LaunchConfiguration('pnp'),
'object_prefix':LaunchConfiguration('object_prefix'),
'objects_path':LaunchConfiguration('objects_path'),
'settings_path':LaunchConfiguration('settings_path')
}],
remappings=[
('rgb/image_rect_color', LaunchConfiguration('rgb_topic')),
('depth_registered/image_raw', LaunchConfiguration('depth_topic')),
('depth_registered/camera_info', LaunchConfiguration('camera_info_topic'))]),
])
-12
View File
@@ -1,12 +0,0 @@
std_msgs/Header header
# All arrays should have the same size
std_msgs/Int32[] ids
std_msgs/Int32[] widths
std_msgs/Int32[] heights
std_msgs/String[] file_paths
std_msgs/Int32[] inliers
std_msgs/Int32[] outliers
# 3x3 homography matrix: [h11, h12, h13, h21, h22, h23, h31, h32, h33] (h31 = dx and h32 = dy, see QTransform)
std_msgs/Float32MultiArray[] homographies
-5
View File
@@ -1,5 +0,0 @@
# objects format:
# [ObjectId1, objectWidth, objectHeight, h11, h12, h13, h21, h22, h23, h31, h32, h33, ObjectId2...]
# where h## is a 3x3 homography matrix (h31 = dx and h32 = dy, see QTransform)
std_msgs/Header header
std_msgs/Float32MultiArray objects
-53
View File
@@ -1,53 +0,0 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>find_object_2d</name>
<version>0.7.0</version>
<description>The find_object_2d package</description>
<maintainer email="matlabbe@gmail.com">Mathieu Labbe</maintainer>
<author>Mathieu Labbe</author>
<license>BSD</license>
<url type="bugtracker">https://github.com/introlab/find-object/issues</url>
<url type="repository">https://github.com/introlab/find-object</url>
<buildtool_depend condition="$ROS_VERSION == 1">catkin</buildtool_depend>
<buildtool_depend condition="$ROS_VERSION == 2">ament_cmake</buildtool_depend>
<depend condition="$ROS_VERSION == 1">roscpp</depend>
<depend condition="$ROS_VERSION == 1">tf</depend>
<depend condition="$ROS_VERSION == 2">rclcpp</depend>
<depend condition="$ROS_VERSION == 2">tf2</depend>
<depend condition="$ROS_VERSION == 2">tf2_ros</depend>
<depend condition="$ROS_VERSION == 2">tf2_geometry_msgs</depend>
<build_depend condition="$ROS_VERSION == 2">ros_environment</build_depend>
<depend condition="$ROS_VERSION == 2">builtin_interfaces</depend>
<build_depend condition="$ROS_VERSION == 2">rosidl_default_generators</build_depend>
<exec_depend condition="$ROS_VERSION == 2">rosidl_default_runtime</exec_depend>
<member_of_group condition="$ROS_VERSION == 2">rosidl_interface_packages</member_of_group>
<build_depend condition="$ROS_VERSION == 1">message_generation</build_depend>
<build_depend>qtbase5-dev</build_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>std_srvs</build_depend>
<build_depend>geometry_msgs</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>message_filters</build_depend>
<exec_depend condition="$ROS_VERSION == 1">message_runtime</exec_depend>
<exec_depend>qtbase5-dev</exec_depend>
<exec_depend>cv_bridge</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>std_srvs</exec_depend>
<exec_depend>geometry_msgs</exec_depend>
<exec_depend>image_transport</exec_depend>
<exec_depend>message_filters</exec_depend>
<export>
<build_type condition="$ROS_VERSION == 1">catkin</build_type>
<build_type condition="$ROS_VERSION == 2">ament_cmake</build_type>
</export>
</package>
-67
View File
@@ -1,67 +0,0 @@
name: find-object
base: core18
version: '@PROJECT_VERSION@+git'
summary: Find-Object project, visit http://introlab.github.io/find-object/
description: |
Features:
- You can change any parameters at runtime, make it easier to test feature detectors and descriptors without always recompiling.
- Detectors/descriptors supported (from OpenCV): BRIEF, Dense, FAST, GoodFeaturesToTrack, MSER, ORB, SIFT, STAR, SURF, FREAK and BRISK.
- Sample code with the OpenCV C++ interface below...
- For an example of an application using SURF descriptors: see my project RTAB-Map (an appearance-based loop closure detector for SLAM).
grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots
apps:
find-object:
command: desktop-launch find_object
plugs: [unity7, x11, opengl, home, network, network-bind, removable-media, raw-usb, wayland, desktop-legacy, desktop]
parts:
desktop-qt5:
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
source-subdir: qt
plugin: make
make-parameters: ["FLAVOR=qt5"]
build-packages:
- qtbase5-dev
- dpkg-dev
stage-packages:
- libxkbcommon0
- ttf-ubuntu-font-family
- dmz-cursor-theme
- light-themes
- adwaita-icon-theme
- gnome-themes-standard
- shared-mime-info
- libqt5gui5
- libgdk-pixbuf2.0-0
- libgtk2.0-0
- libqt5svg5 # for loading icon themes which are svg
- try: [appmenu-qt5] # not available on core18
- locales-all
find-object:
after: [desktop-qt5]
plugin: cmake
source: .
build-packages:
- libopencv-dev
- qtbase5-dev
organize:
usr/lib/x86_64-linux-gnu/blas/libblas.so.3: usr/lib/x86_64-linux-gnu/libblas.so.3
usr/lib/x86_64-linux-gnu/blas/libblas.so.3.7.1: usr/lib/x86_64-linux-gnu/libblas.so.3.7.1
usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3: usr/lib/x86_64-linux-gnu/liblapack.so.3
usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.7.1: usr/lib/x86_64-linux-gnu/liblapack.so.3.7.1
stage-packages:
- libopencv-calib3d3.2
- libopencv-core3.2
- libopencv-features2d3.2
- libopencv-flann3.2
- libopencv-imgcodecs3.2
- libopencv-imgproc3.2
- libopencv-video3.2
- libqt5core5a
- libqt5gui5
- libqt5network5
- libqt5widgets5
-58
View File
@@ -1,58 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "AboutDialog.h"
#include "ui_aboutDialog.h"
#include <opencv2/core/version.hpp>
#include "find_object/Version.h"
namespace find_object {
AboutDialog::AboutDialog(QWidget * parent) :
QDialog(parent)
{
ui_ = new Ui_aboutDialog();
ui_->setupUi(this);
ui_->label_version->setText(PROJECT_VERSION);
QString cv_version = CV_VERSION;
#if FINDOBJECT_NONFREE == 1
cv_version.append(" [With nonfree]");
#else
cv_version.append(" [Without nonfree]");
#endif
ui_->label_version_opencv->setText(cv_version);
ui_->label_version_qt->setText(QT_VERSION_STR);
}
AboutDialog::~AboutDialog()
{
delete ui_;
}
}
-53
View File
@@ -1,53 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 ABOUTDIALOG_H_
#define ABOUTDIALOG_H_
#include <QDialog>
#include <QtCore/QUrl>
class Ui_aboutDialog;
namespace find_object {
class AboutDialog : public QDialog
{
Q_OBJECT
public:
AboutDialog(QWidget * parent = 0);
virtual ~AboutDialog();
private:
Ui_aboutDialog * ui_;
};
} // namespace find_object
#endif /* ABOUTDIALOG_H_ */
-461
View File
@@ -1,461 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/Camera.h"
#include "find_object/Settings.h"
#include "find_object/utilite/ULogger.h"
#include "find_object/ObjWidget.h"
#include "find_object/QtOpenCV.h"
#include "AddObjectDialog.h"
#include "ui_addObjectDialog.h"
#include "KeypointItem.h"
#include "ObjSignature.h"
#include <stdio.h>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QMessageBox>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc_c.h>
namespace find_object {
AddObjectDialog::AddObjectDialog(Camera * camera, const cv::Mat & image, bool mirrorView, QWidget * parent, Qt::WindowFlags f) :
QDialog(parent, f),
camera_(camera),
objWidget_(0),
objSignature_(0)
{
ui_ = new Ui_addObjectDialog();
ui_->setupUi(this);
detector_ = Settings::createKeypointDetector();
extractor_ = Settings::createDescriptorExtractor();
UASSERT(detector_ != 0 && extractor_ != 0);
connect(ui_->pushButton_cancel, SIGNAL(clicked()), this, SLOT(cancel()));
connect(ui_->pushButton_back, SIGNAL(clicked()), this, SLOT(back()));
connect(ui_->pushButton_next, SIGNAL(clicked()), this, SLOT(next()));
connect(ui_->pushButton_takePicture, SIGNAL(clicked()), this, SLOT(takePicture()));
connect(ui_->comboBox_selection, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSelectionMode()));
connect(ui_->cameraView, SIGNAL(selectionChanged()), this, SLOT(updateNextButton()));
connect(ui_->cameraView, SIGNAL(roiChanged(const cv::Rect &)), this, SLOT(updateNextButton(const cv::Rect &)));
ui_->cameraView->setMirrorView(mirrorView);
if((camera_ && camera_->isRunning()) || image.empty())
{
this->setState(kTakePicture);
}
else if(!image.empty())
{
update(image);
this->setState(kSelectFeatures);
}
}
AddObjectDialog::~AddObjectDialog()
{
delete detector_;
delete extractor_;
if(objWidget_)
{
delete objWidget_;
objWidget_ = 0;
}
if(objSignature_)
{
delete objSignature_;
objSignature_ = 0;
}
delete ui_;
}
void AddObjectDialog::retrieveObject(ObjWidget ** widget, ObjSignature ** signature)
{
*widget = objWidget_;
objWidget_= 0;
*signature = objSignature_;
objSignature_ = 0;
}
void AddObjectDialog::closeEvent(QCloseEvent* event)
{
if(camera_)
{
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)));
}
QDialog::closeEvent(event);
}
void AddObjectDialog::next()
{
setState(state_+1);
}
void AddObjectDialog::back()
{
setState(state_-1);
}
void AddObjectDialog::cancel()
{
this->reject();
}
void AddObjectDialog::takePicture()
{
next();
}
void AddObjectDialog::updateNextButton()
{
updateNextButton(cv::Rect());
}
void AddObjectDialog::updateNextButton(const cv::Rect & rect)
{
roi_ = rect;
if(roi_.height && roi_.width && cameraImage_.cols)
{
//clip roi
if( roi_.x >= cameraImage_.cols ||
roi_.x+roi_.width <= 0 ||
roi_.y >= cameraImage_.rows ||
roi_.y+roi_.height <= 0)
{
//Not valid...
roi_ = cv::Rect();
}
else
{
if(roi_.x < 0)
{
roi_.x = 0;
}
if(roi_.x + roi_.width > cameraImage_.cols)
{
roi_.width = cameraImage_.cols - roi_.x;
}
if(roi_.y < 0)
{
roi_.y = 0;
}
if(roi_.y + roi_.height > cameraImage_.rows)
{
roi_.height = cameraImage_.rows - roi_.y;
}
}
}
if(state_ == kSelectFeatures)
{
if(ui_->comboBox_selection->currentIndex() == 1)
{
if(ui_->cameraView->selectedItems().size() > 0)
{
ui_->pushButton_next->setEnabled(true);
}
else
{
ui_->pushButton_next->setEnabled(false);
}
}
else
{
if(roi_.width == 0 || roi_.height == 0)
{
ui_->pushButton_next->setEnabled(false);
}
else
{
ui_->pushButton_next->setEnabled(true);
}
}
}
}
void AddObjectDialog::changeSelectionMode()
{
this->setState(kSelectFeatures);
}
void AddObjectDialog::setState(int state)
{
state_ = state;
if(state == kTakePicture)
{
ui_->pushButton_cancel->setEnabled(true);
ui_->pushButton_back->setEnabled(false);
ui_->pushButton_next->setEnabled(false);
ui_->pushButton_takePicture->setEnabled(true);
ui_->label_instruction->setText(tr("Place the object in front of the camera and click \"Take picture\"."));
ui_->pushButton_next->setText(tr("Next"));
ui_->cameraView->setVisible(true);
ui_->cameraView->clearRoiSelection();
ui_->objectView->setVisible(false);
ui_->cameraView->setGraphicsViewMode(false);
ui_->comboBox_selection->setVisible(false);
if(!camera_ || !camera_->start())
{
QMessageBox::critical(this, tr("Camera error"), tr("Camera is not started!"));
ui_->pushButton_takePicture->setEnabled(false);
}
else
{
connect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
connect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)));
}
}
else if(state == kSelectFeatures)
{
if(camera_)
{
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)));
camera_->pause();
}
ui_->pushButton_cancel->setEnabled(true);
ui_->pushButton_back->setEnabled(camera_);
ui_->pushButton_next->setEnabled(false);
ui_->pushButton_takePicture->setEnabled(false);
ui_->pushButton_next->setText(tr("Next"));
ui_->cameraView->setVisible(true);
ui_->cameraView->clearRoiSelection();
ui_->objectView->setVisible(false);
ui_->comboBox_selection->setVisible(true);
if(ui_->comboBox_selection->currentIndex() == 1)
{
ui_->label_instruction->setText(tr("Select features representing the object."));
ui_->cameraView->setGraphicsViewMode(true);
}
else
{
ui_->label_instruction->setText(tr("Select region representing the object."));
ui_->cameraView->setGraphicsViewMode(false);
}
updateNextButton(cv::Rect());
}
else if(state == kVerifySelection)
{
if(camera_)
{
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &)), this, SLOT(update(const cv::Mat &)));
disconnect(camera_, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)));
camera_->pause();
}
ui_->pushButton_cancel->setEnabled(true);
ui_->pushButton_back->setEnabled(true);
ui_->pushButton_takePicture->setEnabled(false);
ui_->pushButton_next->setText(tr("End"));
ui_->cameraView->setVisible(true);
ui_->objectView->setVisible(true);
ui_->objectView->setMirrorView(ui_->cameraView->isMirrorView());
ui_->objectView->setSizedFeatures(ui_->cameraView->isSizedFeatures());
ui_->comboBox_selection->setVisible(false);
if(ui_->comboBox_selection->currentIndex() == 1)
{
ui_->cameraView->setGraphicsViewMode(true);
}
else
{
ui_->cameraView->setGraphicsViewMode(false);
}
std::vector<cv::KeyPoint> selectedKeypoints = ui_->cameraView->selectedKeypoints();
// Select keypoints
if(!cameraImage_.empty() &&
((ui_->comboBox_selection->currentIndex() == 1 && selectedKeypoints.size()) ||
(ui_->comboBox_selection->currentIndex() == 0 && roi_.width && roi_.height)))
{
if(ui_->comboBox_selection->currentIndex() == 1)
{
roi_ = computeROI(selectedKeypoints);
}
cv::Mat imgRoi = cv::Mat(cameraImage_, roi_).clone();
if(ui_->comboBox_selection->currentIndex() == 1)
{
if(roi_.x != 0 || roi_.y != 0)
{
for(unsigned int i=0; i<selectedKeypoints.size(); ++i)
{
selectedKeypoints.at(i).pt.x -= roi_.x;
selectedKeypoints.at(i).pt.y -= roi_.y;
}
}
}
else
{
// Extract keypoints
selectedKeypoints.clear();
detector_->detect(imgRoi, selectedKeypoints);
}
ui_->objectView->updateImage(cvtCvMat2QImage(imgRoi));
ui_->objectView->updateData(selectedKeypoints, QMultiMap<int,int>());
ui_->objectView->setMinimumSize(roi_.width, roi_.height);
ui_->objectView->update();
ui_->pushButton_next->setEnabled(true);
}
else
{
UINFO("Please select items");
ui_->pushButton_next->setEnabled(false);
}
ui_->label_instruction->setText(tr("Selection : %1 features").arg(selectedKeypoints.size()));
}
else if(state == kClosing)
{
std::vector<cv::KeyPoint> keypoints = ui_->objectView->keypoints();
if((ui_->comboBox_selection->currentIndex() == 1 && keypoints.size()) ||
(ui_->comboBox_selection->currentIndex() == 0 && roi_.width && roi_.height))
{
cv::Mat descriptors;
cv::Mat imgRoi(cameraImage_, roi_);
if(keypoints.size())
{
// Extract descriptors
if(Settings::currentDetectorType() == Settings::currentDescriptorType())
{
detector_->compute(imgRoi, keypoints, descriptors);
}
else
{
extractor_->compute(imgRoi, keypoints, descriptors);
}
if(keypoints.size() != (unsigned int)descriptors.rows)
{
UERROR("keypoints=%d != descriptors=%d", (int)keypoints.size(), descriptors.rows);
}
}
if(objWidget_)
{
delete objWidget_;
objWidget_ = 0;
}
if(objSignature_)
{
delete objSignature_;
objSignature_ = 0;
}
objSignature_ = new ObjSignature(0, imgRoi.clone(), "");
objSignature_->setData(keypoints, descriptors);
objWidget_ = new ObjWidget(0, keypoints, QMultiMap<int,int>(), cvtCvMat2QImage(imgRoi.clone()));
this->accept();
}
}
}
void AddObjectDialog::update(const cv::Mat & image)
{
update(image, Header(), cv::Mat(), 0.0);
}
void AddObjectDialog::update(const cv::Mat & image, const Header & header, const cv::Mat & depth, float depthConstant)
{
cameraImage_ = cv::Mat();
if(!image.empty())
{
// convert to grayscale
if(image.channels() != 1 || image.depth() != CV_8U)
{
cv::cvtColor(image, cameraImage_, CV_BGR2GRAY);
}
else
{
cameraImage_ = image.clone();
}
// Extract keypoints
std::vector<cv::KeyPoint> keypoints;
detector_->detect(cameraImage_, keypoints);
ui_->cameraView->updateImage(cvtCvMat2QImage(cameraImage_));
ui_->cameraView->updateData(keypoints, QMultiMap<int,int>());
ui_->cameraView->update();
}
else
{
UWARN("Camera cannot get more images (maybe the end of stream is reached)...");
camera_->stop();
}
}
cv::Rect AddObjectDialog::computeROI(const std::vector<cv::KeyPoint> & kpts)
{
cv::Rect roi(0,0,0,0);
int x1=0,x2=0,h1=0,h2=0;
for(unsigned int i=0; i<kpts.size(); ++i)
{
float radius = kpts.at(i).size / 2;
if(i==0)
{
x1 = int(kpts.at(i).pt.x - radius);
x2 = int(kpts.at(i).pt.x + radius);
h1 = int(kpts.at(i).pt.y - radius);
h2 = int(kpts.at(i).pt.y + radius);
}
else
{
if(x1 > int(kpts.at(i).pt.x - radius))
{
x1 = int(kpts.at(i).pt.x - radius);
}
else if(x2 < int(kpts.at(i).pt.x + radius))
{
x2 = int(kpts.at(i).pt.x + radius);
}
if(h1 > int(kpts.at(i).pt.y - radius))
{
h1 = int(kpts.at(i).pt.y - radius);
}
else if(h2 < int(kpts.at(i).pt.y + radius))
{
h2 = int(kpts.at(i).pt.y + radius);
}
}
roi.x = x1;
roi.y = h1;
roi.width = x2-x1;
roi.height = h2-h1;
//UINFO("ptx=%d, pty=%d", (int)kpts.at(i).pt.x, (int)kpts.at(i).pt.y);
//UINFO("x=%d, y=%d, w=%d, h=%d", roi.x, roi.y, roi.width, roi.height);
}
return roi;
}
} // namespace find_object
-91
View File
@@ -1,91 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 ADDOBJECTDIALOG_H_
#define ADDOBJECTDIALOG_H_
#include <QDialog>
#include <QtCore/QTimer>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/core/core.hpp>
#include "find_object/Header.h"
class Ui_addObjectDialog;
namespace find_object {
class ObjWidget;
class Camera;
class KeypointItem;
class Feature2D;
class ObjSignature;
class AddObjectDialog : public QDialog {
Q_OBJECT
public:
AddObjectDialog(Camera * camera, const cv::Mat & image, bool mirrorView, QWidget * parent = 0, Qt::WindowFlags f = 0);
virtual ~AddObjectDialog();
// ownership transferred to caller
void retrieveObject(ObjWidget ** widget, ObjSignature ** signature);
private Q_SLOTS:
void update(const cv::Mat &);
void update(const cv::Mat &, const find_object::Header &, const cv::Mat &, float);
void next();
void back();
void cancel();
void takePicture();
void updateNextButton();
void updateNextButton(const cv::Rect &);
void changeSelectionMode();
protected:
virtual void closeEvent(QCloseEvent* event);
private:
void setState(int state);
cv::Rect computeROI(const std::vector<cv::KeyPoint> & kpts);
private:
Ui_addObjectDialog * ui_;
Camera * camera_;
ObjWidget * objWidget_;
ObjSignature * objSignature_;
cv::Mat cameraImage_;
cv::Rect roi_;
Feature2D * detector_;
Feature2D * extractor_;
enum State{kTakePicture, kSelectFeatures, kVerifySelection, kClosing};
int state_;
};
} // namespace find_object
#endif /* ADDOBJECTDIALOG_H_ */
-281
View File
@@ -1,281 +0,0 @@
### Qt Gui stuff ###
SET(headers_ui
../include/${PROJECT_PREFIX}/MainWindow.h
../include/${PROJECT_PREFIX}/FindObject.h
../include/${PROJECT_PREFIX}/Camera.h
../include/${PROJECT_PREFIX}/TcpServer.h
../include/${PROJECT_PREFIX}/ObjWidget.h
./AddObjectDialog.h
./CameraTcpServer.h
./ParametersToolBox.h
./AboutDialog.h
./RectItem.h
./ImageDropWidget.h
./rtabmap/PdfPlot.h
./utilite/UPlot.h
)
IF(CATKIN_BUILD)
SET(headers_ui
${headers_ui}
./ros1/CameraROS.h
./ros1/FindObjectROS.h
)
ENDIF(CATKIN_BUILD)
IF(COLCON_BUILD)
SET(headers_ui
${headers_ui}
./ros2/CameraROS.h
./ros2/FindObjectROS.h
)
ENDIF(COLCON_BUILD)
SET(uis
./ui/mainWindow.ui
./ui/addObjectDialog.ui
./ui/aboutDialog.ui
)
SET(qrc
./resources.qrc
)
IF(QT4_FOUND)
# generate rules for building source files from the resources
QT4_ADD_RESOURCES(srcs_qrc ${qrc})
#Generate .h files from the .ui files
QT4_WRAP_UI(moc_uis ${uis})
#This will generate moc_* for Qt
QT4_WRAP_CPP(moc_srcs ${headers_ui})
### Qt Gui stuff end###
ELSE()
QT5_ADD_RESOURCES(srcs_qrc ${qrc})
QT5_WRAP_UI(moc_uis ${uis})
QT5_WRAP_CPP(moc_srcs ${headers_ui})
ENDIF()
SET(SRC_FILES
./MainWindow.cpp
./AddObjectDialog.cpp
./KeypointItem.cpp
./RectItem.cpp
./QtOpenCV.cpp
./Camera.cpp
./CameraTcpServer.cpp
./ParametersToolBox.cpp
./Settings.cpp
./ObjWidget.cpp
./ImageDropWidget.cpp
./FindObject.cpp
./AboutDialog.cpp
./TcpServer.cpp
./Vocabulary.cpp
./JsonWriter.cpp
./utilite/ULogger.cpp
./utilite/UPlot.cpp
./utilite/UDirectory.cpp
./utilite/UFile.cpp
./utilite/UConversion.cpp
./rtabmap/PdfPlot.cpp
./json/jsoncpp.cpp
./Compression.cpp
${moc_srcs}
${moc_uis}
${srcs_qrc}
)
IF(CATKIN_BUILD)
SET(SRC_FILES
${SRC_FILES}
./ros1/CameraROS.cpp
./ros1/FindObjectROS.cpp
)
ENDIF(CATKIN_BUILD)
IF(COLCON_BUILD)
SET(SRC_FILES
${SRC_FILES}
./ros2/CameraROS.cpp
./ros2/FindObjectROS.cpp
)
ENDIF(COLCON_BUILD)
SET(INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../include
${CMAKE_CURRENT_SOURCE_DIR}
${OpenCV_INCLUDE_DIRS}
${CMAKE_CURRENT_BINARY_DIR} # for qt ui generated in binary dir
${ZLIB_INCLUDE_DIRS}
)
IF(QT4_FOUND)
INCLUDE(${QT_USE_FILE})
ENDIF(QT4_FOUND)
SET(LIBRARIES
${QT_LIBRARIES}
${OpenCV_LIBS}
${ZLIB_LIBRARIES}
)
IF(CATKIN_BUILD)
SET(LIBRARIES
${LIBRARIES}
${catkin_LIBRARIES}
)
ENDIF(CATKIN_BUILD)
IF(COLCON_BUILD)
SET(AMENT_LIBRARIES
rclcpp
rclcpp_components
cv_bridge
sensor_msgs
std_msgs
image_transport
message_filters
tf2
tf2_ros
tf2_geometry_msgs
geometry_msgs
)
ENDIF(COLCON_BUILD)
IF(TORCH_FOUND)
SET(LIBRARIES
${LIBRARIES}
${TORCH_LIBRARIES}
)
SET(SRC_FILES
${SRC_FILES}
superpoint_torch/SuperPoint.cc
)
SET(INCLUDE_DIRS
${TORCH_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/superpoint_torch
${INCLUDE_DIRS}
)
ADD_DEFINITIONS("-DWITH_TORCH")
ENDIF(TORCH_FOUND)
#include files
INCLUDE_DIRECTORIES(${INCLUDE_DIRS})
IF(CATKIN_BUILD)
INCLUDE_DIRECTORIES(SYSTEM ${catkin_INCLUDE_DIRS})
ENDIF(CATKIN_BUILD)
# create a library from the source files
ADD_LIBRARY(find_object ${SRC_FILES})
# Linking with Qt libraries
IF(Qt5_FOUND)
QT5_USE_MODULES(find_object Widgets Core Gui Network PrintSupport)
ENDIF(Qt5_FOUND)
IF(NOT COLCON_BUILD)
TARGET_LINK_LIBRARIES(find_object ${LIBRARIES})
ENDIF()
IF(CATKIN_BUILD)
set_target_properties(find_object PROPERTIES OUTPUT_NAME find_object_2d)
add_dependencies(find_object ${${PROJECT_NAME}_EXPORTED_TARGETS})
ENDIF(CATKIN_BUILD)
IF(COLCON_BUILD)
ament_target_dependencies(find_object ${AMENT_LIBRARIES})
if("$ENV{ROS_DISTRO}" STRGREATER_EQUAL "humble")
rosidl_get_typesupport_target(cpp_typesupport_target ${PROJECT_NAME} "rosidl_typesupport_cpp")
target_link_libraries(find_object ${cpp_typesupport_target} ${LIBRARIES})
else()
# foxy, galatic
target_link_libraries(find_object ${LIBRARIES})
rosidl_target_interfaces(find_object ${PROJECT_NAME} "rosidl_typesupport_cpp")
function(rosidl_get_typesupport_target var generate_interfaces_target typesupport_name)
rosidl_target_interfaces(${var} ${generate_interfaces_target} ${typesupport_name})
endfunction()
add_definitions(-DPRE_ROS_HUMBLE)
endif()
ENDIF(COLCON_BUILD)
IF(NOT ROS_BUILD)
INSTALL(TARGETS find_object
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT runtime
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../include/ DESTINATION "${INSTALL_INCLUDE_DIR}" COMPONENT devel FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE)
ELSEIF(CATKIN_BUILD)
add_executable(find_object_2d ros1/find_object_2d_node.cpp)
target_link_libraries(find_object_2d find_object ${LIBRARIES})
add_executable(print_objects_detected ros1/print_objects_detected_node.cpp)
target_link_libraries(print_objects_detected ${LIBRARIES})
add_dependencies(print_objects_detected ${${PROJECT_NAME}_EXPORTED_TARGETS})
add_executable(tf_example ros1/tf_example_node.cpp)
target_link_libraries(tf_example ${LIBRARIES})
add_dependencies(tf_example ${${PROJECT_NAME}_EXPORTED_TARGETS})
IF(Qt5_FOUND)
QT5_USE_MODULES(find_object_2d Widgets Core Gui Network PrintSupport)
QT5_USE_MODULES(print_objects_detected Widgets Core Gui Network PrintSupport)
QT5_USE_MODULES(tf_example Widgets Core Gui Network PrintSupport)
ENDIF(Qt5_FOUND)
## Mark executables and/or libraries for installation
install(TARGETS
find_object
find_object_2d
print_objects_detected
tf_example
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
ELSE() # COLCON_BUILD
add_executable(find_object_2d_node ros2/find_object_2d_node.cpp)
set_target_properties(find_object_2d_node PROPERTIES OUTPUT_NAME find_object_2d)
ament_target_dependencies(find_object_2d_node ${AMENT_LIBRARIES})
target_link_libraries(find_object_2d_node find_object ${LIBRARIES})
add_executable(print_objects_detected ros2/print_objects_detected_node.cpp)
ament_target_dependencies(print_objects_detected ${AMENT_LIBRARIES})
target_link_libraries(print_objects_detected find_object ${LIBRARIES})
add_executable(tf_example ros2/tf_example_node.cpp)
ament_target_dependencies(tf_example ${AMENT_LIBRARIES})
target_link_libraries(tf_example find_object ${LIBRARIES})
# Only required when using messages built from the same package
# https://index.ros.org/doc/ros2/Tutorials/Rosidl-Tutorial/
get_default_rmw_implementation(rmw_implementation)
find_package("${rmw_implementation}" REQUIRED)
get_rmw_typesupport(typesupport_impls "${rmw_implementation}" LANGUAGE "cpp")
foreach(typesupport_impl ${typesupport_impls})
rosidl_get_typesupport_target(find_object_2d_node
${PROJECT_NAME} ${typesupport_impl}
)
rosidl_get_typesupport_target(print_objects_detected
${PROJECT_NAME} ${typesupport_impl}
)
rosidl_get_typesupport_target(tf_example
${PROJECT_NAME} ${typesupport_impl}
)
endforeach()
## Mark executables and/or libraries for installation
install(TARGETS
find_object
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
install(TARGETS
find_object_2d_node
print_objects_detected
tf_example
DESTINATION lib/${PROJECT_NAME}
)
ENDIF()
-296
View File
@@ -1,296 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/Camera.h"
#include "find_object/Settings.h"
#include "find_object/utilite/ULogger.h"
#include "find_object/QtOpenCV.h"
#include <stdio.h>
#include <opencv2/imgproc/imgproc.hpp>
#if CV_MAJOR_VERSION > 3
#include <opencv2/videoio/videoio_c.h>
#endif
#include <QtCore/QFile>
#include "utilite/UDirectory.h"
#include "CameraTcpServer.h"
namespace find_object {
Camera::Camera(QObject * parent) :
QObject(parent),
currentImageIndex_(0),
cameraTcpServer_(0)
{
qRegisterMetaType<cv::Mat>("cv::Mat");
connect(&cameraTimer_, SIGNAL(timeout()), this, SLOT(takeImage()));
}
Camera::~Camera()
{
this->stop();
}
void Camera::stop()
{
stopTimer();
capture_.release();
images_.clear();
currentImageIndex_ = 0;
if(cameraTcpServer_)
{
cameraTcpServer_->close();
delete cameraTcpServer_;
cameraTcpServer_ = 0;
}
}
void Camera::pause()
{
stopTimer();
}
int Camera::getTotalFrames()
{
if(images_.size())
{
return images_.size();
}
else if(capture_.isOpened())
{
return (int)capture_.get(CV_CAP_PROP_FRAME_COUNT);
}
return 0;
}
int Camera::getCurrentFrameIndex()
{
if(images_.size())
{
return currentImageIndex_;
}
else if(capture_.isOpened())
{
return (int)capture_.get(CV_CAP_PROP_POS_FRAMES);
}
return 0;
}
void Camera::moveToFrame(int frame)
{
if(frame < images_.size())
{
currentImageIndex_ = frame;
}
else if(capture_.isOpened() && frame < (int)capture_.get(CV_CAP_PROP_FRAME_COUNT))
{
capture_.set(CV_CAP_PROP_POS_FRAMES, frame);
}
}
int Camera::getPort()
{
if(cameraTcpServer_)
{
return cameraTcpServer_->getPort();
}
return 0;
}
void Camera::takeImage()
{
cv::Mat img;
if(capture_.isOpened())
{
capture_.read(img);// capture a frame
}
else if(!images_.empty())
{
if(currentImageIndex_ < (unsigned int)images_.size())
{
img = cv::imread(images_[currentImageIndex_++]);
}
}
else if(cameraTcpServer_)
{
img = cameraTcpServer_->getImage();
if(cameraTcpServer_->imagesBuffered() > 0 && Settings::getCamera_9queueSize() == 0)
{
UWARN("%d images buffered so far...", cameraTcpServer_->imagesBuffered());
}
}
if(img.empty())
{
if(cameraTcpServer_)
{
if(!cameraTcpServer_->isConnected())
{
cameraTcpServer_->waitForNewConnection(100);
}
}
else
{
// In case of a directory of images or a video
this->stop();
Q_EMIT finished(); // notify that there are no more images
}
}
else
{
//resize
if( Settings::getCamera_2imageWidth() &&
Settings::getCamera_3imageHeight() &&
Settings::getCamera_2imageWidth() != img.cols &&
Settings::getCamera_3imageHeight() != img.rows)
{
cv::Mat resampled;
cv::resize(img, resampled, cv::Size(Settings::getCamera_2imageWidth(), Settings::getCamera_3imageHeight()));
Q_EMIT imageReceived(resampled);
}
else if(capture_.isOpened())
{
Q_EMIT imageReceived(img.clone()); // clone required with VideoCapture::read()
}
else
{
Q_EMIT imageReceived(img); // clone not required with cv::imread()
}
}
}
bool Camera::start()
{
if(!capture_.isOpened() && images_.empty() && cameraTcpServer_ == 0)
{
if(Settings::getCamera_6useTcpCamera())
{
cameraTcpServer_ = new CameraTcpServer(Settings::getCamera_8port(), this);
if(!cameraTcpServer_->isListening())
{
UWARN("CameraTCP: Cannot listen to port %d", cameraTcpServer_->getPort());
delete cameraTcpServer_;
cameraTcpServer_ = 0;
}
else
{
UINFO("CameraTCP: listening to port %d (IP=%s)",
cameraTcpServer_->getPort(),
cameraTcpServer_->getHostAddress().toString().toStdString().c_str());
}
}
else
{
QString path = Settings::getCamera_5mediaPath();
if(UDirectory::exists(path.toStdString()))
{
//Images directory
QString ext = Settings::getGeneral_imageFormats();
ext.remove('*');
ext.remove('.');
UDirectory dir(path.toStdString(), ext.toStdString()); // this will load fileNames matching the extensions (in natural order)
const std::list<std::string> & fileNames = dir.getFileNames();
currentImageIndex_ = 0;
images_.clear();
// Modify to have full path
for(std::list<std::string>::const_iterator iter = fileNames.begin(); iter!=fileNames.end(); ++iter)
{
images_.append(path.toStdString() + UDirectory::separator() + *iter);
}
UINFO("Camera: Reading %d images from directory \"%s\"...", (int)images_.size(), path.toStdString().c_str());
if(images_.isEmpty())
{
UWARN("Camera: Directory \"%s\" is empty (no images matching the \"%s\" extensions). "
"If you want to disable loading automatically this directory, "
"clear the Camera/mediaPath parameter. By default, webcam will be used instead of the directory.",
path.toStdString().c_str(),
ext.toStdString().c_str());
}
}
else if(!path.isEmpty())
{
//Video file
capture_.open(path.toStdString().c_str());
if(!capture_.isOpened())
{
UWARN("Camera: Cannot open file \"%s\". If you want to disable loading "
"automatically this video file, clear the Camera/mediaPath parameter. "
"By default, webcam will be used instead of the file.", path.toStdString().c_str());
}
else
{
UINFO("Camera: Reading from video file \"%s\"...", path.toStdString().c_str());
}
}
if(!capture_.isOpened() && images_.empty())
{
//set camera device
capture_.open(Settings::getCamera_1deviceId());
if(Settings::getCamera_2imageWidth() && Settings::getCamera_3imageHeight())
{
capture_.set(CV_CAP_PROP_FRAME_WIDTH, double(Settings::getCamera_2imageWidth()));
capture_.set(CV_CAP_PROP_FRAME_HEIGHT, double(Settings::getCamera_3imageHeight()));
}
UINFO("Camera: Reading from camera device %d...", Settings::getCamera_1deviceId());
}
}
}
if(!capture_.isOpened() && images_.empty() && cameraTcpServer_ == 0)
{
UERROR("Camera: Failed to open a capture object!");
return false;
}
startTimer();
return true;
}
void Camera::startTimer()
{
updateImageRate();
cameraTimer_.start();
}
void Camera::stopTimer()
{
cameraTimer_.stop();
}
void Camera::updateImageRate()
{
if(Settings::getCamera_4imageRate())
{
cameraTimer_.setInterval((int)(1000.0/Settings::getCamera_4imageRate()));
}
else
{
cameraTimer_.setInterval(0);
}
}
} // namespace find_object
-190
View File
@@ -1,190 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/Settings.h"
#include "find_object/utilite/ULogger.h"
#include "CameraTcpServer.h"
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QNetworkInterface>
#include <QtCore/QDataStream>
namespace find_object {
CameraTcpServer::CameraTcpServer(quint16 port, QObject *parent) :
QTcpServer(parent),
blockSize_(0)
{
if (!this->listen(QHostAddress::Any, port))
{
UERROR("Unable to start the Camera TCP server: %s", this->errorString().toStdString().c_str());
return;
}
}
cv::Mat CameraTcpServer::getImage()
{
cv::Mat img;
if(images_.size())
{
// if queue changed after tcp connection ended with images still in the buffer
int queue = Settings::getCamera_9queueSize();
while(queue > 0 && images_.size() > queue)
{
images_.pop_front();
}
img = images_.front();
images_.pop_front();
}
if(this->findChildren<QTcpSocket*>().size() == 1)
{
this->findChildren<QTcpSocket*>().first()->waitForReadyRead(100);
}
return img;
}
bool CameraTcpServer::isConnected() const
{
return this->findChildren<QTcpSocket*>().size() > 0;
}
QHostAddress CameraTcpServer::getHostAddress() const
{
QHostAddress hostAddress;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
// use the first non-localhost IPv4 address
for (int i = 0; i < ipAddressesList.size(); ++i)
{
if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address())
{
hostAddress = ipAddressesList.at(i).toString();
break;
}
}
// if we did not find one, use IPv4 localhost
if (hostAddress.isNull())
{
hostAddress = QHostAddress(QHostAddress::LocalHost);
}
return hostAddress;
}
quint16 CameraTcpServer::getPort() const
{
return this->serverPort();
}
#if QT_VERSION >= 0x050000
void CameraTcpServer::incomingConnection(qintptr socketDescriptor)
#else
void CameraTcpServer::incomingConnection(int socketDescriptor)
#endif
{
QList<QTcpSocket*> clients = this->findChildren<QTcpSocket*>();
if(clients.size() >= 1)
{
UWARN("A client is already connected. Only one connection allowed at the same time.");
QTcpSocket socket;
socket.setSocketDescriptor(socketDescriptor);
socket.close(); // close without sending an acknowledge
}
else
{
QTcpSocket * socket = new QTcpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(readReceivedData()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(socket, SIGNAL(disconnected()), this, SLOT(connectionLost()));
socket->setSocketDescriptor(socketDescriptor);
socket->write(QByteArray("1")); // send acknowledge
}
}
void CameraTcpServer::readReceivedData()
{
QTcpSocket * client = (QTcpSocket*)sender();
QDataStream in(client);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize_ == 0)
{
if (client->bytesAvailable() < (int)sizeof(quint64))
{
return;
}
in >> blockSize_;
}
if (client->bytesAvailable() < (int)blockSize_)
{
return;
}
std::vector<unsigned char> buf(blockSize_);
in.readRawData((char*)buf.data(), blockSize_);
images_.push_back(cv::imdecode(buf, cv::IMREAD_UNCHANGED));
int queue = Settings::getCamera_9queueSize();
while(queue > 0 && images_.size() > queue)
{
images_.pop_front();
}
blockSize_ = 0;
}
void CameraTcpServer::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError)
{
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
UWARN("CameraTcp: Tcp error: The host was not found. Please "
"check the host name and port settings.\n");
break;
case QAbstractSocket::ConnectionRefusedError:
UWARN("CameraTcp: The connection was refused by the peer. "
"Make sure your images server is running, "
"and check that the host name and port "
"settings are correct.");
break;
default:
//UERROR("The following error occurred: %s.", this->errorString().toStdString().c_str());
break;
}
}
void CameraTcpServer::connectionLost()
{
//printf("[WARNING] CameraTcp: Connection lost!\n");
((QTcpSocket*)sender())->close();
sender()->deleteLater();
blockSize_ = 0; // reset
}
} // namespace find_object
-68
View File
@@ -1,68 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 CAMERATCPCLIENT_H_
#define CAMERATCPCLIENT_H_
#include <QtGlobal>
#include <QtNetwork/QTcpServer>
#include <opencv2/opencv.hpp>
namespace find_object {
class CameraTcpServer : public QTcpServer
{
Q_OBJECT;
public:
CameraTcpServer(quint16 port = 0, QObject * parent = 0);
cv::Mat getImage();
int imagesBuffered() const {return images_.size();}
bool isConnected() const;
QHostAddress getHostAddress() const;
quint16 getPort() const;
protected:
#if QT_VERSION >= 0x050000
virtual void incomingConnection ( qintptr socketDescriptor );
#else
virtual void incomingConnection ( int socketDescriptor );
#endif
private Q_SLOTS:
void readReceivedData();
void displayError(QAbstractSocket::SocketError socketError);
void connectionLost();
private:
quint64 blockSize_;
QVector<cv::Mat> images_;
};
} // namespace find_object
#endif /* CAMERATCPCLIENT_H_ */
-79
View File
@@ -1,79 +0,0 @@
/*
* Compression.cpp
*
* Created on: Sep 10, 2018
* Author: labm2414
*/
#include <Compression.h>
#include <zlib.h>
#include "find_object/utilite/ULogger.h"
namespace find_object {
std::vector<unsigned char> compressData(const cv::Mat & data)
{
std::vector<unsigned char> bytes;
if(!data.empty())
{
uLong sourceLen = uLong(data.total())*uLong(data.elemSize());
uLong destLen = compressBound(sourceLen);
bytes.resize(destLen);
int errCode = compress(
(Bytef *)bytes.data(),
&destLen,
(const Bytef *)data.data,
sourceLen);
bytes.resize(destLen+3*sizeof(int));
*((int*)&bytes[destLen]) = data.rows;
*((int*)&bytes[destLen+sizeof(int)]) = data.cols;
*((int*)&bytes[destLen+2*sizeof(int)]) = data.type();
if(errCode == Z_MEM_ERROR)
{
UERROR("Z_MEM_ERROR : Insufficient memory.");
}
else if(errCode == Z_BUF_ERROR)
{
UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
}
}
return bytes;
}
cv::Mat uncompressData(const unsigned char * bytes, unsigned long size)
{
cv::Mat data;
if(bytes && size>=3*sizeof(int))
{
//last 3 int elements are matrix size and type
int height = *((int*)&bytes[size-3*sizeof(int)]);
int width = *((int*)&bytes[size-2*sizeof(int)]);
int type = *((int*)&bytes[size-1*sizeof(int)]);
data = cv::Mat(height, width, type);
uLongf totalUncompressed = uLongf(data.total())*uLongf(data.elemSize());
int errCode = uncompress(
(Bytef*)data.data,
&totalUncompressed,
(const Bytef*)bytes,
uLong(size));
if(errCode == Z_MEM_ERROR)
{
UERROR("Z_MEM_ERROR : Insufficient memory.");
}
else if(errCode == Z_BUF_ERROR)
{
UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
}
else if(errCode == Z_DATA_ERROR)
{
UERROR("Z_DATA_ERROR : The compressed data (referenced by source) was corrupted.");
}
}
return data;
}
} /* namespace find_object */
-20
View File
@@ -1,20 +0,0 @@
/*
* Compression.h
*
* Created on: Sep 10, 2018
* Author: labm2414
*/
#ifndef SRC_COMPRESSION_H_
#define SRC_COMPRESSION_H_
#include <opencv2/opencv.hpp>
namespace find_object {
std::vector<unsigned char> compressData(const cv::Mat & data);
cv::Mat uncompressData(const unsigned char * bytes, unsigned long size);
}
#endif /* SRC_COMPRESSION_H_ */
File diff suppressed because it is too large Load Diff
-66
View File
@@ -1,66 +0,0 @@
/*
* ImageDropWidget.cpp
*
* Created on: Dec 22, 2014
* Author: mathieu
*/
#include <ImageDropWidget.h>
#include <find_object/Settings.h>
#include <QtGui/QDragEnterEvent>
#include <QtCore/QRegExp>
#include <QtCore/QUrl>
#include <QMimeData>
namespace find_object {
ImageDropWidget::ImageDropWidget(QWidget *parent, Qt::WindowFlags flags) :
QWidget(parent, flags)
{
setAcceptDrops(true);
}
ImageDropWidget::~ImageDropWidget()
{
}
void ImageDropWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasUrls())
{
event->acceptProposedAction();
}
}
void ImageDropWidget::dropEvent(QDropEvent *event)
{
QStringList fileNames;
QStringList extensions = Settings::getGeneral_imageFormats().split(" ");
QList<QUrl> urls = event->mimeData()->urls();
for(int i=0; i<urls.size(); ++i)
{
QString path = urls.at(i).toLocalFile();
for(int j=0; j<extensions.size(); ++j)
{
QRegExp reg(extensions[j]);
reg.setPatternSyntax(QRegExp::Wildcard);
if(reg.exactMatch(path))
{
fileNames.push_back(path);
break;
}
}
}
if(fileNames.size())
{
Q_EMIT imagesReceived(fileNames);
}
event->acceptProposedAction();
}
}
-34
View File
@@ -1,34 +0,0 @@
/*
* ImageDropWidget.h
*
* Created on: Dec 22, 2014
* Author: mathieu
*/
#ifndef IMAGEDROPWIDGET_H_
#define IMAGEDROPWIDGET_H_
#include <QWidget>
namespace find_object {
class ImageDropWidget : public QWidget {
Q_OBJECT;
public:
ImageDropWidget(QWidget *parent = 0, Qt::WindowFlags flags = 0);
virtual ~ImageDropWidget();
Q_SIGNALS:
void imagesReceived(const QStringList &);
protected:
virtual void dragEnterEvent(QDragEnterEvent *event);
virtual void dropEvent(QDropEvent *event);
};
}
#endif /* IMAGEDROPWIDGET_H_ */
-122
View File
@@ -1,122 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/JsonWriter.h"
#include "find_object/utilite/ULogger.h"
#include <QtCore/QFile>
#include <QtCore/QTextStream>
#include <QtCore/QFileInfo>
#include "json/json.h"
namespace find_object {
void JsonWriter::write(const DetectionInfo & info, const QString & path)
{
if(!path.isEmpty())
{
Json::Value root;
if(info.objDetected_.size())
{
Json::Value detections;
QMultiMap<int, int>::const_iterator iterInliers = info.objDetectedInliersCount_.constBegin();
QMultiMap<int, int>::const_iterator iterOutliers = info.objDetectedOutliersCount_.constBegin();
QMultiMap<int, QSize>::const_iterator iterSizes = info.objDetectedSizes_.constBegin();
QMultiMap<int, QString>::const_iterator iterFilePaths = info.objDetectedFilePaths_.constBegin();
for(QMultiMap<int, QTransform>::const_iterator iter = info.objDetected_.constBegin(); iter!= info.objDetected_.end();)
{
char index = 'a';
int id = iter.key();
while(iter != info.objDetected_.constEnd() && id == iter.key())
{
QString name = QString("object_%1%2").arg(id).arg(info.objDetected_.count(id)>1?QString(index++):"");
detections.append(name.toStdString());
Json::Value homography;
homography.append(iter.value().m11());
homography.append(iter.value().m12());
homography.append(iter.value().m13());
homography.append(iter.value().m21());
homography.append(iter.value().m22());
homography.append(iter.value().m23());
homography.append(iter.value().m31()); // dx
homography.append(iter.value().m32()); // dy
homography.append(iter.value().m33());
root[name.toStdString()]["width"] = iterSizes.value().width();
root[name.toStdString()]["height"] = iterSizes.value().height();
root[name.toStdString()]["homography"] = homography;
root[name.toStdString()]["inliers"] = iterInliers.value();
root[name.toStdString()]["outliers"] = iterOutliers.value();
root[name.toStdString()]["filepath"] = iterFilePaths.value().toStdString();
QString filename;
if(!iterFilePaths.value().isEmpty())
{
QFileInfo file(iterFilePaths.value());
filename=file.fileName();
}
root[name.toStdString()]["filename"] = filename.toStdString();
++iter;
++iterInliers;
++iterOutliers;
++iterSizes;
++iterFilePaths;
}
}
root["objects"] = detections;
}
if(info.matches_.size())
{
Json::Value matchesValues;
const QMap<int, QMultiMap<int, int> > & matches = info.matches_;
for(QMap<int, QMultiMap<int, int> >::const_iterator iter = matches.constBegin();
iter != matches.end();
++iter)
{
QString name = QString("matches_%1").arg(iter.key());
root[name.toStdString()] = iter.value().size();
matchesValues.append(name.toStdString());
}
root["matches"] = matchesValues;
}
// write in a nice readible way
Json::StyledWriter styledWriter;
//std::cout << styledWriter.write(root);
QFile file(path);
file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out << styledWriter.write(root).c_str();
file.close();
}
}
} // namespace find_object
-137
View File
@@ -1,137 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "KeypointItem.h"
#include <QtGui/QPen>
#include <QtGui/QBrush>
#include <QGraphicsScene>
namespace find_object {
KeypointItem::KeypointItem(int id, qreal x, qreal y, int r, const cv::KeyPoint & kpt, int wordID, const QColor & color, QGraphicsItem * parent) :
QGraphicsEllipseItem(x, y, r, r, parent),
placeHolder_(0),
id_(id),
kpt_(kpt),
wordID_(wordID)
{
this->setPen(QPen(color));
this->setBrush(QBrush(color));
this->setAcceptHoverEvents(true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
}
KeypointItem::~KeypointItem()
{
}
void KeypointItem::setColor(const QColor & color)
{
this->setPen(QPen(color));
this->setBrush(QBrush(color));
if(placeHolder_)
{
QList<QGraphicsItem *> items = placeHolder_->childItems();
if(items.size())
{
((QGraphicsTextItem *)items.front())->setDefaultTextColor(this->pen().color().rgb());
}
}
}
void KeypointItem::showDescription()
{
if(!placeHolder_ || !placeHolder_->isVisible())
{
if(!placeHolder_)
{
QString info = QString( "Keypoint = %1\n"
"Word = %2\n"
"Response = %3\n"
"Angle = %4\n"
"X = %5\n"
"Y = %6\n"
"Size = %7").arg(id_).arg(wordID_).arg(kpt_.response).arg(kpt_.angle).arg(kpt_.pt.x).arg(kpt_.pt.y).arg(kpt_.size);
placeHolder_ = new QGraphicsRectItem();
placeHolder_->setVisible(false);
this->scene()->addItem(placeHolder_);
placeHolder_->setBrush(QBrush(QColor ( 0, 0, 0, 170 ))); // Black transparent background
QGraphicsTextItem * text = new QGraphicsTextItem(placeHolder_);
text->setDefaultTextColor(this->pen().color().rgb());
text->setPlainText(info);
placeHolder_->setRect(text->boundingRect());
}
QPen pen = this->pen();
this->setPen(QPen(pen.color(), pen.width()+2));
placeHolder_->setZValue(this->zValue()+1);
placeHolder_->setPos(this->mapToScene(0,0));
placeHolder_->setVisible(true);
}
}
void KeypointItem::hideDescription()
{
if(placeHolder_ && placeHolder_->isVisible())
{
placeHolder_->setVisible(false);
this->setPen(QPen(pen().color(), pen().width()-2));
}
}
void KeypointItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
{
this->showDescription();
QGraphicsEllipseItem::hoverEnterEvent(event);
}
void KeypointItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event )
{
if(!this->hasFocus())
{
this->hideDescription();
}
QGraphicsEllipseItem::hoverEnterEvent(event);
}
void KeypointItem::focusInEvent ( QFocusEvent * event )
{
this->showDescription();
QGraphicsEllipseItem::focusInEvent(event);
}
void KeypointItem::focusOutEvent ( QFocusEvent * event )
{
this->hideDescription();
QGraphicsEllipseItem::focusOutEvent(event);
}
} // namespace find_object
-69
View File
@@ -1,69 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 KEYPOINTITEM_H_
#define KEYPOINTITEM_H_
#include <QGraphicsEllipseItem>
#include <QGraphicsTextItem>
#include <QtGui/QPen>
#include <QtGui/QBrush>
#include <opencv2/features2d/features2d.hpp>
namespace find_object {
class KeypointItem : public QGraphicsEllipseItem
{
public:
KeypointItem(int id, qreal x, qreal y, int r, const cv::KeyPoint & kpt, int wordID = -1, const QColor & color = Qt::green, QGraphicsItem * parent = 0);
virtual ~KeypointItem();
void setColor(const QColor & color);
void setWordID(int id) {wordID_ = id;}
int wordID() const {return wordID_;}
int id() const {return id_;}
protected:
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
virtual void focusInEvent ( QFocusEvent * event );
virtual void focusOutEvent ( QFocusEvent * event );
private:
void showDescription();
void hideDescription();
private:
QGraphicsRectItem * placeHolder_;
int id_;
cv::KeyPoint kpt_;
int wordID_;
};
} // namespace find_object
#endif /* KEYPOINTITEM_H_ */
File diff suppressed because it is too large Load Diff
-202
View File
@@ -1,202 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 OBJSIGNATURE_H_
#define OBJSIGNATURE_H_
#include <opencv2/opencv.hpp>
#include <QtCore/QString>
#include <QtCore/QMultiMap>
#include <QtCore/QRect>
#include <QtCore/QDataStream>
#include <QtCore/QByteArray>
#include <QtCore/QFileInfo>
#include <Compression.h>
namespace find_object {
class ObjSignature {
public:
ObjSignature() :
id_(-1)
{}
ObjSignature(int id, const cv::Mat & image, const QString & filePath) :
id_(id),
image_(image),
rect_(0,0,image.cols, image.rows),
filePath_(filePath)
{}
virtual ~ObjSignature() {}
void setData(const std::vector<cv::KeyPoint> & keypoints, const cv::Mat & descriptors)
{
keypoints_ = keypoints;
descriptors_ = descriptors;
}
void setWords(const QMultiMap<int, int> & words) {words_ = words;}
void setId(int id) {id_ = id;}
void removeImage() {image_ = cv::Mat();}
const QRect & rect() const {return rect_;}
int id() const {return id_;}
const QString & filePath() const {return filePath_;}
const cv::Mat & image() const {return image_;}
const std::vector<cv::KeyPoint> & keypoints() const {return keypoints_;}
const cv::Mat & descriptors() const {return descriptors_;}
const QMultiMap<int, int> & words() const {return words_;}
void save(QDataStream & streamPtr) const
{
streamPtr << id_;
streamPtr << filePath_;
streamPtr << (int)keypoints_.size();
for(unsigned int j=0; j<keypoints_.size(); ++j)
{
streamPtr << keypoints_.at(j).angle <<
keypoints_.at(j).class_id <<
keypoints_.at(j).octave <<
keypoints_.at(j).pt.x <<
keypoints_.at(j).pt.y <<
keypoints_.at(j).response <<
keypoints_.at(j).size;
}
std::vector<unsigned char> bytes = compressData(descriptors_);
qint64 dataSize = bytes.size();
int old = 0;
if(dataSize <= std::numeric_limits<int>::max())
{
// old: rows, cols, type
streamPtr << old << old << old << dataSize;
streamPtr << QByteArray::fromRawData((const char*)bytes.data(), dataSize);
}
else
{
UERROR("Descriptors (compressed) are too large (%d MB) to be saved! Limit is 2 GB (based on max QByteArray size).",
dataSize/(1024*1024));
// old: rows, cols, type, dataSize
streamPtr << old << old << old << old;
streamPtr << QByteArray(); // empty
}
streamPtr << words_;
if(!image_.empty())
{
std::vector<unsigned char> bytes;
QString ext = QFileInfo(filePath_).suffix();
if(ext.isEmpty())
{
// default png
cv::imencode(".png", image_, bytes);
}
else
{
cv::imencode(std::string(".")+ext.toStdString(), image_, bytes);
}
streamPtr << QByteArray::fromRawData((const char*)bytes.data(), (int)bytes.size());
}
else
{
streamPtr << QByteArray();
}
streamPtr << rect_;
}
void load(QDataStream & streamPtr, bool ignoreImage)
{
int nKpts;
streamPtr >> id_ >> filePath_ >> nKpts;
keypoints_.resize(nKpts);
for(int i=0;i<nKpts;++i)
{
streamPtr >>
keypoints_[i].angle >>
keypoints_[i].class_id >>
keypoints_[i].octave >>
keypoints_[i].pt.x >>
keypoints_[i].pt.y >>
keypoints_[i].response >>
keypoints_[i].size;
}
int rows,cols,type;
qint64 dataSize;
streamPtr >> rows >> cols >> type >> dataSize;
if(rows == 0 && cols == 0 && type == 0)
{
// compressed descriptors
UASSERT(dataSize <= std::numeric_limits<int>::max());
QByteArray data;
streamPtr >> data;
descriptors_ = uncompressData((unsigned const char*)data.data(), dataSize);
}
else
{
// old raw format
QByteArray data;
streamPtr >> data;
if(data.size())
{
descriptors_ = cv::Mat(rows, cols, type, data.data()).clone();
}
else if(dataSize)
{
UERROR("Error reading descriptor data for object=%d", id_);
}
}
streamPtr >> words_;
QByteArray image;
streamPtr >> image;
if(!ignoreImage && image.size())
{
std::vector<unsigned char> bytes(image.size());
memcpy(bytes.data(), image.data(), image.size());
image_ = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
}
streamPtr >> rect_;
}
private:
int id_;
cv::Mat image_;
QRect rect_;
QString filePath_;
std::vector<cv::KeyPoint> keypoints_;
cv::Mat descriptors_;
QMultiMap<int, int> words_; // <word id, keypoint indexes>
};
} // namespace find_object
#endif /* OBJSIGNATURE_H_ */
-830
View File
@@ -1,830 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/Settings.h"
#include "find_object/utilite/ULogger.h"
#include "find_object/ObjWidget.h"
#include "find_object/QtOpenCV.h"
#include "KeypointItem.h"
#include <opencv2/highgui/highgui.hpp>
#include <QWidget>
#include <QContextMenuEvent>
#include <QMenu>
#include <QFileDialog>
#include <QAction>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QVBoxLayout>
#include <QGraphicsRectItem>
#include <QInputDialog>
#include <QPen>
#include <QLabel>
#include <QColorDialog>
#include <QtCore/QDir>
#include <stdio.h>
namespace find_object {
ObjWidget::ObjWidget(QWidget * parent) :
QWidget(parent),
id_(0),
graphicsView_(0),
graphicsViewInitialized_(false),
alpha_(100),
color_(Qt::red)
{
setupUi();
}
ObjWidget::ObjWidget(int id, const std::vector<cv::KeyPoint> & keypoints, const QMultiMap<int,int> & words, const QImage & image, QWidget * parent) :
QWidget(parent),
id_(id),
graphicsView_(0),
graphicsViewInitialized_(false),
alpha_(100),
color_(QColor((Qt::GlobalColor)((id % 10 + 7)==Qt::yellow?Qt::darkYellow:(id % 10 + 7))))
{
setupUi();
this->updateImage(image);
this->updateData(keypoints, words);
}
ObjWidget::~ObjWidget()
{
}
void ObjWidget::setupUi()
{
graphicsView_ = new QGraphicsView(this);
graphicsView_->setVisible(false);
graphicsView_->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
graphicsView_->setScene(new QGraphicsScene(graphicsView_));
label_ = new QLabel();
label_->setAlignment(Qt::AlignCenter);
label_->setTextInteractionFlags(Qt::TextSelectableByMouse);
this->setLayout(new QVBoxLayout(this));
this->layout()->addWidget(graphicsView_);
this->layout()->addWidget(label_);
this->layout()->setContentsMargins(0,0,0,0);
menu_ = new QMenu(tr(""), this);
showImage_ = menu_->addAction(tr("Show image"));
showImage_->setCheckable(true);
showImage_->setChecked(true);
showFeatures_ = menu_->addAction(tr("Show features"));
showFeatures_->setCheckable(true);
showFeatures_->setChecked(true);
mirrorView_ = menu_->addAction(tr("Mirror view"));
mirrorView_->setCheckable(true);
mirrorView_->setChecked(false);
graphicsViewMode_ = menu_->addAction(tr("Graphics view"));
graphicsViewMode_->setCheckable(true);
graphicsViewMode_->setChecked(false);
autoScale_ = menu_->addAction(tr("Scale view"));
autoScale_->setCheckable(true);
autoScale_->setChecked(true);
autoScale_->setEnabled(false);
sizedFeatures_ = menu_->addAction(tr("Sized features"));
sizedFeatures_->setCheckable(true);
sizedFeatures_->setChecked(false);
menu_->addSeparator();
setColor_ = menu_->addAction(tr("Set color..."));
setAlpha_ = menu_->addAction(tr("Set alpha..."));
menu_->addSeparator();
saveImage_ = menu_->addAction(tr("Save picture..."));
menu_->addSeparator();
delete_ = menu_->addAction(tr("Delete"));
delete_->setEnabled(false);
this->setId(id_);
graphicsView_->setRubberBandSelectionMode(Qt::ContainsItemShape);
graphicsView_->setDragMode(QGraphicsView::RubberBandDrag);
connect(graphicsView_->scene(), SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
}
void ObjWidget::setId(int id)
{
color_ = QColor((Qt::GlobalColor)((id % 10 + 7)==Qt::yellow?Qt::darkYellow:(id % 10 + 7)));
id_=id;
if(id_)
{
savedFileName_ = QString("object_%1.png").arg(id_);
}
}
void ObjWidget::setGraphicsViewMode(bool on)
{
graphicsViewMode_->setChecked(on);
graphicsView_->setVisible(on && graphicsView_->scene()->items().size());
autoScale_->setEnabled(on);
//update items' color
if(on)
{
if(!graphicsViewInitialized_)
{
this->setupGraphicsView();
}
else
{
for(int i=0; i<keypointItems_.size(); ++i)
{
QColor color = kptColors_.at(i);
color.setAlpha(alpha_);
keypointItems_[i]->setColor(color);
}
}
}
if(autoScale_->isChecked())
{
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
}
else
{
graphicsView_->resetTransform();
graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0));
}
}
void ObjWidget::setAutoScale(bool autoScale)
{
autoScale_->setChecked(autoScale);
if(graphicsViewMode_)
{
if(autoScale)
{
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
}
else
{
graphicsView_->resetTransform();
graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0));
}
}
}
void ObjWidget::setSizedFeatures(bool on)
{
sizedFeatures_->setChecked(on);
if(graphicsViewInitialized_)
{
for(unsigned int i=0; i<(unsigned int)keypointItems_.size() && i<keypoints_.size(); ++i)
{
float size = 14;
if(on && keypoints_[i].size>14.0f)
{
size = keypoints_[i].size;
}
float radius = size*1.2f/9.0f*2.0f;
keypointItems_.at(i)->setRect(keypoints_[i].pt.x-radius, keypoints_[i].pt.y-radius, radius*2, radius*2);
}
}
if(!graphicsViewMode_->isChecked())
{
this->update();
}
}
void ObjWidget::setMirrorView(bool on)
{
mirrorView_->setChecked(on);
graphicsView_->setTransform(QTransform().scale(this->isMirrorView()?-1.0:1.0, 1.0));
if(graphicsViewMode_->isChecked() && autoScale_->isChecked())
{
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
}
else if(!graphicsViewMode_->isChecked())
{
this->update();
}
}
void ObjWidget::setAlpha(int alpha)
{
if(alpha>=0 && alpha<=255)
{
alpha_ = alpha;
if(graphicsViewInitialized_)
{
for(int i=0; i<keypointItems_.size() && i<kptColors_.size(); ++i)
{
QColor color = kptColors_.at(i);
color.setAlpha(alpha_);
keypointItems_.at(i)->setColor(color);
}
}
for(int i=0; i<rectItems_.size(); ++i)
{
QPen pen = rectItems_.at(i)->pen();
QColor color = pen.color();
color.setAlpha(alpha_);
pen.setColor(color);
rectItems_.at(i)->setPen(pen);
}
if(!graphicsViewMode_->isChecked())
{
this->update();
}
}
}
void ObjWidget::setTextLabel(const QString & text)
{
label_->setText(text);
}
void ObjWidget::updateImage(const QImage & image)
{
pixmap_ = QPixmap();
rect_ = QRect();
if(!image.isNull())
{
pixmap_ = QPixmap::fromImage(image);
rect_ = pixmap_.rect();
}
label_->setVisible(image.isNull());
}
void ObjWidget::updateData(const std::vector<cv::KeyPoint> & keypoints, const QMultiMap<int, int> & words)
{
keypoints_ = keypoints;
kptColors_ = QVector<QColor>((int)keypoints.size(), defaultColor(0));
keypointItems_.clear();
rectItems_.clear();
this->updateWords(words);
graphicsView_->scene()->clear();
graphicsViewInitialized_ = false;
mouseCurrentPos_ = mousePressedPos_; // this will reset roi selection
//this->setMinimumSize(image_.size());
if(graphicsViewMode_->isChecked())
{
this->setupGraphicsView();
}
else
{
this->update();
}
}
void ObjWidget::updateWords(const QMultiMap<int,int> & words)
{
words_.clear();
for(QMultiMap<int,int>::const_iterator iter=words.begin(); iter!=words.end(); ++iter)
{
words_.insert(iter.value(), iter.key());
}
for(int i=0; i<kptColors_.size(); ++i)
{
kptColors_[i] = defaultColor(words_.size()?words_.value(i,-1):0);
if(keypointItems_.size() == kptColors_.size())
{
keypointItems_[i]->setWordID(words_.value(i,-1));
keypointItems_[i]->setColor(defaultColor(words_.size()?keypointItems_[i]->wordID():0));
}
}
}
void ObjWidget::resetKptsColor()
{
for(int i=0; i<kptColors_.size(); ++i)
{
if(keypointItems_.size() == kptColors_.size())
{
kptColors_[i] = defaultColor(keypointItems_[i]->wordID());
keypointItems_[i]->setColor(this->defaultColor(keypointItems_[i]->wordID()));
}
else
{
kptColors_[i] = defaultColor(words_.value(i,-1));
}
}
qDeleteAll(rectItems_.begin(), rectItems_.end());
rectItems_.clear();
}
void ObjWidget::resetKptsWordID()
{
words_.clear();
for(int i=0; i<keypointItems_.size(); ++i)
{
keypointItems_[i]->setWordID(-1);
}
}
void ObjWidget::setKptColor(int index, const QColor & color)
{
if(index < kptColors_.size())
{
kptColors_[index] = color;
}
else
{
UWARN("PROBLEM index =%d > size=%d\n", index, kptColors_.size());
}
if(graphicsViewMode_->isChecked())
{
if(index < keypointItems_.size())
{
QColor c = color;
c.setAlpha(alpha_);
keypointItems_.at(index)->setColor(c);
}
}
}
void ObjWidget::setKptWordID(int index, int wordID)
{
words_.insert(index, wordID);
if(index < keypointItems_.size())
{
keypointItems_.at(index)->setWordID(wordID);
}
}
void ObjWidget::addRect(QGraphicsRectItem * rect)
{
if(graphicsViewInitialized_)
{
graphicsView_->scene()->addItem(rect);
}
rect->setZValue(1);
QPen pen = rect->pen();
QColor color = pen.color();
color.setAlpha(alpha_);
pen.setColor(color);
rect->setPen(pen);
rectItems_.append(rect);
}
QList<QGraphicsItem*> ObjWidget::selectedItems() const
{
return graphicsView_->scene()->selectedItems();
}
bool ObjWidget::isImageShown() const
{
return showImage_->isChecked();
}
bool ObjWidget::isFeaturesShown() const
{
return showFeatures_->isChecked();
}
bool ObjWidget::isSizedFeatures() const
{
return sizedFeatures_->isChecked();
}
bool ObjWidget::isMirrorView() const
{
return mirrorView_->isChecked();
}
void ObjWidget::setDeletable(bool deletable)
{
delete_->setEnabled(deletable);
}
void ObjWidget::setImageShown(bool shown)
{
showImage_->setChecked(shown);
if(graphicsViewMode_->isChecked())
{
this->updateItemsShown();
}
else
{
this->update();
}
}
void ObjWidget::setFeaturesShown(bool shown)
{
showFeatures_->setChecked(shown);
if(graphicsViewMode_->isChecked())
{
this->updateItemsShown();
}
else
{
this->update();
}
}
void ObjWidget::computeScaleOffsets(float & scale, float & offsetX, float & offsetY)
{
scale = 1.0f;
offsetX = 0.0f;
offsetY = 0.0f;
if(!rect_.isNull())
{
float w = rect_.width();
float h = rect_.height();
float widthRatio = float(this->rect().width()) / w;
float heightRatio = float(this->rect().height()) / h;
//printf("w=%f, h=%f, wR=%f, hR=%f, sW=%d, sH=%d\n", w, h, widthRatio, heightRatio, this->rect().width(), this->rect().height());
if(widthRatio < heightRatio)
{
scale = widthRatio;
}
else
{
scale = heightRatio;
}
//printf("ratio=%f\n",ratio);
w *= scale;
h *= scale;
if(w < this->rect().width())
{
offsetX = (this->rect().width() - w)/2.0f;
}
if(h < this->rect().height())
{
offsetY = (this->rect().height() - h)/2.0f;
}
//printf("offsetX=%f, offsetY=%f\n",offsetX, offsetY);
}
}
void ObjWidget::paintEvent(QPaintEvent *event)
{
if(graphicsViewMode_->isChecked())
{
QWidget::paintEvent(event);
}
else
{
if(!rect_.isNull())
{
//Scale
float ratio, offsetX, offsetY;
this->computeScaleOffsets(ratio, offsetX, offsetY);
QPainter painter(this);
if(mirrorView_->isChecked())
{
painter.translate(offsetX+rect_.width()*ratio, offsetY);
painter.scale(-ratio, ratio);
}
else
{
painter.translate(offsetX, offsetY);
painter.scale(ratio, ratio);
}
if(!pixmap_.isNull() && showImage_->isChecked())
{
painter.drawPixmap(QPoint(0,0), pixmap_);
}
if(showFeatures_->isChecked())
{
drawKeypoints(&painter);
}
for(int i=0; i<rectItems_.size(); ++i)
{
painter.save();
painter.setTransform(rectItems_.at(i)->transform(), true);
painter.setPen(rectItems_.at(i)->pen());
painter.drawRect(rectItems_.at(i)->rect());
painter.restore();
}
if(mouseCurrentPos_ != mousePressedPos_)
{
painter.save();
int left, top, right, bottom;
left = mousePressedPos_.x() < mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x();
top = mousePressedPos_.y() < mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y();
right = mousePressedPos_.x() > mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x();
bottom = mousePressedPos_.y() > mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y();
if(mirrorView_->isChecked())
{
int l = left;
left = qAbs(right - rect_.width());
right = qAbs(l - rect_.width());
}
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(QColor(0,0,0,100)));
painter.drawRect(0, 0, rect_.width(), top);
painter.drawRect(0, top, left, bottom-top);
painter.drawRect(right, top, rect_.width()-right, bottom-top);
painter.drawRect(0, bottom, rect_.width(), rect_.height()-bottom);
painter.restore();
}
}
}
}
void ObjWidget::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
if(graphicsViewMode_->isChecked() && autoScale_->isChecked())
{
graphicsView_->fitInView(graphicsView_->sceneRect(), Qt::KeepAspectRatio);
}
}
void ObjWidget::mousePressEvent(QMouseEvent * event)
{
float scale, offsetX, offsetY;
this->computeScaleOffsets(scale, offsetX, offsetY);
mousePressedPos_.setX((event->pos().x()-offsetX)/scale);
mousePressedPos_.setY((event->pos().y()-offsetY)/scale);
mouseCurrentPos_ = mousePressedPos_;
this->update();
QWidget::mousePressEvent(event);
}
void ObjWidget::mouseMoveEvent(QMouseEvent * event)
{
float scale, offsetX, offsetY;
this->computeScaleOffsets(scale, offsetX, offsetY);
mouseCurrentPos_.setX((event->pos().x()-offsetX)/scale);
mouseCurrentPos_.setY((event->pos().y()-offsetY)/scale);
this->update();
QWidget::mouseMoveEvent(event);
}
void ObjWidget::mouseReleaseEvent(QMouseEvent * event)
{
if(!rect_.isNull())
{
int left,top,bottom,right;
left = mousePressedPos_.x() < mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x();
top = mousePressedPos_.y() < mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y();
right = mousePressedPos_.x() > mouseCurrentPos_.x() ? mousePressedPos_.x():mouseCurrentPos_.x();
bottom = mousePressedPos_.y() > mouseCurrentPos_.y() ? mousePressedPos_.y():mouseCurrentPos_.y();
if(mirrorView_->isChecked())
{
int l = left;
left = qAbs(right - rect_.width());
right = qAbs(l - rect_.width());
}
Q_EMIT roiChanged(cv::Rect(left, top, right-left, bottom-top));
}
QWidget::mouseReleaseEvent(event);
}
void ObjWidget::contextMenuEvent(QContextMenuEvent * event)
{
QAction * action = menu_->exec(event->globalPos());
if(action == saveImage_)
{
QString text;
if(savedFileName_.isEmpty())
{
savedFileName_=Settings::workingDirectory()+"/figure.png";
}
text = QFileDialog::getSaveFileName(this, tr("Save figure to ..."), savedFileName_, "*.png *.xpm *.jpg *.pdf");
if(!text.isEmpty())
{
if(!text.endsWith(".png") && !text.endsWith(".xpm") && !text.endsWith(".jpg") && !text.endsWith(".pdf"))
{
text.append(".png");//default
}
savedFileName_ = text;
getSceneAsPixmap().save(text);
}
}
else if(action == showFeatures_ || action == showImage_)
{
if(graphicsViewMode_->isChecked())
{
this->updateItemsShown();
}
else
{
this->update();
}
}
else if(action == mirrorView_)
{
this->setMirrorView(mirrorView_->isChecked());
}
else if(action == delete_)
{
Q_EMIT removalTriggered(this);
}
else if(action == graphicsViewMode_)
{
this->setGraphicsViewMode(graphicsViewMode_->isChecked());
}
else if(action == autoScale_)
{
this->setAutoScale(autoScale_->isChecked());
}
else if(action == sizedFeatures_)
{
this->setSizedFeatures(sizedFeatures_->isChecked());
}
else if(action == setColor_)
{
QColor color = QColorDialog::getColor(color_, this);
if(color.isValid())
{
for(int i=0; i<kptColors_.size(); ++i)
{
if(kptColors_[i] == color_)
{
kptColors_[i] = color;
if(graphicsViewMode_->isChecked())
{
keypointItems_[i]->setColor(color);
}
}
}
for(int i=0; i<rectItems_.size(); ++i)
{
if(rectItems_[i]->pen().color() == color_)
{
QPen p = rectItems_[i]->pen();
p.setColor(color);
rectItems_[i]->setPen(p);
}
}
color_ = color;
}
}
else if(action == setAlpha_)
{
bool ok;
int newAlpha = QInputDialog::getInt(this, tr("Set alpha"), tr("Alpha:"), alpha_, 0, 255, 5, &ok);
if(ok)
{
this->setAlpha(newAlpha);
}
}
}
QPixmap ObjWidget::getSceneAsPixmap()
{
if(graphicsViewMode_->isChecked())
{
QPixmap img(graphicsView_->sceneRect().width(), graphicsView_->sceneRect().height());
QPainter p(&img);
graphicsView_->scene()->render(&p, graphicsView_->sceneRect(), graphicsView_->sceneRect());
return img;
}
else
{
return QPixmap::grabWidget(this);
}
}
void ObjWidget::updateItemsShown()
{
QList<QGraphicsItem*> items = graphicsView_->scene()->items();
for(int i=0; i<items.size(); ++i)
{
if(qgraphicsitem_cast<KeypointItem*>(items.at(i)))
{
items.at(i)->setVisible(showFeatures_->isChecked());
}
else if(qgraphicsitem_cast<QGraphicsPixmapItem*>(items.at(i)))
{
items.at(i)->setVisible(showImage_->isChecked());
}
}
}
void ObjWidget::drawKeypoints(QPainter * painter)
{
QList<KeypointItem *> items;
KeypointItem * item = 0;
int i = 0;
for(std::vector<cv::KeyPoint>::const_iterator iter = keypoints_.begin(); iter != keypoints_.end(); ++iter, ++i )
{
const cv::KeyPoint & r = *iter;
float size = 14;
if(r.size>14.0f && sizedFeatures_->isChecked())
{
size = r.size;
}
float radius = size*1.2f/9.0f*2.0f;
QColor color(kptColors_.at(i).red(), kptColors_.at(i).green(), kptColors_.at(i).blue(), alpha_);
if(graphicsViewMode_->isChecked())
{
// YELLOW = NEW and multiple times
item = new KeypointItem(i, r.pt.x-radius, r.pt.y-radius, radius*2, r, words_.value(i, -1), color);
item->setVisible(this->isFeaturesShown());
item->setZValue(2);
graphicsView_->scene()->addItem(item);
item->setColor(defaultColor(item->wordID()));
kptColors_[i] = defaultColor(item->wordID());
keypointItems_.append(item);
}
if(painter)
{
painter->save();
painter->setPen(color);
painter->setBrush(color);
painter->drawEllipse(r.pt.x-radius, r.pt.y-radius, radius*2, radius*2);
painter->restore();
}
}
}
QColor ObjWidget::defaultColor(int id) const
{
QColor color(id >= 0 ? Qt::yellow : Qt::white);
color.setAlpha(alpha_);
return color;
}
std::vector<cv::KeyPoint> ObjWidget::selectedKeypoints() const
{
std::vector<cv::KeyPoint> selected;
if(graphicsViewMode_->isChecked())
{
QList<QGraphicsItem*> items = graphicsView_->scene()->selectedItems();
for(int i=0; i<items.size(); ++i)
{
if(qgraphicsitem_cast<KeypointItem*>(items.at(i)))
{
selected.push_back(keypoints_.at(((KeypointItem*)items.at(i))->id()));
}
}
}
return selected;
}
void ObjWidget::setupGraphicsView()
{
if(!rect_.isNull())
{
graphicsView_->setVisible(true);
graphicsView_->scene()->setSceneRect(rect_);
QList<KeypointItem*> items;
QRectF sceneRect = graphicsView_->sceneRect();
QGraphicsPixmapItem * pixmapItem = graphicsView_->scene()->addPixmap(pixmap_);
pixmapItem->setVisible(this->isImageShown());
this->drawKeypoints();
for(int i=0; i<rectItems_.size(); ++i)
{
graphicsView_->scene()->addItem(rectItems_.at(i));
}
if(autoScale_->isChecked())
{
graphicsView_->fitInView(sceneRect, Qt::KeepAspectRatio);
}
graphicsViewInitialized_ = true;
}
else
{
graphicsView_->setVisible(false);
}
}
} // namespace find_object
-823
View File
@@ -1,823 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/Settings.h"
#include "ParametersToolBox.h"
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QLineEdit>
#include <QLabel>
#include <QGroupBox>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QMessageBox>
#include <stdio.h>
#include "find_object/utilite/ULogger.h"
#include <opencv2/opencv_modules.hpp>
namespace find_object {
ParametersToolBox::ParametersToolBox(QWidget *parent) :
QToolBox(parent)
{
}
ParametersToolBox::~ParametersToolBox()
{
}
QWidget * ParametersToolBox::getParameterWidget(const QString & key)
{
return this->findChild<QWidget*>(key);
}
QStringList ParametersToolBox::resetPage(int index)
{
QStringList paramChanged;
const QObjectList & children = this->widget(index)->children();
for(int j=0; j<children.size();++j)
{
QString key = children.at(j)->objectName();
// ignore only the nextObjID setting, to avoid problem with saved objects
if(key.compare(Settings::kGeneral_nextObjID()) != 0)
{
QVariant value = Settings::getDefaultParameters().value(key, QVariant());
if(value.isValid())
{
Settings::setParameter(key, value);
if(qobject_cast<QComboBox*>(children.at(j)))
{
if(((QComboBox*)children.at(j))->currentIndex() != value.toString().split(':').first().toInt())
{
((QComboBox*)children.at(j))->setCurrentIndex(value.toString().split(':').first().toInt());
paramChanged.append(key);
}
}
else if(qobject_cast<QSpinBox*>(children.at(j)))
{
if(((QSpinBox*)children.at(j))->value() != value.toInt())
{
((QSpinBox*)children.at(j))->setValue(value.toInt());
paramChanged.append(key);
}
}
else if(qobject_cast<QDoubleSpinBox*>(children.at(j)))
{
if(((QDoubleSpinBox*)children.at(j))->value() != value.toDouble())
{
((QDoubleSpinBox*)children.at(j))->setValue(value.toDouble());
paramChanged.append(key);
}
}
else if(qobject_cast<QCheckBox*>(children.at(j)))
{
if(((QCheckBox*)children.at(j))->isChecked() != value.toBool())
{
((QCheckBox*)children.at(j))->setChecked(value.toBool());
paramChanged.append(key);
}
}
else if(qobject_cast<QLineEdit*>(children.at(j)))
{
if(((QLineEdit*)children.at(j))->text().compare(value.toString()) != 0)
{
((QLineEdit*)children.at(j))->setText(value.toString());
paramChanged.append(key);
}
}
}
}
}
return paramChanged;
}
void ParametersToolBox::resetCurrentPage()
{
this->blockSignals(true);
QStringList paramChanged = this->resetPage(this->currentIndex());
this->blockSignals(false);
Q_EMIT parametersChanged(paramChanged);
}
void ParametersToolBox::resetAllPages()
{
QStringList paramChanged;
this->blockSignals(true);
for(int i=0; i< this->count(); ++i)
{
paramChanged.append(this->resetPage(i));
}
this->blockSignals(false);
Q_EMIT parametersChanged(paramChanged);
}
void ParametersToolBox::updateParametersVisibility()
{
//show/hide not used parameters
QComboBox * descriptorBox = this->findChild<QComboBox*>(Settings::kFeature2D_2Descriptor());
QComboBox * detectorBox = this->findChild<QComboBox*>(Settings::kFeature2D_1Detector());
if(descriptorBox && detectorBox)
{
QString group = Settings::kFeature2D_2Descriptor().split('/').first();
QWidget * panel = 0;
for(int i=0; i<this->count(); ++i)
{
if(this->widget(i)->objectName().compare(group) == 0)
{
panel = this->widget(i);
break;
}
}
if(panel)
{
const QObjectList & objects = panel->children();
QString descriptorName = descriptorBox->currentText();
QString detectorName = detectorBox->currentText();
for(int i=0; i<objects.size(); ++i)
{
if(!objects[i]->objectName().isEmpty())
{
if(objects[i]->objectName().contains(descriptorName) || objects[i]->objectName().contains(detectorName))
{
((QWidget*)objects[i])->setVisible(true);
}
else if(objects[i]->objectName().contains("Fast") && detectorName == QString("ORB"))
{
((QWidget*)objects[i])->setVisible(true); // ORB uses some FAST parameters
}
else if(!objects[i]->objectName().split('/').at(1).at(0).isDigit())
{
((QWidget*)objects[i])->setVisible(false);
}
}
}
}
}
QComboBox * nnBox = this->findChild<QComboBox*>(Settings::kNearestNeighbor_1Strategy());
if(nnBox)
{
QString group = Settings::kNearestNeighbor_1Strategy().split('/').first();
QWidget * panel = 0;
for(int i=0; i<this->count(); ++i)
{
if(this->widget(i)->objectName().compare(group) == 0)
{
panel = this->widget(i);
break;
}
}
if(panel)
{
const QObjectList & objects = panel->children();
QString nnName = nnBox->currentText();
for(int i=0; i<objects.size(); ++i)
{
if(!objects[i]->objectName().isEmpty())
{
if(objects[i]->objectName().contains(nnName))
{
((QWidget*)objects[i])->setVisible(true);
}
else if(!objects[i]->objectName().split('/').at(1).at(0).isDigit())
{
((QWidget*)objects[i])->setVisible(false);
if(nnBox->currentIndex() < 6 && objects[i]->objectName().split('/').at(1).contains("search"))
{
//show flann search parameters
((QWidget*)objects[i])->setVisible(true);
}
}
else if(objects[i]->objectName().split('/').at(1).contains("Distance_type"))
{
// don't show distance when bruteforce is selected
((QWidget*)objects[i])->setVisible(nnBox->currentIndex() != 6);
}
}
}
}
}
}
void ParametersToolBox::setupUi()
{
this->removeItem(0); // remove dummy page used in .ui
QWidget * currentItem = 0;
const ParametersMap & parameters = Settings::getParameters();
for(ParametersMap::const_iterator iter=parameters.constBegin();
iter!=parameters.constEnd();
++iter)
{
QStringList splitted = iter.key().split('/');
QString group = splitted.first();
QString name = splitted.last();
if(currentItem == 0 || currentItem->objectName().compare(group) != 0)
{
currentItem = new QWidget(this);
this->addItem(currentItem, group);
currentItem->setObjectName(group);
QVBoxLayout * layout = new QVBoxLayout(currentItem);
currentItem->setLayout(layout);
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(0);
layout->addSpacerItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding));
addParameter(layout, iter.key(), iter.value());
}
else
{
addParameter((QVBoxLayout*)currentItem->layout(), iter.key(), iter.value());
}
}
updateParametersVisibility();
}
void ParametersToolBox::updateParameter(const QString & key)
{
QWidget * widget = this->findChild<QWidget*>(key);
QString type = Settings::getParametersType().value(key);
if(type.compare("QString") == 0)
{
QString value = Settings::getParameter(key).toString();
if(value.contains(';'))
{
// It's a list, just change the index
QStringList splitted = value.split(':');
((QComboBox*)widget)->setCurrentIndex(splitted.first().toInt());
}
else
{
((QLineEdit*)widget)->setText(value);
}
}
else if(type.compare("int") == 0)
{
((QSpinBox*)widget)->setValue(Settings::getParameter(key).toInt());
}
else if(type.compare("uint") == 0)
{
((QSpinBox*)widget)->setValue(Settings::getParameter(key).toInt());
}
else if(type.compare("double") == 0)
{
((QDoubleSpinBox*)widget)->setValue(Settings::getParameter(key).toDouble());
}
else if(type.compare("float") == 0)
{
((QDoubleSpinBox*)widget)->setValue(Settings::getParameter(key).toDouble());
}
else if(type.compare("bool") == 0)
{
((QCheckBox*)widget)->setChecked(Settings::getParameter(key).toBool());
}
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const QVariant & value)
{
QString type = Settings::getParametersType().value(key);
if(type.compare("QString") == 0)
{
addParameter(layout, key, value.toString());
}
else if(type.compare("int") == 0)
{
addParameter(layout, key, value.toInt());
}
else if(type.compare("uint") == 0)
{
addParameter(layout, key, value.toInt());
}
else if(type.compare("double") == 0)
{
addParameter(layout, key, value.toDouble());
}
else if(type.compare("float") == 0)
{
addParameter(layout, key, value.toDouble());
}
else if(type.compare("bool") == 0)
{
addParameter(layout, key, value.toBool());
}
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const QString & value)
{
if(value.contains(';'))
{
QComboBox * widget = new QComboBox(this);
widget->setObjectName(key);
QStringList splitted = value.split(':');
widget->addItems(splitted.last().split(';'));
if(key.compare(Settings::kFeature2D_1Detector()) == 0)
{
#if FINDOBJECT_NONFREE == 0
#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(OPENCV_DEV))))
widget->setItemData(5, 0, Qt::UserRole - 1); // disable SIFT
#endif
widget->setItemData(7, 0, Qt::UserRole - 1); // disable SURF
#endif
#if CV_MAJOR_VERSION < 3
widget->setItemData(9, 0, Qt::UserRole - 1); // disable AGAST
widget->setItemData(10, 0, Qt::UserRole - 1); // disable KAZE
widget->setItemData(11, 0, Qt::UserRole - 1); // disable AKAZE
#else
widget->setItemData(0, 0, Qt::UserRole - 1); // disable Dense
#ifndef HAVE_OPENCV_XFEATURES2D
widget->setItemData(6, 0, Qt::UserRole - 1); // disable Star
#endif
#endif
#if FINDOBJECT_TORCH == 0
widget->setItemData(12, 0, Qt::UserRole - 1); // disable SuperPointTorch
#endif
}
if(key.compare(Settings::kFeature2D_2Descriptor()) == 0)
{
#if FINDOBJECT_NONFREE == 0
#if CV_MAJOR_VERSION < 4 || (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION < 3 || (CV_MINOR_VERSION==3 && !defined(OPENCV_DEV))))
widget->setItemData(2, 0, Qt::UserRole - 1); // disable SIFT
#endif
widget->setItemData(3, 0, Qt::UserRole - 1); // disable SURF
#endif
#if CV_MAJOR_VERSION < 3
widget->setItemData(6, 0, Qt::UserRole - 1); // disable KAZE
widget->setItemData(7, 0, Qt::UserRole - 1); // disable AKAZE
widget->setItemData(8, 0, Qt::UserRole - 1); // disable LUCID
widget->setItemData(9, 0, Qt::UserRole - 1); // disable LATCH
widget->setItemData(10, 0, Qt::UserRole - 1); // disable DAISY
#else
#ifndef HAVE_OPENCV_XFEATURES2D
widget->setItemData(0, 0, Qt::UserRole - 1); // disable Brief
widget->setItemData(5, 0, Qt::UserRole - 1); // disable Freak
widget->setItemData(8, 0, Qt::UserRole - 1); // disable LUCID
widget->setItemData(9, 0, Qt::UserRole - 1); // disable LATCH
widget->setItemData(10, 0, Qt::UserRole - 1); // disable DAISY
#endif
#endif
#if FINDOBJECT_TORCH == 0
widget->setItemData(11, 0, Qt::UserRole - 1); // disable SuperPointTorch
#endif
}
if(key.compare(Settings::kNearestNeighbor_1Strategy()) == 0)
{
#if FINDOBJECT_NONFREE == 0 && CV_MAJOR_VERSION < 3
// disable FLANN approaches (cannot be used with binary descriptors)
widget->setItemData(0, 0, Qt::UserRole - 1);
widget->setItemData(1, 0, Qt::UserRole - 1);
widget->setItemData(2, 0, Qt::UserRole - 1);
widget->setItemData(3, 0, Qt::UserRole - 1);
widget->setItemData(4, 0, Qt::UserRole - 1);
#endif
}
if(key.compare(Settings::kHomography_method()) == 0)
{
#if CV_MAJOR_VERSION < 3
// disable RHO approach
widget->setItemData(2, 0, Qt::UserRole - 1);
#endif
}
widget->setCurrentIndex(splitted.first().toInt());
connect(widget, SIGNAL(currentIndexChanged(int)), this, SLOT(changeParameter(int)));
addParameter(layout, key, widget);
}
else
{
QLineEdit * widget = new QLineEdit(value, this);
widget->setObjectName(key);
connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
addParameter(layout, key, widget);
}
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const double & value)
{
QDoubleSpinBox * widget = new QDoubleSpinBox(this);
int decimals = 0;
int decimalValue = 0;
QString str = QString::number(Settings::getDefaultParameters().value(key).toDouble());
str.remove( QRegExp("0+$") );
if(!str.isEmpty())
{
str.replace(',', '.');
QStringList items = str.split('.');
if(items.size() == 2)
{
decimals = items.back().length();
decimalValue = items.back().toInt();
}
}
double def = Settings::getDefaultParameters().value(key).toDouble();
if(def<0.001 || (decimals >= 4 && decimalValue>0))
{
widget->setDecimals(5);
widget->setSingleStep(0.0001);
}
else if(def<0.01 || (decimals >= 3 && decimalValue>0))
{
widget->setDecimals(4);
widget->setSingleStep(0.001);
}
else if(def<0.1 || (decimals >= 2 && decimalValue>0))
{
widget->setDecimals(3);
widget->setSingleStep(0.01);
}
else if(def<1.0 || (decimals >= 1 && decimalValue>0))
{
widget->setDecimals(2);
widget->setSingleStep(0.1);
}
else
{
widget->setDecimals(1);
}
if(def>0.0)
{
widget->setMaximum(def*1000000.0);
}
else if(def==0.0)
{
widget->setMaximum(1000000.0);
}
else if(def<0.0)
{
widget->setMinimum(def*1000000.0);
widget->setMaximum(0.0);
}
widget->setValue(value);
widget->setObjectName(key);
connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
addParameter(layout, key, widget);
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const int & value)
{
QSpinBox * widget = new QSpinBox(this);
int def = Settings::getDefaultParameters().value(key).toInt();
if(def>0)
{
widget->setMaximum(def*1000000);
}
else if(def == 0)
{
widget->setMaximum(1000000);
}
else if(def<0)
{
widget->setMinimum(def*1000000);
widget->setMaximum(0);
}
widget->setValue(value);
widget->setObjectName(key);
connect(widget, SIGNAL(editingFinished()), this, SLOT(changeParameter()));
addParameter(layout, key, widget);
}
void ParametersToolBox::addParameter(QVBoxLayout * layout,
const QString & key,
const bool & value)
{
QCheckBox * widget = new QCheckBox(this);
widget->setChecked(value);
widget->setObjectName(key);
connect(widget, SIGNAL(toggled(bool)), this, SLOT(changeParameter(bool)));
addParameter(layout, key, widget);
}
void ParametersToolBox::addParameter(QVBoxLayout * layout, const QString & key, QWidget * widget)
{
QHBoxLayout * hLayout = new QHBoxLayout();
layout->insertLayout(layout->count()-1, hLayout);
QString tmp = key.split('/').last();
if(tmp.at(0).isDigit())
{
tmp.remove(0,1);
}
QLabel * label = new QLabel(tmp, this);
label->setObjectName(key+"/label");
label->setToolTip(QString("<FONT>%1</FONT>").arg(Settings::getDescriptions().value(key, "")));
label->setTextInteractionFlags(Qt::TextSelectableByMouse);
hLayout->addWidget(label);
hLayout->addWidget(widget);
}
void ParametersToolBox::changeParameter(const QString & value)
{
if(sender())
{
Settings::setParameter(sender()->objectName(), value);
QStringList paramChanged;
paramChanged.append(sender()->objectName());
Q_EMIT parametersChanged(paramChanged);
}
}
void ParametersToolBox::changeParameter()
{
if(sender())
{
QDoubleSpinBox * doubleSpinBox = qobject_cast<QDoubleSpinBox*>(sender());
QSpinBox * spinBox = qobject_cast<QSpinBox*>(sender());
QLineEdit * lineEdit = qobject_cast<QLineEdit*>(sender());
if(doubleSpinBox)
{
Settings::setParameter(sender()->objectName(), doubleSpinBox->value());
}
else if(spinBox)
{
if(spinBox->objectName().compare(Settings::kHomography_minimumInliers()) == 0 &&
spinBox->value() < 4)
{
Settings::setHomography_minimumInliers(4);
spinBox->blockSignals(true);
this->updateParameter(Settings::kHomography_minimumInliers());
spinBox->blockSignals(false);
}
else
{
Settings::setParameter(sender()->objectName(), spinBox->value());
}
}
else if(lineEdit)
{
Settings::setParameter(sender()->objectName(), lineEdit->text());
}
QStringList paramChanged;
paramChanged.append(sender()->objectName());
Q_EMIT parametersChanged(paramChanged);
}
}
void ParametersToolBox::changeParameter(bool value)
{
if(sender())
{
// Workaround as stateChanged(int) is not always emitted, using toggled(bool) instead
changeParameter(sender(), value?Qt::Checked:Qt::Unchecked);
}
}
void ParametersToolBox::changeParameter(int value)
{
if(sender())
{
changeParameter(sender(), value);
}
}
void ParametersToolBox::changeParameter(QObject * sender, int value)
{
if(sender)
{
QStringList paramChanged;
QComboBox * comboBox = qobject_cast<QComboBox*>(sender);
QCheckBox * checkBox = qobject_cast<QCheckBox*>(sender);
bool descriptorChanged = false;
if(comboBox && comboBox->objectName().compare(Settings::kFeature2D_1Detector()) == 0)
{
QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor());
if(comboBox->objectName().compare(Settings::kFeature2D_1Detector()) == 0 &&
comboBox->currentText() != descriptorBox->currentText() &&
Settings::getFeature2D_2Descriptor().contains(comboBox->currentText()))
{
QMessageBox::StandardButton b = QMessageBox::question(this,
tr("Use corresponding descriptor type?"),
tr("Current selected detector type (\"%1\") has its own corresponding descriptor type.\n"
"Do you want to use its corresponding descriptor?")
.arg(comboBox->currentText()),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if(b == QMessageBox::Yes)
{
int index = descriptorBox->findText(comboBox->currentText());
if(index >= 0)
{
QStringList tmp = Settings::getFeature2D_2Descriptor().split(':');
UASSERT(tmp.size() == 2);
QString newTmp = QString::number(index)+":"+tmp.back();
Settings::setFeature2D_2Descriptor(newTmp);
descriptorBox->blockSignals(true);
this->updateParameter(Settings::kFeature2D_2Descriptor());
descriptorBox->blockSignals(false);
paramChanged.append(Settings::kFeature2D_2Descriptor());
descriptorChanged = true;
}
else
{
UERROR("Combo box detector type not found \"%s\"?!", comboBox->currentText().toStdString().c_str());
}
}
}
}
bool nnStrategyChanged = false;
//verify binary issue with nearest neighbor strategy
if((comboBox && (comboBox->objectName().compare(Settings::kFeature2D_2Descriptor()) == 0 ||
comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0)) ||
descriptorChanged ||
(checkBox && checkBox->objectName().compare(Settings::kNearestNeighbor_7ConvertBinToFloat()) == 0))
{
QComboBox * descriptorBox = (QComboBox*)this->getParameterWidget(Settings::kFeature2D_2Descriptor());
QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
QCheckBox * binToFloatCheckbox = (QCheckBox*)this->getParameterWidget(Settings::kNearestNeighbor_7ConvertBinToFloat());
bool isBinaryDescriptor = descriptorBox->currentText().compare("ORB") == 0 ||
descriptorBox->currentText().compare("Brief") == 0 ||
descriptorBox->currentText().compare("BRISK") == 0 ||
descriptorBox->currentText().compare("FREAK") == 0 ||
descriptorBox->currentText().compare("AKAZE") == 0 ||
descriptorBox->currentText().compare("LATCH") == 0 ||
descriptorBox->currentText().compare("LUCID") == 0;
bool binToFloat = binToFloatCheckbox->isChecked();
if(isBinaryDescriptor && !binToFloat && nnBox->currentText().compare("Lsh") != 0 && nnBox->currentText().compare("BruteForce") != 0)
{
QMessageBox::warning(this,
tr("Warning"),
tr("Current selected descriptor type (\"%1\") is binary while nearest neighbor strategy is not (\"%2\").\n"
"Falling back to \"BruteForce\" nearest neighbor strategy with Hamming distance (by default).")
.arg(descriptorBox->currentText())
.arg(nnBox->currentText()));
QString tmp = Settings::getNearestNeighbor_1Strategy();
*tmp.begin() = '6'; // set BruteForce
Settings::setNearestNeighbor_1Strategy(tmp);
tmp = Settings::getNearestNeighbor_2Distance_type();
*tmp.begin() = '8'; // set HAMMING
Settings::setNearestNeighbor_2Distance_type(tmp);
nnBox->blockSignals(true);
distBox->blockSignals(true);
this->updateParameter(Settings::kNearestNeighbor_1Strategy());
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
nnBox->blockSignals(false);
distBox->blockSignals(false);
if(sender == nnBox)
{
this->updateParametersVisibility();
return;
}
nnStrategyChanged = true;
paramChanged.append(Settings::kNearestNeighbor_1Strategy());
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
}
else if((!isBinaryDescriptor || binToFloat) && nnBox->currentText().compare("Lsh") == 0)
{
if(binToFloat)
{
QMessageBox::warning(this,
tr("Warning"),
tr("Current selected descriptor type (\"%1\") is binary, but binary to float descriptors conversion is activated while nearest neighbor strategy is (\"%2\").\n"
"Disabling binary to float descriptors conversion and use Hamming distance (by default).")
.arg(descriptorBox->currentText())
.arg(nnBox->currentText()));
binToFloatCheckbox->blockSignals(true);
if(checkBox && checkBox->objectName().compare(Settings::kNearestNeighbor_7ConvertBinToFloat()) == 0)
{
Settings::setParameter(checkBox->objectName(), false);
value = 0;
}
else
{
paramChanged.append(Settings::kNearestNeighbor_7ConvertBinToFloat());
}
this->updateParameter(Settings::kNearestNeighbor_7ConvertBinToFloat());
binToFloatCheckbox->blockSignals(false);
QString tmp = Settings::getNearestNeighbor_2Distance_type();
*tmp.begin() = '8'; // set HAMMING
Settings::setNearestNeighbor_2Distance_type(tmp);
distBox->blockSignals(true);
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
distBox->blockSignals(false);
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
}
else
{
QMessageBox::warning(this,
tr("Warning"),
tr("Current selected descriptor type (\"%1\") is not binary while nearest neighbor strategy is (\"%2\").\n"
"Falling back to \"KDTree\" nearest neighbor strategy with Euclidean_L2 distance (by default).")
.arg(descriptorBox->currentText())
.arg(nnBox->currentText()));
QString tmp = Settings::getNearestNeighbor_1Strategy();
*tmp.begin() = '1'; // set KDTree
Settings::setNearestNeighbor_1Strategy(tmp);
tmp = Settings::getNearestNeighbor_2Distance_type();
*tmp.begin() = '0'; // set EUCLIDEAN_L2
Settings::setNearestNeighbor_2Distance_type(tmp);
nnBox->blockSignals(true);
distBox->blockSignals(true);
this->updateParameter(Settings::kNearestNeighbor_1Strategy());
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
nnBox->blockSignals(false);
distBox->blockSignals(false);
if(sender == nnBox)
{
this->updateParametersVisibility();
return;
}
nnStrategyChanged = true;
paramChanged.append(Settings::kNearestNeighbor_1Strategy());
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
}
}
}
// Distance issue when using nearest neighbor strategy using CV_32F type, though Lsh support all type (doesn't crash at least)
if(nnStrategyChanged ||
(comboBox && (comboBox->objectName().compare(Settings::kNearestNeighbor_1Strategy()) == 0 ||
comboBox->objectName().compare(Settings::kNearestNeighbor_2Distance_type()) == 0)))
{
QComboBox * nnBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_1Strategy());
QComboBox * distBox = (QComboBox*)this->getParameterWidget(Settings::kNearestNeighbor_2Distance_type());
if(nnBox->currentText().compare("BruteForce") != 0 && nnBox->currentText().compare("Lsh") != 0 && distBox->currentIndex() > 1)
{
QMessageBox::warning(this,
tr("Warning"),
tr("Current selected nearest neighbor strategy type (\"%1\") cannot handle distance strategy (\"%2\").\n"
"Falling back to \"EUCLIDEAN_L2\" distance strategy (by default).")
.arg(nnBox->currentText())
.arg(distBox->currentText()));
QString tmp = Settings::getNearestNeighbor_2Distance_type();
*tmp.begin() = '0'; // set index
Settings::setNearestNeighbor_2Distance_type(tmp);
distBox->blockSignals(true);
this->updateParameter(Settings::kNearestNeighbor_2Distance_type());
distBox->blockSignals(false);
if(sender == distBox)
{
this->updateParametersVisibility();
return;
}
paramChanged.append(Settings::kNearestNeighbor_2Distance_type());
}
}
if(comboBox)
{
QStringList items;
for(int i=0; i<comboBox->count(); ++i)
{
items.append(comboBox->itemText(i));
}
QString merged = QString::number(value) + QString(":") + items.join(";");
Settings::setParameter(sender->objectName(), merged);
}
if(checkBox)
{
Settings::setParameter(sender->objectName(), value==Qt::Checked?true:false);
}
this->updateParametersVisibility();
paramChanged.append(sender->objectName());
Q_EMIT parametersChanged(paramChanged);
}
}
} // namespace find_object
-78
View File
@@ -1,78 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 PARAMETERSTOOLBOX_H_
#define PARAMETERSTOOLBOX_H_
#include <QToolBox>
class QVBoxLayout;
class QAbstractButton;
namespace find_object {
class ParametersToolBox: public QToolBox
{
Q_OBJECT
public:
ParametersToolBox(QWidget *parent = 0);
virtual ~ParametersToolBox();
void setupUi();
QWidget * getParameterWidget(const QString & key);
void updateParameter(const QString & key);
private:
void addParameter(QVBoxLayout * layout, const QString & key, const QVariant & value);
void addParameter(QVBoxLayout * layout, const QString & key, const QString & value);
void addParameter(QVBoxLayout * layout, const QString & key, const int & value);
void addParameter(QVBoxLayout * layout, const QString & key, const double & value);
void addParameter(QVBoxLayout * layout, const QString & key, const bool & value);
void addParameter(QVBoxLayout * layout, const QString & name, QWidget * widget);
void changeParameter(QObject * sender, int value);
Q_SIGNALS:
void parametersChanged(const QStringList & name);
private Q_SLOTS:
void changeParameter();
void changeParameter(const QString & value);
void changeParameter(bool value);
void changeParameter(int value);
void resetCurrentPage();
void resetAllPages();
private:
QStringList resetPage(int index);
void updateParametersVisibility();
};
} // namespace find_object
#endif /* PARAMETERSTOOLBOX_H_ */
-159
View File
@@ -1,159 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/QtOpenCV.h"
#include <opencv2/core/core_c.h>
#include <stdio.h>
namespace find_object {
QImage cvtCvMat2QImage(const cv::Mat & image, bool isBgr)
{
QImage qtemp;
if(!image.empty() && image.depth() == CV_8U)
{
if(image.channels()==3)
{
const unsigned char * data = image.data;
if(image.channels() == 3)
{
qtemp = QImage(image.cols, image.rows, QImage::Format_RGB32);
for(int y = 0; y < image.rows; ++y, data += image.cols*image.elemSize())
{
for(int x = 0; x < image.cols; ++x)
{
QRgb * p = ((QRgb*)qtemp.scanLine (y)) + x;
if(isBgr)
{
*p = qRgb(data[x * image.channels()+2], data[x * image.channels()+1], data[x * image.channels()]);
}
else
{
*p = qRgb(data[x * image.channels()], data[x * image.channels()+1], data[x * image.channels()+2]);
}
}
}
}
}
else if(image.channels() == 1)
{
// mono grayscale
qtemp = QImage(image.data, image.cols, image.rows, image.cols, QImage::Format_Indexed8).copy();
QVector<QRgb> my_table;
for(int i = 0; i < 256; i++) my_table.push_back(qRgb(i,i,i));
qtemp.setColorTable(my_table);
}
else
{
printf("Wrong image format, must have 1 or 3 channels\n");
}
}
return qtemp;
}
cv::Mat cvtQImage2CvMat(const QImage & image)
{
cv::Mat cvImage;
if(!image.isNull() && image.depth() == 32 && image.format() == QImage::Format_RGB32)
{
// assume RGB (3 channels)
int channels = 3;
cvImage = cv::Mat(image.height(), image.width(), CV_8UC3);
unsigned char * data = cvImage.data;
for(int y = 0; y < image.height(); ++y, data+=cvImage.cols*cvImage.elemSize())
{
for(int x = 0; x < image.width(); ++x)
{
QRgb rgb = image.pixel(x, y);
data[x * channels+2] = qRed(rgb); //r
data[x * channels+1] = qGreen(rgb); //g
data[x * channels] = qBlue(rgb); //b
}
}
}
else
{
printf("Failed to convert image : depth=%d(!=32) format=%d(!=%d)\n", image.depth(), image.format(), QImage::Format_RGB32);
}
return cvImage;
}
#if CV_MAJOR_VERSION < 3
QImage cvtIplImage2QImage(const IplImage * image)
{
QImage qtemp;
if (image && image->depth == IPL_DEPTH_8U && cvGetSize(image).width>0)
{
const char * data = image->imageData;
qtemp= QImage(image->width, image->height,QImage::Format_RGB32);
for(int y = 0; y < image->height; ++y, data +=image->widthStep )
{
for(int x = 0; x < image->width; ++x)
{
uint *p = (uint*)qtemp.scanLine (y) + x;
*p = qRgb(data[x * image->nChannels+2], data[x * image->nChannels+1],data[x * image->nChannels]);
}
}
}
else if(image && image->depth != IPL_DEPTH_8U)
{
printf("Wrong iplImage format, must be 8_bits\n");
}
return qtemp;
}
// Returned image must be released explicitly (using cvReleaseImage()).
IplImage * cvtQImage2IplImage(const QImage & image)
{
IplImage * iplTmp = 0;
if(!image.isNull() && image.depth() == 32 && image.format() == QImage::Format_RGB32)
{
// assume RGB (3 channels)
int channels = 3;
iplTmp = cvCreateImage(cvSize(image.width(), image.height()), IPL_DEPTH_8U, channels);
char * data = iplTmp->imageData;
for(int y = 0; y < image.height(); ++y, data+=iplTmp->widthStep)
{
for(int x = 0; x < image.width(); ++x)
{
QRgb rgb = image.pixel(x, y);
data[x * channels+2] = qRed(rgb); //r
data[x * channels+1] = qGreen(rgb); //g
data[x * channels] = qBlue(rgb); //b
}
}
}
else
{
printf("Failed to convert image : depth=%d(!=32) format=%d(!=%d)\n", image.depth(), image.format(), QImage::Format_RGB32);
}
return iplTmp;
}
#endif
} // namespace find_object
-155
View File
@@ -1,155 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "RectItem.h"
#include <QtGui/QPen>
#include <QtGui/QBrush>
#include <QGraphicsScene>
namespace find_object {
RectItem::RectItem(int id, const QRectF &rect, QGraphicsItem * parent) :
QGraphicsRectItem(rect, parent),
placeHolder_(0),
id_(id)
{
this->setAcceptHoverEvents(true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
}
RectItem::~RectItem()
{
}
void RectItem::setColor(const QColor & color)
{
this->setPen(QPen(color));
this->setBrush(QBrush(color));
if(placeHolder_)
{
QList<QGraphicsItem *> items = placeHolder_->childItems();
if(items.size())
{
((QGraphicsTextItem *)items.front())->setDefaultTextColor(this->pen().color().rgb());
}
}
}
void RectItem::showDescription()
{
if(!placeHolder_ || !placeHolder_->isVisible())
{
if(!placeHolder_)
{
placeHolder_ = new QGraphicsRectItem();
placeHolder_->setVisible(false);
this->scene()->addItem(placeHolder_);
placeHolder_->setBrush(QBrush(QColor ( 0, 0, 0, 170 ))); // Black transparent background
QGraphicsTextItem * text = new QGraphicsTextItem(placeHolder_);
text->setDefaultTextColor(this->pen().color().rgb());
QTransform t = this->transform();
QPolygonF rectH = this->mapToScene(this->rect());
float angle = 90.0f;
for(int a=0; a<rectH.size(); ++a)
{
// Find the smaller angle
QLineF ab(rectH.at(a).x(), rectH.at(a).y(), rectH.at((a+1)%4).x(), rectH.at((a+1)%4).y());
QLineF cb(rectH.at((a+1)%4).x(), rectH.at((a+1)%4).y(), rectH.at((a+2)%4).x(), rectH.at((a+2)%4).y());
float angleTmp = ab.angle(cb);
if(angleTmp > 90.0f)
{
angleTmp = 180.0f - angleTmp;
}
if(angleTmp < angle)
{
angle = angleTmp;
}
}
text->setPlainText(tr(
"Object=%1\n"
"Homography= [\n"
" %2 %3 %4\n"
" %5 %6 %7\n"
" %8 %9 %10]\n"
"Angle=%11").arg(id_)
.arg(t.m11()).arg(t.m12()).arg(t.m13())
.arg(t.m21()).arg(t.m22()).arg(t.m23())
.arg(t.m31()).arg(t.m32()).arg(t.m33())
.arg(angle));
placeHolder_->setRect(text->boundingRect());
}
QPen pen = this->pen();
this->setPen(QPen(pen.color(), pen.width()*2));
placeHolder_->setZValue(this->zValue()+1);
placeHolder_->setPos(0,0);
placeHolder_->setVisible(true);
Q_EMIT hovered(id_);
}
}
void RectItem::hideDescription()
{
if(placeHolder_ && placeHolder_->isVisible())
{
placeHolder_->setVisible(false);
this->setPen(QPen(pen().color(), pen().width()/2));
}
}
void RectItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
{
this->showDescription();
QGraphicsRectItem::hoverEnterEvent(event);
}
void RectItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event )
{
if(!this->hasFocus())
{
this->hideDescription();
}
QGraphicsRectItem::hoverEnterEvent(event);
}
void RectItem::focusInEvent ( QFocusEvent * event )
{
this->showDescription();
QGraphicsRectItem::focusInEvent(event);
}
void RectItem::focusOutEvent ( QFocusEvent * event )
{
this->hideDescription();
QGraphicsRectItem::focusOutEvent(event);
}
} // namespace find_object
-69
View File
@@ -1,69 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 RECTITEM_H_
#define RECTITEM_H_
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <QtGui/QPen>
#include <QtGui/QBrush>
namespace find_object {
class RectItem : public QObject, public QGraphicsRectItem
{
Q_OBJECT;
public:
RectItem(int id, const QRectF &rect, QGraphicsItem * parent = 0);
virtual ~RectItem();
void setColor(const QColor & color);
int id() const {return id_;}
Q_SIGNALS:
void hovered(int);
protected:
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
virtual void focusInEvent ( QFocusEvent * event );
virtual void focusOutEvent ( QFocusEvent * event );
private:
void showDescription();
void hideDescription();
private:
QGraphicsRectItem * placeHolder_;
int id_;
};
} // namespace find_object
#endif /* RECTITEM_H_ */
File diff suppressed because it is too large Load Diff
-209
View File
@@ -1,209 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/TcpServer.h"
#include "find_object/utilite/ULogger.h"
#include <QtNetwork/QNetworkInterface>
#include <QtNetwork/QTcpSocket>
#include <QtGui/QTransform>
#include <opencv2/highgui/highgui.hpp>
namespace find_object {
TcpServer::TcpServer(quint16 port, QObject * parent) :
QTcpServer(parent)
{
if (!this->listen(QHostAddress::Any, port))
{
UERROR("Unable to start the TCP server: %s", this->errorString().toStdString().c_str());
return;
}
connect(this, SIGNAL(newConnection()), this, SLOT(addClient()));
}
QHostAddress TcpServer::getHostAddress() const
{
QHostAddress hostAddress;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
// use the first non-localhost IPv4 address
for (int i = 0; i < ipAddressesList.size(); ++i)
{
if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address())
{
hostAddress = ipAddressesList.at(i).toString();
break;
}
}
// if we did not find one, use IPv4 localhost
if (hostAddress.isNull())
{
hostAddress = QHostAddress(QHostAddress::LocalHost);
}
return hostAddress;
}
quint16 TcpServer::getPort() const
{
return this->serverPort();
}
void TcpServer::publishDetectionInfo(const DetectionInfo & info)
{
QList<QTcpSocket*> clients = this->findChildren<QTcpSocket*>();
if(clients.size())
{
UINFO("TCP server: Publish detected objects");
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << info;
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
for(QList<QTcpSocket*>::iterator iter = clients.begin(); iter!=clients.end(); ++iter)
{
(*iter)->write(block);
}
}
}
void TcpServer::addClient()
{
while(this->hasPendingConnections())
{
QTcpSocket * client = this->nextPendingConnection();
connect(client, SIGNAL(readyRead()), this, SLOT(readReceivedData()));
connect(client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(client, SIGNAL(disconnected()), this, SLOT(connectionLost()));
}
}
void TcpServer::readReceivedData()
{
QTcpSocket * client = (QTcpSocket*)sender();
QDataStream in(client);
in.setVersion(QDataStream::Qt_4_0);
if (blockSizes_.value(client->socketDescriptor(), 0) == 0)
{
if (client->bytesAvailable() < (int)sizeof(quint64))
{
return;
}
in >> blockSizes_[client->socketDescriptor()];
}
if (client->bytesAvailable() < (int)blockSizes_[client->socketDescriptor()])
{
return;
}
quint32 serviceType;
in >> serviceType;
bool ok = true;
if(serviceType == kAddObject)
{
int id;
in >> id;
QString fileName;
in >> fileName;
quint64 imageSize;
in >> imageSize;
std::vector<unsigned char> buf(imageSize);
in.readRawData((char*)buf.data(), imageSize);
cv::Mat image = cv::imdecode(buf, cv::IMREAD_UNCHANGED);
UINFO("TCP service: Add %d \"%s\"", id, fileName.toStdString().c_str());
Q_EMIT addObject(image, id, fileName);
}
else if(serviceType == kRemoveObject)
{
int id;
in >> id;
UINFO("TCP service: Remove %d", id);
Q_EMIT removeObject(id);
}
else if(serviceType == kDetectObject)
{
std::vector<unsigned char> buf(blockSizes_[client->socketDescriptor()]);
in.readRawData((char*)buf.data(), blockSizes_[client->socketDescriptor()]-sizeof(quint32));
cv::Mat image = cv::imdecode(buf, cv::IMREAD_UNCHANGED);
UINFO("TCP service: Detect object");
Q_EMIT detectObject(image);
}
else
{
UERROR("Unknown service type called %d", serviceType);
ok = false;
}
blockSizes_.remove(client->socketDescriptor());
client->write(QByteArray(ok?"1":"0")); // send acknowledge
}
void TcpServer::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError)
{
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
UWARN("CameraTcp: Tcp error: The host was not found. Please "
"check the host name and port settings.\n");
break;
case QAbstractSocket::ConnectionRefusedError:
UWARN("CameraTcp: The connection was refused by the peer. "
"Make sure your images server is running, "
"and check that the host name and port "
"settings are correct.");
break;
default:
//UERROR("The following error occurred: %s.", this->errorString().toStdString().c_str());
break;
}
}
void TcpServer::connectionLost()
{
//printf("[WARNING] CameraTcp: Connection lost!\n");
blockSizes_.remove(((QTcpSocket*)sender())->socketDescriptor());
((QTcpSocket*)sender())->close();
sender()->deleteLater();
}
} // namespace find_object
-534
View File
@@ -1,534 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/Settings.h"
#include "find_object/utilite/ULogger.h"
#include "Compression.h"
#include "Vocabulary.h"
#include <QtCore/QVector>
#include <QDataStream>
#include <QTime>
#include <stdio.h>
#if CV_MAJOR_VERSION < 3
#include <opencv2/gpu/gpu.hpp>
#define CVCUDA cv::gpu
#else
#include <opencv2/core/cuda.hpp>
#define CVCUDA cv::cuda
#ifdef HAVE_OPENCV_CUDAFEATURES2D
#include <opencv2/cudafeatures2d.hpp>
#endif
#endif
namespace find_object {
Vocabulary::Vocabulary()
{
}
Vocabulary::~Vocabulary()
{
}
void Vocabulary::clear()
{
wordToObjects_.clear();
notIndexedDescriptors_ = cv::Mat();
notIndexedWordIds_.clear();
if(Settings::getGeneral_vocabularyFixed() && Settings::getGeneral_invertedSearch())
{
this->update(); // if vocabulary structure has changed
// If the dictionary is fixed, don't clear indexed descriptors
return;
}
indexedDescriptors_ = cv::Mat();
}
void Vocabulary::save(QDataStream & streamSessionPtr, bool saveVocabularyOnly) const
{
// save index
if(saveVocabularyOnly)
{
QMultiMap<int, int> dummy;
streamSessionPtr << dummy;
}
else
{
UINFO("Saving %d object references...", wordToObjects_.size());
streamSessionPtr << wordToObjects_;
}
// save words
qint64 rawDataSize = indexedDescriptors_.rows * indexedDescriptors_.cols * indexedDescriptors_.elemSize();
UINFO("Compressing words... (%dx%d, %d MB)", indexedDescriptors_.rows, indexedDescriptors_.cols, rawDataSize/(1024*1024));
std::vector<unsigned char> bytes = compressData(indexedDescriptors_);
qint64 dataSize = bytes.size();
UINFO("Compressed = %d MB", dataSize/(1024*1024));
int old = 0;
if(dataSize <= std::numeric_limits<int>::max())
{
// old: rows, cols, type
streamSessionPtr << old << old << old << dataSize;
streamSessionPtr << QByteArray::fromRawData((const char*)bytes.data(), dataSize);
}
else
{
UERROR("Vocabulary (compressed) is too large (%d MB) to be saved! Limit is 2 GB (based on max QByteArray size).",
dataSize/(1024*1024));
// old: rows, cols, type, dataSize
streamSessionPtr << old << old << old << old;
streamSessionPtr << QByteArray(); // empty
}
}
void Vocabulary::load(QDataStream & streamSessionPtr, bool loadVocabularyOnly)
{
// load index
if(loadVocabularyOnly)
{
QMultiMap<int, int> dummy;
streamSessionPtr >> dummy;
// clear index
wordToObjects_.clear();
}
else
{
UINFO("Loading words to objects references...");
streamSessionPtr >> wordToObjects_;
UINFO("Loaded %d object references...", wordToObjects_.size());
}
// load words
int rows,cols,type;
qint64 dataSize;
streamSessionPtr >> rows >> cols >> type >> dataSize;
if(rows == 0 && cols == 0 && type == 0)
{
// compressed vocabulary
UINFO("Loading words... (compressed format: %d MB)", dataSize/(1024*1024));
UASSERT(dataSize <= std::numeric_limits<int>::max());
QByteArray data;
streamSessionPtr >> data;
UINFO("Uncompress vocabulary...");
indexedDescriptors_ = uncompressData((unsigned const char*)data.data(), dataSize);
UINFO("Words: %dx%d (%d MB)", indexedDescriptors_.rows, indexedDescriptors_.cols,
(indexedDescriptors_.rows * indexedDescriptors_.cols * indexedDescriptors_.elemSize()) / (1024*1024));
}
else
{
// old raw format
UINFO("Loading words... (old format: %dx%d (%d MB))", rows, cols, dataSize/(1024*1024));
QByteArray data;
streamSessionPtr >> data;
UINFO("Allocate memory...");
if(data.size())
{
indexedDescriptors_ = cv::Mat(rows, cols, type, data.data()).clone();
}
else if(dataSize)
{
UERROR("Error reading vocabulary data...");
}
}
UINFO("Update vocabulary index...");
update();
}
bool Vocabulary::save(const QString & filename) const
{
// save descriptors
cv::FileStorage fs(filename.toStdString(), cv::FileStorage::WRITE);
if(fs.isOpened())
{
fs << "Descriptors" << indexedDescriptors_;
return true;
}
else
{
UERROR("Failed to open vocabulary file \"%s\"", filename.toStdString().c_str());
}
return false;
}
bool Vocabulary::load(const QString & filename)
{
// save descriptors
cv::FileStorage fs(filename.toStdString(), cv::FileStorage::READ);
if(fs.isOpened())
{
cv::Mat tmp;
fs["Descriptors"] >> tmp;
if(!tmp.empty())
{
// clear index
wordToObjects_.clear();
indexedDescriptors_ = tmp;
update();
return true;
}
else
{
UERROR("Failed to read \"Descriptors\" matrix field (doesn't exist or is empty) from vocabulary file \"%s\"", filename.toStdString().c_str());
}
}
else
{
UERROR("Failed to open vocabulary file \"%s\"", filename.toStdString().c_str());
}
return false;
}
QMultiMap<int, int> Vocabulary::addWords(const cv::Mat & descriptorsIn, int objectId)
{
QMultiMap<int, int> words;
if (descriptorsIn.empty())
{
return words;
}
cv::Mat descriptors;
if(descriptorsIn.type() == CV_8U && Settings::getNearestNeighbor_7ConvertBinToFloat())
{
descriptorsIn.convertTo(descriptors, CV_32F);
}
else
{
descriptors = descriptorsIn;
}
if(Settings::getGeneral_vocabularyIncremental() || Settings::getGeneral_vocabularyFixed())
{
int k = 2;
cv::Mat results;
cv::Mat dists;
bool globalSearch = false;
if(!indexedDescriptors_.empty() && indexedDescriptors_.rows >= (int)k)
{
if(indexedDescriptors_.type() != descriptors.type() || indexedDescriptors_.cols != descriptors.cols)
{
if(Settings::getGeneral_vocabularyFixed())
{
UERROR("Descriptors (type=%d size=%d) to search in vocabulary are not the same type/size as those in the vocabulary (type=%d size=%d)! Empty words returned.",
descriptors.type(), descriptors.cols, indexedDescriptors_.type(), indexedDescriptors_.cols);
return words;
}
else
{
UFATAL("Descriptors (type=%d size=%d) to search in vocabulary are not the same type/size as those in the vocabulary (type=%d size=%d)!",
descriptors.type(), descriptors.cols, indexedDescriptors_.type(), indexedDescriptors_.cols);
}
}
this->search(descriptors, results, dists, k);
if( dists.type() == CV_32S )
{
cv::Mat temp;
dists.convertTo(temp, CV_32F);
dists = temp;
}
globalSearch = true;
}
if(!Settings::getGeneral_vocabularyFixed())
{
notIndexedWordIds_.reserve(notIndexedWordIds_.size() + descriptors.rows);
notIndexedDescriptors_.reserve(notIndexedDescriptors_.rows + descriptors.rows);
}
int matches = 0;
for(int i = 0; i < descriptors.rows; ++i)
{
QMultiMap<float, int> fullResults; // nearest descriptors sorted by distance
if(notIndexedDescriptors_.rows)
{
UASSERT(notIndexedDescriptors_.type() == descriptors.type() && notIndexedDescriptors_.cols == descriptors.cols);
// Check if this descriptor matches with a word not already added to the vocabulary
// Do linear search only
cv::Mat tmpResults;
cv::Mat tmpDists;
if(descriptors.type()==CV_8U)
{
//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).
int normType = cv::NORM_HAMMING;
if(Settings::currentDescriptorType().compare("ORB") &&
(Settings::getFeature2D_ORB_WTA_K()==3 || Settings::getFeature2D_ORB_WTA_K()==4))
{
normType = cv::NORM_HAMMING2;
}
cv::batchDistance( descriptors.row(i),
notIndexedDescriptors_,
tmpDists,
CV_32S,
tmpResults,
normType,
notIndexedDescriptors_.rows>=k?k:1,
cv::Mat(),
0,
false);
}
else
{
cv::flann::Index tmpIndex;
#if CV_MAJOR_VERSION == 2 and CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >= 12
tmpIndex.build(notIndexedDescriptors_, cv::Mat(), cv::flann::LinearIndexParams(), cvflann::FLANN_DIST_L2);
#else
tmpIndex.build(notIndexedDescriptors_, cv::flann::LinearIndexParams(), cvflann::FLANN_DIST_L2);
#endif
tmpIndex.knnSearch(descriptors.row(i), tmpResults, tmpDists, notIndexedDescriptors_.rows>1?k:1, cvflann::FLANN_DIST_L2);
}
if( tmpDists.type() == CV_32S )
{
cv::Mat temp;
tmpDists.convertTo(temp, CV_32F);
tmpDists = temp;
}
for(int j = 0; j < tmpResults.cols; ++j)
{
if(tmpResults.at<int>(0,j) >= 0)
{
//printf("local i=%d, j=%d, tmpDist=%f tmpResult=%d\n", i ,j, tmpDists.at<float>(0,j), tmpResults.at<int>(0,j));
fullResults.insert(tmpDists.at<float>(0,j), notIndexedWordIds_.at(tmpResults.at<int>(0,j)));
}
}
}
if(globalSearch)
{
for(int j=0; j<k; ++j)
{
if(results.at<int>(i,j) >= 0)
{
//printf("global i=%d, j=%d, dist=%f\n", i ,j, dists.at<float>(i,j));
fullResults.insert(dists.at<float>(i,j), results.at<int>(i,j));
}
}
}
bool matched = false;
if(Settings::getNearestNeighbor_3nndrRatioUsed() &&
fullResults.size() >= 2 &&
fullResults.begin().key() <= Settings::getNearestNeighbor_4nndrRatio() * (++fullResults.begin()).key())
{
matched = true;
}
if((matched || !Settings::getNearestNeighbor_3nndrRatioUsed()) &&
Settings::getNearestNeighbor_5minDistanceUsed())
{
if(fullResults.begin().key() <= Settings::getNearestNeighbor_6minDistance())
{
matched = true;
}
else
{
matched = false;
}
}
if(!matched && !Settings::getNearestNeighbor_3nndrRatioUsed() && !Settings::getNearestNeighbor_5minDistanceUsed())
{
matched = true; // no criterion, match to the nearest descriptor
}
if(matched)
{
words.insert(fullResults.begin().value(), i);
wordToObjects_.insert(fullResults.begin().value(), objectId);
++matches;
}
else if(!Settings::getGeneral_invertedSearch() || !Settings::getGeneral_vocabularyFixed())
{
//concatenate new words
notIndexedWordIds_.push_back(indexedDescriptors_.rows + notIndexedDescriptors_.rows);
notIndexedDescriptors_.push_back(descriptors.row(i));
words.insert(notIndexedWordIds_.back(), i);
wordToObjects_.insert(notIndexedWordIds_.back(), objectId);
}
else
{
words.insert(-1, i); // invalid word
}
}
}
else
{
for(int i = 0; i < descriptors.rows; ++i)
{
wordToObjects_.insert(indexedDescriptors_.rows + notIndexedDescriptors_.rows+i, objectId);
words.insert(indexedDescriptors_.rows + notIndexedDescriptors_.rows+i, i);
notIndexedWordIds_.push_back(indexedDescriptors_.rows + notIndexedDescriptors_.rows+i);
}
//just concatenate descriptors
notIndexedDescriptors_.push_back(descriptors);
}
return words;
}
void Vocabulary::update()
{
if(!notIndexedDescriptors_.empty())
{
if(!indexedDescriptors_.empty())
{
UASSERT(indexedDescriptors_.cols == notIndexedDescriptors_.cols &&
indexedDescriptors_.type() == notIndexedDescriptors_.type() );
}
//concatenate descriptors
indexedDescriptors_.push_back(notIndexedDescriptors_);
notIndexedDescriptors_ = cv::Mat();
notIndexedWordIds_.clear();
}
if(!indexedDescriptors_.empty() && !Settings::isBruteForceNearestNeighbor())
{
cv::flann::IndexParams * params = Settings::createFlannIndexParams();
#if CV_MAJOR_VERSION == 2 and CV_MINOR_VERSION == 4 and CV_SUBMINOR_VERSION >= 12
flannIndex_.build(indexedDescriptors_, cv::Mat(), *params, Settings::getFlannDistanceType());
#else
flannIndex_.build(indexedDescriptors_, *params, Settings::getFlannDistanceType());
#endif
delete params;
}
}
void Vocabulary::search(const cv::Mat & descriptorsIn, cv::Mat & results, cv::Mat & dists, int k)
{
if(!indexedDescriptors_.empty())
{
cv::Mat descriptors;
if(descriptorsIn.type() == CV_8U && Settings::getNearestNeighbor_7ConvertBinToFloat())
{
descriptorsIn.convertTo(descriptors, CV_32F);
}
else
{
descriptors = descriptorsIn;
}
UASSERT(descriptors.type() == indexedDescriptors_.type() && descriptors.cols == indexedDescriptors_.cols);
if(Settings::isBruteForceNearestNeighbor())
{
std::vector<std::vector<cv::DMatch> > matches;
bool isL2NotSqr = false;
if(Settings::getNearestNeighbor_BruteForce_gpu() && CVCUDA::getCudaEnabledDeviceCount())
{
CVCUDA::GpuMat newDescriptorsGpu(descriptors);
CVCUDA::GpuMat lastDescriptorsGpu(indexedDescriptors_);
#if CV_MAJOR_VERSION < 3
if(indexedDescriptors_.type()==CV_8U)
{
CVCUDA::BruteForceMatcher_GPU<cv::Hamming> gpuMatcher;
gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
}
else
{
CVCUDA::BruteForceMatcher_GPU<cv::L2<float> > gpuMatcher;
gpuMatcher.knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
isL2NotSqr = true;
}
#else
#ifdef HAVE_OPENCV_CUDAFEATURES2D
cv::Ptr<cv::cuda::DescriptorMatcher> gpuMatcher;
if(indexedDescriptors_.type()==CV_8U)
{
gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_HAMMING);
gpuMatcher->knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
}
else
{
gpuMatcher = cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_L2);
gpuMatcher->knnMatch(newDescriptorsGpu, lastDescriptorsGpu, matches, k);
isL2NotSqr = true;
}
#else
UERROR("OpenCV3 is not built with CUDAFEATURES2D module, cannot do brute force matching on GPU!");
#endif
#endif
}
else
{
cv::BFMatcher matcher(indexedDescriptors_.type()==CV_8U?cv::NORM_HAMMING:cv::NORM_L2SQR);
matcher.knnMatch(descriptors, indexedDescriptors_, matches, k);
}
//convert back to matrix style
results = cv::Mat((int)matches.size(), k, CV_32SC1);
dists = cv::Mat((int)matches.size(), k, CV_32FC1);
for(unsigned int i=0; i<matches.size(); ++i)
{
for(int j=0; j<k; ++j)
{
results.at<int>(i, j) = matches[i].at(j).trainIdx;
if(isL2NotSqr)
{
// Make sure we use L2SQR to match FLANN
dists.at<float>(i, j) = matches[i].at(j).distance*matches[i].at(j).distance;
}
else
{
dists.at<float>(i, j) = matches[i].at(j).distance;
}
}
}
}
else
{
flannIndex_.knnSearch(descriptors, results, dists, k,
cv::flann::SearchParams(
Settings::getNearestNeighbor_search_checks(),
Settings::getNearestNeighbor_search_eps(),
Settings::getNearestNeighbor_search_sorted()));
}
if( dists.type() == CV_32S )
{
cv::Mat temp;
dists.convertTo(temp, CV_32F);
dists = temp;
}
}
}
} // namespace find_object
-67
View File
@@ -1,67 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 VOCABULARY_H_
#define VOCABULARY_H_
#include <QtCore/QMultiMap>
#include <QtCore/QVector>
#include <opencv2/opencv.hpp>
namespace find_object {
class Vocabulary {
public:
Vocabulary();
virtual ~Vocabulary();
void clear();
QMultiMap<int, int> addWords(const cv::Mat & descriptors, int objectId);
void update();
void search(const cv::Mat & descriptors, cv::Mat & results, cv::Mat & dists, int k);
int size() const {return indexedDescriptors_.rows + notIndexedDescriptors_.rows;}
int dim() const {return !indexedDescriptors_.empty()?indexedDescriptors_.cols:notIndexedDescriptors_.cols;}
int type() const {return !indexedDescriptors_.empty()?indexedDescriptors_.type():notIndexedDescriptors_.type();}
const QMultiMap<int, int> & wordToObjects() const {return wordToObjects_;}
const cv::Mat & indexedDescriptors() const {return indexedDescriptors_;}
void save(QDataStream & streamSessionPtr, bool saveVocabularyOnly = false) const;
void load(QDataStream & streamSessionPtr, bool loadVocabularyOnly = false);
bool save(const QString & filename) const;
bool load(const QString & filename);
private:
cv::flann::Index flannIndex_;
cv::Mat indexedDescriptors_;
cv::Mat notIndexedDescriptors_;
QMultiMap<int, int> wordToObjects_; // <wordId, ObjectId>
QVector<int> notIndexedWordIds_;
};
} // namespace find_object
#endif /* VOCABULARY_H_ */
-249
View File
@@ -1,249 +0,0 @@
/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).
/// It is intented to be used with #include <json/json-forwards.h>
/// This header provides forward declaration for all JsonCpp types.
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: LICENSE
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
The author (Baptiste Lepilleur) explicitly disclaims copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
Copyright (c) 2007-2010 Baptiste Lepilleur
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
========================================================================
(END LICENSE TEXT)
The MIT license is compatible with both the GPL and commercial
software, affording one all of the rights of Public Domain with the
minor nuisance of being required to keep the above copyright notice
and license text in the source code. Note also that by accepting the
Public Domain "license" you can re-license your copy using whatever
license you like.
*/
// //////////////////////////////////////////////////////////////////////
// End of content of file: LICENSE
// //////////////////////////////////////////////////////////////////////
#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
# define JSON_FORWARD_AMALGATED_H_INCLUDED
/// If defined, indicates that the source file is amalgated
/// to prevent private header inclusion.
#define JSON_IS_AMALGATED
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/config.h
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_CONFIG_H_INCLUDED
# define JSON_CONFIG_H_INCLUDED
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
/// If defined, indicates that Json specific container should be used
/// (hash table & simple deque container with customizable allocator).
/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
//# define JSON_VALUE_USE_INTERNAL_MAP 1
/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
/// as if it was a POD) that may cause some validation tool to report errors.
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
/// If defined, indicates that Json use exception to report invalid type manipulation
/// instead of C assert macro.
# define JSON_USE_EXCEPTION 1
/// If defined, indicates that the source file is amalgated
/// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgated header.
#define JSON_IS_AMALGAMATION
# ifdef JSON_IN_CPPTL
# include <cpptl/config.h>
# ifndef JSON_USE_CPPTL
# define JSON_USE_CPPTL 1
# endif
# endif
# ifdef JSON_IN_CPPTL
# define JSON_API CPPTL_API
# elif defined(JSON_DLL_BUILD)
# define JSON_API __declspec(dllexport)
# elif defined(JSON_DLL)
# define JSON_API __declspec(dllimport)
# else
# define JSON_API
# endif
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer
// Storages, and 64 bits integer support is disabled.
// #define JSON_NO_INT64 1
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
// Microsoft Visual Studio 6 only support conversion from __int64 to double
// (no conversion from unsigned __int64).
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6
#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
/// Indicates that the following function is deprecated.
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
#endif
#if !defined(JSONCPP_DEPRECATED)
# define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED)
namespace Json {
typedef int Int;
typedef unsigned int UInt;
# if defined(JSON_NO_INT64)
typedef int LargestInt;
typedef unsigned int LargestUInt;
# undef JSON_HAS_INT64
# else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported
# if defined(_MSC_VER) // Microsoft Visual Studio
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
# else // if defined(_MSC_VER) // Other platforms, use long long
typedef long long int Int64;
typedef unsigned long long int UInt64;
# endif // if defined(_MSC_VER)
typedef Int64 LargestInt;
typedef UInt64 LargestUInt;
# define JSON_HAS_INT64
# endif // if defined(JSON_NO_INT64)
} // end namespace Json
#endif // JSON_CONFIG_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/config.h
// //////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/forwards.h
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_FORWARDS_H_INCLUDED
# define JSON_FORWARDS_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
# include "config.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
// writer.h
class FastWriter;
class StyledWriter;
// reader.h
class Reader;
// features.h
class Features;
// value.h
typedef unsigned int ArrayIndex;
class StaticString;
class Path;
class PathArgument;
class Value;
class ValueIteratorBase;
class ValueIterator;
class ValueConstIterator;
#ifdef JSON_VALUE_USE_INTERNAL_MAP
class ValueMapAllocator;
class ValueInternalLink;
class ValueInternalArray;
class ValueInternalMap;
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
} // namespace Json
#endif // JSON_FORWARDS_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/forwards.h
// //////////////////////////////////////////////////////////////////////
#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-8
View File
@@ -1,8 +0,0 @@
<RCC>
<qresource prefix="images">
<file>resources/Find-Object.png</file>
<file>resources/TheWorkingGroup_video_pause.ico</file>
<file>resources/TheWorkingGroup_video_play.ico</file>
<file>resources/TheWorkingGroup_video_stop.ico</file>
</qresource>
</RCC>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

-194
View File
@@ -1,194 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "find_object/Settings.h"
#include <opencv2/imgproc/imgproc.hpp>
#include "CameraROS.h"
#include <sensor_msgs/image_encodings.h>
using namespace find_object;
CameraROS::CameraROS(bool subscribeDepth, QObject * parent) :
Camera(parent),
subscribeDepth_(subscribeDepth),
approxSync_(0),
exactSync_(0)
{
ros::NodeHandle nh; // public
ros::NodeHandle pnh("~"); // private
qRegisterMetaType<ros::Time>("ros::Time");
qRegisterMetaType<cv::Mat>("cv::Mat");
if(!subscribeDepth_)
{
image_transport::ImageTransport it(nh);
imageSub_ = it.subscribe(nh.resolveName("image"), 1, &CameraROS::imgReceivedCallback, this);
}
else
{
int queueSize = 10;
bool approxSync = true;
pnh.param("queue_size", queueSize, queueSize);
pnh.param("approx_sync", approxSync, approxSync);
ROS_INFO("find_object_ros: queue_size = %d", queueSize);
ROS_INFO("find_object_ros: approx_sync = %s", approxSync?"true":"false");
ros::NodeHandle rgb_nh(nh, "rgb");
ros::NodeHandle rgb_pnh(pnh, "rgb");
ros::NodeHandle depth_nh(nh, "depth_registered");
ros::NodeHandle depth_pnh(pnh, "depth_registered");
image_transport::ImageTransport rgb_it(rgb_nh);
image_transport::ImageTransport depth_it(depth_nh);
image_transport::TransportHints hintsRgb("raw", ros::TransportHints(), rgb_pnh);
image_transport::TransportHints hintsDepth("raw", ros::TransportHints(), depth_pnh);
rgbSub_.subscribe(rgb_it, rgb_nh.resolveName("image_rect_color"), 1, hintsRgb);
depthSub_.subscribe(depth_it, depth_nh.resolveName("image_raw"), 1, hintsDepth);
cameraInfoSub_.subscribe(depth_nh, "camera_info", 1);
if(approxSync)
{
approxSync_ = new message_filters::Synchronizer<MyApproxSyncPolicy>(MyApproxSyncPolicy(queueSize), rgbSub_, depthSub_, cameraInfoSub_);
approxSync_->registerCallback(boost::bind(&CameraROS::imgDepthReceivedCallback, this,
boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3));
}
else
{
exactSync_ = new message_filters::Synchronizer<MyExactSyncPolicy>(MyExactSyncPolicy(queueSize), rgbSub_, depthSub_, cameraInfoSub_);
exactSync_->registerCallback(boost::bind(&CameraROS::imgDepthReceivedCallback, this,
boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3));
}
}
}
CameraROS::~CameraROS()
{
delete approxSync_;
delete exactSync_;
}
QStringList CameraROS::subscribedTopics() const
{
QStringList topics;
if(subscribeDepth_)
{
topics.append(rgbSub_.getTopic().c_str());
topics.append(depthSub_.getTopic().c_str());
topics.append(cameraInfoSub_.getTopic().c_str());
}
else
{
topics.append(imageSub_.getTopic().c_str());
}
return topics;
}
bool CameraROS::start()
{
this->startTimer();
return true;
}
void CameraROS::stop()
{
this->stopTimer();
}
void CameraROS::takeImage()
{
ros::spinOnce();
}
void CameraROS::imgReceivedCallback(const sensor_msgs::ImageConstPtr & msg)
{
if(msg->data.size())
{
cv::Mat image;
cv_bridge::CvImageConstPtr imgPtr = cv_bridge::toCvShare(msg);
try
{
if(msg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
msg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0)
{
image = cv_bridge::cvtColor(imgPtr, "mono8")->image;
}
else
{
image = cv_bridge::cvtColor(imgPtr, "bgr8")->image;
}
Q_EMIT imageReceived(image, Header(msg->header.frame_id.c_str(), msg->header.stamp.sec, msg->header.stamp.nsec), cv::Mat(), 0.0f);
}
catch(const cv_bridge::Exception & e)
{
ROS_ERROR("find_object_ros: Could not convert input image to mono8 or bgr8 format, encoding detected is %s... cv_bridge exception: %s", msg->encoding.c_str(), e.what());
}
}
}
void CameraROS::imgDepthReceivedCallback(
const sensor_msgs::ImageConstPtr& rgbMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg)
{
if(depthMsg->encoding.compare(sensor_msgs::image_encodings::TYPE_16UC1)!=0 &&
depthMsg->encoding.compare(sensor_msgs::image_encodings::TYPE_32FC1)!=0)
{
ROS_ERROR("find_object_ros: Depth image type must be 32FC1 or 16UC1");
return;
}
if(rgbMsg->data.size())
{
cv_bridge::CvImageConstPtr ptr = cv_bridge::toCvShare(rgbMsg);
cv_bridge::CvImageConstPtr ptrDepth = cv_bridge::toCvShare(depthMsg);
float depthConstant = 1.0f/cameraInfoMsg->K[4];
cv::Mat image;
cv_bridge::CvImageConstPtr imgPtr = cv_bridge::toCvShare(rgbMsg);
try
{
if(rgbMsg->encoding.compare(sensor_msgs::image_encodings::MONO8) == 0 ||
rgbMsg->encoding.compare(sensor_msgs::image_encodings::MONO16) == 0)
{
image = cv_bridge::cvtColor(imgPtr, "mono8")->image;
}
else
{
image = cv_bridge::cvtColor(imgPtr, "bgr8")->image;
}
Q_EMIT imageReceived(image, Header(rgbMsg->header.frame_id.c_str(), rgbMsg->header.stamp.sec, rgbMsg->header.stamp.nsec), ptrDepth->image, depthConstant);
}
catch(const cv_bridge::Exception & e)
{
ROS_ERROR("find_object_ros: Could not convert input image to mono8 or bgr8 format, encoding detected is %s... cv_bridge exception: %s", rgbMsg->encoding.c_str(), e.what());
}
}
}
-91
View File
@@ -1,91 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 CAMERAROS_H_
#define CAMERAROS_H_
#include <ros/ros.h>
#include <ros/spinner.h>
#include <cv_bridge/cv_bridge.h>
#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <message_filters/sync_policies/exact_time.h>
#include <image_transport/image_transport.h>
#include <image_transport/subscriber_filter.h>
#include <sensor_msgs/CameraInfo.h>
#include <sensor_msgs/Image.h>
#include "find_object/Camera.h"
#include <QtCore/QStringList>
class CameraROS : public find_object::Camera {
Q_OBJECT
public:
CameraROS(bool subscribeDepth, QObject * parent = 0);
virtual ~CameraROS();
virtual bool start();
virtual void stop();
QStringList subscribedTopics() const;
private Q_SLOTS:
virtual void takeImage();
private:
void imgReceivedCallback(const sensor_msgs::ImageConstPtr & msg);
void imgDepthReceivedCallback(
const sensor_msgs::ImageConstPtr& rgbMsg,
const sensor_msgs::ImageConstPtr& depthMsg,
const sensor_msgs::CameraInfoConstPtr& cameraInfoMsg);
private:
bool subscribeDepth_;
image_transport::Subscriber imageSub_;
image_transport::SubscriberFilter rgbSub_;
image_transport::SubscriberFilter depthSub_;
message_filters::Subscriber<sensor_msgs::CameraInfo> cameraInfoSub_;
typedef message_filters::sync_policies::ApproximateTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyApproxSyncPolicy;
message_filters::Synchronizer<MyApproxSyncPolicy> * approxSync_;
typedef message_filters::sync_policies::ExactTime<
sensor_msgs::Image,
sensor_msgs::Image,
sensor_msgs::CameraInfo> MyExactSyncPolicy;
message_filters::Synchronizer<MyExactSyncPolicy> * exactSync_;
};
#endif /* CAMERAROS_H_ */
-350
View File
@@ -1,350 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include "FindObjectROS.h"
#include <std_msgs/Float32MultiArray.h>
#include "find_object_2d/ObjectsStamped.h"
#include "find_object_2d/DetectionInfo.h"
#include <cmath>
using namespace find_object;
FindObjectROS::FindObjectROS(QObject * parent) :
FindObject(true, parent),
objFramePrefix_("object"),
usePnP_(true)
{
ros::NodeHandle pnh("~"); // public
pnh.param("object_prefix", objFramePrefix_, objFramePrefix_);
pnh.param("pnp", usePnP_, usePnP_);
ROS_INFO("object_prefix = %s", objFramePrefix_.c_str());
ROS_INFO("pnp = %s", usePnP_?"true":"false");
ros::NodeHandle nh; // public
pub_ = nh.advertise<std_msgs::Float32MultiArray>("objects", 1);
pubStamped_ = nh.advertise<find_object_2d::ObjectsStamped>("objectsStamped", 1);
pubInfo_ = nh.advertise<find_object_2d::DetectionInfo>("info", 1);
this->connect(this, SIGNAL(objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)), this, SLOT(publish(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)));
}
void FindObjectROS::publish(const find_object::DetectionInfo & info, const Header & header, const cv::Mat & depth, float depthConstant)
{
// send tf before the message
if(info.objDetected_.size() && !depth.empty() && depthConstant != 0.0f)
{
std::vector<tf::StampedTransform> transforms;
char multiSubId = 'b';
int previousId = -1;
QMultiMap<int, QSize>::const_iterator iterSizes=info.objDetectedSizes_.constBegin();
for(QMultiMap<int, QTransform>::const_iterator iter=info.objDetected_.constBegin();
iter!=info.objDetected_.constEnd();
++iter, ++iterSizes)
{
// get data
int id = iter.key();
float objectWidth = iterSizes->width();
float objectHeight = iterSizes->height();
QString multiSuffix;
if(id == previousId)
{
multiSuffix = QString("_") + multiSubId++;
}
else
{
multiSubId = 'b';
}
previousId = id;
// Find center of the object
QPointF center = iter->map(QPointF(objectWidth/2, objectHeight/2));
cv::Vec3f center3D = this->getDepth(depth,
center.x()+0.5f, center.y()+0.5f,
float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f,
1.0f/depthConstant, 1.0f/depthConstant);
cv::Vec3f axisEndX;
cv::Vec3f axisEndY;
if(!usePnP_)
{
QPointF xAxis = iter->map(QPointF(3*objectWidth/4, objectHeight/2));
axisEndX = this->getDepth(depth,
xAxis.x()+0.5f, xAxis.y()+0.5f,
float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f,
1.0f/depthConstant, 1.0f/depthConstant);
QPointF yAxis = iter->map(QPointF(objectWidth/2, 3*objectHeight/4));
axisEndY = this->getDepth(depth,
yAxis.x()+0.5f, yAxis.y()+0.5f,
float(depth.cols/2)-0.5f, float(depth.rows/2)-0.5f,
1.0f/depthConstant, 1.0f/depthConstant);
}
if((std::isfinite(center3D.val[2]) && usePnP_) ||
(std::isfinite(center3D.val[0]) && std::isfinite(center3D.val[1]) && std::isfinite(center3D.val[2]) &&
std::isfinite(axisEndX.val[0]) && std::isfinite(axisEndX.val[1]) && std::isfinite(axisEndX.val[2]) &&
std::isfinite(axisEndY.val[0]) && std::isfinite(axisEndY.val[1]) && std::isfinite(axisEndY.val[2])))
{
tf::StampedTransform transform;
transform.setIdentity();
transform.child_frame_id_ = QString("%1_%2%3").arg(objFramePrefix_.c_str()).arg(id).arg(multiSuffix).toStdString();
transform.frame_id_ = header.frameId_.toStdString();
transform.stamp_.sec = header.sec_;
transform.stamp_.nsec = header.nsec_;
tf::Quaternion q;
if(usePnP_)
{
std::vector<cv::Point3f> objectPoints(4);
std::vector<cv::Point2f> imagePoints(4);
objectPoints[0] = cv::Point3f(-0.5, -(objectHeight/objectWidth)/2.0f,0);
objectPoints[1] = cv::Point3f(0.5,-(objectHeight/objectWidth)/2.0f,0);
objectPoints[2] = cv::Point3f(0.5,(objectHeight/objectWidth)/2.0f,0);
objectPoints[3] = cv::Point3f(-0.5,(objectHeight/objectWidth)/2.0f,0);
QPointF pt = iter->map(QPointF(0, 0));
imagePoints[0] = cv::Point2f(pt.x(), pt.y());
pt = iter->map(QPointF(objectWidth, 0));
imagePoints[1] = cv::Point2f(pt.x(), pt.y());
pt = iter->map(QPointF(objectWidth, objectHeight));
imagePoints[2] = cv::Point2f(pt.x(), pt.y());
pt = iter->map(QPointF(0, objectHeight));
imagePoints[3] = cv::Point2f(pt.x(), pt.y());
cv::Mat cameraMatrix = cv::Mat::eye(3,3,CV_64FC1);
cameraMatrix.at<double>(0,0) = 1.0f/depthConstant;
cameraMatrix.at<double>(1,1) = 1.0f/depthConstant;
cameraMatrix.at<double>(0,2) = float(depth.cols/2)-0.5f;
cameraMatrix.at<double>(1,2) = float(depth.rows/2)-0.5f;
cv::Mat distCoeffs;
cv::Mat rvec(1,3, CV_64FC1);
cv::Mat tvec(1,3, CV_64FC1);
cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);
cv::Mat R;
cv::Rodrigues(rvec, R);
tf::Matrix3x3 rotationMatrix(
R.at<double>(0,0), R.at<double>(0,1), R.at<double>(0,2),
R.at<double>(1,0), R.at<double>(1,1), R.at<double>(1,2),
R.at<double>(2,0), R.at<double>(2,1), R.at<double>(2,2));
rotationMatrix.getRotation(q);
transform.setOrigin(tf::Vector3(
tvec.at<double>(0)*(center3D.val[2]/tvec.at<double>(2)),
tvec.at<double>(1)*(center3D.val[2]/tvec.at<double>(2)),
tvec.at<double>(2)*(center3D.val[2]/tvec.at<double>(2))));
}
else
{
tf::Vector3 xAxis(axisEndX.val[0] - center3D.val[0], axisEndX.val[1] - center3D.val[1], axisEndX.val[2] - center3D.val[2]);
xAxis.normalize();
tf::Vector3 yAxis(axisEndY.val[0] - center3D.val[0], axisEndY.val[1] - center3D.val[1], axisEndY.val[2] - center3D.val[2]);
yAxis.normalize();
tf::Vector3 zAxis = xAxis.cross(yAxis);
zAxis.normalize();
tf::Matrix3x3 rotationMatrix(
xAxis.x(), yAxis.x() ,zAxis.x(),
xAxis.y(), yAxis.y(), zAxis.y(),
xAxis.z(), yAxis.z(), zAxis.z());
rotationMatrix.getRotation(q);
transform.setOrigin(tf::Vector3(center3D.val[0], center3D.val[1], center3D.val[2]));
}
// set x axis going front of the object, with z up and z left
q *= tf::createQuaternionFromRPY(CV_PI/2.0, CV_PI/2.0, 0);
transform.setRotation(q.normalized());
transforms.push_back(transform);
}
else
{
ROS_WARN("Object %d detected, center 2D at (%f,%f), but invalid depth, cannot set frame \"%s\"! "
"(maybe object is too near of the camera or bad depth image)\n",
id,
center.x(), center.y(),
QString("%1_%2").arg(objFramePrefix_.c_str()).arg(id).toStdString().c_str());
}
}
if(transforms.size())
{
tfBroadcaster_.sendTransform(transforms);
}
}
if(pub_.getNumSubscribers() || pubStamped_.getNumSubscribers() || pubInfo_.getNumSubscribers())
{
std_msgs::Float32MultiArray msg;
find_object_2d::ObjectsStamped msgStamped;
find_object_2d::DetectionInfo infoMsg;
if(pubInfo_.getNumSubscribers())
{
infoMsg.ids.resize(info.objDetected_.size());
infoMsg.widths.resize(info.objDetected_.size());
infoMsg.heights.resize(info.objDetected_.size());
infoMsg.file_paths.resize(info.objDetected_.size());
infoMsg.inliers.resize(info.objDetected_.size());
infoMsg.outliers.resize(info.objDetected_.size());
infoMsg.homographies.resize(info.objDetected_.size());
}
msg.data = std::vector<float>(info.objDetected_.size()*12);
msgStamped.objects.data = std::vector<float>(info.objDetected_.size()*12);
ROS_ASSERT(info.objDetected_.size() == info.objDetectedSizes_.size() &&
info.objDetected_.size() == info.objDetectedFilePaths_.size() &&
info.objDetected_.size() == info.objDetectedInliersCount_.size() &&
info.objDetected_.size() == info.objDetectedOutliersCount_.size());
int infoIndex=0;
int i=0;
QMultiMap<int, QSize>::const_iterator iterSizes=info.objDetectedSizes_.constBegin();
QMultiMap<int, QString>::const_iterator iterFilePaths=info.objDetectedFilePaths_.constBegin();
QMultiMap<int, int>::const_iterator iterInliers=info.objDetectedInliersCount_.constBegin();
QMultiMap<int, int>::const_iterator iterOutliers=info.objDetectedOutliersCount_.constBegin();
for(QMultiMap<int, QTransform>::const_iterator iter=info.objDetected_.constBegin();
iter!=info.objDetected_.constEnd();
++iter, ++iterSizes, ++iterFilePaths, ++infoIndex, ++iterInliers, ++iterOutliers)
{
if(pub_.getNumSubscribers() || pubStamped_.getNumSubscribers())
{
msg.data[i] = msgStamped.objects.data[i] = iter.key(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iterSizes->width(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iterSizes->height(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iter->m11(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iter->m12(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iter->m13(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iter->m21(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iter->m22(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iter->m23(); ++i;
msg.data[i] = msgStamped.objects.data[i] = iter->m31(); ++i;// dx
msg.data[i] = msgStamped.objects.data[i] = iter->m32(); ++i;// dy
msg.data[i] = msgStamped.objects.data[i] = iter->m33(); ++i;
}
if(pubInfo_.getNumSubscribers())
{
infoMsg.ids[infoIndex].data = iter.key();
infoMsg.widths[infoIndex].data = iterSizes->width();
infoMsg.heights[infoIndex].data = iterSizes->height();
infoMsg.file_paths[infoIndex].data = iterFilePaths.value().toStdString();
infoMsg.inliers[infoIndex].data = iterInliers.value();
infoMsg.outliers[infoIndex].data = iterOutliers.value();
infoMsg.homographies[infoIndex].data.resize(9);
infoMsg.homographies[infoIndex].data[0] = iter->m11();
infoMsg.homographies[infoIndex].data[1] = iter->m12();
infoMsg.homographies[infoIndex].data[2] = iter->m13();
infoMsg.homographies[infoIndex].data[3] = iter->m21();
infoMsg.homographies[infoIndex].data[4] = iter->m22();
infoMsg.homographies[infoIndex].data[5] = iter->m23();
infoMsg.homographies[infoIndex].data[6] = iter->m31();
infoMsg.homographies[infoIndex].data[7] = iter->m32();
infoMsg.homographies[infoIndex].data[8] = iter->m33();
}
}
if(pub_.getNumSubscribers())
{
pub_.publish(msg);
}
if(pubStamped_.getNumSubscribers())
{
// use same header as the input image (for synchronization and frame reference)
msgStamped.header.frame_id = header.frameId_.toStdString();
msgStamped.header.stamp.sec = header.sec_;
msgStamped.header.stamp.nsec = header.nsec_;
pubStamped_.publish(msgStamped);
}
if(pubInfo_.getNumSubscribers())
{
// use same header as the input image (for synchronization and frame reference)
infoMsg.header.frame_id = header.frameId_.toStdString();
infoMsg.header.stamp.sec = header.sec_;
infoMsg.header.stamp.nsec = header.nsec_;
pubInfo_.publish(infoMsg);
}
}
}
cv::Vec3f FindObjectROS::getDepth(const cv::Mat & depthImage,
int x, int y,
float cx, float cy,
float fx, float fy)
{
if(!(x >=0 && x<depthImage.cols && y >=0 && y<depthImage.rows))
{
ROS_ERROR("Point must be inside the image (x=%d, y=%d), image size=(%d,%d)",
x, y,
depthImage.cols, depthImage.rows);
return cv::Vec3f(
std::numeric_limits<float>::quiet_NaN (),
std::numeric_limits<float>::quiet_NaN (),
std::numeric_limits<float>::quiet_NaN ());
}
cv::Vec3f pt;
// Use correct principal point from calibration
float center_x = cx; //cameraInfo.K.at(2)
float center_y = cy; //cameraInfo.K.at(5)
bool isInMM = depthImage.type() == CV_16UC1; // is in mm?
// Combine unit conversion (if necessary) with scaling by focal length for computing (X,Y)
float unit_scaling = isInMM?0.001f:1.0f;
float constant_x = unit_scaling / fx; //cameraInfo.K.at(0)
float constant_y = unit_scaling / fy; //cameraInfo.K.at(4)
float bad_point = std::numeric_limits<float>::quiet_NaN ();
float depth;
bool isValid;
if(isInMM)
{
depth = (float)depthImage.at<uint16_t>(y,x);
isValid = depth != 0.0f;
}
else
{
depth = depthImage.at<float>(y,x);
isValid = std::isfinite(depth) && depth > 0.0f;
}
// Check for invalid measurements
if (!isValid)
{
pt.val[0] = pt.val[1] = pt.val[2] = bad_point;
}
else
{
// Fill in XYZ
pt.val[0] = (float(x) - center_x) * depth * constant_x;
pt.val[1] = (float(y) - center_y) * depth * constant_y;
pt.val[2] = depth*unit_scaling;
}
return pt;
}
-71
View File
@@ -1,71 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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 FINDOBJECTROS_H_
#define FINDOBJECTROS_H_
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <tf/transform_broadcaster.h>
#include "find_object/FindObject.h"
#include <QtCore/QObject>
#include <QtCore/QMultiMap>
#include <QtCore/QPair>
#include <QtCore/QRect>
#include <QtGui/QTransform>
class FindObjectROS : public find_object::FindObject
{
Q_OBJECT;
public:
FindObjectROS(QObject * parent = 0);
virtual ~FindObjectROS() {}
public Q_SLOTS:
void publish(const find_object::DetectionInfo & info, const find_object::Header & header, const cv::Mat & depth, float depthConstant);
private:
cv::Vec3f getDepth(const cv::Mat & depthImage,
int x, int y,
float cx, float cy,
float fx, float fy);
private:
ros::Publisher pub_;
ros::Publisher pubStamped_;
ros::Publisher pubInfo_;
std::string objFramePrefix_;
bool usePnP_;
tf::TransformBroadcaster tfBroadcaster_;
};
#endif /* FINDOBJECTROS_H_ */
@@ -1,191 +0,0 @@
/*
Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
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 the Universite de Sherbrooke 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.
*/
#include <ros1/CameraROS.h>
#include <ros1/FindObjectROS.h>
#include <QApplication>
#include <QDir>
#include "find_object/MainWindow.h"
#include "ParametersToolBox.h"
#include "find_object/Settings.h"
#include <signal.h>
using namespace find_object;
bool gui;
std::string settingsPath;
void my_handler_gui(int s){
QApplication::closeAllWindows();
QApplication::quit();
}
void my_handler(int s){
QCoreApplication::quit();
}
void setupQuitSignal(bool gui)
{
// Catch ctrl-c to close the gui
struct sigaction sigIntHandler;
if(gui)
{
sigIntHandler.sa_handler = my_handler_gui;
}
else
{
sigIntHandler.sa_handler = my_handler;
}
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "find_object_2d");
gui = true;
std::string objectsPath;
std::string sessionPath;
settingsPath = QDir::homePath().append("/.ros/find_object_2d.ini").toStdString();
bool subscribeDepth = false;
ros::NodeHandle nh("~");
nh.param("gui", gui, gui);
nh.param("objects_path", objectsPath, objectsPath);
nh.param("session_path", sessionPath, sessionPath);
nh.param("settings_path", settingsPath, settingsPath);
nh.param("subscribe_depth", subscribeDepth, subscribeDepth);
ROS_INFO("gui=%d", (int)gui);
ROS_INFO("objects_path=%s", objectsPath.c_str());
ROS_INFO("session_path=%s", sessionPath.c_str());
ROS_INFO("settings_path=%s", settingsPath.c_str());
ROS_INFO("subscribe_depth = %s", subscribeDepth?"true":"false");
if(settingsPath.empty())
{
settingsPath = QDir::homePath().append("/.ros/find_object_2d.ini").toStdString();
}
else
{
if(!sessionPath.empty())
{
ROS_WARN("\"settings_path\" parameter is ignored when \"session_path\" is set.");
}
QString path = settingsPath.c_str();
if(path.contains('~'))
{
path.replace('~', QDir::homePath());
settingsPath = path.toStdString();
}
}
// Load settings, should be loaded before creating other objects
Settings::init(settingsPath.c_str());
FindObjectROS * findObjectROS = new FindObjectROS();
if(!sessionPath.empty())
{
if(!objectsPath.empty())
{
ROS_WARN("\"objects_path\" parameter is ignored when \"session_path\" is set.");
}
if(!findObjectROS->loadSession(sessionPath.c_str()))
{
ROS_ERROR("Failed to load session \"%s\"", sessionPath.c_str());
}
}
else if(!objectsPath.empty())
{
QString path = objectsPath.c_str();
if(path.contains('~'))
{
path.replace('~', QDir::homePath());
}
if(!findObjectROS->loadObjects(path))
{
ROS_ERROR("No objects loaded from path \"%s\"", path.toStdString().c_str());
}
}
CameraROS * camera = new CameraROS(subscribeDepth);
// Catch ctrl-c to close the gui
setupQuitSignal(gui);
if(gui)
{
QApplication app(argc, argv);
MainWindow mainWindow(findObjectROS, camera); // take ownership
QObject::connect(
&mainWindow,
SIGNAL(objectsFound(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)),
findObjectROS,
SLOT(publish(const find_object::DetectionInfo &, const find_object::Header &, const cv::Mat &, float)));
QStringList topics = camera->subscribedTopics();
if(topics.size() == 1)
{
mainWindow.setSourceImageText(mainWindow.tr(
"<qt>Find-Object subscribed to <b>%1</b> topic.<br/>"
"You can remap the topic when starting the node: <br/>\"rosrun find_object_2d find_object_2d image:=your/image/topic\".<br/>"
"</qt>").arg(topics.first()));
}
else if(topics.size() == 3)
{
mainWindow.setSourceImageText(mainWindow.tr(
"<qt>Find-Object subscribed to : <br/> <b>%1</b> <br/> <b>%2</b> <br/> <b>%3</b><br/>"
"</qt>").arg(topics.at(0)).arg(topics.at(1)).arg(topics.at(2)));
}
mainWindow.show();
app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) );
// loop
mainWindow.startProcessing();
app.exec();
Settings::saveSettings();
}
else
{
QCoreApplication app(argc, argv);
// connect stuff:
QObject::connect(camera, SIGNAL(imageReceived(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)), findObjectROS, SLOT(detect(const cv::Mat &, const find_object::Header &, const cv::Mat &, float)));
//loop
camera->start();
app.exec();
delete camera;
delete findObjectROS;
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show More