Skip to content

Commit fecf13a

Browse files
authored
Merge pull request #1 from k-okada/add_matching_template
update matching template
2 parents b0e571a + 905b3db commit fecf13a

File tree

5 files changed

+104
-29
lines changed

5 files changed

+104
-29
lines changed

CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ opencv_apps_add_nodelet(discrete_fourier_transform discrete_fourier_transform/di
159159
# ./tutorial_code/Histograms_Matching/calcHist_Demo.cpp
160160
# ./tutorial_code/Histograms_Matching/compareHist_Demo.cpp
161161
# ./tutorial_code/Histograms_Matching/EqualizeHist_Demo.cpp
162-
# ./tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp
162+
opencv_apps_add_nodelet(match_template match_template/match_template src/nodelet/match_template_nodelet.cpp) # ./tutorial_code/Histograms_Matching/MatchTemplate_Demo.cpp
163163

164164
# imagecodecs
165165
# ./tutorial_code/imgcodecs/GDAL_IO/gdal-image.cpp
@@ -331,8 +331,6 @@ endif()
331331
# https://github.com/opencv/opencv/blob/2.4/samples/cpp/video_homography.cpp
332332
# https://github.com/opencv/opencv/blob/2.4/samples/cpp/videocapture_pvapi.cpp
333333

334-
opencv_apps_add_nodelet(match_template match_template/match_template src/nodelet/match_template_nodelet.cpp)
335-
336334
add_library(${PROJECT_NAME} SHARED
337335
src/nodelet/nodelet.cpp
338336
${_opencv_apps_nodelet_cppfiles}

cfg/MatchTemplate.cfg

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,13 @@ from dynamic_reconfigure.parameter_generator_catkin import *
3838

3939
gen = ParameterGenerator()
4040
gen.add("use_camera_info", bool_t, 0, "Indicates that the camera_info topic should be subscribed to to get the default input_frame_id. Otherwise the frame from the image message will be used.", False)
41+
match_type = gen.enum([gen.const("CV_TM_SQDIFF", int_t, 0, "Sum of Ssquared Difference"),
42+
gen.const("CV_TM_SQDIFF_NORMED", int_t, 1, "Sum of Normalized Ssquared Difference"),
43+
gen.const("CV_TM_CCORR", int_t, 2, "Correlation"),
44+
gen.const("CV_TM_CCORR_NORMED", int_t, 3, "Normalized Correlation"),
45+
gen.const("CV_TM_CCOEFF", int_t, 4, "Correlation of Coefficient"),
46+
gen.const("CV_TM_CCOEFF_NORMED", int_t, 5, "Normalized Correlation of Coefficient"),
47+
], "An enum for Mathing Mehtods")
48+
gen.add("match_method", int_t, 0, "Matching Methods", 0, 0, 5, edit_method=match_type)
4149

4250
exit(gen.generate(PACKAGE, "match_template", "MatchTemplate"))

launch/match_template.launch

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<arg name="use_camera_info" default="false" doc="Indicates that the camera_info topic should be subscribed to to get the default input_frame_id. Otherwise the frame from the image message will be used." />
55
<arg name="debug_view" default="false" doc="Specify whether the node displays a window to show edge image" />
66
<arg name="match_method" default="0" doc="Matching method. 0:CV_TM_SQDIFF 1:CV_TM_SQDIFF_NORMED 2:CV_TM_CCORR 3:CV_TM_CCORR_NORMED 4:CV_TM_CCOEFF 5:CV_TM_CCOEFF_NORMED" />
7+
<arg name="template_file" default="$(find opencv_apps)/template.png" doc="filename for template image"/>
8+
<arg name="mask_file" default="$(find opencv_apps)/mask.png" doc="filename for mask image"/>
79

810
<!-- match_template_nodelet.cpp -->
911
<node name="$(arg node_name)" pkg="opencv_apps" type="match_template" output="screen">
@@ -12,7 +14,7 @@
1214
<param name="debug_view" value="$(arg debug_view)" />
1315
<param name="match_method" value="$(arg match_method)" />
1416
<param name="use_mask" value="false" />
15-
<param name="template_file" value="$(find opencv_apps)/template.png" />
16-
<param name="mask_file" value="$(find opencv_apps)/mask.png" />
17+
<param name="template_file" value="$(arg template_file)" />
18+
<param name="mask_file" value="$(arg mask_file)" />
1719
</node>
1820
</launch>

src/nodelet/match_template_nodelet.cpp

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include <dynamic_reconfigure/server.h>
5353
#include "opencv_apps/MatchTemplateConfig.h"
5454
#include "opencv_apps/RectArrayStamped.h"
55+
#include <std_msgs/Float64.h>
5556

5657
namespace match_template
5758
{
@@ -61,7 +62,8 @@ namespace match_template
6162
image_transport::Publisher matched_img_pub_;
6263
image_transport::Subscriber img_sub_;
6364
image_transport::CameraSubscriber cam_sub_;
64-
ros::Publisher msg_pub_;
65+
ros::Publisher matched_val_pub_;
66+
ros::Publisher matched_rect_pub_;
6567

6668
boost::shared_ptr < image_transport::ImageTransport > it_;
6769

@@ -72,16 +74,24 @@ namespace match_template
7274

7375
bool debug_view_;
7476
int match_method_;
77+
#if (CV_MAJOR_VERSION >= 3 && CV_MINOR_VERSION >= 2) // mask is only supported since opencv 3.2 (https://github.com/opencv/opencv/pull/3554)
7578
bool use_mask_;
79+
#endif
7680

7781
ros::Time prev_stamp_;
7882

7983
cv::Mat templ_;
84+
#if (CV_MAJOR_VERSION >= 3 && CV_MINOR_VERSION >= 2)
8085
cv::Mat mask_;
86+
#endif
8187

8288
void reconfigureCallback (Config & new_config, uint32_t level)
8389
{
8490
config_ = new_config;
91+
if ( match_method_ != config_.match_method ) {
92+
match_method_ = config_.match_method;
93+
NODELET_WARN_STREAM("Change Mathing Method to " << match_method_);
94+
}
8595
}
8696

8797
const std::string & frameWithDefault (const std::string & frame, const std::string & image_frame)
@@ -118,32 +128,25 @@ namespace match_template
118128
int result_rows = frame.rows - templ_.rows + 1;
119129
cv::Mat result (result_rows, result_cols, CV_32FC1);
120130

121-
//-- Show template
122-
if (debug_view_)
123-
{
124-
cv::imshow ("Template", templ_);
125-
int c = cv::waitKey (1);
126-
}
127-
128131
//! [match_template]
129132
/// Do the Matching and Normalize
130133
bool method_accepts_mask = (match_method_ == CV_TM_SQDIFF || match_method_ == CV_TM_CCORR_NORMED);
134+
#if (CV_MAJOR_VERSION >= 3 && CV_MINOR_VERSION >= 2)
131135
if (use_mask_ && method_accepts_mask)
132136
{
133137
matchTemplate (frame, templ_, result, match_method_, mask_);
134138
}
135139
else
140+
#endif
136141
{
137142
matchTemplate (frame, templ_, result, match_method_);
138143
}
139-
//! [normalize]
140-
//normalize (result, result, 0, 255, cv::NORM_MINMAX, CV_8UC1, cv::Mat ());
141-
normalize (result, result, 0, 255, cv::NORM_MINMAX, CV_8UC1, cv::Mat ());
142144

143145
//! [best_match]
144146
/// Localizing the best match with minMaxLoc
145147
double minVal;
146148
double maxVal;
149+
double matchVal;
147150
cv::Point minLoc;
148151
cv::Point maxLoc;
149152
cv::Point matchLoc;
@@ -154,23 +157,57 @@ namespace match_template
154157
if (match_method_ == CV_TM_SQDIFF || match_method_ == CV_TM_SQDIFF_NORMED || match_method_ == CV_TM_CCORR)
155158
{
156159
matchLoc = minLoc;
160+
matchVal = minVal;
157161
}
158162
else
159163
{
160164
matchLoc = maxLoc;
165+
matchVal = maxVal;
161166
}
167+
NODELET_DEBUG_STREAM(std::fixed << std::setw(12) << minVal << " " << maxVal << " min " << matchVal);
168+
169+
//! [normalize] for visualization
170+
normalize (result, result, 0, 255, cv::NORM_MINMAX, CV_8UC1, cv::Mat ());
171+
162172
rectangle (frame, matchLoc, cv::Point (matchLoc.x + templ_.cols, matchLoc.y + templ_.rows), cv::Scalar::all (0),
163173
2, 8, 0);
164-
rectangle (result, matchLoc, cv::Point (matchLoc.x + templ_.cols, matchLoc.y + templ_.rows),
174+
std::stringstream ss;
175+
ss << std::fixed << std::setw(12) << std::setprecision(0) << matchVal;
176+
cv::putText(frame, ss.str(), cv::Point(0,20), cv::FONT_HERSHEY_PLAIN, 1.5, cv::Scalar(255.0, 255.0, 255.0), 1, CV_AA);
177+
rectangle (result, cv::Point (matchLoc.x - templ_.cols/2, matchLoc.y - templ_.rows/2), cv::Point (matchLoc.x + templ_.cols/2, matchLoc.y + templ_.rows/2),
165178
cv::Scalar::all (0), 2, 8, 0);
166179

180+
//-- Show template and result
181+
if (debug_view_)
182+
{
183+
cv::imshow ("Template", templ_);
184+
cv::imshow ("Soure Image", frame);
185+
cv::imshow ("Result window", result);
186+
int c = cv::waitKey (1);
187+
}
188+
167189
// Publish the image.
168190
sensor_msgs::Image::Ptr out_img =
169191
cv_bridge::CvImage (msg->header, sensor_msgs::image_encodings::BGR8, frame).toImageMsg ();
170192
sensor_msgs::Image::Ptr match_img =
171193
cv_bridge::CvImage (msg->header, sensor_msgs::image_encodings::MONO8, result).toImageMsg ();
172194
img_pub_.publish (out_img);
173195
matched_img_pub_.publish (match_img);
196+
197+
// Publish the result.
198+
opencv_apps::RectArrayStamped matched_rect_msg;
199+
matched_rect_msg.header = msg->header;
200+
opencv_apps::Rect rect_msg;
201+
rect_msg.x = matchLoc.x;
202+
rect_msg.y = matchLoc.y;
203+
rect_msg.width = templ_.cols;
204+
rect_msg.height = templ_.rows;
205+
matched_rect_msg.rects.push_back(rect_msg);
206+
matched_rect_pub_.publish (matched_rect_msg);
207+
208+
std_msgs::Float64 matched_val_msg;
209+
matched_val_msg.data = matchVal;
210+
matched_val_pub_.publish (matched_val_msg);
174211
}
175212
catch (cv::Exception & e)
176213
{
@@ -204,34 +241,35 @@ namespace match_template
204241

205242
pnh_->param ("debug_view", debug_view_, false);
206243
pnh_->param ("match_method", match_method_, (int) CV_TM_SQDIFF);
244+
#if (CV_MAJOR_VERSION >= 3 && CV_MINOR_VERSION >= 2)
207245
pnh_->param ("use_mask", use_mask_, false);
208-
std::string templ_file, mask_file;
246+
#endif
247+
std::string templ_file;
209248
pnh_->param ("template_file", templ_file, std::string ("template.png"));
249+
#if (CV_MAJOR_VERSION >= 3 && CV_MINOR_VERSION >= 2)
250+
std::string mask_file;
210251
pnh_->param ("mask_file", mask_file, std::string ("mask.png"));
252+
#endif
211253

212254
NODELET_INFO ("template_file: %s", templ_file.c_str ());
213255

214256
if (debug_view_)
215257
{
216258
always_subscribe_ = true;
217259
}
260+
#if (CV_MAJOR_VERSION >= 3 && CV_MINOR_VERSION >= 2)
218261
if (use_mask_)
219262
{
220263
mask_ = imread (mask_file, cv::IMREAD_COLOR);
221264
}
222-
if (templ_file.empty ())
223-
{
224-
NODELET_ERROR ("Cannot open template file %s", templ_file.c_str ());
225-
exit (0);
226-
}
227-
//templ_ = imread(templ_file, cv::IMREAD_COLOR);
265+
#endif
228266
templ_ = imread (templ_file, cv::IMREAD_COLOR);
229-
230-
if (debug_view_)
267+
if (!templ_.data)
231268
{
232-
cv::imshow ("Match Template", templ_);
233-
int c = cv::waitKey (1);
269+
NODELET_ERROR ("Cannot open template file (%s)", templ_file.c_str ());
270+
exit (-1);
234271
}
272+
235273
prev_stamp_ = ros::Time (0, 0);
236274

237275
reconfigure_server_ = boost::make_shared < dynamic_reconfigure::Server < Config > >(*pnh_);
@@ -241,7 +279,8 @@ namespace match_template
241279

242280
img_pub_ = advertiseImage (*pnh_, "image", 1);
243281
matched_img_pub_ = advertiseImage (*pnh_, "matched_image", 1);
244-
msg_pub_ = advertise < opencv_apps::RectArrayStamped > (*pnh_, "matched_rectangle", 1);
282+
matched_val_pub_ = advertise< std_msgs::Float64 > (*pnh_, "matched_value", 1);
283+
matched_rect_pub_ = advertise < opencv_apps::RectArrayStamped > (*pnh_, "matched_rectangle", 1);
245284

246285
onInitPostProcess ();
247286
}

test/test-match_template.test

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<launch>
2+
<arg name="gui" default="true" />
3+
<node name="play_face_bag" pkg="rosbag" type="play" args="-l $(find opencv_apps)/test/face_detector_withface_test_diamondback.bag" />
4+
5+
<group ns="wide_stereo/left" >
6+
<node name="image_proc" pkg="image_proc" type="image_proc" />
7+
<node name="image_view" pkg="image_view" type="image_view" args="image:=image_rect_color" if="$(arg gui)" />
8+
9+
<!-- convex_hull.cpp -->
10+
<include file="$(find opencv_apps)/launch/match_template.launch" >
11+
<arg name="debug_view" value="$(arg gui)" />
12+
<arg name="image" value="image_rect" />
13+
<arg name="template_file" value="$(find opencv_apps)/test/template.png" />
14+
<arg name="mask_file" value="" />
15+
</include>
16+
17+
<!-- Test Codes -->
18+
<node name="match_template_saver" pkg="image_view" type="image_saver" args="image:=match_template/image" >
19+
<param name="filename_format" value="$(find opencv_apps)/test/match_template.png"/>
20+
</node>
21+
<param name="match_template_test/topic" value="match_template/matched_rectangle" /> <!-- opencv_apps/ContorArrayStamped -->
22+
<test test-name="match_template_test" pkg="rostest" type="hztest" name="match_template_test" >
23+
<param name="hz" value="20" />
24+
<param name="hzerror" value="15" />
25+
<param name="test_duration" value="5.0" />
26+
</test>
27+
</group>
28+
</launch>

0 commit comments

Comments
 (0)