@@ -66,13 +66,22 @@ bool ColorDetector::load_configuration(const std::string & path)
6666 try {
6767 utils::Color color (
6868 item.key (),
69- item.value ().at (" invert_hue" ).get <bool >(),
70- item.value ().at (" min_hsv" )[0 ],
71- item.value ().at (" max_hsv" )[0 ],
72- item.value ().at (" min_hsv" )[1 ],
73- item.value ().at (" max_hsv" )[1 ],
74- item.value ().at (" min_hsv" )[2 ],
75- item.value ().at (" max_hsv" )[2 ]
69+ utils::Color::Config{
70+ .invert_hue = item.value ().at (" invert_hue" ).get <bool >(),
71+ .use_lab = item.value ().at (" use_lab" ).get <bool >(),
72+ .min_hue = item.value ().at (" min_hsv" )[0 ],
73+ .max_hue = item.value ().at (" max_hsv" )[0 ],
74+ .min_saturation = item.value ().at (" min_hsv" )[1 ],
75+ .max_saturation = item.value ().at (" max_hsv" )[1 ],
76+ .min_value = item.value ().at (" min_hsv" )[2 ],
77+ .max_value = item.value ().at (" max_hsv" )[2 ],
78+ .min_lightness = item.value ().at (" min_lab" )[0 ],
79+ .max_lightness = item.value ().at (" max_lab" )[0 ],
80+ .min_a = item.value ().at (" min_lab" )[1 ],
81+ .max_a = item.value ().at (" max_lab" )[1 ],
82+ .min_b = item.value ().at (" min_lab" )[2 ],
83+ .max_b = item.value ().at (" max_lab" )[2 ]
84+ }
7685 );
7786
7887 colors.push_back (color);
@@ -97,15 +106,21 @@ bool ColorDetector::save_configuration()
97106 nlohmann::json config = nlohmann::json::array ();
98107
99108 for (auto & item : colors) {
100- bool invert_hue = item.invert_hue ;
101- int min_hsv[] = {item.min_hue , item.min_saturation , item.min_value };
102- int max_hsv[] = {item.max_hue , item.max_saturation , item.max_value };
109+ bool invert_hue = item.config .invert_hue ;
110+ bool use_lab = item.config .use_lab ;
111+ int min_hsv[] = {item.config .min_hue , item.config .min_saturation , item.config .min_value };
112+ int max_hsv[] = {item.config .max_hue , item.config .max_saturation , item.config .max_value };
113+ int min_lab[] = {item.config .min_lightness , item.config .min_a , item.config .min_b };
114+ int max_lab[] = {item.config .max_lightness , item.config .max_a , item.config .max_b };
103115
104116 nlohmann::json color = {
105117 {item.name , {
106118 {" invert_hue" , invert_hue},
119+ {" use_lab" , use_lab},
107120 {" min_hsv" , min_hsv},
108- {" max_hsv" , max_hsv}
121+ {" max_hsv" , max_hsv},
122+ {" min_lab" , min_lab},
123+ {" max_lab" , max_lab},
109124 }}
110125 };
111126
@@ -132,13 +147,7 @@ void ColorDetector::configure_color_setting(utils::Color color)
132147{
133148 for (auto & item : colors) {
134149 if (item.name == color.name ) {
135- item.invert_hue = color.invert_hue ;
136- item.min_hue = color.min_hue ;
137- item.max_hue = color.max_hue ;
138- item.min_saturation = color.min_saturation ;
139- item.max_saturation = color.max_saturation ;
140- item.min_value = color.min_value ;
141- item.max_value = color.max_value ;
150+ item.config = color.config ;
142151
143152 break ;
144153 }
@@ -178,11 +187,7 @@ cv::Mat ColorDetector::classify(cv::Mat input)
178187
179188 cv::bitwise_or (mask1, mask2, output);
180189 } else {
181- cv::inRange (input,
182- cv::Scalar (h_min, s_min, v_min),
183- cv::Scalar (h_max, s_max, v_max),
184- output
185- );
190+ cv::inRange (input, hsv_min, hsv_max, output);
186191 }
187192
188193 cv::Mat element = cv::getStructuringElement (cv::MORPH_ELLIPSE, cv::Size (3 , 3 ), cv::Point (1 , 1 ));
@@ -191,6 +196,30 @@ cv::Mat ColorDetector::classify(cv::Mat input)
191196 return output;
192197}
193198
199+ cv::Mat ColorDetector::classify_lab (cv::Mat input)
200+ {
201+ int l_min = min_lightness;
202+ int l_max = max_lightness;
203+
204+ int a_min = min_a + 128 ;
205+ int a_max = max_a + 128 ;
206+
207+ int b_min = min_b + 128 ;
208+ int b_max = max_b + 128 ;
209+
210+ cv::Scalar lab_min = cv::Scalar (l_min, a_min, b_min);
211+ cv::Scalar lab_max = cv::Scalar (l_max, a_max, b_max);
212+
213+ cv::Mat output = input.clone ();
214+
215+ cv::inRange (input, lab_min, lab_max, output);
216+
217+ cv::Mat element = cv::getStructuringElement (cv::MORPH_ELLIPSE, cv::Size (3 , 3 ), cv::Point (1 , 1 ));
218+ cv::morphologyEx (output, output, cv::MORPH_CLOSE, element);
219+
220+ return output;
221+ }
222+
194223cv::Mat ColorDetector::classify_gray (cv::Mat input)
195224{
196225 int v_min = (min_value * 255 ) / 100 ;
@@ -228,16 +257,32 @@ void ColorDetector::detection(const cv::Mat & image)
228257 // iterate every color in colors
229258 for (auto & color : colors) {
230259 color_name = color.name ;
231- invert_hue = color.invert_hue ;
232- min_hue = color.min_hue ;
233- max_hue = color.max_hue ;
234- min_saturation = color.min_saturation ;
235- max_saturation = color.max_saturation ;
236- min_value = color.min_value ;
237- max_value = color.max_value ;
238-
239- cv::Mat field_binary_mat = classify (image);
240- find (field_binary_mat);
260+ invert_hue = color.config .invert_hue ;
261+ use_lab = color.config .use_lab ;
262+ min_hue = color.config .min_hue ;
263+ max_hue = color.config .max_hue ;
264+ min_saturation = color.config .min_saturation ;
265+ max_saturation = color.config .max_saturation ;
266+ min_value = color.config .min_value ;
267+ max_value = color.config .max_value ;
268+ min_lightness = color.config .min_lightness ;
269+ max_lightness = color.config .max_lightness ;
270+ min_a = color.config .min_a ;
271+ max_a = color.config .max_a ;
272+ min_b = color.config .min_b ;
273+ max_b = color.config .max_b ;
274+
275+ if (!use_lab) {
276+ cv::Mat hsv_image;
277+ cv::cvtColor (image, hsv_image, cv::COLOR_BGR2HSV);
278+ cv::Mat field_binary_mat = classify (hsv_image);
279+ find (field_binary_mat);
280+ } else {
281+ cv::Mat lab_image;
282+ cv::cvtColor (image, lab_image, cv::COLOR_BGR2Lab);
283+ cv::Mat field_binary_mat = classify_lab (lab_image);
284+ find (field_binary_mat);
285+ }
241286
242287 // Copy contours to ros2 msg
243288 if (contours.size () >= 0 ) {
0 commit comments