SMACC2
opencv_perception_node.cpp
Go to the documentation of this file.
1// Copyright 2021 RobosoftAI Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*****************************************************************************************************************
16 *
17 * Authors: Pablo Inigo Blasco, Brett Aldrich
18 *
19 ******************************************************************************************************************/
20
21// #include <cv_bridge/cv_bridge.h>
22#include <image_tools/cv_mat_sensor_msgs_image_type_adapter.hpp>
23#include <rclcpp/rclcpp.hpp>
24
25#include <sensor_msgs/msg/image.hpp>
26#include <std_msgs/msg/int32.hpp>
27#include <iostream>
28
29#include <opencv2/opencv.hpp>
30#include <opencv2/features2d.hpp>
31
32#include "image_tools/cv_mat_sensor_msgs_image_type_adapter.hpp"
33
36 sensor_msgs::msg::Image);
37
38rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr detectionPub;
39rclcpp::Publisher<image_tools::ROSCvMatContainer>::SharedPtr debugImagePub;
40rclcpp::Subscription<image_tools::ROSCvMatContainer>::SharedPtr imageSub;
41
42void segmentColor(const cv::Mat& inputRGB, int hueMean, int hueWindow, cv::Mat& out)
43{
44 cv::Mat hsvInput;
45 cv::cvtColor(inputRGB, hsvInput, cv::COLOR_BGR2HSV);
46 cv::inRange(hsvInput, cv::Scalar(hueMean - hueWindow, 20, 20), cv::Scalar(hueMean + hueWindow, 255, 255), out);
47 cv::threshold(out, out, 100, 255, cv::THRESH_BINARY);
48}
49
50int testImage(cv::Mat& input, cv::Mat& debugImage, std::string colorName, int hueMean, int hueWindow)
51{
52 cv::Mat segmented;
53
54 segmentColor(input, hueMean, hueWindow, segmented);
55
56 cv::SimpleBlobDetector::Params params;
57 // params.filterByArea= true;
58 // params.minArea = 10;
59 params.filterByArea = true;
60 params.minArea = 100;
61 params.maxArea = 100000;
62 params.filterByColor = true;
63 params.blobColor = 255;
64
65 auto blobDetector = cv::SimpleBlobDetector::create(params);
66 std::vector<cv::KeyPoint> blobs;
67 blobDetector->detect(segmented, blobs);
68
69 std::cout << "-------" << std::endl;
70 for (auto& b : blobs)
71 {
72 std::cout << "blob " << colorName << " detected: " << b.size << std::endl;
73 }
74
75 if(!blobs.empty())
76 {
77 for(auto& b: blobs)
78 {
79 cv::Rect r;
80 float diameter = b.size;
81 auto radius = diameter*0.5;
82 r.x = b.pt.x - radius;
83 r.y = b.pt.y - radius;
84 r.width = diameter;
85 r.height = diameter;
86 cv::rectangle(debugImage,r, cv::Scalar(255,0,0),1 );
87 }
88 }
89
90 // cv::imshow(colorName + " filter - "+ path, segmented);
91 // cv::waitKey();
92
93 return blobs.size();
94}
95
96int testRed(cv::Mat& input, cv::Mat& debugImage)
97{
98 return testImage(input, debugImage, "red", 130, 20);
99}
100
101int testBlue(cv::Mat& input, cv::Mat& debugImage)
102{
103 return testImage(input, debugImage, "blue", 10, 10);
104}
105
106int testGreen(cv::Mat& input, cv::Mat& debugImage)
107{
108 return testImage(input, debugImage, "green", 50, 10);
109}
110
111int testRed(std::string path, cv::Mat& debugImage)
112{
113 cv::Mat input = cv::imread(path);
114 return testImage(input, debugImage, "red", 130, 20);
115}
116
117int testBlue(std::string path, cv::Mat& debugImage)
118{
119 cv::Mat input = cv::imread(path);
120 return testImage(input, debugImage, "blue", 10, 10);
121}
122
123int testGreen(std::string path, cv::Mat& debugImage)
124{
125 cv::Mat input = cv::imread(path);
126 return testImage(input, debugImage, "green", 50, 10);
127}
128
129void update()
130{
131}
132
134{
135 cv::Mat image = img.cv_mat();
136
138 auto outmat = outimg.cv_mat();
139
140 int detectedColor = 0;
141 if (testRed(image, outmat) > 0)
142 {
143 detectedColor = 1;
144 }
145
146 if (testGreen(image, outmat) > 0)
147 {
148 detectedColor = 2;
149 }
150
151 if (testBlue(image, outmat) > 0)
152 {
153 detectedColor = 3;
154 }
155
156 std_msgs::msg::Int32 detectedColorMsg;
157 detectedColorMsg.data = detectedColor;
158 detectionPub->publish(detectedColorMsg);
159
160
161 outimg.header() = img.header();
162 debugImagePub->publish(outimg);
163}
164
165int main(int argc, char** argv)
166{
167 rclcpp::init(argc, argv);
168 rclcpp::Node::SharedPtr nh;
169
170 detectionPub = nh->create_publisher<std_msgs::msg::Int32>("detected_color", 1);
171 imageSub = nh->create_subscription<image_tools::ROSCvMatContainer>("/image_raw", 1, callback);
172 debugImagePub = nh->create_publisher<image_tools::ROSCvMatContainer>("/opencv_debug_image", 1);
173
174 rclcpp::Rate r(10);
175
176 while (!rclcpp::shutdown())
177 {
178 update();
179 rclcpp::spin_some(nh);
180 r.sleep();
181 }
182
183 /*
184 testRed("../../red1.png");
185 testRed("../../green1.png");
186 testRed("../../blue1.png");
187 testRed("../../red2.png");
188
189 testGreen("../../red1.png");
190 testGreen("../../green1.png");
191 testGreen("../../blue1.png");
192 testGreen("../../red2.png");
193
194 testBlue("../../red1.png");
195 testBlue("../../green1.png");
196 testBlue("../../blue1.png");
197 testBlue("../../red2.png");
198 */
199}
A potentially owning, potentially non-owning, container of a cv::Mat and ROS header.
IMAGE_TOOLS_PUBLIC const std_msgs::msg::Header & header() const
Const access the ROS Header.
IMAGE_TOOLS_PUBLIC const cv::Mat & cv_mat() const
Const access the cv::Mat in this class.
void callback(const image_tools::ROSCvMatContainer &img)
int testBlue(cv::Mat &input, cv::Mat &debugImage)
int main(int argc, char **argv)
int testGreen(cv::Mat &input, cv::Mat &debugImage)
int testRed(cv::Mat &input, cv::Mat &debugImage)
rclcpp::Publisher< image_tools::ROSCvMatContainer >::SharedPtr debugImagePub
void segmentColor(const cv::Mat &inputRGB, int hueMean, int hueWindow, cv::Mat &out)
rclcpp::Subscription< image_tools::ROSCvMatContainer >::SharedPtr imageSub
rclcpp::Publisher< std_msgs::msg::Int32 >::SharedPtr detectionPub
void update()
int testImage(cv::Mat &input, cv::Mat &debugImage, std::string colorName, int hueMean, int hueWindow)
RCLCPP_USING_CUSTOM_TYPE_AS_ROS_MESSAGE_TYPE(image_tools::ROSCvMatContainer, sensor_msgs::msg::Image)