color_gui.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Copyright (c) 2008, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *********************************************************************/
29 
32 #include <string>
33 #include <cv_bridge/cv_bridge.h>
34 
35 #include "cmvision/color_gui.h"
36 #include "cmvision/conversions.h"
37 
39 {
40  char **local_argv = new char *[argc];
41  for (int i = 0; i < argc; i++)
42  local_argv[i] = strdup(wxString(argv[i]).mb_str());
43 
44  ros::init(argc, local_argv, "cmvision");
45  ros::NodeHandle node_handle;
46 
47  // Subscribe to an image stream
48  image_subscriber_ = node_handle.subscribe("image", 1, &ColorGuiApp::imageCB, this);
49 
50  frame_ = new ColorGuiFrame();
51  frame_->Show(true);
52  SetTopWindow(frame_);
53 
54  update_timer_ = new wxTimer(this);
55  update_timer_->Start(33);
56 
57  Connect(update_timer_->GetId(), wxEVT_TIMER, wxTimerEventHandler(ColorGuiApp::OnUpdate), NULL, this);
58 
59  return true;
60 }
61 
62 void ColorGuiApp::OnUpdate(wxTimerEvent &event)
63 {
64  ros::spinOnce();
65 }
66 
67 void ColorGuiApp::imageCB(const sensor_msgs::ImageConstPtr &msg)
68 {
69  frame_->DrawImage(msg);
70 }
71 
73  : wxFrame(NULL, -1, wxT("Color Gui"), wxDefaultPosition, wxSize(800, 600), wxDEFAULT_FRAME_STYLE)
74 {
75 
76  wxInitAllImageHandlers();
77 
78  wxMenuBar *menuBar = new wxMenuBar;
79  wxMenu *file_menu = new wxMenu;
80 
81  wxMenuItem *item = file_menu->Append(ID_Reset, wxT("&Reset\tCtrl-R"));
82  Connect(item->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ColorGuiFrame::OnReset), NULL, this);
83 
84  item = file_menu->Append(wxID_EXIT, wxT("&Quit\tCtrl-Q"));
85  Connect(item->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ColorGuiFrame::OnQuit), NULL, this);
86 
87  menuBar->Append(file_menu, _("&File"));
88 
89  SetMenuBar(menuBar);
90 
91  CreateStatusBar();
92  SetStatusText(_("Click on the image to select colors. Use scroll wheel to zoom."));
93 
94  image_panel_ = new wxPanel(this, wxID_ANY, wxPoint(0, 0), wxSize(640, 480));
95 
96  wxStaticText *rgblabel = new wxStaticText(this, -1, wxT("RGB:"));
97  rgbText_ = new wxTextCtrl(this, -1, wxT(""));
98 
99  wxStaticText *abLabel = new wxStaticText(this, -1, wxT("AB:"));
100  abText_ = new wxTextCtrl(this, -1, wxT(""));
101 
102  wxBoxSizer *hsizer1 = new wxBoxSizer(wxHORIZONTAL);
103  wxBoxSizer *hsizer2 = new wxBoxSizer(wxHORIZONTAL);
104  wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL);
105 
106  hsizer2->Add(rgblabel, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 10);
107  hsizer2->Add(rgbText_, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 2);
108 
109  hsizer2->Add(abLabel, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 10);
110  hsizer2->Add(abText_, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 2);
111  hsizer2->Add(50, 1, 0);
112 
113  vsizer->Add(image_panel_, 0, wxEXPAND);
114  vsizer->Add(20, 2, 0);
115  vsizer->Add(hsizer2, 0, wxALIGN_LEFT | wxEXPAND);
116  this->SetSizer(vsizer);
117 
118  width_ = 0;
119  height_ = 0;
120 
121  scale_ = 1.0;
122  width_ = 0;
123  height_ = 0;
124 
125  rgb_image_ = NULL;
126  lab_image_ = NULL;
127 
128  vision_ = new CMVision();
129 
130  image_panel_->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(ColorGuiFrame::OnClick), NULL, this);
131 
132  Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(ColorGuiFrame::OnMouseWheel));
133 }
134 
135 void ColorGuiFrame::OnQuit(wxCommandEvent &event)
136 {
137  Close(true);
138 }
139 
140 void ColorGuiFrame::DrawImage(const sensor_msgs::ImageConstPtr &msg)
141 {
142  cv::Size size;
143 
144  const sensor_msgs::Image img = *msg;
145 
146  // Get the image as and RGB image
147  cv_bridge::CvImagePtr image_ptr = cv_bridge::toCvCopy(msg, "rgb8");
148 
149  cv::Mat cvImage(image_ptr->image);
150 
151  size = cvImage.size();
152 
153  if (width_ != size.width || height_ != size.height)
154  {
155  if (!rgb_image_)
156  delete[] rgb_image_;
157  rgb_image_ = new unsigned char[size.width * size.height * 3];
158 
159  if (!lab_image_)
160  delete[] lab_image_;
161  lab_image_ = new unsigned char[size.width * size.height * 3];
162 
163  if (!(vision_->initialize(size.width, size.height)))
164  {
165  width_ = height_ = 0;
166  ROS_ERROR("Vision init failed.");
167  return;
168  }
169  }
170 
171  width_ = size.width;
172  height_ = size.height;
173 
174  std::memcpy(rgb_image_, cvImage.data, width_ * height_ * 3);
175  // Convert image to LAB color space
176  cv::cvtColor(cvImage, cvImage, cv::COLOR_RGB2Lab);
177  std::memcpy(lab_image_, cvImage.data, width_ * height_ * 3);
178 
179  // Find the color blobs
180  if (!vision_->processFrame(reinterpret_cast<image_pixel *>(cvImage.data)))
181  {
182  ROS_ERROR("Frame error.");
183  return;
184  }
185 
186  int xsrc = (scale_pos_x_ * scale_) - scale_pos_x_;
187  int ysrc = (scale_pos_y_ * scale_) - scale_pos_y_;
188 
189  wxImage image(width_, height_, rgb_image_, true);
190  image.Rescale(width_ * scale_, height_ * scale_);
191 
192  wxBitmap bitmap(image);
193 
194  wxMemoryDC memDC;
195  memDC.SelectObject(bitmap);
196 
197  wxClientDC dc(image_panel_);
198  if (xsrc < 0 || ysrc < 0)
199  dc.Clear();
200 
201  dc.Blit(0, 0, 640, 480, &memDC, xsrc, ysrc);
202 
203  // Get all the blobs
204  for (int ch = 0; ch < CMV_MAX_COLORS; ++ch)
205  {
206  // Get the descriptive color
207  rgb c = vision_->getColorVisual(ch);
208 
209  // Grab the regions for this color
210  CMVision::region *r = NULL;
211 
212  for (r = vision_->getRegions(ch); r != NULL; r = r->next)
213  {
214  dc.SetBrush(*wxTRANSPARENT_BRUSH);
215  int x1 = (r->x1 * scale_) - xsrc;
216  int y1 = (r->y1 * scale_) - ysrc;
217  int x2 = (r->x2 * scale_) - xsrc;
218  int y2 = (r->y2 * scale_) - ysrc;
219 
220  int w = x2 - x1;
221  int h = y2 - y1;
222 
223  dc.DrawRectangle(x1, y1, w, h);
224  }
225  }
226 
227  int x, y;
228  GetPosition(&x, &y);
229  // Setting size is commented out because it breaks the gui:
230  // Text boxes become invisible.
231  // SetSize(x,y, width_, height_+80);
232 }
233 
234 void ColorGuiFrame::OnReset(wxCommandEvent &event)
235 {
236  vision_->setThreshold(0, 0, 0, 0, 0);
237  rgbText_->SetValue(wxString::FromAscii(""));
238  abText_->SetValue(wxString::FromAscii(""));
239 }
240 
241 void ColorGuiFrame::OnClick(wxMouseEvent &event)
242 {
243  int r, g, b, l, a, b2;
244 
245  int px = (event.m_x / scale_) + ((scale_pos_x_ * scale_) - scale_pos_x_) / scale_;
246  int py = (event.m_y / scale_) + ((scale_pos_y_ * scale_) - scale_pos_y_) / scale_;
247 
248  r = rgb_image_[py * (width_ * 3) + px * 3 + 0];
249  g = rgb_image_[py * (width_ * 3) + px * 3 + 1];
250  b = rgb_image_[py * (width_ * 3) + px * 3 + 2];
251 
252  std::ostringstream stream1;
253  stream1 << "(" << r << ", " << g << ", " << b << ")";
254  rgbText_->SetValue(wxString::FromAscii(stream1.str().c_str()));
255 
256  l = lab_image_[py * (width_ * 3) + px * 3 + 0];
257  a = lab_image_[py * (width_ * 3) + px * 3 + 1];
258  b2 = lab_image_[py * (width_ * 3) + px * 3 + 2];
259 
260  int l_low, l_high, a_low, a_high, b_low, b_high;
261 
262  vision_->getThreshold(0, a_low, a_high, b_low, b_high);
263 
264  if (a_low == 0 && a_high == 0)
265  {
266  a_low = a;
267  a_high = a;
268  }
269  if (b_low == 0 && b_high == 0)
270  {
271  b_low = b2;
272  b_high = b2;
273  }
274 
275  a_low = std::min(a, a_low);
276  a_high = std::max(a, a_high);
277 
278  b_low = std::min(b2, b_low);
279  b_high = std::max(b2, b_high);
280 
281  vision_->setThreshold(0, a_low, a_high, b_low, b_high);
282 
283  std::ostringstream stream;
284  stream << "( " << a_low << ":" << a_high << ", "
285  << b_low << ":" << b_high << " ) ";
286 
287  abText_->SetValue(wxString::FromAscii(stream.str().c_str()));
288 }
289 
290 void ColorGuiFrame::OnMouseWheel(wxMouseEvent &event)
291 {
292  if (event.GetWheelRotation() < 0)
293  scale_ *= 0.9;
294  else
295  scale_ *= 1.1;
296 
297  scale_pos_x_ = event.m_x;
298  scale_pos_y_ = event.m_y;
299 }
ColorGuiFrame::DrawImage
void DrawImage(const sensor_msgs::ImageConstPtr &msg)
Draw an image frame.
Definition: color_gui.cpp:140
ColorGuiFrame::height_
int height_
Definition: color_gui.h:88
ColorGuiFrame::OnQuit
void OnQuit(wxCommandEvent &event)
Quit callback.
Definition: color_gui.cpp:135
ColorGuiFrame::abText_
wxTextCtrl * abText_
Definition: color_gui.h:89
ColorGuiFrame::OnMouseWheel
void OnMouseWheel(wxMouseEvent &event)
Callback for zooming.
Definition: color_gui.cpp:290
boost::shared_ptr
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
ColorGuiFrame::vision_
CMVision * vision_
Definition: color_gui.h:99
ColorGuiFrame::OnClick
void OnClick(wxMouseEvent &event)
On image click callback.
Definition: color_gui.cpp:241
ColorGuiFrame::rgb_image_
unsigned char * rgb_image_
Definition: color_gui.h:93
CMVision::initialize
bool initialize(int nwidth, int nheight)
Definition: cmvision.cc:621
ros::spinOnce
ROSCPP_DECL void spinOnce()
rgb
Definition: cmvision.h:93
ColorGuiFrame::scale_
float scale_
Definition: color_gui.h:97
CMVision::setThreshold
bool setThreshold(int color, int a_low, int a_high, int b_low, int b_high)
Definition: cmvision.cc:880
CMVision::region
Definition: cmvision.h:110
max
num max(num a, num b)
Definition: cmvision.cc:57
CMVision::getThreshold
bool getThreshold(int color, int &a_low, int &a_high, int &b_low, int &b_high)
Definition: cmvision.cc:865
conversions.h
ColorGuiFrame::width_
int width_
Definition: color_gui.h:88
CMVision::getColorVisual
rgb getColorVisual(int color)
Definition: cmvision.h:211
ColorGuiApp::OnUpdate
void OnUpdate(wxTimerEvent &event)
On update, used for ros::spin.
Definition: color_gui.cpp:62
ColorGuiApp::imageCB
void imageCB(const sensor_msgs::ImageConstPtr &msg)
The image callback.
Definition: color_gui.cpp:67
ColorGuiFrame::ID_Reset
@ ID_Reset
Definition: color_gui.h:95
cv_bridge::toCvCopy
CvImagePtr toCvCopy(const sensor_msgs::CompressedImage &source, const std::string &encoding=std::string())
ColorGuiFrame::rgbText_
wxTextCtrl * rgbText_
Definition: color_gui.h:90
CMVision::region::next
region * next
Definition: cmvision.h:120
lab
Definition: cmvision.h:85
ColorGuiFrame::scale_pos_x_
int scale_pos_x_
Definition: color_gui.h:96
ColorGuiFrame::scale_pos_y_
int scale_pos_y_
Definition: color_gui.h:96
CMVision::region::x1
int x1
Definition: cmvision.h:113
ColorGuiFrame::lab_image_
unsigned char * lab_image_
Definition: color_gui.h:94
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
min
num min(num a, num b)
Definition: cmvision.cc:64
ColorGuiApp::update_timer_
wxTimer * update_timer_
Definition: color_gui.h:88
ColorGuiFrame::OnReset
void OnReset(wxCommandEvent &event)
Reset callback.
Definition: color_gui.cpp:234
ColorGuiApp::frame_
ColorGuiFrame * frame_
Definition: color_gui.h:89
CMVision::region::x2
int x2
Definition: cmvision.h:113
ColorGuiFrame::image_panel_
wxPanel * image_panel_
Definition: color_gui.h:91
CMVision::region::y1
int y1
Definition: cmvision.h:113
ColorGuiFrame::ColorGuiFrame
ColorGuiFrame()
Constructor.
Definition: color_gui.cpp:72
CMV_MAX_COLORS
#define CMV_MAX_COLORS
Definition: cmvision.h:68
CMVision::processFrame
bool processFrame(image_pixel *image)
Definition: cmvision.cc:906
ColorGuiFrame
Definition: color_gui.h:39
cv_bridge.h
ROS_ERROR
#define ROS_ERROR(...)
CMVision
Definition: cmvision.h:108
CMVision::getRegions
region * getRegions(int color_id)
Definition: cmvision.cc:970
ColorGuiApp::OnInit
bool OnInit()
On init of the application.
Definition: color_gui.cpp:38
color_gui.h
ColorGuiApp::image_subscriber_
ros::Subscriber image_subscriber_
Definition: color_gui.h:87
NULL
#define NULL
Definition: cmvision.h:82
ros::NodeHandle
CMVision::region::y2
int y2
Definition: cmvision.h:113


cmvision
Author(s): Nate Koenig, Nate Koenig
autogenerated on Wed Mar 2 2022 00:03:25