From: Pierre M. <sid...@us...> - 2005-06-02 16:58:38
|
Update of /cvsroot/robotflow/RobotFlow/Probes/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16024 Added Files: VisualROISelection.cc Log Message: New probe for selecting a region of interest in an image or video frame. --- NEW FILE: VisualROISelection.cc --- /* Copyright (C) 2004 Pierre Moisan (Pie...@US...) This library is free software; 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 2.1 of the License, or (at your option) any later version. This library 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _VISUALROISELECTION_CC_ #define _VISUALROISELECTION_CC_ #include "Object.h" #include "ObjectRef.h" #include "Exception.h" #include "Image.h" #include "BufferedNode.h" #include <gnome.h> #include <pthread.h> #include "gdk-pixbuf/gdk-pixbuf.h" #include "libgnomecanvas/gnome-canvas-pixbuf.h" #include "cv.h" #include "VisualROI.h" using namespace std; using namespace FD; namespace RobotFlow { //forward declaration class VisualROISelection; DECLARE_NODE(VisualROISelection) /*Node * @name VisualROISelection * @category RobotFlow:Probes * @description Region of interest selection interface * * @parameter_name WIDTH * @parameter_description The width of the video frame * @parameter_type int * @parameter_value 320 * * @parameter_name HEIGHT * @parameter_description The height of the video frame * @parameter_type int * @parameter_value 240 * * @parameter_name NUM_CHANNELS * @parameter_type int * @parameter_value 3 * @parameter_description Number of channels of the video frame. * * @input_name IN_IMAGE * @input_type Image * @input_description Current frame * * @output_name OUT_ROI * @output_type VisualROI * @output_description The user defined region of interest * END*/ class VisualROISelection : public BufferedNode { friend void on_save_button_clicked (GtkButton *button, VisualROISelection *cSelection); friend void on_show_button_clicked (GtkButton *button, VisualROISelection *cSelection); friend gboolean pixbuf_event_function (GnomeCanvasItem *canvasitem, GdkEvent *event, VisualROISelection *cSelection); public: VisualROISelection(string nodeName, ParameterSet params) : BufferedNode(nodeName, params), m_saving(false), m_show(true), m_skip(0), m_pixbuf_item(NULL), m_last_count(-1), m_roi(NULL) { // Buffered node inputs m_inImageID = addInput("IN_IMAGE"); // Buffered node inputs m_outROIID = addOutput("OUT_ROI"); m_width = dereference_cast<int>(parameters.get("WIDTH")); m_height = dereference_cast<int>(parameters.get("HEIGHT")); m_numChannels = dereference_cast<int>(parameters.get("NUM_CHANNELS")); m_numBytesInFrame = m_width*m_height*m_numChannels; m_roiColor[0] = 0; m_roiColor[1] = 0; m_roiColor[2] = 255; //create pixbuf m_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, m_width, m_height); CvSize size; size.width = m_width; size.height = m_height; m_curFrame = cvCreateImage(size, IPL_DEPTH_8U, m_numChannels); } virtual ~VisualROISelection() { gdk_threads_enter(); gtk_object_destroy(GTK_OBJECT(window1)); cvReleaseImage(&m_curFrame); delete m_roi; gdk_threads_leave(); } void initialize() { BufferedNode::initialize(); gdk_threads_enter(); window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_object_set_data (GTK_OBJECT (window1), "window1", window1); gtk_window_set_title (GTK_WINDOW (window1), _("window1")); vbox1 = gtk_vbox_new (FALSE, 0); gtk_widget_ref (vbox1); gtk_object_set_data_full (GTK_OBJECT (window1), "vbox1", vbox1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (vbox1); gtk_container_add (GTK_CONTAINER (window1), vbox1); vbox2 = gtk_vbox_new (FALSE, 0); gtk_widget_ref (vbox2); gtk_object_set_data_full (GTK_OBJECT (window1), "vbox2", vbox2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (vbox2); gtk_box_pack_start (GTK_BOX (vbox1), vbox2, TRUE, TRUE, 0); scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL); gtk_widget_ref (scrolledwindow2); gtk_object_set_data_full (GTK_OBJECT (window1), "scrolledwindow2", scrolledwindow2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (scrolledwindow2); gtk_box_pack_start (GTK_BOX (vbox2), scrolledwindow2, TRUE, TRUE, 0); gtk_widget_push_visual (gdk_rgb_get_visual()); gtk_widget_push_colormap (gdk_rgb_get_cmap()); canvas1 = gnome_canvas_new (); gtk_widget_pop_colormap (); gtk_widget_pop_visual (); gtk_widget_ref (canvas1); gtk_object_set_data_full (GTK_OBJECT (window1), "canvas1", canvas1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (canvas1); gtk_container_add (GTK_CONTAINER (scrolledwindow2), canvas1); gtk_widget_set_usize (canvas1, 320, 240); gtk_widget_set_events (canvas1, GDK_BUTTON1_MOTION_MASK); gtk_widget_set_extension_events (canvas1, GDK_EXTENSION_EVENTS_CURSOR); gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas1), 0, 0, 100, 100); hbox1 = gtk_hbox_new (FALSE, 0); gtk_widget_ref (hbox1); gtk_object_set_data_full (GTK_OBJECT (window1), "hbox1", hbox1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (hbox1); gtk_box_pack_start (GTK_BOX (vbox2), hbox1, TRUE, TRUE, 0); //SAVE save_button = gtk_button_new_with_label (_("Save")); gtk_widget_ref (save_button); gtk_object_set_data_full (GTK_OBJECT (window1), "save_button", save_button, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (save_button); gtk_box_pack_start (GTK_BOX (hbox1), save_button, FALSE, FALSE, 0); //SHOW BUTTON show_button = gtk_button_new_with_label (_("Show")); gtk_widget_ref (show_button); gtk_object_set_data_full (GTK_OBJECT (window1), "show_button", show_button, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (show_button); gtk_box_pack_start (GTK_BOX (hbox1), show_button, FALSE, TRUE, 0); //creating pixbuf item m_pixbuf_item = gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS(canvas1)), gnome_canvas_pixbuf_get_type(), "pixbuf",m_pixbuf,NULL); //update window size and position gtk_window_set_default_size (GTK_WINDOW(window1),min(m_width + 100,800), min(m_height + 200,600)); gtk_window_set_position (GTK_WINDOW(window1),GTK_WIN_POS_CENTER); //update the scrollbars gnome_canvas_set_scroll_region (GNOME_CANVAS(canvas1),0.0, 0.0, m_width, (double) m_height); //connecting signals gtk_signal_connect (GTK_OBJECT (save_button), "clicked", GTK_SIGNAL_FUNC (on_save_button_clicked), this); gtk_signal_connect (GTK_OBJECT (show_button), "clicked", GTK_SIGNAL_FUNC (on_show_button_clicked), this); gtk_signal_connect(GTK_OBJECT(m_pixbuf_item), "event", GTK_SIGNAL_FUNC(pixbuf_event_function), this); gtk_widget_show (window1); gdk_threads_leave(); } void display_pixbuf() { gdk_threads_enter(); if (!m_imageRef->isNil()) { // Getting image IplImage *my_image = m_curFrame; unsigned char *image_data = (unsigned char*) my_image->imageData; unsigned char *pixbuf_data = gdk_pixbuf_get_pixels(m_pixbuf); int num_channels = gdk_pixbuf_get_n_channels(m_pixbuf); //copying image data for (int i = 0; i < m_width * m_height; i++) { //RED or HUE pixbuf_data[2] = *image_data++; //GREEN or SATURATION pixbuf_data[1] = *image_data++; //BLUE or VALUE pixbuf_data[0] = *image_data++; //next pixbuf pixel pixbuf_data += num_channels; } //update canvas. gnome_canvas_request_redraw (GNOME_CANVAS(canvas1), 0, 0, m_width, m_height); } gdk_threads_leave(); } void calculate(int output_id, int count, Buffer &out) { try { m_imageRef = getInput(m_inImageID, count); // Verify input image sanity if (object_cast<Image>(m_imageRef).get_width() != m_width || object_cast<Image>(m_imageRef).get_height() != m_height || object_cast<Image>(m_imageRef).get_pixelsize() != m_numChannels) { throw new GeneralException ("VisualROISelection::calculate : image parameters do not correspond to given input.",__FILE__,__LINE__); } memcpy(m_curFrame->imageData, object_cast<Image>(m_imageRef).get_data(), m_numBytesInFrame); if (m_show && m_roi) { m_roi->DrawROI(m_curFrame, (const unsigned char *)m_roiColor); } if (m_saving) { // Set a new ROI delete m_roi; int hsX = (m_BBx2 - m_BBx1)/2; int hsY = (m_BBy2 - m_BBy1)/2; int xCen = m_BBx1+hsX+1; int yCen = m_BBy1+hsY+1; cout << "Creating a new ROI: xCen=" << xCen << " yCen=" << yCen << " hsX=" << hsX << " hsY=" << hsY << endl; m_roi = new VisualROI(e_VISUALROI_elliptical, xCen, yCen, hsX, hsY, 0); } /* if (m_last_count != count) { if (m_skip == 0) { display_pixbuf(); } else if (count % m_skip == 0) { display_pixbuf(); } m_last_count = count; } */ display_pixbuf(); if (m_saving && m_roi) { m_saving = false; VisualROI *outROI = new VisualROI(*m_roi); (*outputs[m_outROIID].buffer)[count] = ObjectRef(outROI); } else { (*outputs[m_outROIID].buffer)[count] = ObjectRef(nilObject); } }//try catch (BaseException *e) { throw e->add(new GeneralException("Exception in VisualROISelection::calculate:",__FILE__,__LINE__)); } } private: int m_inImageID; int m_outROIID; bool m_show; bool m_saving; int m_skip; int m_width; int m_height; int m_numChannels; int m_numBytesInFrame; int m_BBx1; int m_BBx2; int m_BBy1; int m_BBy2; unsigned char m_roiColor[3]; GtkWidget *window1; GtkWidget *vbox1; GtkWidget *vbox2; GtkWidget *scrolledwindow2; GtkWidget *canvas1; GtkWidget *hbox1; GtkWidget *save_button; GtkWidget *show_button; GnomeCanvasItem *m_pixbuf_item; GdkPixbuf *m_pixbuf; int m_last_count; ObjectRef m_imageRef; VisualROI *m_roi; IplImage *m_curFrame; }; void on_save_button_clicked (GtkButton *button, VisualROISelection *cSelection) { cSelection->m_saving = true; } void on_show_button_clicked (GtkButton *button, VisualROISelection *cSelection) { cSelection->m_show = !cSelection->m_show; } gboolean pixbuf_event_function( GnomeCanvasItem *canvasitem, GdkEvent *event, VisualROISelection *cSelection) { static double x,y; static GnomeCanvasItem *item = NULL; double item_x, item_y; double x1,y1,x2,y2; item_x = event->button.x; item_y = event->button.y; switch (event->type) { case GDK_BUTTON_PRESS: if(item) { gtk_object_destroy(GTK_OBJECT(item)); } if (!cSelection->m_imageRef->isNil()) { item = gnome_canvas_item_new ( gnome_canvas_root(GNOME_CANVAS(cSelection->canvas1)), gnome_canvas_ellipse_get_type(), "x1",item_x, "y1",item_y, "x2",item_x, "y2",item_y, "outline_color", "blue", NULL); x = item_x; y = item_y; } break; case GDK_MOTION_NOTIFY: if (event->motion.state & GDK_BUTTON1_MASK && item) { //resizing if (item_x > x) { gnome_canvas_item_set (item, "x2",item_x,NULL); } else { gnome_canvas_item_set (item, "x1",item_x,"x2",x,NULL); } if (item_y > y) { gnome_canvas_item_set (item, "y2",item_y,NULL); } else { gnome_canvas_item_set (item, "y1",item_y,"y2",y,NULL); } } break; case GDK_BUTTON_RELEASE: //destroying the rectangle if (item) { //getting image Image &my_image = object_cast<Image>(cSelection->m_imageRef); int width = my_image.get_width(); int height = my_image.get_height(); //getting rect boundaries gtk_object_get(GTK_OBJECT(item),"x1",&x1,"y1",&y1,"x2",&x2,"y2",&y2,NULL); cSelection->m_BBx1 = (int)max(x1,0.0); cSelection->m_BBy1 = (int)max(y1,0.0); cSelection->m_BBx2 = (int)min(x2,(double) width); cSelection->m_BBy2 = (int)min(y2,(double) height); gtk_object_destroy(GTK_OBJECT(item)); item = NULL; } break; case GDK_LEAVE_NOTIFY: break; default: break; } return TRUE; } } #endif |