diff --git a/Utilities/otbedison/GUI/BgImagPGM.cpp b/Utilities/otbedison/GUI/BgImagPGM.cpp old mode 100755 new mode 100644 index bfce6715c3cbed5b479d29cdcd1085c3470048f3..636622e9e724c016ff9e3ad9c0fedb5026a4b058 --- a/Utilities/otbedison/GUI/BgImagPGM.cpp +++ b/Utilities/otbedison/GUI/BgImagPGM.cpp @@ -8,33 +8,33 @@ // Modified by: Bogdan Georgescu // read gray pgm ///////////////////////////////////////////////////////////////////////////// - + #ifdef __GNUG__ #pragma implementation "BgImagPGM.h" #endif - + // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" - + #ifdef __BORLANDC__ #pragma hdrstop #endif - + #ifndef WX_PRECOMP #include "wx/setup.h" #endif - + #include "BgImagPGM.h" #include <wx/log.h> #include <wx/intl.h> #include <wx/txtstrm.h> - + //----------------------------------------------------------------------------- // bgPGMHandler //----------------------------------------------------------------------------- - + IMPLEMENT_DYNAMIC_CLASS(bgPGMHandler,wxImageHandler) - + void bgPGMHandler::Skip_Comment(wxInputStream &stream) { wxTextInputStream text_stream(stream); @@ -44,18 +44,18 @@ void bgPGMHandler::Skip_Comment(wxInputStream &stream) Skip_Comment(stream); } } - + bool bgPGMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) ) { wxUint32 width, height; wxUint16 maxval; char c(0); image->Destroy(); - + /* * Read the PGM header */ - + wxBufferedInputStream buf_stream(stream); wxTextInputStream text_stream(buf_stream); Skip_Comment(buf_stream); @@ -96,11 +96,11 @@ bool bgPGMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose *ptr++=(unsigned char)value; *ptr++=(unsigned char)value; *ptr++=(unsigned char)value; -#if wxCHECK_VERSION(2, 3, 0) - if (!buf_stream) -#else - if (buf_stream.LastError()!=wxSTREAM_NOERROR) -#endif +#if wxCHECK_VERSION(2, 3, 0) + if (!buf_stream) +#else + if (buf_stream.LastError()!=wxSTREAM_NOERROR) +#endif { if (verbose) wxLogError(_("PNM: File seems truncated.")); return FALSE; @@ -122,26 +122,26 @@ bool bgPGMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose } } image->SetMask( FALSE ); -#if wxCHECK_VERSION(2, 3, 0) - const wxStreamError err = buf_stream.GetLastError(); - return err == wxSTREAM_NO_ERROR || err == wxSTREAM_EOF; -#else - return (buf_stream.LastError()==wxStream_NOERROR || buf_stream.LastError()==wxStream_EOF); -#endif +#if wxCHECK_VERSION(2, 3, 0) + const wxStreamError err = buf_stream.GetLastError(); + return err == wxSTREAM_NO_ERROR || err == wxSTREAM_EOF; +#else + return (buf_stream.LastError()==wxStream_NOERROR || buf_stream.LastError()==wxStream_EOF); +#endif } - + bool bgPGMHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool WXUNUSED(verbose) ) { //wxTextOutputStream text_stream(stream); //text_stream << "P5" << endl //<< image->GetWidth() << " " << image->GetHeight() << endl //<< "255" << endl; - char header[70]; - int width, height; - width = image->GetWidth(); - height = image->GetHeight(); - sprintf(header, "P5\n%d %d\n255\n", width, height); - stream.Write(header, strlen(header)); + char header[70]; + int width, height; + width = image->GetWidth(); + height = image->GetHeight(); + sprintf(header, "P5\n%d %d\n255\n", width, height); + stream.Write(header, strlen(header)); unsigned char *ptr = image->GetData(); // convert it to bw; unsigned char *tptr; @@ -155,13 +155,13 @@ bool bgPGMHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool WXUNUS } stream.Write(tptr,width*height); delete [] tptr; -#if wxCHECK_VERSION(2, 3, 0) - return stream.IsOk(); -#else - return (stream.LastError()==wxStream_NOERROR); -#endif +#if wxCHECK_VERSION(2, 3, 0) + return stream.IsOk(); +#else + return (stream.LastError()==wxStream_NOERROR); +#endif } - + bool bgPGMHandler::DoCanRead( wxInputStream& stream ) { off_t pos = stream.TellI(); diff --git a/Utilities/otbedison/GUI/BgImagPGM.h b/Utilities/otbedison/GUI/BgImagPGM.h old mode 100755 new mode 100644 index 8c4c3be24ed1a319afcb2573b99ab7d1ff03d8b6..637b46b1e5f5f7eb3864c83af6ee0dd00577a4c2 --- a/Utilities/otbedison/GUI/BgImagPGM.h +++ b/Utilities/otbedison/GUI/BgImagPGM.h @@ -8,29 +8,29 @@ // Modified by: Bogdan Georgescu // read gray pgm ///////////////////////////////////////////////////////////////////////////// - + #ifndef _BG_IMAGPGM_H_ #define _BG_IMAGPGM_H_ - + #ifdef __GNUG__ #pragma interface "BgImagPGM.h" #endif - + #include <wx/image.h> - + //----------------------------------------------------------------------------- // bgPGMHandler //----------------------------------------------------------------------------- - + #define RED_WEIGHT 0.299 #define GREEN_WEIGHT 0.587 #define BLUE_WEIGHT 0.114 - + class bgPGMHandler : public wxImageHandler { - + DECLARE_DYNAMIC_CLASS(bgPGMHandler) - + public: inline bgPGMHandler() { @@ -39,14 +39,14 @@ public: m_type = wxBITMAP_TYPE_ANY; m_mime = "image/pgm"; }; - + virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=TRUE, int index=0 ); virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=TRUE ); virtual bool DoCanRead( wxInputStream& stream ); - + void Skip_Comment(wxInputStream &stream); }; - + #endif - + // _BG_IMAGPGM_H_ \ No newline at end of file diff --git a/Utilities/otbedison/GUI/BgImagPNM.cpp b/Utilities/otbedison/GUI/BgImagPNM.cpp old mode 100755 new mode 100644 index 6fa2dff057097125c792354fca8f9f2ba9e23308..97bcdf2f6ee0a85c097882e2ae6f895cef2a2788 --- a/Utilities/otbedison/GUI/BgImagPNM.cpp +++ b/Utilities/otbedison/GUI/BgImagPNM.cpp @@ -8,35 +8,35 @@ // Modified by: Chris M. Christoudias // read/write pnm images ///////////////////////////////////////////////////////////////////////////// - + #ifdef __GNUG__ #pragma implementation "BgImagPNM.h" #endif - + // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" - + #ifdef __BORLANDC__ #pragma hdrstop #endif - + #ifndef WX_PRECOMP #include "wx/setup.h" #endif - + #include "BgImagPNM.h" #include <wx/log.h> #include <wx/intl.h> #include <wx/txtstrm.h> -#include <string.h> -#include <stdio.h> - +#include <string.h> +#include <stdio.h> + //----------------------------------------------------------------------------- // bgPGMHandler //----------------------------------------------------------------------------- - + IMPLEMENT_DYNAMIC_CLASS(bgPNMHandler,wxImageHandler) - + void bgPNMHandler::Skip_Comment(wxInputStream &stream) { wxTextInputStream text_stream(stream); @@ -46,24 +46,24 @@ void bgPNMHandler::Skip_Comment(wxInputStream &stream) Skip_Comment(stream); } } - + bool bgPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) ) { wxUint32 width, height; wxUint16 maxval; char c(0); image->Destroy(); - + /* * Read the PGM header */ - + wxBufferedInputStream buf_stream(stream); wxTextInputStream text_stream(buf_stream); Skip_Comment(buf_stream); if (buf_stream.GetC()==wxT('P')) c=buf_stream.GetC(); switch (c) - { + { case wxT('2'): case wxT('5'): case wxT('6'): break; @@ -97,11 +97,11 @@ bool bgPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose *ptr++=(unsigned char)value; *ptr++=(unsigned char)value; *ptr++=(unsigned char)value; -#if wxCHECK_VERSION(2, 3, 0) - if (!buf_stream) -#else - if (buf_stream.LastError()!=wxSTREAM_NOERROR) -#endif +#if wxCHECK_VERSION(2, 3, 0) + if (!buf_stream) +#else + if (buf_stream.LastError()!=wxSTREAM_NOERROR) +#endif { if (verbose) wxLogError(_("PNM: File seems truncated.")); return FALSE; @@ -121,37 +121,37 @@ bool bgPNMHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose ptr[idx--] = ptr[i]; ptr[idx--] = ptr[i]; } - } - if (c=='6') // Raw color - { - buf_stream.Read( ptr, width*height*3 ); - } + } + if (c=='6') // Raw color + { + buf_stream.Read( ptr, width*height*3 ); + } image->SetMask( FALSE ); -#if wxCHECK_VERSION(2, 3, 0) - const wxStreamError err = buf_stream.GetLastError(); - return err == wxSTREAM_NO_ERROR || err == wxSTREAM_EOF; -#else - return (buf_stream.LastError()==wxStream_NOERROR || buf_stream.LastError()==wxStream_EOF); -#endif +#if wxCHECK_VERSION(2, 3, 0) + const wxStreamError err = buf_stream.GetLastError(); + return err == wxSTREAM_NO_ERROR || err == wxSTREAM_EOF; +#else + return (buf_stream.LastError()==wxStream_NOERROR || buf_stream.LastError()==wxStream_EOF); +#endif } - + bool bgPNMHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool WXUNUSED(verbose) ) { - char header[70]; - int width, height; - width = image->GetWidth(); - height = image->GetHeight(); - sprintf(header, "P6\n%d %d\n255\n", width, height); + char header[70]; + int width, height; + width = image->GetWidth(); + height = image->GetHeight(); + sprintf(header, "P6\n%d %d\n255\n", width, height); stream.Write(header, strlen(header)); unsigned char *ptr = image->GetData(); stream.Write(ptr,width*height*3); -#if wxCHECK_VERSION(2, 3, 0) - return stream.IsOk(); -#else - return (stream.LastError()==wxStream_NOERROR); -#endif +#if wxCHECK_VERSION(2, 3, 0) + return stream.IsOk(); +#else + return (stream.LastError()==wxStream_NOERROR); +#endif } - + bool bgPNMHandler::DoCanRead( wxInputStream& stream ) { off_t pos = stream.TellI(); @@ -161,7 +161,7 @@ bool bgPNMHandler::DoCanRead( wxInputStream& stream ) switch (stream.GetC()) { case '2': - case '5': + case '5': case '6': stream.SeekI(pos); return TRUE; diff --git a/Utilities/otbedison/GUI/BgImagPNM.h b/Utilities/otbedison/GUI/BgImagPNM.h old mode 100755 new mode 100644 index adcbfcfd75c840fb5ac02c69d7f667a15fd22930..e75744728c2e36ade9ad32bb2f85d37329178ded --- a/Utilities/otbedison/GUI/BgImagPNM.h +++ b/Utilities/otbedison/GUI/BgImagPNM.h @@ -8,20 +8,20 @@ // Modified by: Chris M. Christoudias // read/write pnm image ///////////////////////////////////////////////////////////////////////////// - + #ifndef _BG_IMAGPNM_H_ #define _BG_IMAGPNM_H_ - + #ifdef __GNUG__ #pragma interface "BgImagPNM.h" #endif - + #include <wx/image.h> - + //----------------------------------------------------------------------------- // bgPGMHandler //----------------------------------------------------------------------------- - + class bgPNMHandler : public wxImageHandler { DECLARE_DYNAMIC_CLASS(bgPNMHandler) @@ -33,12 +33,12 @@ public: m_type = wxBITMAP_TYPE_PNM; m_mime = "image/pnm"; }; - + virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=TRUE, int index=0 ); virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=TRUE ); virtual bool DoCanRead( wxInputStream& stream ); - + void Skip_Comment(wxInputStream &stream); }; - -#endif + +#endif diff --git a/Utilities/otbedison/GUI/bgimsystem.cpp b/Utilities/otbedison/GUI/bgimsystem.cpp old mode 100755 new mode 100644 index 39481dfb20c70ca4b15281aea85e92420456d9f0..a57939d2c1e37ec84c3ad5b16472e686de315788 --- a/Utilities/otbedison/GUI/bgimsystem.cpp +++ b/Utilities/otbedison/GUI/bgimsystem.cpp @@ -1,8229 +1,8229 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: bgimsystem.cpp -// Purpose: Image processing system -// Author: Bogdan Georgescu, Chris M. Christoudias -// Modified by: -// Created: 06/22/2000 -// Copyright: (c) Bogdan Georgescu, Chris M. Christoudias -// Version: v0.1 -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ - #pragma hdrstop -#endif - -#ifndef WX_PRECOMP - #include "wx/wx.h" -#endif - -#include <wx/toolbar.h> -#include <wx/progdlg.h> - -#if defined(__WXGTK__) || defined(__WXMOTIF__) - #include "icons/mondrian.xpm" - #include "icons/new.xpm" - #include "icons/open.xpm" - #include "icons/save.xpm" - #include "icons/copy.xpm" - #include "icons/cut.xpm" - #include "icons/paste.xpm" - #include "icons/print.xpm" - #include "icons/help.xpm" -#endif - -#include <wx/html/htmlwin.h> - -#include "BgImagPGM.h" -#include "BgImagPNM.h" - -// Edge detection include stuff -#include <math.h> -#include "BgImage.h" -#include "BgEdge.h" -#include "BgEdgeList.h" -#include "BgEdgeDetect.h" -#include "BgDefaults.h" - -#include "msImageProcessor.h" - -#include <stdio.h> -#include <string.h> -#include "bgimsystem.h" - -IMPLEMENT_APP(BgApp) -// --------------------------------------------------------------------------- -// global variables -// --------------------------------------------------------------------------- - -BgMdiFrame *g_frame = (BgMdiFrame *) NULL; -wxList g_children; - -// For drawing lines in a canvas -static long g_xpos = -1; -static long g_ypos = -1; - -static int gs_nFrames = 0; -static bool on_exit = false; -#define DEFAULT_LOG_SIZE 100 - -// --------------------------------------------------------------------------- -// event tables -// --------------------------------------------------------------------------- - -BEGIN_EVENT_TABLE(BgMdiFrame, wxMDIParentFrame) -EVT_MENU(BG_ABOUT, BgMdiFrame::OnAbout) -EVT_MENU(BG_HELP, BgMdiFrame::OnHelp) -EVT_MENU(BG_QUIT, BgMdiFrame::OnQuit) -EVT_MENU(BG_NEW_EDGE_WINDOW, BgMdiFrame::OnNewEdgeWindow) -EVT_MENU(BG_NEW_SEGM_WINDOW, BgMdiFrame::OnNewSegmWindow) -EVT_MENU(BG_LOAD_IMAGE, BgMdiFrame::OnLoadImage) -EVT_MENU(BG_LOAD_IMAGE_EDGE, BgMdiFrame::OnLoadImageEdge) -EVT_MENU(BG_SEGM_LOAD_IMAGE, BgMdiFrame::OnLoadImageSegm) -EVT_MENU(BG_SAVE_RESULT, BgMdiFrame::OnSaveResult) -EVT_MENU(BG_CROSS, BgMdiFrame::ZoomControl) -EVT_MENU(BG_ZOOM_IN, BgMdiFrame::ZoomControl) -EVT_MENU(BG_ZOOM_OUT, BgMdiFrame::ZoomControl) -EVT_MENU(BG_POINTER, BgMdiFrame::ZoomControl) -EVT_CLOSE(BgMdiFrame::OnClose) - -EVT_SIZE(BgMdiFrame::OnSize) -END_EVENT_TABLE() - -// Note that BG_NEW_WINDOW and BG_ABOUT commands get passed -// to the parent window for processing, so no need to -// duplicate event handlers here. - -BEGIN_EVENT_TABLE(BgMdiEdgeChild, wxMDIChildFrame) -EVT_MENU(BG_LOAD_IMAGE_EDGE, BgMdiEdgeChild::OnLoadImage) -EVT_MENU(BG_EDGE_DETECT, BgMdiEdgeChild::OnEdgeDetect) -EVT_MENU(BG_CHANGE_PARAM_EDGE, BgMdiEdgeChild::OnChangeParam) -EVT_MENU(BG_CHILD_EDGE_QUIT, BgMdiEdgeChild::OnQuit) -EVT_MENU(BG_EDGE_VIEW_ORIG, BgMdiEdgeChild::OnViewOrig) -EVT_MENU(BG_EDGE_VIEW_EDGE, BgMdiEdgeChild::OnViewEdge) -EVT_MENU(BG_EDGE_SAVE_MAP, BgMdiEdgeChild::OnSaveEdgeMap) - -EVT_SET_FOCUS(BgMdiEdgeChild::OnFocus) -EVT_CLOSE(BgMdiEdgeChild::OnClose) -EVT_SIZE(BgMdiEdgeChild::OnSize) - -EVT_BUTTON(BG_EDGE_DETECT, BgMdiEdgeChild::OnEdgeDetect) -EVT_BUTTON(BG_CHANGE_PARAM_EDGE, BgMdiEdgeChild::OnChangeParam) -EVT_CHECKBOX(BG_EDGE_CVIEW_ORIG, BgMdiEdgeChild::OnCViewOrig) -EVT_CHECKBOX(BG_EDGE_CVIEW_EDGE, BgMdiEdgeChild::OnCViewEdge) - -EVT_COMMAND(BG_EVENT_UPDATE_ID, BG_EVENT_UPDATE, BgMdiEdgeChild::OnUpdateNum) - -END_EVENT_TABLE() - -BEGIN_EVENT_TABLE(BgMdiSegmentChild, wxMDIChildFrame) -EVT_MENU(BG_SEGM_LOAD_IMAGE, BgMdiSegmentChild::OnLoadImage) -EVT_MENU(BG_SEGM_SAVE_SEGMENTED, BgMdiSegmentChild::OnSaveSegmentedImage) -EVT_MENU(BG_SEGM_SAVE_EDGEMAP, BgMdiSegmentChild::OnSaveBoundaries) -EVT_MENU(BG_CHILD_SEGM_QUIT, BgMdiSegmentChild::OnQuit) -EVT_MENU(BG_SEGM_SEGMENT, BgMdiSegmentChild::OnSegment) -EVT_MENU(BG_SEGM_LOAD_MAP, BgMdiSegmentChild::LoadCustomWeightMap) -EVT_MENU(BG_SEGM_SPEEDUP_NONE, BgMdiSegmentChild::OnUpdateSpeedUpLevel) -EVT_MENU(BG_SEGM_SPEEDUP_MEDM, BgMdiSegmentChild::OnUpdateSpeedUpLevel) -EVT_MENU(BG_SEGM_SPEEDUP_HIGH, BgMdiSegmentChild::OnUpdateSpeedUpLevel) -EVT_MENU(BG_CANVAS_VIEW1_GRADMAP, BgMdiSegmentChild::OnUpdatePlotWindow1) -EVT_MENU(BG_CANVAS_VIEW1_CONFMAP, BgMdiSegmentChild::OnUpdatePlotWindow1) -EVT_MENU(BG_CANVAS_VIEW1_WEITMAP, BgMdiSegmentChild::OnUpdatePlotWindow1) -EVT_MENU(BG_CANVAS_VIEW1_CUSTMAP, BgMdiSegmentChild::OnUpdatePlotWindow1) -EVT_MENU(BG_CANVAS_VIEW2_GRADMAP, BgMdiSegmentChild::OnUpdatePlotWindow2) -EVT_MENU(BG_CANVAS_VIEW2_CONFMAP, BgMdiSegmentChild::OnUpdatePlotWindow2) -EVT_MENU(BG_CANVAS_VIEW2_WEITMAP, BgMdiSegmentChild::OnUpdatePlotWindow2) -EVT_MENU(BG_CANVAS_VIEW2_CUSTMAP, BgMdiSegmentChild::OnUpdatePlotWindow2) -EVT_MENU(BG_CANVAS_SAVE_GRADMAP, BgMdiSegmentChild::OnSaveEdgeInformation) -EVT_MENU(BG_CANVAS_SAVE_CONFMAP, BgMdiSegmentChild::OnSaveEdgeInformation) -EVT_MENU(BG_CANVAS_SAVE_WEITMAP, BgMdiSegmentChild::OnSaveEdgeInformation) - -EVT_SET_FOCUS(BgMdiSegmentChild::OnFocus) -EVT_CLOSE(BgMdiSegmentChild::OnClose) -EVT_SIZE(BgMdiSegmentChild::OnSize) - -EVT_BUTTON(BG_SEGM_LOAD_IMAGE, BgMdiSegmentChild::OnLoadImage) -EVT_BUTTON(BG_SEGM_SEGMENT, BgMdiSegmentChild::OnSegment) -EVT_BUTTON(BG_SEGM_LOAD_MAP, BgMdiSegmentChild::LoadCustomWeightMap) -EVT_RADIOBOX(BG_SEGM_VIEW_IMSEG, BgMdiSegmentChild::OnViewImSeg) -EVT_RADIOBOX(BG_SEGM_OPERATION, BgMdiSegmentChild::OnChangeOperation) -EVT_CHECKBOX(BG_SEGM_VIEW_EDGES, BgMdiSegmentChild::OnViewBoundaries) -EVT_CHECKBOX(BG_SEGM_USE_EDGE_MAP, BgMdiSegmentChild::OnUseWeightMap) -EVT_COMBOBOX(BG_SEGM_CHANGE_PARAMS, BgMdiSegmentChild::OnChangeParameters) - -EVT_TEXT(BG_SEGM_TEXT_SIGMAS, BgMdiSegmentChild::OnUpdateTextBoxes) -EVT_TEXT(BG_SEGM_TEXT_SIGMAR, BgMdiSegmentChild::OnUpdateTextBoxes) -EVT_TEXT(BG_SEGM_TEXT_MINREG, BgMdiSegmentChild::OnUpdateTextBoxes) -EVT_TEXT(BG_SEGM_TEXT_GRADWIN, BgMdiSegmentChild::OnUpdateTextBoxes) -EVT_TEXT(BG_SEGM_TEXT_AIJ, BgMdiSegmentChild::OnUpdateTextBoxes) -EVT_TEXT(BG_SEGM_TEXT_EPSILON, BgMdiSegmentChild::OnUpdateTextBoxes) - -END_EVENT_TABLE() - -BEGIN_EVENT_TABLE(BgImCanvas, wxScrolledWindow) -EVT_RIGHT_DOWN(BgImCanvas::OnMouseRightDown) -EVT_MOUSE_EVENTS(BgImCanvas::OnEvent) - -EVT_MENU(BG_IMC_ADDNODE, BgImCanvas::OnCustomAddNode) -EVT_MENU(BG_IMC_DELETENODE, BgImCanvas::OnCustomDeleteNode) -EVT_MENU(BG_IMC_SELTYPE_ELLIPSE, BgImCanvas::OnCTypeEllipse) -EVT_MENU(BG_IMC_SELTYPE_VLINE, BgImCanvas::OnCTypeVLine) -EVT_MENU(BG_IMC_SELTYPE_HLINE, BgImCanvas::OnCTypeHLine) -EVT_MENU(BG_IMC_SELTYPE_LINE, BgImCanvas::OnCTypeLine) -EVT_MENU(BG_IMC_SELTYPE_BOX, BgImCanvas::OnCTypeBox) -EVT_MENU(BG_IMC_SELTYPE_CUSTOM, BgImCanvas::OnCTypeCustom) - -//EVT_SCROLLWIN(BgImCanvas::OnScroll) - -END_EVENT_TABLE() - -BEGIN_EVENT_TABLE(BgParamDialog, wxDialog) -EVT_BUTTON(BG_PARAMD_OK, BgParamDialog::OnOk) -EVT_BUTTON(BG_PARAMD_CANCEL, BgParamDialog::OnCancel) -END_EVENT_TABLE() - -BEGIN_EVENT_TABLE(BgSpeedSelect, wxDialog) -EVT_BUTTON(BG_SPEEDSEL_OK, BgSpeedSelect::OnOk) -EVT_BUTTON(BG_SPEEDSEL_CANCEL, BgSpeedSelect::OnCancel) -END_EVENT_TABLE() - -BEGIN_EVENT_TABLE(BgDialog, wxDialog) -EVT_BUTTON(BG_DIALOG_OK, BgDialog::OnExit) -EVT_PAINT(BgDialog::OnPaint) -END_EVENT_TABLE() - -BEGIN_EVENT_TABLE(BgHoverBar, wxWindow) -EVT_BUTTON(BG_CANVAS_VIEW_BUTTON, BgHoverBar::ShowMenu) -EVT_BUTTON(BG_CANVAS_SAVE_BUTTON, BgHoverBar::ShowMenu) -END_EVENT_TABLE() - -BEGIN_EVENT_TABLE(BgMenuPanel, wxPanel) -EVT_BUTTON(BG_CANVAS_VIEW_BUTTON, BgMenuPanel::ShowMenu) -EVT_BUTTON(BG_CANVAS_SAVE_BUTTON, BgMenuPanel::ShowMenu) -EVT_SIZE(BgMenuPanel::OnSize) -END_EVENT_TABLE() - -// =========================================================================== -// implementation -// =========================================================================== - -// --------------------------------------------------------------------------- -// Global Data used for Multi-Threaded Enviornment -// --------------------------------------------------------------------------- - -bool stop_flag; -int percentDone; - -// --------------------------------------------------------------------------- -// Log function -// --------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- -// wxLogTextCtrl implementation -// ---------------------------------------------------------------------------- - -bgLogTextCtrl::bgLogTextCtrl(wxTextCtrl *pTextCtrl) -{ - m_pTextCtrl = pTextCtrl; -} - -void bgLogTextCtrl::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) -{ - wxString msg; - TimeStamp(&msg); - msg << szString; - - m_pTextCtrl->AppendText(msg); -} - -#define VAR_LOG_BUFFER_SIZE (4096) - -static wxChar varszBuf[VAR_LOG_BUFFER_SIZE]; - -FILE* glogfile; - -void bgLog(const char* szFormat, ...) -{ - va_list argptr; - va_start(argptr, szFormat); - wxVsnprintf(varszBuf, WXSIZEOF(varszBuf), szFormat, argptr); - va_end(argptr); - ::wxLogMessage(varszBuf); - bgLogFile(varszBuf); -} - -void bgLogVar(const char* first, va_list alist) -{ -// va_start(alist, first); - wxVsnprintf(varszBuf, WXSIZEOF(varszBuf), first, alist); -// va_end(alist); - ::wxLogMessage(varszBuf); - bgLogFile(varszBuf); -} - -void bgLogFile(const char* szFormat, ...) -{ - if (glogfile == 0) - glogfile = fopen("filelog.txt", "w"); - va_list argptr; - va_start(argptr, szFormat); - vfprintf(glogfile, szFormat, argptr); - va_end(argptr); - fflush(glogfile); -} - -inline int bgRound(double inline_x) -{ - return ((int) (inline_x+0.5)); -} - -// --------------------------------------------------------------------------- -// BgApp -// --------------------------------------------------------------------------- - -// Initialise this in OnInit, not statically -bool BgApp::OnInit() -{ - // Create the main frame window - - g_frame = new BgMdiFrame((wxFrame *)NULL, -1, "Edge Detection and Image SegmentatiON System (EDISON)", - wxPoint(10, 10), wxSize(1024, 768), - wxDEFAULT_FRAME_STYLE | wxHSCROLL | wxVSCROLL); -#ifdef __WXMSW__ -#if 0 - // Experimental: change the window menu - wxMenu* windowMenu = new wxMenu; - windowMenu->Append(5000, "My menu item!"); - frame->SetWindowMenu(windowMenu); -#endif -#endif - - // Give it an icon -#ifdef __WXMSW__ - g_frame->SetIcon(wxIcon("bg_icn")); -#else - g_frame->SetIcon(wxIcon( mondrian_xpm )); -#endif - - // Make a menubar - wxMenu *file_menu = new wxMenu; - - file_menu->Append(BG_NEW_EDGE_WINDOW, "New &edge window\tAlt-E", "Create a new edge detect window"); - file_menu->Append(BG_NEW_SEGM_WINDOW, "New &segment window\tAlt-S", "Create a new segmentation window"); - file_menu->Append(BG_LOAD_IMAGE_EDGE, "&Load edge image\tCtrl-L", "Load a new image to perform edge detection"); - file_menu->Append(BG_SEGM_LOAD_IMAGE, "&Load segment image\tShift-L", "Load a new image to perform segmentation"); - file_menu->Append(BG_QUIT, "E&xit\tAlt-X", "Quit the program"); - - wxMenu *help_menu = new wxMenu; - help_menu->Append(BG_ABOUT, "&About"); - help_menu->Append(BG_HELP, "&Help\tCtrl-H"); - - wxMenuBar *menu_bar = new wxMenuBar; - - menu_bar->Append(file_menu, "&File"); - menu_bar->Append(help_menu, "&Help"); - - // Associate the menu bar with the frame - g_frame->SetMenuBar(menu_bar); - - g_frame->CreateStatusBar(); - - g_frame->Show(TRUE); - - SetTopWindow(g_frame); - -#if wxUSE_LIBPNG - wxImage::AddHandler( new wxPNGHandler ); -#endif - -#if wxUSE_LIBJPEG - wxImage::AddHandler( new wxJPEGHandler ); -#endif - -#if wxUSE_LIBTIFF - wxImage::AddHandler( new wxTIFFHandler ); -#endif - -#if wxUSE_GIF - wxImage::AddHandler( new wxGIFHandler ); -#endif - -#if wxUSE_PCX - wxImage::AddHandler( new wxPCXHandler ); -#endif - - wxImage::AddHandler( new bgPNMHandler ); - wxImage::AddHandler( new bgPGMHandler ); - return TRUE; -} - -// --------------------------------------------------------------------------- -// BgMdiFrame -// --------------------------------------------------------------------------- - -// Define my frame constructor -BgMdiFrame::BgMdiFrame(wxWindow *parent, - const wxWindowID id, - const wxString& title, - const wxPoint& pos, - const wxSize& size, - const long style) - : wxMDIParentFrame(parent, id, title, pos, size, style) -{ - logtext_ = new wxTextCtrl(this, -1, "Log window.\n", - wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY); - logtext_->SetBackgroundColour("wheat"); - bglogctrl_ = new bgLogTextCtrl(logtext_); - logTargetOld_ = wxLog::SetActiveTarget(bglogctrl_); - logsize_ = DEFAULT_LOG_SIZE; - - CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL); - InitToolBar(GetToolBar()); - - //get program location directory - strcpy(programDir_, wxGetCwd()); - - //get help directory location - //(NOTE: This code must be altered to function properly in UNIX.) - strcpy(helpDir_, programDir_); - strcat(helpDir_, "\\doc\\help.html"); - - // Accelerators - wxAcceleratorEntry entries[13]; - entries[0].Set(wxACCEL_ALT, (int) 'E', BG_NEW_EDGE_WINDOW); - entries[1].Set(wxACCEL_ALT, (int) 'S', BG_NEW_SEGM_WINDOW); - entries[2].Set(wxACCEL_ALT, (int) 'X', BG_QUIT); - entries[3].Set(wxACCEL_ALT, (int) 'C', BG_CHILD_EDGE_QUIT); - entries[4].Set(wxACCEL_SHIFT, (int) 'C', BG_CHILD_SEGM_QUIT); - entries[5].Set(wxACCEL_CTRL, (int) 'H', BG_HELP); - entries[6].Set(wxACCEL_CTRL, (int) 'S', BG_EDGE_SAVE_MAP); - entries[7].Set(wxACCEL_SHIFT, (int) 'S', BG_SEGM_SAVE_SEGMENTED); - entries[8].Set(wxACCEL_CTRL, (int) 'L', BG_LOAD_IMAGE_EDGE); - entries[9].Set(wxACCEL_SHIFT, (int) 'L', BG_SEGM_LOAD_IMAGE); - entries[10].Set(wxACCEL_SHIFT, (int) 'M', BG_SEGM_LOAD_MAP); - entries[11].Set(wxACCEL_CTRL, (int) 'R', BG_EDGE_DETECT); - entries[12].Set(wxACCEL_SHIFT, (int) 'R', BG_SEGM_SEGMENT); - wxAcceleratorTable accel(13, entries); - SetAcceleratorTable(accel); - - // bgFileLog - //glogfile = fopen("filelog.txt", "w"); - glogfile = 0; -} - -void BgMdiFrame::OnClose(wxCloseEvent& event) -{ - if ( event.CanVeto() && (gs_nFrames > 0) ) - { - wxString msg; - if (gs_nFrames == 1) - msg.Printf(_T("%d window still open, close anyhow?"), gs_nFrames); - else - msg.Printf(_T("%d windows still open, close anyhow?"), gs_nFrames); - if ( wxMessageBox(msg, "Please confirm", - wxICON_QUESTION | wxYES_NO) != wxYES ) - { - event.Veto(); - - return; - } - } - - //indicate that the system is exiting - on_exit = true; - - wxLog::SetActiveTarget(logTargetOld_); - delete bglogctrl_; - delete logtext_; - - // bgFileLog - if (glogfile != 0) - fclose(glogfile); - - event.Skip(); -} - -//sets the title of the active child frame -void BgMdiFrame::SetChildTitle(wxMDIChildFrame *activeChild, int zconst, int maxZoom, int minZoom) -{ - wxString title; - if(activeChild->GetId() == BG_EDGE_WINDOW) - { - BgMdiEdgeChild *edgeChild = (BgMdiEdgeChild *) activeChild; - if(maxZoom) - title.Printf(_T("Edge Detection Frame %d - %s (%d x %d) x %d [Maximum Zoom]"), edgeChild->window_number_, edgeChild->filename_, edgeChild->width_, edgeChild->height_, zconst); - else if(minZoom) - title.Printf(_T("Edge Detection Frame %d - %s (%d x %d) [Original Image]"), edgeChild->window_number_, edgeChild->filename_, edgeChild->width_, edgeChild->height_); - else - title.Printf(_T("Edge Detection Frame %d - %s (%d x %d) x %d [Zoom]"), edgeChild->window_number_, edgeChild->filename_, edgeChild->width_, edgeChild->height_, zconst); - } - else if(activeChild->GetId() == BG_SEGM_WINDOW) - { - BgMdiSegmentChild *segmChild = (BgMdiSegmentChild *) activeChild; - if(maxZoom) - title.Printf(_T("Segmentation Frame %d - %s (%d x %d) x %d [Maximum Zoom]"), segmChild->window_number_, segmChild->filename_, segmChild->width_, segmChild->height_, zconst); - else if(minZoom) - title.Printf(_T("Segmentation Frame %d - %s (%d x %d) [Original Image]"), segmChild->window_number_, segmChild->filename_, segmChild->width_, segmChild->height_); - else - title.Printf(_T("Segmentation Frame %d - %s (%d x %d) x %d [Zoom]"), segmChild->window_number_, segmChild->filename_, segmChild->width_, segmChild->height_, zconst); - } - activeChild->SetTitle(title); - return; -} - -//updates toolbar when maximum zoom occurs -void BgMdiFrame::UpdateZoomControl(wxMDIChildFrame *activeChild, int maxZoom, int minZoom) -{ - if(activeChild->GetId() == BG_EDGE_WINDOW) - { - if(maxZoom) - ((BgMdiEdgeChild *) activeChild)->maxZoom_ = true; - else - ((BgMdiEdgeChild *) activeChild)->maxZoom_ = false; - if(minZoom) - ((BgMdiEdgeChild *) activeChild)->minZoom_ = true; - else - ((BgMdiEdgeChild *) activeChild)->minZoom_ = false; - ((BgMdiEdgeChild *) activeChild)->UpdateZoomControl(); - } - else if (activeChild->GetId() == BG_SEGM_WINDOW) - { - if(maxZoom) - ((BgMdiSegmentChild *) activeChild)->maxZoom_ = true; - else - ((BgMdiSegmentChild *) activeChild)->maxZoom_ = false; - if(minZoom) - ((BgMdiSegmentChild *) activeChild)->minZoom_ = true; - else - ((BgMdiSegmentChild *) activeChild)->minZoom_ = false; - ((BgMdiSegmentChild *) activeChild)->UpdateZoomControl(); - } -} - -void BgMdiFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) -{ - Close(); -} - -void BgMdiFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) -{ - const int BG_DIALOG_INDENT = 30, BG_DIALOG_TOP_MARGIN = 15; - BgDialog aboutDialog(this, -1, "About EDISON", wxPoint(-1,-1), wxSize(450, 300), wxDEFAULT_DIALOG_STYLE | wxDIALOG_MODAL | wxBORDER | wxSYSTEM_MENU, "aboutDialog"); - wxFont myFont(9, wxSWISS, wxNORMAL, wxBOLD, false); - BgText bgText(0, "Edge Detection and Image SegmentatiON System (EDISON) v1.1", myFont, BG_DIALOG_INDENT, BG_DIALOG_TOP_MARGIN); - aboutDialog.AddText(&bgText); - myFont.SetWeight(wxNORMAL); - myFont.SetUnderlined(true); - bgText.SetId(1); - bgText.SetFont(myFont); - bgText.SetText("Authors"); - bgText.SetPlotLocation(BG_DIALOG_INDENT, BG_DIALOG_TOP_MARGIN+15); - aboutDialog.AddText(&bgText); - myFont.SetUnderlined(false); - bgText.SetId(2); - bgText.SetFont(myFont); - bgText.SetText(": Bogdan Georgescu, Chris Christoudias (freeware) 2002"); - bgText.SetPlotLocation(BG_DIALOG_INDENT+44, BG_DIALOG_TOP_MARGIN+15); - aboutDialog.AddText(&bgText); - bgText.SetId(3); - bgText.SetText("Center for Advanced Information Processing (CAIP), Rutgers University"); - bgText.SetPlotLocation(BG_DIALOG_INDENT, BG_DIALOG_TOP_MARGIN+30); - aboutDialog.AddText(&bgText); - wxBitmap riul_logo("riul_logo", wxBITMAP_TYPE_RESOURCE), caip_logo("caip_logo", wxBITMAP_TYPE_RESOURCE), rutgers_logo("rutgers_logo", wxBITMAP_TYPE_RESOURCE); - BgBitmap myBitmap(&riul_logo, 0, BG_DIALOG_INDENT+20, BG_DIALOG_TOP_MARGIN+60); - aboutDialog.AddBitmap(&myBitmap); - myBitmap.SetId(1); - myBitmap.SetMap(&caip_logo); - myBitmap.SetPlotLocation(BG_DIALOG_INDENT+85, BG_DIALOG_TOP_MARGIN+170); - aboutDialog.AddBitmap(&myBitmap); - myBitmap.SetId(2); - myBitmap.SetMap(&rutgers_logo); - myBitmap.SetPlotLocation(BG_DIALOG_INDENT+145, BG_DIALOG_TOP_MARGIN+165); - aboutDialog.AddBitmap(&myBitmap); - aboutDialog.Centre(wxBOTH); - aboutDialog.ShowModal(); -} - -void BgMdiFrame::OnHelp(wxCommandEvent& WXUNUSED(event) ) -{ - wxDialog helpDialog(this, -1, "Help Window", wxPoint(10,10), wxSize(800,600), wxDEFAULT_DIALOG_STYLE | wxDIALOG_MODAL | wxBORDER | wxSYSTEM_MENU); - wxHtmlWindow helpWind(&helpDialog, -1, wxPoint(10,10), wxSize(770,550)); - helpWind.LoadPage(helpDir_); - helpDialog.ShowModal(); - bgLog("\n"); -} - -void BgMdiFrame::OnLoadImage(wxCommandEvent& WXUNUSED(event)) -{ - - wxMDIChildFrame *activeChild = GetActiveChild(); - wxCommandEvent zcev; - if(activeChild) - { - if(activeChild->GetId() == BG_EDGE_WINDOW) - ((BgMdiEdgeChild*) activeChild)->OnLoadImage(zcev); - else if(activeChild->GetId() == BG_SEGM_WINDOW) - ((BgMdiSegmentChild*) activeChild)->OnLoadImage(zcev); - } else - { - //read an image - char *pathname, *filename; - GetImageFileInfo(&pathname, &filename); - if(pathname) - { - - //get current width and height of this window - int width, height; - GetSize(&width, &height); - - //half window width - width = width/2; - - //create an edge window - OnNewEdgeWindow(zcev); - - //load read image into edge window - activeChild = GetActiveChild(); - ((BgMdiEdgeChild*) activeChild)->ReadImage(pathname, filename); - ((BgMdiEdgeChild*) activeChild)->RunEnable(); - - //set position and size of edge detection window - activeChild->SetSize(0,-30,width,height); - - //create a segmentation window - OnNewSegmWindow(zcev); - - //load read image into segment window - activeChild = GetActiveChild(); - ((BgMdiSegmentChild*) activeChild)->ReadImage(pathname, filename); - ((BgMdiSegmentChild*) activeChild)->RunEnable(); - - //set position and size of segmnetation window - activeChild->SetSize(width,-30,width,height); - - //de-allocate memory used by filename - delete [] filename; - } - } - -} - -void BgMdiFrame::OnLoadImageEdge(wxCommandEvent& WXUNUSED(event)) -{ - BgMdiEdgeChild* activeChild; - activeChild = 0; - activeChild = (BgMdiEdgeChild*) GetActiveChild(); - wxCommandEvent zcev; - if (activeChild != 0) - { - activeChild->OnLoadImage(zcev); - } else - { - OnNewEdgeWindow(zcev); - activeChild = (BgMdiEdgeChild*) GetActiveChild(); - activeChild->OnLoadImage(zcev); - } -} - -void BgMdiFrame::OnLoadImageSegm(wxCommandEvent& WXUNUSED(event)) -{ - BgMdiSegmentChild* activeChild; - activeChild = 0; - activeChild = (BgMdiSegmentChild*) GetActiveChild(); - wxCommandEvent zcev; - if (activeChild != 0) - { - activeChild->OnLoadImage(zcev); - } else - { - OnNewSegmWindow(zcev); - activeChild = (BgMdiSegmentChild*) GetActiveChild(); - activeChild->OnLoadImage(zcev); - } -} - -void BgMdiFrame::OnSaveResult(wxCommandEvent& WXUNUSED(event)) -{ - wxMDIChildFrame* activeChild = GetActiveChild(); - if(activeChild) - { - wxCommandEvent zcev; - if (activeChild->GetId() == BG_EDGE_WINDOW) - ((BgMdiEdgeChild *) activeChild)->OnSaveEdgeMap(zcev); - else if (activeChild->GetId() == BG_SEGM_WINDOW) - ((BgMdiSegmentChild *) activeChild)->OnSaveSegmentedImage(zcev); - } -} - -void BgMdiFrame::OnNewEdgeWindow(wxCommandEvent& WXUNUSED(event) ) -{ - - //indicate that another child frame will be created - gs_nFrames++; - - // Make another frame, containing a edge processing window - BgMdiEdgeChild *subframe = new BgMdiEdgeChild(g_frame, "Edge Detection Frame", - wxPoint(-1, -1), wxSize(-1, -1), - wxDEFAULT_FRAME_STYLE); - - wxString title; - title.Printf(_T("Edge Detection Frame %d"), gs_nFrames); - - subframe->SetTitle(title); - - // Give it an icon -#ifdef __WXMSW__ - subframe->SetIcon(wxIcon("chrt_icn")); -#else - subframe->SetIcon(wxIcon( mondrian_xpm )); -#endif - - // Make a menubar - wxMenu *file_menu = new wxMenu; - - file_menu->Append(BG_NEW_EDGE_WINDOW, "New &edge window\tAlt-E", "Create a new edge detection window"); - file_menu->Append(BG_NEW_SEGM_WINDOW, "New &segment window\tAlt-S", "Create a new segmentation window"); - file_menu->Append(BG_LOAD_IMAGE_EDGE, "&Load image\tCtrl-L", "Load image to perform edge detection"); - file_menu->Append(BG_EDGE_SAVE_MAP, "&Save edge map\tCtrl-S"); - file_menu->Append(BG_CHILD_EDGE_QUIT, "&Close edge window\tAlt-C", "Close this window"); - file_menu->Append(BG_QUIT, "E&xit\tAlt-X"); - - wxMenu *edge_menu = new wxMenu; - - edge_menu->Append(BG_EDGE_DETECT, "Edge Detect\tCtrl-R"); - edge_menu->Append(BG_CHANGE_PARAM_EDGE, "Change Parameters..."); - - wxMenu *view_menu = new wxMenu; - - subframe->miViewOrig_ = new wxMenuItem(view_menu, BG_EDGE_VIEW_ORIG, "Original", "View original", TRUE); - subframe->miViewEdge_ = new wxMenuItem(view_menu, BG_EDGE_VIEW_EDGE, "Edge map", "View edge map", TRUE); - - view_menu->Append(subframe->miViewOrig_); - view_menu->Append(subframe->miViewEdge_); - - wxMenu *help_menu = new wxMenu; - help_menu->Append(BG_ABOUT, "&About"); - help_menu->Append(BG_HELP, "&Help\tCtrl-H"); - - wxMenuBar *menu_bar = new wxMenuBar; - - menu_bar->Append(file_menu, "&File"); - menu_bar->Append(edge_menu, "&Edge Detect"); - menu_bar->Append(view_menu, "&View"); - menu_bar->Append(help_menu, "&Help"); - - //disable items on menu bar - menu_bar->Enable(BG_EDGE_DETECT, false); - menu_bar->Enable(BG_EDGE_SAVE_MAP, false); - - // Associate the menu bar with the frame - subframe->SetMenuBar(menu_bar); - - subframe->CreateStatusBar(); - subframe->SetStatusText(title); - - int width, height; - subframe->GetClientSize(&width, &height); - - subframe->Show(TRUE); - subframe->miViewOrig_->Check(TRUE); - subframe->miViewEdge_->Check(TRUE); -} - -void BgMdiFrame::OnNewSegmWindow(wxCommandEvent& WXUNUSED(event) ) -{ - - //indicate that another child frame will be created - gs_nFrames++; - - // Make another frame, containing a edge processing window - BgMdiSegmentChild *subframe = new BgMdiSegmentChild(g_frame, "Segmentation Frame", - wxPoint(-1, -1), wxSize(-1, -1), - wxDEFAULT_FRAME_STYLE); - - wxString title; - title.Printf(_T("Segmentation Frame %d"), gs_nFrames); - - subframe->SetTitle(title); - - // Give it an icon -#ifdef __WXMSW__ - subframe->SetIcon(wxIcon("chrt_icn")); -#else - subframe->SetIcon(wxIcon( mondrian_xpm )); -#endif - - // Make a menubar - wxMenu *file_menu = new wxMenu; - file_menu->Append(BG_NEW_EDGE_WINDOW, "New &edge window\tAlt-E", "Create a new edge detection window"); - file_menu->Append(BG_NEW_SEGM_WINDOW, "New &segment window\tAlt-S", "Create a new segmentation window"); - file_menu->Append(BG_SEGM_LOAD_IMAGE, "&Load image\tShift-L", "Load image to perform segmentation"); - file_menu->Append(BG_SEGM_SAVE_SEGMENTED, "&Save result\tShift-S"); - file_menu->Append(BG_CHILD_SEGM_QUIT, "&Close window\tShift-C", "Close this window"); - file_menu->Append(BG_QUIT, "E&xit\tAlt-X"); - - wxMenu *segm_menu = new wxMenu; - segm_menu->Append(BG_SEGM_SEGMENT, "Segment Image\tShift-R"); - segm_menu->AppendSeparator(); - wxMenu *speedup_menu = new wxMenu; - speedup_menu->Append(BG_SEGM_SPEEDUP_NONE, "&None", "", true); - speedup_menu->Append(BG_SEGM_SPEEDUP_MEDM, "&Medium", "", true); - speedup_menu->Append(BG_SEGM_SPEEDUP_HIGH, "&High", "", true); - wxMenuItem *segm_menu_item = new wxMenuItem(segm_menu, BG_SEGM_SPEEDUP, "Speedup", "", false, speedup_menu); - segm_menu->Append(segm_menu_item); - - wxMenu *weightmap_menu = new wxMenu; - weightmap_menu->Append(BG_SEGM_LOAD_MAP, "Load custom weight &map\tShift-M", "Load map images to perform segmentation"); - weightmap_menu->AppendSeparator(); - weightmap_menu->Append(BG_SEGM_USE_MAP, "&Use custom weight map", "", true); - - wxMenu *help_menu = new wxMenu; - help_menu->Append(BG_ABOUT, "&About"); - help_menu->Append(BG_HELP, "&Help\tCtrl-H"); - - wxMenuBar *menu_bar = new wxMenuBar; - menu_bar->Append(file_menu, "&File"); - menu_bar->Append(segm_menu, "&Algorithm"); - menu_bar->Append(weightmap_menu, "&Weight Map"); - menu_bar->Append(help_menu, "&Help"); - - //disable items on menu bar - menu_bar->Enable(BG_SEGM_SEGMENT, false); - menu_bar->Enable(BG_SEGM_SAVE_SEGMENTED, false); - menu_bar->Enable(BG_SEGM_LOAD_MAP, false); - menu_bar->Enable(BG_SEGM_USE_MAP, false); - - //check speedup to medium - menu_bar->Check(BG_SEGM_SPEEDUP_MEDM, true); - - // Associate the menu bar with the frame - subframe->SetMenuBar(menu_bar); - subframe->CreateStatusBar(); - subframe->SetStatusText(title); - - subframe->Show(TRUE); - subframe->Fit(); -} - -void BgMdiFrame::GetImageFileInfo(char **pathname, char **filename) -{ - -// get the file name -#if defined(__WXGTK__) || defined(__WXMOTIF__) - wxFileDialog filedialog(this,"Choose an image file","","", - "*",wxOPEN); -#else - wxFileDialog filedialog(this,"Choose an image file","","", - "Common image files|*.png;*.bmp;*.gif;*.tif;*.tiff;*.jpg;*.pnm;*.pgm;*.ppm|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm|PGM/PPM files (*.pgm,*.ppm)|*.pgm;*.ppm", - wxOPEN); -#endif - - //retrieve and check filename - *filename = (char *) NULL; - *pathname = (char *) NULL; - BgImCanvas *temp = new BgImCanvas(this, this, wxDefaultPosition, wxDefaultSize); - if(filedialog.ShowModal()==wxID_OK) - { - char* temp_str = (char *) filedialog.GetPath().c_str(); - *pathname = new char [strlen(temp_str) + 1]; - strcpy(*pathname, temp_str); - temp_str = (char *) filedialog.GetFilename().c_str(); - *filename = new char [strlen(temp_str) + 1]; - strcpy(*filename, temp_str); - if (temp->SetImage(*pathname) == 0) - { - delete [] *pathname; - delete [] *filename; - *pathname = (char *) NULL; - *filename = (char *) NULL; - } - else - bgLog("Image %s loaded\n",filedialog.GetPath().c_str()); - } - - //de-allocate memory - delete temp; - - //done. - return; -} - -//manages toolbar zoom controls -void BgMdiFrame::ZoomControl(wxCommandEvent& event) -{ - //set display - wxToolBar *toolbar = GetToolBar(); - switch (event.m_id) - { - case BG_CROSS: - toolbar->ToggleTool(BG_CROSS, true); - toolbar->ToggleTool(BG_ZOOM_IN, false); - toolbar->ToggleTool(BG_ZOOM_OUT, false); - toolbar->ToggleTool(BG_POINTER, false); - break; - case BG_ZOOM_IN: - toolbar->ToggleTool(BG_CROSS, false); - toolbar->ToggleTool(BG_ZOOM_IN, true); - toolbar->ToggleTool(BG_ZOOM_OUT, false); - toolbar->ToggleTool(BG_POINTER, false); - break; - case BG_ZOOM_OUT: - toolbar->ToggleTool(BG_CROSS, false); - toolbar->ToggleTool(BG_ZOOM_IN, false); - toolbar->ToggleTool(BG_ZOOM_OUT, true); - toolbar->ToggleTool(BG_POINTER, false); - break; - //BG_POINTER: - default: - toolbar->ToggleTool(BG_CROSS, false); - toolbar->ToggleTool(BG_ZOOM_IN, false); - toolbar->ToggleTool(BG_ZOOM_OUT, false); - toolbar->ToggleTool(BG_POINTER, true); - break; - } - - //set zoom functionality - wxMDIChildFrame *activeChild = GetActiveChild(); - if(activeChild->GetId() == BG_EDGE_WINDOW) - { - switch (event.m_id) - { - case BG_CROSS: - ((BgMdiEdgeChild *) activeChild)->ZoomWindow(); - break; - case BG_ZOOM_IN: - ((BgMdiEdgeChild *) activeChild)->ZoomIn(); - break; - case BG_ZOOM_OUT: - ((BgMdiEdgeChild *) activeChild)->ZoomOut(); - break; - //BG_POINTER: - default: - ((BgMdiEdgeChild *) activeChild)->NoZoom(); - break; - } - } - else if(activeChild->GetId() == BG_SEGM_WINDOW) - { - switch (event.m_id) - { - case BG_CROSS: - ((BgMdiSegmentChild *) activeChild)->ZoomWindow(); - break; - case BG_ZOOM_IN: - ((BgMdiSegmentChild *) activeChild)->ZoomIn(); - break; - case BG_ZOOM_OUT: - ((BgMdiSegmentChild *) activeChild)->ZoomOut(); - break; - //BG_POINTER: - default: - ((BgMdiSegmentChild *) activeChild)->NoZoom(); - break; - } - } - - return; - -} - - -void BgMdiFrame::OnSize(wxSizeEvent& WXUNUSED(event)) -{ - int w, h; - GetClientSize(&w, &h); - logtext_->SetSize(0, h-logsize_, w, logsize_); - GetClientWindow()->SetSize(0, 0, w, h-logsize_); -} - - -void BgMdiFrame::InitToolBar(wxToolBar* toolBar) -{ - const int BITMAP_COUNT = 9; - wxBitmap* bitmaps[BITMAP_COUNT]; - -#ifdef __WXMSW__ - bitmaps[0] = new wxBitmap( "icon1", wxBITMAP_TYPE_RESOURCE); - bitmaps[1] = new wxBitmap( "icon7", wxBITMAP_TYPE_RESOURCE); - bitmaps[2] = new wxBitmap( "icon8", wxBITMAP_TYPE_RESOURCE); - bitmaps[3] = new wxBitmap( "icon2", wxBITMAP_TYPE_RESOURCE); - bitmaps[4] = new wxBitmap( "icon3", wxBITMAP_TYPE_RESOURCE); - bitmaps[5] = new wxBitmap( "icon9", wxBITMAP_TYPE_RESOURCE); - bitmaps[6] = new wxBitmap("icon10", wxBITMAP_TYPE_RESOURCE); - bitmaps[7] = new wxBitmap("icon11", wxBITMAP_TYPE_RESOURCE); - bitmaps[8] = new wxBitmap("icon12", wxBITMAP_TYPE_RESOURCE); -#else - bitmaps[0] = new wxBitmap( bnew_xpm ); - bitmaps[1] = new wxBitmap( bnsg_xpm ); - bitmaps[2] = new wxBitmap( bhelp_xpm ); - bitmaps[3] = new wxBitmap( bopen_xpm ); - bitmaps[4] = new wxBitmap( bsave_xpm ); - bitmaps[5] = new wxBitmap( bcros_xpm ); - bitmaps[6] = new wxBitmap( bzin_xpm ); - bitmaps[7] = new wxBitmap( bzout_xpm ); - bitmaps[8] = new wxBitmap( bpoin_xpm ); - -#endif - -#ifdef __WXMSW__ - int width = 24; -#else - int width = 16; -#endif - int currentX = 5; - - //add tools to tool bar - toolBar->AddTool( BG_NEW_EDGE_WINDOW, *(bitmaps[0]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "New edge window"); - currentX += width + 5; - toolBar->AddTool( BG_NEW_SEGM_WINDOW, *(bitmaps[1]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "New segment window"); - currentX += width + 5; - toolBar->AddTool( BG_LOAD_IMAGE, *(bitmaps[3]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Load image for processing"); - currentX += width + 5; - toolBar->AddTool( BG_SAVE_RESULT, *(bitmaps[4]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Save result"); - currentX += width + 5; - toolBar->AddSeparator(); - toolBar->AddTool( BG_CROSS, *(bitmaps[5]), wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, "Zoom Window"); - currentX += width + 5; - toolBar->AddTool( BG_ZOOM_IN, *(bitmaps[6]), wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, "Zoom In"); - currentX += width + 5; - toolBar->AddTool( BG_ZOOM_OUT, *(bitmaps[7]), wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, "Zoom Out"); - currentX += width + 5; - toolBar->AddTool( BG_POINTER, *(bitmaps[8]), wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, "Select"); - currentX += width + 5; - toolBar->AddSeparator(); - toolBar->AddTool( BG_HELP, *bitmaps[2], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Help"); - - //set bitmap size of controls buttons to 20x20 - wxSize tool_size(20,20); - toolBar->SetToolBitmapSize(tool_size); - - toolBar->Realize(); - - //disable certain tools - toolBar->EnableTool(BG_SAVE_RESULT, false); - toolBar->EnableTool(BG_CROSS, false); - toolBar->EnableTool(BG_ZOOM_IN, false); - toolBar->EnableTool(BG_ZOOM_OUT, false); - toolBar->EnableTool(BG_POINTER, false); - - int i; - for (i = 0; i < BITMAP_COUNT; i++) - delete bitmaps[i]; -} - -// --------------------------------------------------------------------------- -// BgPointSet -// --------------------------------------------------------------------------- - -BgPointSet::BgPointSet() -{ - x_ = y_ = 0; - n_ = 0; - type_ = 0; - pen_.SetColour(*wxBLUE); - //pen_.SetColour(*wxWHITE); - pen_.SetWidth(1); - pen_.SetStyle(wxSOLID); -} - -BgPointSet::~BgPointSet() -{ - CleanData(); -} - -void BgPointSet::CleanData() -{ - if (n_ > 0) - { - delete [] x_; - delete [] y_; - x_ = y_ = 0; - n_ = 0; - } -} - -void BgPointSet::SetPoints(int* x, int* y, int n) -{ - CleanData(); - n_ = n; - x_ = new int[n_]; - y_ = new int[n_]; - for (int i=0; i<n; i++) - { - x_[i] = x[i]; - y_[i] = y[i]; - } -} - -// --------------------------------------------------------------------------- -// BgCurveSet -// --------------------------------------------------------------------------- - -BgCurveSet::BgCurveSet() -{ - x_ = y_ = 0; - xs_ = ys_ = 0; - n_ = 0; - type_ = -1; - pen_.SetColour(*wxBLUE); - pen_.SetWidth(3); - pen_.SetStyle(wxSOLID); - isDragging_ = 0; -} - -BgCurveSet::~BgCurveSet() -{ - CleanData(); -} - -void BgCurveSet::CleanData() -{ - if (n_ > 0) - { - delete [] x_; - delete [] y_; - x_ = y_ = 0; - n_ = 0; - } - type_ = -1; - xs_ = ys_ = 0; -} - -void BgCurveSet::SetCurve(BgCurveSet* bgc) -{ - CleanData(); - type_ = bgc->type_; - n_ = bgc->n_; - x_ = new int[n_]; - y_ = new int[n_]; - xs_ = bgc->xs_; - ys_ = bgc->ys_; - for (int i=0; i<n_; i++) - { - x_[i] = bgc->x_[i]; - y_[i] = bgc->y_[i]; - } -} - -void BgCurveSet::SetParamCurve(int type, double* x, double* y, int n, int xs, int ys) -{ - CleanData(); - type_ = type; - n_ = n; - x_ = new int[n_]; - y_ = new int[n_]; - xs_ = xs; - ys_ = ys; - for (int i=0; i<n; i++) - { - x_[i] = (int) (x[i]*xs); - y_[i] = (int) (ys-y[i]*ys); - } -} - -void BgCurveSet::GetParamCurve(double* x, double* y, int& type, int& n) -{ - for (int i=0; i<n_; i++) - { - x[i] = ((double)x_[i])/xs_; - y[i] = ((double)(ys_-y_[i]))/ys_; - } - type = type_; - n = n_; -} - -void BgCurveSet::DrawYourself(unsigned char* buf, int val) -{ - int j; - switch (type_) - { - case -1: - break; - case FC_ELLIPSE: - DrawEllipticArc(buf, val, -x_[0], y_[0], 2*x_[0], 2*(ys_-y_[0]), 0, 90); - break; - case FC_VERT_LINE: - DrawLine(buf, val, x_[0], 0, x_[0], ys_); - break; - case FC_HORIZ_LINE: - DrawLine(buf, val, 0, y_[0], xs_, y_[0]); - break; - case FC_LINE: - DrawLine(buf, val, 0, y_[0], x_[0], ys_); - break; - case FC_SQUARE_BOX: - DrawLine(buf, val, 0, y_[0], x_[0], y_[0]); - DrawLine(buf, val, x_[0], y_[0], x_[0], ys_); - break; - case FC_CUSTOM: - // lines - for (j=0; j<(n_-1); j++) - DrawLine(buf, val, x_[j], y_[j], x_[j+1], y_[j+1]); - // control points - for (j=0; j<n_; j++) - DrawPoint(buf, val ,x_[j], y_[j]); - break; - } - -} - -void BgCurveSet::DrawPoint(unsigned char* buf, int val, int x, int y) -{ - int r, c; - int dx, dy; - for (dx=-2; dx<=2; dx++) - { - for (dy=-2; dy<=2; dy++) - { - c=x+dx; - r=y+dy; - if ((c>=0) && (c<xs_) && (r>=0) && (r<ys_) && ((abs(dx)+abs(dy))<4)) - buf[c+r*ys_] = val; - } - } -} - -void BgCurveSet::DrawLine(unsigned char* buf, int val, int xs, int ys, int xe, int ye) -{ - int r, c; - double dsx, dsy, dex, dey; - if (abs(xs-xe)>abs(ys-ye)) - { - // x scan - if (xs > xe) - { - dsx = xe; - dsy = ye; - dex = xs; - dey = ys; - } - else - { - dex = xe; - dey = ye; - dsx = xs; - dsy = ys; - } - - for (c = (int) dsx; c<=(int)dex; c++) - { - if (c>=0 && c<xs_) - { - r = bgRound(dey-(dey-dsy)*(dex-c)/(dex-dsx)); - if (r>=0 && r<ys_) - { - buf[c+r*xs_] = val; - // +/- 1 - if ((r+1)<ys_) buf[c+(r+1)*xs_] = val; - if ((r-1)>=0) buf[c+(r-1)*xs_] = val; - // +/- 2 - if ((r+2)<ys_) buf[c+(r+2)*xs_] = val; - if ((r-2)>=0) buf[c+(r-2)*xs_] = val; - } - } - } - } - else - { - // y scan - if (ys > ye) - { - dsx = xe; - dsy = ye; - dex = xs; - dey = ys; - } - else - { - dex = xe; - dey = ye; - dsx = xs; - dsy = ys; - } - - // check bounds - - for (r = (int) dsy; r<=(int) dey; r++) - { - if (r>=0 && r<ys_) - { - c = bgRound(dex-(dex-dsx)*(dey-r)/(dey-dsy)); - if (c>=0 && c<xs_) - { - buf[c+r*xs_] = val; - // +/- 1 - if ((c+1)<xs_) buf[c+1+r*xs_] = val; - if ((c-1)>=0) buf[c-1+r*xs_] = val; - // +/- 2 - if ((c+2)<xs_) buf[c+2+r*xs_] = val; - if ((c-2)>=0) buf[c-2+r*xs_] = val; - } - } - } - } -} -void BgCurveSet::DrawEllipticArc(unsigned char* buf, int val, int x, int y, int w, int h, int sa, int ea) -{ - double xc, yc, rx, ry; - rx = w/2; - ry = h/2; - xc = x+rx; - yc = y+ry; - int r, c; - -// if (rx > ry) -// { - // x scan - for (c = (int) xc; c<=(int) (xc+rx); c++) - { - if (c>=0 && c<xs_) - { - r = bgRound(yc-ry*sqrt(1-(c-xc)*(c-xc)/(rx*rx))); - if (r>=0 && r<ys_) - { - buf[c+r*xs_] = val; - // +/- 1 - if ((r+1)<ys_) buf[c+(r+1)*xs_] = val; - if ((r-1)>=0) buf[c+(r-1)*xs_] = val; - // +/- 2 - if ((r+2)<ys_) buf[c+(r+2)*xs_] = val; - if ((r-2)>=0) buf[c+(r-2)*xs_] = val; - } - } - } -// } -// else -// { - // y scan - for (r = (int)(yc-ry); r<=(int) yc; r++) - { - if (r>=0 && r<ys_) - { - c = bgRound(xc+rx*sqrt(1-(r-yc)*(r-yc)/(ry*ry))); - if (c>=0 && c<xs_) - { - buf[c+r*xs_] = val; - // +/- 1 - if ((c+1)<xs_) buf[c+1+r*xs_] = val; - if ((c-1)>=0) buf[c-1+r*xs_] = val; - // +/- 2 - if ((c+2)<xs_) buf[c+2+r*xs_] = val; - if ((c-2)>=0) buf[c-2+r*xs_] = val; - } - } - } -// } -} - -void BgCurveSet::StartDragging(int x, int y) -{ - isDragging_ = 1; - int j; - switch (type_) - { - case -1: - break; - case FC_ELLIPSE: - if (abs(x)<3) - ltodrag_ = 1; - else if (abs(y-ys_)<3) - ltodrag_ = 2; - else - ltodrag_ = 0; - break; - case FC_VERT_LINE: - ltodrag_ = 0; - break; - case FC_HORIZ_LINE: - ltodrag_ = 0; - break; - case FC_LINE: - if (abs(x)<3) - ltodrag_ = 1; - else if (abs(y-ys_)<3) - ltodrag_ = 2; - else - ltodrag_ = 0; - break; - case FC_SQUARE_BOX: - if (abs((abs(x-x_[0])-abs(y-y_[0])))<3) - { - // drag corner - ltodrag_ = 2; - } - else if (abs(x-x_[0])>abs(y-y_[0])) - { - // drag horizontal - ltodrag_ = 0; - } - else - { - // drag vertical - ltodrag_ = 1; - } - break; - case FC_CUSTOM: - // find point to drag - int mind = abs(x-x_[0]) + abs(y-y_[0]); - int cmind, mj; - mj = 0; - for (j=1; j<n_; j++) - { - cmind = abs(x-x_[j]) + abs(y-y_[j]); - if (cmind < mind) - { - mind = cmind; - mj = j; - } - } - ltodrag_ = mj; - break; - } -} - -void BgCurveSet::DragTo(int x, int y) -{ - if ((x<0) || (y<0) || (x>=xs_) || (y>=ys_)) - return; - double k, ry; - switch (type_) - { - case -1: - break; - case FC_ELLIPSE: - // modify ellipse to drag - if (ltodrag_ == 0) - { - k = ((double)x_[0])/(ys_-y_[0]); - ry = sqrt(((double)x*x)/(k*k)+(y-ys_)*(y-ys_)); - x_[0] = bgRound(k*ry); - y_[0] = bgRound(ys_-ry); - } - else if (ltodrag_ == 1) - { - y_[0] = y; - } - else - { - x_[0] = x; - } - break; - case FC_VERT_LINE: - x_[0] = x; - break; - case FC_HORIZ_LINE: - y_[0] = y; - break; - case FC_LINE: - // modify line to drag - if (ltodrag_ == 0) - { - k = ((double) (ys_-y_[0])/x_[0]); - y_[0] = ys_-bgRound((double (ys_-y)+k*x)); - x_[0] = bgRound((double (ys_-y)+k*x)/(k)); - } - else if (ltodrag_ == 1) - { - y_[0] = y; - } - else - { - x_[0] = x; - } - break; - case FC_SQUARE_BOX: - if (ltodrag_ == 0) - y_[0] = y; - else if (ltodrag_ == 1) - x_[0] = x; - else - { - x_[0] = x; - y_[0] = y; - } - break; - case FC_CUSTOM: - // modify line to drag - if (ltodrag_ == 0) - { - y_[0] = y; - } else if (ltodrag_ == (n_-1)) - { - x_[n_-1] = x; - } else - { - x_[ltodrag_] = x; - y_[ltodrag_] = y; - } - break; - } -} - -void BgCurveSet::EndDragging(int x, int y) -{ - isDragging_ = 0; -} - -// --------------------------------------------------------------------------- -// BgParameterHistory -// --------------------------------------------------------------------------- - -BgParameterHistory::BgParameterHistory( void ) -{ - params_ = (void *) NULL; - listSize_ = 0; - next_ = (BgParameterHistory *) NULL; -} - -BgParameterHistory::BgParameterHistory(void *parameters, int itemCount) -{ - params_ = parameters; - listSize_ = itemCount; - next_ = (BgParameterHistory *) NULL; -} - - -BgParameterHistory::~BgParameterHistory( void ) -{ - if(params_) delete [] params_; -} - -// --------------------------------------------------------------------------- -// BgParameterHistoryBox -// --------------------------------------------------------------------------- - -BgParameterHistoryBox::BgParameterHistoryBox(wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, int n, long style, const wxValidator& validator, const wxString& name) - : wxComboBox(parent, id, value, pos, size, 0, (wxString*) NULL, style, validator, name) -{ - //initialize history list - maxCount_ = n; - listCount_ = 0; - historyList_ = (BgParameterHistory *) NULL; - - //initialize combo box - Append("Current"); - SetSelection(0); -} - -BgParameterHistoryBox::~BgParameterHistoryBox( void ) -{ - //delete history... - BgParameterHistory *temp; - while(historyList_) - { - temp = historyList_; - historyList_ = historyList_->next_; - delete temp; - } -} - -void BgParameterHistoryBox::AddParameterList(void *parameters, int itemCount) -{ - if(listCount_ < maxCount_) - { - BgParameterHistory *newHistory = new BgParameterHistory(parameters, itemCount); - newHistory->next_ = historyList_; - historyList_ = newHistory; - listCount_++; - char str[40]; - sprintf(str, "Parameter List -%d", listCount_); - Append(str); - } - else - { - BgParameterHistory *newHistory = historyList_; - while(newHistory->next_->next_) newHistory = newHistory->next_; - if(newHistory->next_->params_) delete newHistory->next_->params_; - newHistory->next_->params_ = parameters; - newHistory->next_->listSize_ = itemCount; - newHistory->next_->next_ = historyList_; - historyList_ = newHistory->next_; - newHistory->next_ = (BgParameterHistory *) NULL; - } -} - -void *BgParameterHistoryBox::GetParameterListData(int indexNumber) -{ - if(indexNumber < listCount_) - { - BgParameterHistory *currentHistory = historyList_; - int count = 0; - while(indexNumber != count) - { - currentHistory = currentHistory->next_; - count++; - } - return currentHistory->params_; - } - return (void *) NULL; -} - -int BgParameterHistoryBox::GetParameterListCount(int indexNumber) -{ - if(indexNumber < listCount_) - { - BgParameterHistory *currentHistory = historyList_; - int count = 0; - while(indexNumber != count) - { - currentHistory = currentHistory->next_; - count++; - } - return currentHistory->listSize_; - } - return -1; -} - -void BgParameterHistoryBox::UseParameterList(int indexNumber) -{ - if((indexNumber < listCount_) && (indexNumber != 0)) - { - BgParameterHistory *previousHistory = historyList_; - int count = 0; - while(count != indexNumber - 1) - { - previousHistory = previousHistory->next_; - count++; - } - BgParameterHistory *currentHistory = previousHistory->next_; - previousHistory->next_ = currentHistory->next_; - currentHistory->next_ = historyList_; - historyList_ = currentHistory; - } - return; -} - -void BgParameterHistoryBox::SetCurrentList(void *parameters, int itemCount) -{ - currentList_.params_ = parameters; - currentList_.listSize_ = itemCount; -} - -void *BgParameterHistoryBox::GetCurrentListData( void ) -{ - return currentList_.params_; -} - -int BgParameterHistoryBox::GetCurrentListCount( void ) -{ - return currentList_.listSize_; -} - -// --------------------------------------------------------------------------- -// BgText -// --------------------------------------------------------------------------- - -//default constructor -BgText::BgText(void) -{ - text_ = (char *) NULL; - font_ = (wxFont *) NULL; - id_ = 0; - x_ = 0; - y_ = 0; -} - -//overloaded constructor -BgText::BgText(int id, char *text, wxFont font, int x, int y) -{ - text_ = new char [strlen(text) + 1]; - strcpy(text_, text); - font_ = new wxFont; - (*font_) = font; - id_ = id; - x_ = x; - y_ = y; -} - -//destructor -BgText::~BgText(void) -{ - delete text_; - delete font_; -} - -//sets text string -//pre : text is a character string used to set the text -// field of the text object -//post: the text field of the text object has been set to text -void BgText::SetText(char *text) -{ - if((text_)&&(strlen(text) > strlen(text_))) - { - delete [] text_; - text_ = new char [strlen(text) + 1]; - } - strcpy(text_, text); - return; -} - -//sets font of text -//pre : font specifies the new font of the text object -//post: the font of the text object has been changed to font -void BgText::SetFont(wxFont font) -{ - if(!font_) font_ = new wxFont; - (*font_) = font; - return; -} - -//sets id of text -//pre : id is the new id of the text object -//post: the id of the text object has been set to id -void BgText::SetId(int id) -{ - id_ = id; -} - -//sets plot location of text -//pre : (x,y) determine the new plot location of the text object -//post: the plot location of the text object has been set to (x,y) -void BgText::SetPlotLocation(int x, int y) -{ - x_ = x; - y_ = y; -} - -// --------------------------------------------------------------------------- -// BgTextObj -// --------------------------------------------------------------------------- - -//constructor -BgTextObj::BgTextObj(BgText *text) -{ - text_ = new BgText(text->id_, text->text_, *(text->font_), text->x_, text->y_); - next_ = NULL; -} - -//destructor -BgTextObj::~BgTextObj(void) -{ - delete text_; -} - -// --------------------------------------------------------------------------- -// BgTextList -// --------------------------------------------------------------------------- - -// *** public methods *** // - -//constructor -BgTextList::BgTextList(void) -{ - head_ = cur_ = (BgTextObj *) NULL; - itemcount_ = 0; -} - -//destructor -BgTextList::~BgTextList(void) -{ - cur_ = head_; - while(cur_) - DeleteText(); -} - -//adds text object to list -//pre : text is a text object to be added to the list -//post: text has been added to the list -int BgTextList::AddText(BgText *text) -{ - //search for existsing text object - int id = text->id_; - cur_ = head_; - while((cur_)&&(cur_->text_->id_ != id)) - cur_ = cur_->next_; - - //if it exists change its contents - if(cur_) - { - BgText *tmp_text = cur_->text_; - tmp_text->SetText(text->text_); - tmp_text->SetFont(*(text->font_)); - tmp_text->SetPlotLocation(text->x_, text->y_); - } - //otherwise add it to existing list - else - { - BgTextObj *temp; - if((temp = new BgTextObj(text)) == NULL) - return 1; - - temp->next_ = head_; - if(head_ == NULL) - cur_ = temp; - head_ = temp; - itemcount_++; - } - - return 0; -} - -//removes text object from list -//pre : textId is the id of the text to be removed from the -// list -//post: text object having id textId has been removed from the -// list if it exists (1 is returned upon error) -int BgTextList::RemoveText(int textId) -{ - cur_ = head_; - while((cur_)&&(cur_->text_->id_ != textId)) - cur_ = cur_->next_; - - if(cur_) - { - DeleteText(); - return 0; - } - else - return 1; -} - -//returns text object from text list -//post: the text object pointed to by cur_ is returned -BgText *BgTextList::GetText(void) -{ - if(cur_) - { - BgText *text; - text = cur_->text_; - cur_ = cur_->next_; - return text; - } - else - return (BgText *) NULL; -} - -//resets cur_ pointer to head of the list -void BgTextList::ResetList(void) -{ - cur_ = head_; -} - -//returns the number of text objects contained -//within the list -//post: count of text objects contained by list is returned -int BgTextList::GetTextCount(void) -{ - return itemcount_; -} - -// *** private methods *** - -//deletes a text object node pointed to -//by cur_ -//post: text object has been deleted from the text list -void BgTextList::DeleteText(void) -{ - if(cur_ == head_) - { - head_ = head_->next_; - delete cur_; - cur_ = head_; - } - else - { - BgTextObj *temp = cur_; - cur_ = cur_->next_; - if(!cur_) cur_ = head_; - delete temp; - } -} - -// --------------------------------------------------------------------------- -// BgBitmap -// --------------------------------------------------------------------------- - -//default constructor -BgBitmap::BgBitmap(void) -{ - bitmap_ = (wxBitmap *) NULL; - location_x_ = location_y_ = 0; - id_ = 0; -} - -//overloaded constructor -BgBitmap::BgBitmap(wxBitmap *bitmap, int id, int location_x, int location_y) -{ - bitmap_ = new wxBitmap; - (*bitmap_) = (*bitmap); - id_ = id; - location_x_ = location_x; - location_y_ = location_y; -} - -//destructor -BgBitmap::~BgBitmap(void) -{ - if(bitmap_) delete bitmap_; -} - -//set bitmap content -//pre : bitmap is the new bitmap content -//post: bitmap content has been changed to that of bitmap -void BgBitmap::SetMap(wxBitmap *bitmap) -{ - if(!bitmap_) bitmap_ = new wxBitmap; - (*bitmap_) = (*bitmap); -} - -//set plot location -//pre : (location_x, location_y) define new plot location of bitmap -//post: plot location of bitmap has been set to (location_x, location_y) -void BgBitmap::SetPlotLocation(int location_x, int location_y) -{ - location_x_ = location_x; - location_y_ = location_y; -} - -//set bitmap id -//pre : id is the new bitmap id -//post: the bitmap id has been set to id -void BgBitmap::SetId(int id) -{ - id_ = id; -} - -// --------------------------------------------------------------------------- -// BgBitmapObj -// --------------------------------------------------------------------------- - -//default constructor -BgBitmapObj::BgBitmapObj(void) -{ - bitmap_ = (BgBitmap *) NULL; - next_ = (BgBitmapObj *) NULL; -} - -//overloaded constructor -BgBitmapObj::BgBitmapObj(BgBitmap* bitmap) -{ - bitmap_ = new BgBitmap(bitmap->bitmap_, bitmap->id_, - bitmap->location_x_, bitmap->location_y_); - next_ = (BgBitmapObj *) NULL; -} - -//destructor -BgBitmapObj::~BgBitmapObj(void) -{ - if(bitmap_) delete bitmap_; -} - -// --------------------------------------------------------------------------- -// BgBitmap -// --------------------------------------------------------------------------- - -//constructor -BgBitmapList::BgBitmapList(void) -{ - head_ = cur_ = (BgBitmapObj *) NULL; - itemcount_ = 0; -} - -//destuctor -BgBitmapList::~BgBitmapList(void) -{ - cur_ = head_; - while(cur_) - DeleteBitmap(); -} - -//add a bitmap object to the list -//pre : bitmap is a bitmap object to be added to the list -//post: bitmap has been added to the list -int BgBitmapList::AddBitmap(BgBitmap *bitmap) -{ - BgBitmapObj *temp; - if((temp = new BgBitmapObj(bitmap)) == NULL) - return 1; - - temp->next_ = head_; - if(head_ == NULL) - cur_ = temp; - head_ = temp; - itemcount_++; - - return 0; -} - -//remove bitmap from list -//pre : bitmap is to be removed from list -//post: bitmap has been removed from the list -void BgBitmapList::RemoveBitmap(BgBitmap *bitmap) -{ - int id = bitmap->id_; - cur_ = head_; - while((cur_)&&(cur_->bitmap_->id_ != id)) - cur_ = cur_->next_; - DeleteBitmap(); -} - -//get bitmap from the list pointed to by cur_ -//post: bitmap pointed to by cur_ has been returned -// and cur_ has been incremented to the next list -// item -BgBitmap *BgBitmapList::GetBitmap(void) -{ - BgBitmap *temp = (BgBitmap *) NULL; - if(cur_) - { - temp = cur_->bitmap_; - cur_ = cur_->next_; - } - - return temp; -} - -//reset bitmap list cur_ pointer -//post: cur_ has been set to the head of the list -void BgBitmapList::ResetList(void) -{ - cur_ = head_; -} - -//get the number of bitmaps stored by list -//post: bitmap count has been returned -int BgBitmapList::GetBitmapCount(void) -{ - return itemcount_; -} - -//delete bitmap object from list -//post: bitmap object pointed to by cur has been deleted -void BgBitmapList::DeleteBitmap(void) -{ - if(cur_) - { - BgBitmapObj *temp = cur_; - cur_ = cur_->next_; - delete temp; - itemcount_--; - } -} - -// --------------------------------------------------------------------------- -// BgAxis -// --------------------------------------------------------------------------- - -//default constructor -BgAxis::BgAxis(void) -{ - start_x_ = 0; start_y_ = 0; - length_ = 0; - ticknum_ = 0; - direction_ = 0; - start_val_ = 0; stop_val_ = 0; - label_ = (BgText *) NULL; - rotation_ = 0; -} - -//overloaded constructor -BgAxis::BgAxis(int start_x, int start_y, int length, int ticknum, int direction, float start_val, float stop_val) -{ - start_x_ = start_x; - start_y_ = start_y; - length_ = length; - ticknum_ = ticknum; - direction_ = direction; - start_val_ = start_val; - stop_val_ = stop_val; - label_ = (BgText *) NULL; - rotation_ = 0; -} - -//destuctor -BgAxis::~BgAxis(void) -{ - if(label_) delete label_; -} - -//set plotting origin -//pre : (start_x, start_y) specify the new axis plotting origin -//post: axis plotting origin has been set to (start_x, start_y) -void BgAxis::SetPlotOrigin(int start_x, int start_y) -{ - start_x_ = start_x; - start_y_ = start_y; -} - -//set axis length -//pre : length specifies the new length of the axis -//post: the axis lengh has been set to length -void BgAxis::SetLength(int length) -{ - length_ = length; -} - -//set axis tick number -//pre : ticknum is the new tick number of the axis -//post: the axis tick number has been set to ticknum -void BgAxis::SetTicknum(int ticknum) -{ - ticknum_ = ticknum; -} - -//set axis boundaries -//pre : (start_val, stop_val) define the new axis boundaries -//post: the axis boundaries have been set to (start_val, stop_val) -void BgAxis::SetBounds(float start_val, float stop_val) -{ - start_val_ = start_val; - stop_val_ = stop_val; -} - -//add axis label -//pre : label specifies the axis label -//post: the axis has been labeled using label -void BgAxis::Label(BgText *label) -{ - if(label_) delete label_; - char *text = label->text_; - int label_length = 3*strlen(text); - //horizontal axis - if(direction_ == 0) - { - label_x_ = start_x_ + length_/2 - label_length; - label_y_ = start_y_ + 30; - } - //vertical axis - else - { - label_x_ = start_x_ - 60; - label_y_ = start_y_ - length_/2 + label_length; - } - label_ = new BgText(label->id_, text, *(label->font_), label_x_, label_y_); -} - -//removes axis label -//post: the axis label has been removed -void BgAxis::RemoveLabel(void) -{ - if(label_) delete label_; - label_ = (BgText *) NULL; -} - -//sets label rotation -//pre : rotation specifies clockwise label rotation (rotation = 0 -// leaves the label parallel to the axis) -//post: label rotation has been set to rotation -void BgAxis::SetLabelRotation(int rotation) -{ - rotation_ = rotation; -} - -//draw axis object -//pre : dc is a dc object used to draw onto a window -//post: the axis has been drawn onto the window using -// using the dc object -void BgAxis::PlotAxis(wxDC *dc) -{ - //set tick length - int ticklength = 8; - - //calculate axis ending locations - int end_x = start_x_ + length_; - int end_y = start_y_ - length_; - - //define shift in x and y direction - int shift_x = 5; - int shift_y = 5; - - //create font - wxFont plotFont(7, wxSWISS, wxNORMAL, wxNORMAL, false, "", wxFONTENCODING_DEFAULT); - - //plot axis line - //horizontal axis - if(direction_ == 0) - { - //draw axis line - dc->DrawLine(start_x_, start_y_, end_x, start_y_); - dc->DrawLine(start_x_, start_y_+1, end_x, start_y_+1); - - //draw tick marks - int increment = length_/ticknum_; - if(length_%ticknum_ != 0) increment++; - int x_location = start_x_; - while(x_location < end_x) - { - dc->DrawLine(x_location, start_y_, x_location, start_y_+ticklength); - dc->DrawLine(x_location+1, start_y_, x_location+1, start_y_+ticklength); - x_location = x_location + increment; - } - dc->DrawLine(end_x-1, start_y_, end_x-1, start_y_+ticklength); - dc->DrawLine(end_x, start_y_, end_x, start_y_+ticklength); - - //draw floating point axis markers - x_location = start_x_ - shift_x; - float marker_x = start_val_; - float marker_increment = (stop_val_ - start_val_)/ticknum_; - char marker_str[8]; - int i = 0, fixed_y = start_y_ + 10; - char align[6]; - if(stop_val_ < 10) - strcpy(align, "%4.2f"); - else - { - strcpy(align, "%4.0f"); - x_location = x_location - shift_x; - shift_x = 2*shift_x; - } - dc->SetFont(plotFont); - for(i = 0; i < ticknum_; i++) - { - sprintf(marker_str, align, marker_x); - dc->DrawText(marker_str, x_location, fixed_y); - marker_x += marker_increment; - x_location += increment; - } - sprintf(marker_str, align, marker_x); - dc->DrawText(marker_str, end_x - shift_x, fixed_y); - - //add label - if(label_) - { - dc->SetFont(*(label_->font_)); - dc->DrawRotatedText(label_->text_, label_x_, label_y_, 0+rotation_); - } - } - //vertical axis - else - { - //draw axis line - dc->DrawLine(start_x_, start_y_, start_x_, end_y); - dc->DrawLine(start_x_-1, start_y_, start_x_-1, end_y); - - //draw tick marks - int increment = length_/ticknum_; - if(length_%ticknum_ != 0) increment++; - int y_location = end_y; - while(y_location < start_y_) - { - dc->DrawLine(start_x_, y_location, start_x_-ticklength, y_location); - dc->DrawLine(start_x_, y_location+1, start_x_-ticklength, y_location+1); - y_location = y_location + increment; - } - dc->DrawLine(start_x_, start_y_, start_x_-ticklength, start_y_); - dc->DrawLine(start_x_, start_y_+1, start_x_-ticklength, start_y_+1); - - //draw floating point axis markers - y_location = start_y_; - float marker_y = start_val_; - float marker_increment = (stop_val_ - start_val_)/ticknum_; - char marker_str[8]; - int i = 0, fixed_x = start_x_ - 30; - char align[6]; - if(stop_val_ < 10) - strcpy(align, "%4.2f"); - else - strcpy(align, "%4.0f"); - dc->SetFont(plotFont); - sprintf(marker_str, align, marker_y); - dc->DrawText(marker_str, fixed_x, y_location - shift_y); - marker_y += marker_increment; - y_location -= increment; - for(i = 1; i < ticknum_; i++) - { - sprintf(marker_str, align, marker_y); - dc->DrawText(marker_str, fixed_x, y_location); - marker_y += marker_increment; - y_location -= increment; - } - sprintf(marker_str, align, marker_y); - dc->DrawText(marker_str, fixed_x, end_y - shift_y); - - //add label - if(label_) - { - dc->SetFont(*(label_->font_)); - dc->DrawRotatedText(label_->text_, label_x_, label_y_, 90+rotation_); - } - } -} - -// --------------------------------------------------------------------------- -// BgThread -// --------------------------------------------------------------------------- - -BgThread::BgThread(wxThreadKind kind, void foo(void*), void *Object) : wxThread(kind) -{ - function_ = foo; - Object_ = Object; -} - -BgThread::~BgThread( void ) -{ - function_ = NULL; - Object_ = NULL; -} - -void *BgThread::Entry( void ) -{ - function_(Object_); - return (void *) NULL; -} - -// --------------------------------------------------------------------------- -// BgDialog -// --------------------------------------------------------------------------- - -BgDialog::BgDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name) - : wxDialog(parent, id, title, pos, size, style, name) -{ - - okButton_ = new wxButton(this, BG_DIALOG_OK, "OK", wxPoint(size.GetWidth()/2-40, size.GetHeight()-60)); -} - -BgDialog::~BgDialog( void ) -{ - delete okButton_; -} - -void BgDialog::AddText(BgText *text) -{ - tlist_.AddText(text); -} - -void BgDialog::AddBitmap(BgBitmap *bitmap) -{ - blist_.AddBitmap(bitmap); -} - -void BgDialog::RemoveText(int id) -{ - tlist_.RemoveText(id); -} - -void BgDialog::RemoveBitmap(BgBitmap *bitmap) -{ - blist_.RemoveBitmap(bitmap); -} - -void BgDialog::OnPaint(wxPaintEvent& WXUNUSED(event)) -{ - - wxPaintDC dc(this); - - //draw new text to the image from text object list - BgText *bgText; - tlist_.ResetList(); - while(bgText = tlist_.GetText()) - { - dc.SetFont(*(bgText->font_)); - dc.DrawText(bgText->text_, bgText->x_, bgText->y_); - } - - //draw bitmaps - blist_.ResetList(); - BgBitmap *bitmap; - while(bitmap = blist_.GetBitmap()) - dc.DrawBitmap(*(bitmap->bitmap_), bitmap->location_x_, bitmap->location_y_, true); - -} - -void BgDialog::OnExit(wxCommandEvent& WXUNUSED(event)) -{ - EndModal(wxID_OK); -} - -// --------------------------------------------------------------------------- -// BgHoverBar -// --------------------------------------------------------------------------- - -BgHoverBar::BgHoverBar(wxWindow* parent, wxWindowID id, int gradViewId, int confViewId, int weitViewId, int custViewId, int gradSaveId, int confSaveId, int weitSaveId) - : wxWindow(parent, id, wxDefaultPosition, wxDefaultSize, wxRAISED_BORDER) -{ - //set the size of the window - SetSize(120,30); - - //place a button using a bitmap - menuButton1_ = new wxBitmapButton(this, BG_CANVAS_VIEW_BUTTON, wxBitmap("down_arrow", wxBITMAP_TYPE_RESOURCE), wxPoint(33,2), wxSize(18,20)); - menuButton2_ = new wxBitmapButton(this, BG_CANVAS_SAVE_BUTTON, wxBitmap("down_arrow", wxBITMAP_TYPE_RESOURCE), wxPoint(92,2), wxSize(18,20)); - menuText1_ = new wxStaticText(this, -1, "View", wxPoint(5,5), wxSize(25,20)); - menuText2_ = new wxStaticText(this, -1, "Save", wxPoint(62,5), wxSize(25,20)); - - //get view menu identification constants - gradViewId_ = gradViewId; - confViewId_ = confViewId; - weitViewId_ = weitViewId; - custViewId_ = custViewId; - gradSaveId_ = gradSaveId; - confSaveId_ = confSaveId; - weitSaveId_ = weitSaveId; - - //create view menu - view_menu = new wxMenu; - view_menu->Append(gradViewId_, "&Gradient Map", "", true); - view_menu->Append(confViewId_, "&Confidence Map", "", true); - view_menu->Append(weitViewId_, "&Weight Map", "", true); - view_menu->Append(custViewId_, "C&ustom Weight Map", "", true); - - //create save menu - save_menu = new wxMenu; - save_menu->Append(gradSaveId_, "&Gradient Map"); - save_menu->Append(confSaveId_, "&Confidence Map"); - save_menu->Append(weitSaveId_, "&Weight Map"); - -} - -BgHoverBar::~BgHoverBar( void ) -{ - //de-allocate menus... - delete view_menu; - delete save_menu; -} - -void BgHoverBar::ShowMenu(wxCommandEvent& event) -{ - int buttonId = event.GetId(); - if(buttonId == BG_CANVAS_VIEW_BUTTON) - { - menuText1_->SetForegroundColour(wxColour(0,0,100)); - menuText2_->SetForegroundColour(wxColour(0,0,0)); - menuText1_->Refresh(); - menuText2_->Refresh(); - PopupMenu(view_menu, 0, 26); - } - else - { - menuText1_->SetForegroundColour(wxColour(0,0,0)); - menuText2_->SetForegroundColour(wxColour(0,0,100)); - menuText1_->Refresh(); - menuText2_->Refresh(); - PopupMenu(save_menu, 0, 26); - } - Update(); -} - -void BgHoverBar::CheckViewItem(long viewItemId) -{ - view_menu->Check(gradViewId_, false); - view_menu->Check(confViewId_, false); - view_menu->Check(weitViewId_, false); - view_menu->Check(custViewId_, false); - view_menu->Check(viewItemId, true); -} - -void BgHoverBar::Update( void ) -{ - menuText1_->SetForegroundColour(wxColour(0,0,0)); - menuText2_->SetForegroundColour(wxColour(0,0,0)); - menuText1_->Refresh(); - menuText2_->Refresh(); -} - -// --------------------------------------------------------------------------- -// BgMenuPanel -// --------------------------------------------------------------------------- - -BgMenuPanel::BgMenuPanel(wxWindow* parent, wxWindowID id, int gradViewId, int confViewId, int weitViewId, int custViewId, int gradSaveId, int confSaveId, int weitSaveId) - : wxPanel(parent, id, wxDefaultPosition, wxDefaultSize) -{ - //keep pointer to scroll window - scrollWindow_ = (wxWindow *) NULL; - - //set the position and size of the window - SetSize(0,0,120,30); - - //place a button using a bitmap - menuButton1_ = new wxBitmapButton(this, BG_CANVAS_VIEW_BUTTON, wxBitmap("down_arrow", wxBITMAP_TYPE_RESOURCE), wxPoint(33,2), wxSize(18,20)); - menuButton2_ = new wxBitmapButton(this, BG_CANVAS_SAVE_BUTTON, wxBitmap("down_arrow", wxBITMAP_TYPE_RESOURCE), wxPoint(92,2), wxSize(18,20)); - menuText1_ = new wxStaticText(this, -1, "View", wxPoint(5,5), wxSize(25,20)); - menuText2_ = new wxStaticText(this, -1, "Save", wxPoint(62,5), wxSize(25,20)); - - //get view menu identification constants - gradViewId_ = gradViewId; - confViewId_ = confViewId; - weitViewId_ = weitViewId; - custViewId_ = custViewId; - gradSaveId_ = gradSaveId; - confSaveId_ = confSaveId; - weitSaveId_ = weitSaveId; - - //create view menu - view_menu = new wxMenu; - view_menu->Append(gradViewId_, "&Gradient Map", "", true); - view_menu->Append(confViewId_, "&Confidence Map", "", true); - view_menu->Append(weitViewId_, "&Weight Map", "", true); - view_menu->Append(custViewId_, "C&ustom Weight Map", "", true); - - //create save menu - save_menu = new wxMenu; - save_menu->Append(gradSaveId_, "&Gradient Map"); - save_menu->Append(confSaveId_, "&Confidence Map"); - save_menu->Append(weitSaveId_, "&Weight Map"); - -} - -BgMenuPanel::~BgMenuPanel( void ) -{ - //de-allocate menus... - delete view_menu; - delete save_menu; -} - -void BgMenuPanel::ShowMenu(wxCommandEvent& event) -{ - int buttonId = event.GetId(); - if(buttonId == BG_CANVAS_VIEW_BUTTON) - { - menuText1_->SetForegroundColour(wxColour(0,0,200)); - menuText2_->SetForegroundColour(wxColour(0,0,0)); - menuText1_->Refresh(); - menuText2_->Refresh(); - PopupMenu(view_menu, 0, 26); - } - else - { - menuText1_->SetForegroundColour(wxColour(0,0,0)); - menuText2_->SetForegroundColour(wxColour(0,0,200)); - menuText1_->Refresh(); - menuText2_->Refresh(); - PopupMenu(save_menu, 0, 26); - } - Update(); -} - -void BgMenuPanel::CheckViewItem(long viewItemId) -{ - view_menu->Check(gradViewId_, false); - view_menu->Check(confViewId_, false); - view_menu->Check(weitViewId_, false); - view_menu->Check(custViewId_, false); - view_menu->Check(viewItemId, true); -} - -void BgMenuPanel::Update( void ) -{ - menuText1_->SetForegroundColour(wxColour(0,0,0)); - menuText2_->SetForegroundColour(wxColour(0,0,0)); - menuText1_->Refresh(); - menuText2_->Refresh(); -} - -void BgMenuPanel::EnableMenu(bool enable) -{ - menuText1_->Enable(enable); - menuText2_->Enable(enable); - menuButton1_->Enable(enable); - menuButton2_->Enable(enable); -} - -//adjusts size of scroll window -void BgMenuPanel::OnSize(wxSizeEvent& WXUNUSED(event)) -{ - if(scrollWindow_) - { - int w, h; - GetClientSize(&w, &h); - scrollWindow_->SetSize(0,PLOT_MENU_HEIGHT,w,h-PLOT_MENU_HEIGHT); - } -} - -void BgMenuPanel::SetScrollWindow(wxWindow *scrollwindow) -{ - scrollWindow_ = scrollwindow; -} - -// --------------------------------------------------------------------------- -// BgLineSet -// --------------------------------------------------------------------------- - -BgLineSet::BgLineSet() -{ - xs_ = ys_ = xe_ = ye_ = 0; - lineParam_ = 0; - n_ = 0; - pen_.SetColour(*wxRED); - //pen_.SetColour(*wxWHITE); - pen_.SetWidth(2); - pen_.SetStyle(wxSOLID); -} - -BgLineSet::~BgLineSet() -{ - CleanData(); -} - -void BgLineSet::CleanData() -{ - if (n_ > 0) - { - delete [] xs_; - delete [] xe_; - delete [] ys_; - delete [] ye_; - delete [] lineParam_; - xs_ = ys_ = xe_ = ye_ = 0; - lineParam_ = 0; - n_ = 0; - } -} - -void BgLineSet::SetLines(int* xs, int* xe, int* ys, int* ye, double* lineParam, int n) -{ - CleanData(); - n_ = n; - xs_ = new int[n_]; - xe_ = new int[n_]; - ys_ = new int[n_]; - ye_ = new int[n_]; - lineParam_ = new double[n_*3]; - int i; - for (i=0; i<n; i++) - { - xs_[i] = xs[i]; - ys_[i] = ys[i]; - xe_[i] = xe[i]; - ye_[i] = ye[i]; - } - for (i=0; i<(3*n); i++) - lineParam_[i] = lineParam[i]; -} - -void BgLineSet::SetLines(double* startp, double* endp, double* lineParam, int n) -{ - CleanData(); - n_ = n; - xs_ = new int[n_]; - xe_ = new int[n_]; - ys_ = new int[n_]; - ye_ = new int[n_]; - lineParam_ = new double[n_*3]; - int i; - for (i=0; i<n; i++) - { - xs_[i] = (int) startp[2*i]; - ys_[i] = (int) startp[2*i+1]; - xe_[i] = (int) endp[2*i]; - ye_[i] = (int) endp[2*i+1]; - } - for (i=0; i<(3*n); i++) - lineParam_[i] = lineParam[i]; -} - -// --------------------------------------------------------------------------- -// BgImCanvas -// --------------------------------------------------------------------------- - -// Define a constructor for my canvas -BgImCanvas::BgImCanvas(wxWindow *child_frame, wxWindow *parent, const wxPoint& pos, const wxSize& size) -: wxScrolledWindow(parent, -1, pos, size, - wxSIMPLE_BORDER|wxVSCROLL|wxHSCROLL) -{ - SetBackgroundColour(wxColour("WHITE")); - pbitmap=(wxBitmap*) NULL; - pimage=(wxImage*) NULL; - hasbitmap=FALSE; - showbitmap_ = TRUE; - m_dirty = FALSE; - nLineSets_ = nPointSets_ = 0; - - //set pointer to child frame (e.g. used to update window title) - child_frame_ = child_frame; - - // clickable curve stuff - nCurveSets_ = 0; - ccx_ = RANK_CONF_IMSIZEX; - ccy_ = RANK_CONF_IMSIZEY; - curveClick_ = new unsigned char[ccx_*ccy_]; - isDragging_ = 0; - FillCurveClick(); - mouseModif_ = 0; - crossCursor_ = 0; - showtrack_ = 0; - - //initialize window events - has_focus = false; - leaving = false; - - //initialize plotting canvas - x_offset_ = 0; - y_offset_ = 0; - textObjectCount_ = 0; - xAxis = (BgAxis *) NULL; - yAxis = (BgAxis *) NULL; - clear_display_ = false; - - //initializing zooming parameters - zoom_in = false; - zoom_out = false; - zoom_window = false; - zoom_level = 1; - - //initialize empty zoom box and refresh box - zoombox = (wxImage *) NULL; - refresh_box = (wxImage *) NULL; - - //initialize point map - point_map = NULL; - point_colour = (wxColour *) NULL; - - //initialize zoomed image buffer - zImg = NULL; - - //initialize zoom window corner - cx = 0; - cy = 0; - - //initialize mouse pointer location - m_x_ = 0; - m_y_ = 0; - - //initialize zoom buffers - buf = (unsigned char *) NULL; - - //initialize hover window such that - //it does not popup - popup = 0; - - //initialize hover window - menuWindow = (wxWindow *) NULL; - - //pay attention to updates - noUpdate_ = false; - - //construct zoom cursors - //?????????????????????????????? - wxString str; - str.Printf(wxT("icon10")); - bgCURSOR_MAGNIFIER_PLUS = new wxCursor(str, wxBITMAP_TYPE_CUR_RESOURCE); - //bgCURSOR_MAGNIFIER_PLUS = new wxCursor("icon10", wxBITMAP_TYPE_RESOURCE, 0, 0); - str.Printf(wxT("icon11")); - bgCURSOR_MAGNIFIER_MINUS = new wxCursor(str, wxBITMAP_TYPE_CUR_RESOURCE); - //bgCURSOR_MAGNIFIER_MINUS = new wxCursor("icon11", wxBITMAP_TYPE_RESOURCE, 0, 0); - - //build local menu - localMenu_ = new wxMenu(); - localMenu_->Append(BG_IMC_ADDNODE,"Add node"); - localMenu_->Append(BG_IMC_DELETENODE,"Delete node"); - localMenu_->AppendSeparator(); - localMenu_->Append(BG_IMC_SELTYPE_ELLIPSE,"Arc"); - localMenu_->Append(BG_IMC_SELTYPE_VLINE,"Vertical line"); - localMenu_->Append(BG_IMC_SELTYPE_HLINE,"Horizontal line"); - localMenu_->Append(BG_IMC_SELTYPE_LINE,"Line"); - localMenu_->Append(BG_IMC_SELTYPE_BOX,"Box"); - localMenu_->Append(BG_IMC_SELTYPE_CUSTOM,"Custom"); -} - -BgImCanvas::~BgImCanvas() -{ - ClearData(); - if(xAxis) delete xAxis; - if(yAxis) delete yAxis; - delete [] curveClick_; - delete localMenu_; - delete bgCURSOR_MAGNIFIER_PLUS; - delete bgCURSOR_MAGNIFIER_MINUS; -} - -void BgImCanvas::OnCustomAddNode(wxCommandEvent& WXUNUSED(event)) -{ - if ((lmEventCurve_ < 0) || (lmEventCurve_ >= nCurveSets_) || - (curveSet_[lmEventCurve_]->type_!=FC_CUSTOM)) - { - return; - } - int n, type; - n = curveSet_[lmEventCurve_]->n_; - double *tx, *ty; - tx = new double[n+1]; - ty = new double[n+1]; - curveSet_[lmEventCurve_]->GetParamCurve(tx, ty, type, n); - double x, y; - x = ((double) lmEventX_)/ccx_; - y = (ccy_ - ((double) lmEventY_))/ccy_; - - // determine closest line - double cx, cy, cr, ax, ay, dx, dy; - double mny = 10; - int ci = -1; - int i; - for (i=0; i<(n-1); i++) - { - cx = tx[i+1]-tx[i]; - cy = ty[i+1]-ty[i]; - cr = sqrt(cx*cx+cy*cy); - if (cr <= 0) - continue; - ax = x-tx[i]; - ay = y-ty[i]; - dx = (cx*ax+cy*ay)/cr; - dy = fabs((-cy*ax+cx*ay)/cr); - if ((dx>=0) && (dx<=cr)) - { - if (dy<mny) - { - mny = dy; - ci = i; - } - } - } - if (ci >= 0) - { - // modify curve - for (i=n; i>ci; i--) - { - tx[i] = tx[i-1]; - ty[i] = ty[i-1]; - } - tx[ci+1] = x; - ty[ci+1] = y; - curveSet_[lmEventCurve_]->SetParamCurve(type, tx, ty, n+1, ccx_, ccy_); - } - - delete [] ty; - delete [] tx; - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - - FillCurveClick(); - return; -} -void BgImCanvas::OnCustomDeleteNode(wxCommandEvent& WXUNUSED(event)) -{ - if ((lmEventCurve_ < 0) || (lmEventCurve_ >= nCurveSets_) || - (lmEventNode_ < 0) || (lmEventNode_ >= (curveSet_[lmEventCurve_]->n_-1))) - { - return; - } - if (lmEventNode_ == 0) - { - bgLog("Cannot delete first node.\n"); - return; - } - if (lmEventNode_ == (curveSet_[lmEventCurve_]->n_-1)) - { - bgLog("Cannot delete last node.\n"); - return; - } - // delete the node - int i; - int n = curveSet_[lmEventCurve_]->n_; - int *tx, *ty; - tx = curveSet_[lmEventCurve_]->x_; - ty = curveSet_[lmEventCurve_]->y_; - for (i=lmEventNode_; i<(n-1); i++) - { - tx[i] = tx[i+1]; - ty[i] = ty[i+1]; - } - curveSet_[lmEventCurve_]->n_ = n-1; - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - FillCurveClick(); - return; -} -void BgImCanvas::OnCTypeEllipse(wxCommandEvent& WXUNUSED(event)) -{ - if (lmEventCurve_ < nCurveSets_) - { - if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) - { - curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; - curveSet_[lmEventCurve_]->n_ = 1; - } - curveSet_[lmEventCurve_]->type_ = FC_ELLIPSE; - FillCurveClick(); - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - } -} -void BgImCanvas::OnCTypeVLine(wxCommandEvent& WXUNUSED(event)) -{ - if (lmEventCurve_ < nCurveSets_) - { - if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) - { - curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; - curveSet_[lmEventCurve_]->n_ = 1; - } - curveSet_[lmEventCurve_]->type_ = FC_VERT_LINE; - FillCurveClick(); - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - } -} -void BgImCanvas::OnCTypeHLine(wxCommandEvent& WXUNUSED(event)) -{ - if (lmEventCurve_ < nCurveSets_) - { - if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) - { - curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; - curveSet_[lmEventCurve_]->n_ = 1; - } - curveSet_[lmEventCurve_]->type_ = FC_HORIZ_LINE; - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - FillCurveClick(); - } -} -void BgImCanvas::OnCTypeLine(wxCommandEvent& WXUNUSED(event)) -{ - if (lmEventCurve_ < nCurveSets_) - { - if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) - { - curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; - curveSet_[lmEventCurve_]->n_ = 1; - } - curveSet_[lmEventCurve_]->type_ = FC_LINE; - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - FillCurveClick(); - } -} -void BgImCanvas::OnCTypeBox(wxCommandEvent& WXUNUSED(event)) -{ - if (lmEventCurve_ < nCurveSets_) - { - if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) - { - curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; - curveSet_[lmEventCurve_]->n_ = 1; - } - curveSet_[lmEventCurve_]->type_ = FC_SQUARE_BOX; - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - FillCurveClick(); - } -} -void BgImCanvas::OnCTypeCustom(wxCommandEvent& WXUNUSED(event)) -{ - if (lmEventCurve_ < nCurveSets_) - { - if (curveSet_[lmEventCurve_]->type_ != FC_CUSTOM) - { - double x[3]; - double y[3]; - int n,type; - curveSet_[lmEventCurve_]->GetParamCurve(x,y,type,n); - n = 3; - type = FC_CUSTOM; - x[2] = x[0]; - x[0] = 0; - y[2] = 0; - x[2] = (x[2]>1) ? 1:x[2]; - x[2] = (x[2]<0) ? 0:x[2]; - y[0] = (y[0]>1) ? 1:y[0]; - y[0] = (y[0]<0) ? 0:y[0]; - x[1] = (x[0]+x[2])*2.0/3.0; - y[1] = (y[0]+y[2])*2.0/3.0; - curveSet_[lmEventCurve_]->SetParamCurve(type, x, y, n, ccx_, ccy_); - } - curveSet_[lmEventCurve_]->type_ = FC_CUSTOM; - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - FillCurveClick(); - } -} - -void BgImCanvas::AddPointSet(BgPointSet* ps) -{ - pointSet_[nPointSets_++] = ps; - - //update point map if the point set consists - //of data points (not circles) - if((ps->type_ == 1)&&(hasbitmap)) - { - int nt, *tx, *ty; - nt = ps->n_; - tx = ps->x_; - ty = ps->y_; - int i, dp, width = pimage->GetWidth(); - for(i=0; i<nt; i++) - { - dp = ty[i]*width+tx[i]; - point_map[dp] = true; - } - } - - //define new pen colour is yet defined, define it - if(point_colour) delete point_colour; - point_colour = new wxColour(ps->pen_.GetColour()); - - //add point data to zoomed image (if it has been defined, - //i.e. an image has been loaded into the image canvas) - if(zImg) AddPoints(zImg, ((pimage->GetWidth())*zoom_level)); - - Refresh(); -} - -void BgImCanvas::RemovePointSet(BgPointSet* ps) -{ - int i = 0; - while (i<nPointSets_ && pointSet_[i]!=ps) - i++; - if (i<nPointSets_) - { - i++; - while(i<nPointSets_) - { - pointSet_[i-1] = pointSet_[i]; - i++; - } - nPointSets_--; - } - - //adjust point map accordingly - if((point_map)&&(ps->type_ == 1)) //point - { - int width = pimage->GetWidth(); - int nt, *tx, *ty; - nt = ps->n_; - tx = ps->x_; - ty = ps->y_; - for(i=0; i<nt; i++) - point_map[ty[i]*width+tx[i]] = false; - } - - //delete pen colour if no more point sets exist - if(nPointSets_ == 0) - { - delete point_colour; - point_colour = (wxColour *) NULL; - } - - //remove this point set from the zoomed image... - - /*********************************************************/ - - if(zImg) - { - delete [] zImg; - int width, height; - width = (pimage->GetWidth())*zoom_level; - height = (pimage->GetHeight())*zoom_level; - zImg = new unsigned char [3*width*height]; - if(zoom_level > 1) - bgZoomIn(&zImg, pimage->GetData(), pimage->GetWidth(), pimage->GetHeight(), zoom_level, false); - else if(zoom_level == 1) - memcpy(zImg, pimage->GetData(), 3*width*height*sizeof(unsigned char)); - - //add any other point sets that may exist - AddPoints(zImg, width); - } - - /*********************************************************/ - - Refresh(false); - -} - -void BgImCanvas::AddLineSet(BgLineSet* ls) -{ - lineSet_[nLineSets_++] = ls; - Refresh(); -} - -void BgImCanvas::AddTrackSet(int x, int y, int hx, int hy) -{ - trackval_[0] = x; - trackval_[1] = y; - hx_ = hx; - hy_ = hy; - showtrack_ = 1; - Refresh(); - -} - -void BgImCanvas::RemoveTrackSet() -{ - showtrack_ = 0; - Refresh(); -} - - -void BgImCanvas::RemoveLineSet(BgLineSet* ls) -{ - int i = 0; - while (i<nLineSets_ && lineSet_[i]!=ls) - i++; - if (i<nLineSets_) - { - i++; - while(i<nLineSets_) - { - lineSet_[i-1] = lineSet_[i]; - i++; - } - nLineSets_--; - } - Refresh(); -} - -void BgImCanvas::AddCurveSet(BgCurveSet* cs) -{ - curveSet_[nCurveSets_++] = cs; - Refresh(); -} - -void BgImCanvas::RemoveCurveSet(BgCurveSet* cs) -{ - int i = 0; - while (i<nCurveSets_ && curveSet_[i]!=cs) - i++; - if (i<nCurveSets_) - { - i++; - while(i<nCurveSets_) - { - curveSet_[i-1] = curveSet_[i]; - i++; - } - nCurveSets_--; - } - Refresh(); -} - -//adds text object to be dran to the image -//pre : bgText is the text object to be plotted -//post: bgText has been added to the image -void BgImCanvas::AddText(BgText *bgText) -{ - //add text to text list - if(tlist_.AddText(bgText)) - { - bgLog("BgImCanvas::AddText Error: Out of memory.\n"); - return; - } - - //obtain new text object count - textObjectCount_ = tlist_.GetTextCount(); -} - -//clears all text object from text list -void BgImCanvas::RemoveText(int text_id) -{ - tlist_.RemoveText(text_id); - return; -} - -//adds horizontal axis -void BgImCanvas::AddHorizontalAxis(int start_x, int start_y, int length, int ticknum, float start_val, float stop_val) -{ - if(xAxis) delete xAxis; - xAxis = new BgAxis(start_x, start_y, length, ticknum, 0, start_val, stop_val); -} - -//adds horizontal axis -void BgImCanvas::AddVerticalAxis(int start_x, int start_y, int length, int ticknum, float start_val, float stop_val) -{ - if(yAxis) delete yAxis; - yAxis = new BgAxis(start_x, start_y, length, ticknum, 1, start_val, stop_val); -} - -//clears axis -void BgImCanvas::ClearAxis( void ) -{ - if(xAxis) delete xAxis; - if(yAxis) delete yAxis; - xAxis = yAxis = (BgAxis *) NULL; -} - -//labels horizontal axis -void BgImCanvas::LabelHorizontalAxis(BgText *bgText) -{ - if(xAxis) xAxis->Label(bgText); -} - -//labels vertical axis -void BgImCanvas::LabelVerticalAxis(BgText *bgText) -{ - if(yAxis) yAxis->Label(bgText); -} - -//removes label on horizontal axis -void BgImCanvas::RemoveHorizontalAxisLabel(void) -{ - if(xAxis) xAxis->RemoveLabel(); -} - -//removes lable on vertical axis -void BgImCanvas::RemoveVerticalAxisLabel(void) -{ - if(yAxis) yAxis->RemoveLabel(); -} - -//rotates horizontal axis label clockwise from default position -void BgImCanvas::RotateHorizontalAxisLabel(int rotation) -{ - if(xAxis) xAxis->SetLabelRotation(rotation); -} - -//rotates vertical axis label clockwise from default position -void BgImCanvas::RotateVerticalAxisLabel(int rotation) -{ - if(yAxis) yAxis->SetLabelRotation(rotation); -} - -//plot bitmap at specified location -void BgImCanvas::AddBitmap(BgBitmap *bitmap) -{ - blist_.AddBitmap(bitmap); -} - -//remove bitmap from plot -void BgImCanvas::RemoveBitmap(BgBitmap *bitmap) -{ - blist_.RemoveBitmap(bitmap); -} - -//clears display -void BgImCanvas::ClearDisplay(void) -{ - clear_display_ = true; - Refresh(); -} - -void BgImCanvas::ClearData(int refresh) -{ - if(hasbitmap==TRUE) { - delete pbitmap; - delete pimage; - } - if(zoombox) delete zoombox; - if(refresh_box) delete refresh_box; - if(zImg) delete zImg; - if(point_map) delete [] point_map; - if(buf) delete [] buf; - hasbitmap=FALSE; - pbitmap=(wxBitmap*) NULL; - pimage=(wxImage*) NULL; - zoombox=(wxImage*) NULL; - refresh_box=(wxImage*) NULL; - zImg=NULL; - point_map=NULL; - showtrack_ = 0; - if (refresh > 0) - Refresh(); -} - -int BgImCanvas::SetImage(wxString imname) -{ - ClearData(); - pimage=new wxImage(); - if (!pimage->LoadFile(imname)) - { - delete pimage; - wxLogError("Can't load image "+imname); - return 0; - } - else - { - SetScrollbars(1, 1, (pimage->GetWidth())/1, (pimage->GetHeight())/1); -#if wxCHECK_VERSION(2, 3, 0) - pbitmap = new wxBitmap(pimage); -#else - pbitmap = new wxBitmap(pimage->ConvertToBitmap()); -#endif - hasbitmap=TRUE; - m_dirty=TRUE; - - //create point map - CreatePointMap(pimage->GetWidth(), pimage->GetHeight()); - - //take account for zoom (takes care of refresh) - Zoom(zoom_level); - } - return 1; -} - -void BgImCanvas::SetImage(wxImage& image) -{ - ClearData(); - pimage=new wxImage(); - *pimage = image; - SetScrollbars(1, 1, (pimage->GetWidth())/1, (pimage->GetHeight())/1); - -#if wxCHECK_VERSION(2, 3, 0) - pbitmap = new wxBitmap(pimage); -#else - pbitmap = new wxBitmap(pimage->ConvertToBitmap()); -#endif - hasbitmap=TRUE; - m_dirty=TRUE; - - //create point map - CreatePointMap(image.GetWidth(), image.GetHeight()); - - //take account for zoom (takes care of refresh) - Zoom(zoom_level); - -} - -void BgImCanvas::SetSameImage(wxImage& image) -{ - *pimage = image; -#if wxCHECK_VERSION(2, 3, 0) - *pbitmap = wxBitmap(image); -#else - *pbitmap = image.ConvertToBitmap(); -#endif - - //create point map - CreatePointMap(image.GetWidth(), image.GetHeight()); - - //take account for zoom (takes care of refresh) - Zoom(zoom_level); -} - -void BgImCanvas::SetImageFromGray(unsigned char* data, int w, int h) -{ - ClearData(); - - pimage = new wxImage(w, h); - - int i; - unsigned char* itTData; - itTData = pimage->GetData(); - - for (i=0; i<w*h; i++) - { - *(itTData++)=data[i]; - *(itTData++)=data[i]; - *(itTData++)=data[i]; - } - SetScrollbars(1, 1, (pimage->GetWidth())/1, (pimage->GetHeight())/1); - -#if wxCHECK_VERSION(2, 3, 0) - pbitmap = new wxBitmap(pimage); -#else - pbitmap = new wxBitmap(pimage->ConvertToBitmap()); -#endif - hasbitmap=TRUE; - m_dirty=TRUE; - - //create point map - CreatePointMap(w, h); - - //take account for zoom (takes care of refresh) - Zoom(zoom_level); -} - -void BgImCanvas::SetImage(unsigned char* data, int w, int h, bool colorim) -{ - ClearData(); - - pimage = new wxImage(w, h); - - int i; - unsigned char* itTData; - itTData = pimage->GetData(); - - if (colorim == false) - { - for (i=0; i<w*h; i++) - { - *(itTData++)=data[i]; - *(itTData++)=data[i]; - *(itTData++)=data[i]; - } - } else - { - for (i=0; i<(3*w*h); i++) - { - *(itTData++)=data[i]; - } - } - SetScrollbars(1, 1, (pimage->GetWidth())/1, (pimage->GetHeight())/1); - -#if wxCHECK_VERSION(2, 3, 0) - pbitmap = new wxBitmap(pimage); -#else - pbitmap = new wxBitmap(pimage->ConvertToBitmap()); -#endif - hasbitmap=TRUE; - m_dirty=TRUE; - - - //create point map - CreatePointMap(w, h); - - //take account for zoom (takes care of refresh) - Zoom(zoom_level); -} - -/* -Still needs work!!!!!! -*/ - -void BgImCanvas::ShowBitmap(bool showbitmap) -{ - showbitmap_ = showbitmap; - if(hasbitmap) - { - //compute height and width of original image - int width = pimage->GetWidth(); - int height = pimage->GetHeight(); - - //paint zoom image - if(!showbitmap_) - memset(zImg, 255, 3*zoom_level*zoom_level*width*height*sizeof(unsigned char)); - else - bgZoomIn(&zImg, pimage->GetData(), width, height, zoom_level, false); - - //plot points from point set onto zoom image - AddPoints(zImg, width*zoom_level); - - //re-draw image onto canvas - Refresh(); - } - return; -} - - -// Define the repainting behaviour -void BgImCanvas::OnDraw(wxDC& dc) -{ - //clear the display - if(clear_display_) - { - clear_display_ = false; - dc.Clear(); - return; - } - - //do not update the display (good for keeping - //a display clear in light of onSize() events - //for example) - if(noUpdate_) return; - - //catch leaving event - if((zoom_window)&&(leaving)) - { - //if a refresh window remains, plot it and delete it - if(refresh_box) - { -#if wxCHECK_VERSION(2, 3, 0) - dc.DrawBitmap(wxBitmap(refresh_box), cx, cy); -#else - dc.DrawBitmap(refresh_box->ConvertToBitmap(), cx, cy); -#endif - delete refresh_box; - refresh_box = (wxImage*) NULL; - } - - //retrieve leaving event - leaving = false; - - //exit - return; - } - - - if (hasbitmap==false) - { - dc.Clear(); - return; - } - //re-plot image bitmap - if(hasbitmap==true && showbitmap_==true) - { - if((!zoom_window)||(!has_focus)) - dc.DrawBitmap(*pbitmap,0+x_offset_,0+y_offset_); - } - else if(!zoom_window) - { - dc.Clear(); - } - if (showtrack_ == 1) - { - wxPen tPen=dc.GetPen(); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.SetPen(*wxRED_PEN); - //+x_offset_+y_offset_ - dc.DrawEllipse(trackval_[0]-2, trackval_[1]-2, 5,5); - dc.DrawEllipse(trackval_[0]-hx_, trackval_[1]-hy_, 2*hx_+1, 2*hy_+1); - dc.SetPen(tPen); - dc.SetBrush(wxNullBrush); - } - if ((nPointSets_ > 0)&&((!zoom_window)||(!has_focus))) - { - int i,j; - int* tx; - int* ty; - int x, xc; - int y, yc; - int nt; - wxPen tPen=dc.GetPen(); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - for (i=0; i<nPointSets_; i++) - { - dc.SetPen(pointSet_[i]->pen_); - nt = pointSet_[i]->n_; - tx = pointSet_[i]->x_; - ty = pointSet_[i]->y_; - if(pointSet_[i]->type_ == 0) // circle - { - for (j=0; j<nt; j++) - { - dc.DrawEllipse(tx[j]-2+x_offset_, ty[j]-2+y_offset_, 5,5); - } - } - else if(pointSet_[i]->type_ == 1) // point - { - for (j=0; j<nt; j++) - { - xc = zoom_level*(tx[j] + x_offset_); - yc = zoom_level*(ty[j] + y_offset_); - for(y=0; y<zoom_level; y++) - { - for(x=0; x<zoom_level; x++) - { - dc.DrawPoint(xc+x, yc+y); - } - } - } - } - } - dc.SetPen(tPen); - dc.SetBrush(wxNullBrush); - } - - if (nLineSets_ > 0) - { - int i,j; - int* tsx; - int* tsy; - int* tex; - int* tey; - int nt; - wxPen tPen=dc.GetPen(); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - for (i=0; i<nLineSets_; i++) - { - dc.SetPen(lineSet_[i]->pen_); - nt = lineSet_[i]->n_; - tsx = lineSet_[i]->xs_; - tsy = lineSet_[i]->ys_; - tex = lineSet_[i]->xe_; - tey = lineSet_[i]->ye_; - for (j=0; j<nt; j++) - { - dc.DrawLine(tsx[j]+x_offset_, tsy[j]+y_offset_, tex[j]+x_offset_, tey[j]+y_offset_); - } - } - dc.SetPen(tPen); - dc.SetBrush(wxNullBrush); - } - int txs,tys,txe,tye; - - if (nCurveSets_ > 0) - { - int i,j; - int* tx; - int* ty; - int xs, ys; - int nt; - wxPen tPen=dc.GetPen(); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - for (i=0; i<nCurveSets_; i++) - { - dc.SetPen(curveSet_[i]->pen_); - tx = curveSet_[i]->x_; - ty = curveSet_[i]->y_; - nt = curveSet_[i]->n_; - xs = curveSet_[i]->xs_; - ys = curveSet_[i]->ys_; - - switch (curveSet_[i]->type_) - { - case -1: - break; - case FC_ELLIPSE: - MyDrawEllipticArc(dc,-tx[0]+x_offset_, ty[0]+y_offset_, 2*tx[0], 2*(ys-ty[0]), 0, 90); - break; - case FC_VERT_LINE: - // if ((tx[0]>=0) && (tx[0]<xs)) - dc.DrawLine(tx[0]+x_offset_, 0+y_offset_, tx[0]+x_offset_, ys+y_offset_); - break; - case FC_HORIZ_LINE: - if ((ty[0]>=0) && (ty[0]<ys)) - dc.DrawLine(0+x_offset_, ty[0]+y_offset_, xs+x_offset_, ty[0]+y_offset_); - break; - case FC_LINE: - // determine clipping - tye = ys; - txe = tx[0]; - txe = (txe<=0)?1:txe; - txs = 0; - tys = ty[0]; - tys = (tys>ys)?ys:tys; - if (txe>xs) - { - tye = ccy_-((ccy_-tys)*(txe-xs))/txe; - txe = xs; - } - if (tys<0) - { - txs= (txe*(-tys))/(tye-tys); - tys= 0; - } - - dc.DrawLine(0+x_offset_, ty[0]+y_offset_, tx[0]+x_offset_, ys+y_offset_); - break; - case FC_SQUARE_BOX: - txs = (tx[0]<0)?0:tx[0]; - txs = (txs>=xs)?xs-1:txs; - tys = (ty[0]<0)?0:ty[0]; - tys = (tys>=ys)?ys-1:tys; - dc.DrawLine(0+x_offset_, tys+y_offset_, txs+x_offset_, tys+y_offset_); - dc.DrawLine(txs+x_offset_, tys+y_offset_, txs+x_offset_, ys+y_offset_); - break; - case FC_CUSTOM: - for (j=0; j<(nt-1); j++) - dc.DrawLine(tx[j]+x_offset_, ty[j]+y_offset_, tx[j+1]+x_offset_, ty[j+1]+y_offset_); - break; - } - // wxPen pPen=dc.GetPen(); - // pPen.SetWidth(17); - // pPen.SetColour(64,64,64); - // dc.SetPen(pPen); - switch (curveSet_[i]->type_) - { - case -1: - break; - case FC_ELLIPSE: - case FC_LINE: - // dc.DrawPoint(0,ty[0]); - // dc.DrawPoint(tx[0],ys); - dc.DrawRectangle(0-2+x_offset_,ty[0]-2+y_offset_,5,5); - dc.DrawRectangle(tx[0]-2+x_offset_,ys-2+y_offset_,5,5); - break; - case FC_SQUARE_BOX: - // dc.DrawPoint(0,ty[0]); - // dc.DrawPoint(tx[0],ys); - // dc.DrawPoint(tx[0],ty[0]); - dc.DrawRectangle(0-2+x_offset_,ty[0]-2+y_offset_,5,5); - dc.DrawRectangle(tx[0]-2+x_offset_,ys-2+y_offset_,5,5); - dc.DrawRectangle(tx[0]-2+x_offset_,ty[0]-2+y_offset_,5,5); - break; - case FC_CUSTOM: - for (j=0; j<nt; j++) - dc.DrawRectangle(tx[j]-2+x_offset_,ty[j]-2+y_offset_,5,5); - // dc.DrawPoint(tx[j],ty[j]); - break; - } - } - dc.SetPen(tPen); - dc.SetBrush(wxNullBrush); - } - - if (isDragging_ == 1) - { - int j; - int* tx; - int* ty; - int xs, ys; - int nt; - wxPen tPen=dc.GetPen(); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.SetPen(dragCurve_.pen_); - tx = dragCurve_.x_; - ty = dragCurve_.y_; - nt = dragCurve_.n_; - xs = dragCurve_.xs_; - ys = dragCurve_.ys_; - - switch (dragCurve_.type_) - { - case -1: - break; - case FC_ELLIPSE: - MyDrawEllipticArc(dc,-tx[0]+x_offset_, ty[0]+y_offset_, 2*tx[0], 2*(ys-ty[0]), 0, 90); - break; - case FC_VERT_LINE: - // if ((tx[0]>=0) && (tx[0]<xs)) - dc.DrawLine(tx[0]+x_offset_, 0+y_offset_, tx[0]+x_offset_, ys+y_offset_); - break; - case FC_HORIZ_LINE: - if ((ty[0]>=0) && (ty[0]<ys)) - dc.DrawLine(0+x_offset_, ty[0]+y_offset_, xs+x_offset_, ty[0]+y_offset_); - break; - case FC_LINE: - // determine clipping - tye = ys; - txe = tx[0]; - txe = (txe<=0)?1:txe; - txs = 0; - tys = ty[0]; - tys = (tys>ys)?ys:tys; - if (txe>xs) - { - tye = ccy_-((ccy_-tys)*(txe-xs))/txe; - txe = xs; - } - if (tys<0) - { - txs= (txe*(-tys))/(tye-tys); - tys= 0; - } - - dc.DrawLine(0+x_offset_, ty[0]+y_offset_, tx[0]+x_offset_, ys+y_offset_); - break; - case FC_SQUARE_BOX: - txs = (tx[0]<0)?0:tx[0]; - txs = (txs>=xs)?xs-1:txs; - tys = (ty[0]<0)?0:ty[0]; - tys = (tys>=ys)?ys-1:tys; - dc.DrawLine(0+x_offset_, tys+y_offset_, txs+x_offset_, tys+y_offset_); - dc.DrawLine(txs+x_offset_, tys+y_offset_, txs+x_offset_, ys+y_offset_); - break; - case FC_CUSTOM: - for (j=0; j<(nt-1); j++) - dc.DrawLine(tx[j]+x_offset_, ty[j]+y_offset_, tx[j+1]+x_offset_, ty[j+1]+y_offset_); - break; - } - - dc.SetPen(tPen); - dc.SetBrush(wxNullBrush); - - } - - //draw horizontal and vertical axis - if(xAxis) xAxis->PlotAxis(&dc); - if(yAxis) yAxis->PlotAxis(&dc); - - //draw new text to the image from text object list - BgText *bgText; - tlist_.ResetList(); - while(bgText = tlist_.GetText()) - { - dc.SetFont(*(bgText->font_)); - dc.DrawText(bgText->text_, bgText->x_, bgText->y_); - } - - //draw bitmaps - blist_.ResetList(); - BgBitmap *bitmap; - while(bitmap = blist_.GetBitmap()) - dc.DrawBitmap(*(bitmap->bitmap_), bitmap->location_x_, bitmap->location_y_, true); - - //draw zoom window box - if((zoom_window)&&(has_focus)) - { - //draw refresh window -#if wxCHECK_VERSION(2, 3, 0) - if(refresh_box) dc.DrawBitmap(wxBitmap(refresh_box), cx, cy); -#else - if(refresh_box) dc.DrawBitmap(refresh_box->ConvertToBitmap(), cx, cy); -#endif - - //compute height and width of zoom box and window - int zWidth, zHeight; - int dWidth, dHeight; - zWidth = zoombox->GetWidth(); - zHeight = zoombox->GetHeight(); - GetSize(&dWidth, &dHeight); - - //compute upper corner of window - cx = m_x_ - zWidth/2; - cy = m_y_ - zHeight/2; - - //check bounds.... - if(cx < 0) cx = 0; - if(cy < 0) cy = 0; - if(cx >= dWidth - zWidth) cx = dWidth - zWidth - 1; - if(cy >= dHeight - zHeight) cy = dHeight - zHeight - 1; - - //place in image coordinate frame - cx = cx + GetScrollPos(wxHORIZONTAL); - cy = cy + GetScrollPos(wxVERTICAL); - - //check bounds - int width = pimage->GetWidth()*zoom_level, height = pimage->GetHeight()*zoom_level; - if(cx >= width - zWidth) cx = width - zWidth - 1; - if(cy >= height - zHeight) cy = height - zHeight - 1; - - //draw zoom window -#if wxCHECK_VERSION(2, 3, 0) - dc.DrawBitmap(wxBitmap(zoombox), cx, cy); -#else - dc.DrawBitmap(zoombox->ConvertToBitmap(), cx, cy); -#endif - - //create refresh box for next iteration - DefineRefreshBox(); - } - -} - -//adds an image margin to the image -//pre : (x_margin, y_margin) define the margins in the -// x and y direction respectively -//post: an image margin has been added -void BgImCanvas::AddMargin(int x_margin, int y_margin) -{ - //shift the image - x_offset_ = x_margin; - y_offset_ = y_margin; - - //redraw the image - Refresh(); - -} - -//overloaded zoom function that does not use current mouse position -int BgImCanvas::Zoom(int zconst) -{ - return Zoom(zconst, 0, 0); -} - -//allows one to zoom into/out of the image dispalyed by the image canvas -//pre : zconst is the zoom constant -// (m_x, m_y) is the current position of the mouse -//post: the image has been zoomed in by a factor of zconst -// returns 1 when zoom not possible due to image constraints, -// zoom at maximum or minimum image dimensions, or possible error -int BgImCanvas::Zoom(int zconst, int m_x, int m_y) -{ - //must have bitmap to zoom - if(hasbitmap) - { - //determine zooming action - int action; - if(zconst < zoom_level) - action = ZOOM_OUT; - else if(zconst > zoom_level) - action = ZOOM_IN; - - //check bounds - int width = pimage->GetWidth(), height = pimage->GetHeight(); - if(zconst < 0) - { - //take absolute value of zoom constant - int pos_zc = -zconst; - - //compute new width - if(width%pos_zc) - width = width/pos_zc+1; - else - width /= pos_zc; - - //compute new height - if(height%pos_zc) - height = height/pos_zc+1; - else - height /= -zconst; - - //make sure width and height are above minimum - //before continuing - if((width < MIN_WIDTH)||(height < MIN_HEIGHT)) - return 1; - } - else if (zconst > 0) - { - width *= zconst; - height *= zconst; - if((width > MAX_WIDTH)||(height > MAX_HEIGHT)) - return 1; - } - else - { - //zconst equals zero (ambiguous so exit) - return 1; - } - - //set zoom_level - zoom_level = zconst; - - if(zoom_level == 1) - { - delete pbitmap; -#if wxCHECK_VERSION(2, 3, 0) - pbitmap = new wxBitmap(pimage); -#else - pbitmap = new wxBitmap(pimage->ConvertToBitmap()); -#endif - if(zImg) delete zImg; - zImg = new unsigned char [3*height*width]; - memcpy(zImg, pimage->GetData(), 3*height*width); - } - else if(zoom_level > 1) - { - //zoom into image using zoom level - wxImage tempIm(width, height); - if(zImg) delete [] zImg; - zImg = new unsigned char [3*width*height]; - bgZoomIn(&zImg, pimage->GetData(), pimage->GetWidth(), pimage->GetHeight(), zoom_level, false); - memcpy(tempIm.GetData(), zImg, 3*width*height*sizeof(unsigned char)); - - //reset the bitmap using zoomed image - delete pbitmap; -#if wxCHECK_VERSION(2, 3, 0) - pbitmap = new wxBitmap(tempIm); -#else - pbitmap = new wxBitmap(tempIm.ConvertToBitmap()); -#endif - } - else if(zoom_level < -1) - { - //zoom out of image using zoom level - wxImage tempIm(width, height); - if(zImg) delete [] zImg; - zImg = new unsigned char [3*width*height]; - bgZoomOut(&zImg, pimage->GetData(), pimage->GetWidth(), pimage->GetHeight(), (-zoom_level), false); - memcpy(tempIm.GetData(), zImg, 3*width*height*sizeof(unsigned char)); - - //reset the bitmap using zoomed image - delete pbitmap; -#if wxCHECK_VERSION(2, 3, 0) - pbitmap = new wxBitmap(tempIm); -#else - pbitmap = new wxBitmap(tempIm.ConvertToBitmap()); -#endif - } - - //if a bitmap is not to be shown, clear (make white) the - //zoomed image - if(!showbitmap_) - memset(zImg, 255, 3*width*height*sizeof(unsigned char)); - - //add point data to zoomed image - AddPoints(zImg, width); - - //re-display image - Refresh(); - - //set scroll bars according to current mouse position and zooming action - AdjustScroll(m_x, m_y, action); - - //return 1 when maximum or minimum image dimension has occured - if((width == MAX_WIDTH)||(width == MIN_WIDTH)||(height == MAX_HEIGHT)||(height == MIN_HEIGHT)) - return 1; - - //return 1 when close to maximum or minimum image dimension... - /*********************************************************************/ - - if(zconst > 0) - { - width += pimage->GetWidth(); - height += pimage->GetHeight(); - if((width > MAX_WIDTH)||(height > MAX_HEIGHT)) - return 1; - } - else if(zconst < 0) - { - - //obtain width and height of original image - width = pimage->GetWidth(); - height = pimage->GetHeight(); - - //take absolute value of zoom constant - int pos_zc = -zconst; - - //compute new width - if(width%pos_zc) - width = width/pos_zc+1; - else - width /= pos_zc; - - //compute new height - if(height%pos_zc) - height = height/pos_zc+1; - else - height /= -zconst; - width = (pimage->GetWidth()); - - //check image bounds... - if((width < MIN_WIDTH)||(height < MIN_HEIGHT)) - return 1; - } - - /*********************************************************************/ - } - - //done. - return 0; - -} - -//allows one to zoom into the image stored by the image canvas -//pre : (m_x, m_y) is the current mouse position -//post: the image has been zoomed in by a factor of zoom_level+1 -// 1 is returned when max zoom level is reached -int BgImCanvas::ZoomIn(int m_x, int m_y) -{ - //must have bitmap to zoom into - if(hasbitmap) - { - //make sure zoom level is not at maximum before proceeding - - //max_zoom_level has value 0 when unspecified - if((max_zoom_level)&&(zoom_level == max_zoom_level)) - { - wxWindow *parent = child_frame_->GetParent(); - ((BgMdiFrame *) parent)->UpdateZoomControl((wxMDIChildFrame *) child_frame_, true, false); - return 1; - } - - //zoom image - int zconst = zoom_level + 1; - if(zconst == -1) zconst = 1; - int maxZoom = Zoom(zconst, m_x, m_y); - - //take into account maximum zoom level - maxZoom = (maxZoom || ((max_zoom_level)&&(zoom_level == max_zoom_level))); - - //set title of child frame - wxWindow *parent = child_frame_->GetParent(); - ((BgMdiFrame *) parent)->SetChildTitle((wxMDIChildFrame *) child_frame_, zoom_level, maxZoom, false); - - //update zoom control of child frame - ((BgMdiFrame *) parent)->UpdateZoomControl((wxMDIChildFrame *) child_frame_, maxZoom, false); - - //indicate if max zoom has occured - return maxZoom; - } - - //done. - return 0; -} - -//allows one to zoom out of the image stored by the image canvas -//pre : (m_x, m_y) is the current mouse position -//post: the image has been zoomed out by a factor of zoom_level-1 -// returns 1 if minimum zoom has occured -int BgImCanvas::ZoomOut(int m_x, int m_y) -{ - //must have bitmap to zoom into - if(hasbitmap) - { - //make sure zoom level is not at minimum before proceeding - - //min_zoom_level has value 0 when unspecified - if((min_zoom_level)&&(zoom_level == min_zoom_level)) - { - wxWindow *parent = child_frame_->GetParent(); - ((BgMdiFrame *) parent)->UpdateZoomControl((wxMDIChildFrame *) child_frame_, false, true); - return 1; - } - - //zoom image - int zconst = zoom_level - 1; - if(zconst == 0) zconst = -2; - int minZoom = Zoom(zconst, m_x, m_y); - - //take into account mininimum zoom level; - minZoom = (int)(minZoom ||((min_zoom_level)&&(zoom_level == min_zoom_level))); - - //set title of child frame - wxWindow *parent = child_frame_->GetParent(); - ((BgMdiFrame *) parent)->SetChildTitle((wxMDIChildFrame *) child_frame_, zoom_level, false, minZoom); - - //update zoom control of child frame - ((BgMdiFrame *) parent)->UpdateZoomControl((wxMDIChildFrame *) child_frame_, false, minZoom); - - //indicate if min zoom has occured - return minZoom; - } - - //done. - return 0; -} - -//sets max zoom level -void BgImCanvas::SetMaxZoomLevel(int mzl) -{ - max_zoom_level = mzl; -} - -//sets min zoom level -void BgImCanvas::SetMinZoomLevel(int mzl) -{ - min_zoom_level = mzl; -} - - -#define WIN_PERC 16 - -void BgImCanvas::DefineZoomBox(int l_x, int h_x, int l_y, int h_y) -{ - - //obtain image height and width - int iWidth = pimage->GetWidth(), iHeight = pimage->GetHeight(); - - //calculate box height and width - static int bWidth = h_x-l_x+1, bHeight = h_y-l_y+1; - - //allocate/deallocate memory - if((bWidth != h_x-l_x+1)||(!buf)) - { - bWidth = h_x-l_x+1; - bHeight = h_y-l_y+1; - if(buf) delete buf; - buf = new unsigned char [3*bWidth*bHeight]; - } - - //get point pen colour - unsigned char r, g, b; - if(point_colour) - { - r = point_colour->Red(); - g = point_colour->Green(); - b = point_colour->Blue(); - } - - //crop image data and store it into buf (if the bitmap is being displayed...) - unsigned char *imData = pimage->GetData(); - int bx, by, ix, iy, idp, bdp; - if(showbitmap_) - { - for(by=0; by<bHeight; by++) - { - for(bx=0; bx<bWidth; bx++) - { - ix = bx + l_x; - iy = by + l_y; - idp = 3*(iy*iWidth + ix); - bdp = 3*(by*bWidth + bx); - buf[bdp ] = imData[idp ]; - buf[bdp+1] = imData[idp+1]; - buf[bdp+2] = imData[idp+2]; - - //account for point sets using point map - if(point_map[idp/3]) - { - buf[bdp] = r; - buf[bdp+1] = g; - buf[bdp+2] = b; - } - } - } - } - //create blank (white) image and plot point set onto it - //prior to zoom - else - { - memset(buf, 255, 3*bWidth*bHeight*sizeof(unsigned char)); - for(by=0; by<bHeight; by++) - { - for(bx=0; bx<bWidth; bx++) - { - ix = bx + l_x; - iy = by + l_y; - idp = 3*(iy*iWidth + ix); - bdp = 3*(by*bWidth + bx); - - //account for point sets using point map - if(point_map[idp/3]) - { - buf[bdp] = r; - buf[bdp+1] = g; - buf[bdp+2] = b; - } - } - } - } - - //zoom the data in buf... - - //set zoom window size and allocate memory - static int zWidth = bWidth*zoom_level*2; - static int zHeight = bHeight*zoom_level*2; - if((zWidth != bWidth*zoom_level*2)||(!zoombox)) - { - zWidth = bWidth*zoom_level*2; - zHeight = bHeight*zoom_level*2; - if(zoombox) delete zoombox; - zoombox = new wxImage(zWidth, zHeight); - - } - - //create a zoom box image using buf - unsigned char *zbData = zoombox->GetData(); - bgZoomIn(&zbData, buf, bWidth, bHeight, zoom_level*2, false); - - //done. - return; -} - -void BgImCanvas::DefineRefreshBox(void) -{ - - //obtain image height and width - int iWidth = pimage->GetWidth()*zoom_level, iHeight = pimage->GetHeight()*zoom_level; - - //calculate box height and width - static int bWidth = zoombox->GetWidth(), bHeight = zoombox->GetHeight(); - - //allocate/de-allocate memory for refresh box - if((bWidth != zoombox->GetWidth())||(!refresh_box)) - { - bWidth = zoombox->GetWidth(); - bHeight = zoombox->GetHeight(); - if(refresh_box) delete [] refresh_box; - refresh_box = new wxImage(bWidth, bHeight); - } - unsigned char *rBuf = refresh_box->GetData(); - - //get point pen colour - unsigned char r, g, b; - if(point_colour) - { - r = point_colour->Red(); - g = point_colour->Green(); - b = point_colour->Blue(); - } - - //define refresh box... - - //crop image data and store it into rBuf... - unsigned char *imData = pimage->GetData(); - int bx, by, ix, iy, bdp, idp; - for(by=0; by<bHeight; by++) - { - for(bx=0; bx<bWidth; bx++) - { - ix = bx + cx; - iy = by + cy; - idp = 3*(iy*iWidth + ix); - bdp = 3*(by*bWidth + bx); - rBuf[bdp ] = zImg[idp ]; - rBuf[bdp+1] = zImg[idp+1]; - rBuf[bdp+2] = zImg[idp+2]; - } - } - - //done. - return; -} - -//creates point map used by zoom and refresh windows -void BgImCanvas::CreatePointMap(int w, int h) -{ - - //initialze point map - if(point_map) delete [] point_map; - point_map = new bool [w*h]; - memset(point_map, 0, w*h*sizeof(bool)); - - //if point sets already exist then add the, - if (nPointSets_ > 0) - { - //adjust point pen colour to be that of the last - //point set added - if(point_colour) delete point_colour; - point_colour = new wxColour(pointSet_[nPointSets_-1]->pen_.GetColour()); - - int nt, *tx, *ty, i, j; - for (i=0; i<nPointSets_; i++) - { - nt = pointSet_[i]->n_; - tx = pointSet_[i]->x_; - ty = pointSet_[i]->y_; - if(pointSet_[i]->type_ == 1) // point - { - for(j=0; j<nt; j++) - point_map[ty[j]*w+tx[j]] = true; - } - } - } -} - -//adds points from point sets onto specified image -void BgImCanvas::AddPoints(unsigned char *im, int width) -{ - //if point sets have been defined add point data to image - if(nPointSets_ > 0) - { - unsigned char r, g, b; - wxColour pen_colour; - int nt, *tx, *ty, i, j, x, y, dp, offset; - for(i=0; i < nPointSets_; i++) - { - if(pointSet_[i]->type_ == 1) //point - { - //get pen colour - pen_colour = pointSet_[i]->pen_.GetColour(); - r = pen_colour.Red(); - g = pen_colour.Green(); - b = pen_colour.Blue(); - - //place points - nt = pointSet_[i]->n_; - tx = pointSet_[i]->x_; - ty = pointSet_[i]->y_; - for(j=0; j<nt; j++) - { - dp = 3*(ty[j]*width+tx[j])*zoom_level; - for(y=0; y<zoom_level; y++) - { - for(x=0; x<zoom_level; x++) - { - offset = 3*(y*width+x); - im[dp+offset ] = r; - im[dp+offset+1] = g; - im[dp+offset+2] = b; - } - } - } - } - } - } -} - -//displays zoom window at cursor position -void BgImCanvas::DisplayZoomWindow(int m_x, int m_y) -{ - - //set mouse position... - m_x_ = m_x; - m_y_ = m_y; - - //compute width and height of window.... - - /***********************************************************/ - - //obtain image height and width - int w = pimage->GetWidth(), h = pimage->GetHeight(); - - //take percentage of height and width to compute - //box half-width and half-height - int hw, hh; - int wp = WIN_PERC; - if(w%wp) - hw = w/wp + 1; - else - hw = w/wp; - - if(h%wp) - hh = h/wp + 1; - else - hh = h/wp; - - /***********************************************************/ - - //normalize mouse coordinates to image coordinate frame - - /***********************************************************/ - - if(zoom_level > 0) - { - m_x = (m_x + GetScrollPos(wxHORIZONTAL))/zoom_level; - m_y = (m_y + GetScrollPos(wxVERTICAL))/zoom_level; - } - else if(zoom_level < 0) - { - m_x = (m_x + GetScrollPos(wxHORIZONTAL))*(-zoom_level); - m_y = (m_y + GetScrollPos(wxVERTICAL))*(-zoom_level); - } - - /***********************************************************/ - - //make sure x_m and y_m are with bounds before proceeding... - - /***********************************************************/ - - if((m_x < 0)||(m_x >= w)||(m_y < 0)||(m_y >= h)) - return; - - /***********************************************************/ - - //compute zoom window bounds... - - /***********************************************************/ - - //define window bounds based on current mouse position - int low_x, hi_x, low_y, hi_y; - if((low_x = m_x - hw) < 0) low_x = 0; - if((hi_x = m_x + hw) >= w) hi_x = w-1; - if((low_y = m_y - hh) < 0) low_y = 0; - if((hi_y = m_y + hh) >= h) hi_y = h-1; - - //make window larger according to current mouse position - if(m_x <= hw) hi_x += hw-m_x; - if((w-m_x-1) <= hw) low_x -= hw-(w-m_x-1); - if(m_y <= hh) hi_y += hh-m_y; - if((h-m_y-1) <= hh) low_y -= hh-(h-m_y-1); - - /***********************************************************/ - - //define zoom box... - - /***********************************************************/ - - DefineZoomBox(low_x, hi_x, low_y, hi_y); - - /***********************************************************/ - - //display zoomed image over current mouse position... - - /***********************************************************/ - - Refresh(false); - - /***********************************************************/ - - //done. - return; - -} - -/* -void BgImCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event)) -{ -} -*/ -void BgImCanvas::FillCurveClick() -{ - int i; - for (i=0; i<ccx_*ccy_; i++) - curveClick_[i] = 0; - - for (i=0; i<nCurveSets_; i++) - curveSet_[i]->DrawYourself(curveClick_, i+1); - - Refresh(); -// write_pgm_image("curveclick.pgm", curveClick_, 256, 256, "", 4); -} - -/* -void BgImCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) -{ - wxClientDC dc(this); - PrepareDC(dc); - if(hasbitmap==TRUE) - { - dc.DrawBitmap(*pbitmap,0,0); - } - else - { - dc.Clear(); - } -} -*/ - -void BgImCanvas::MyDrawEllipticArc(wxDC& dc, int x, int y, int w, int h, int sa, int ea) -{ - double xc, yc, rx, ry; - rx = w/2; - ry = h/2; - xc = x+rx; - yc = y+ry; - int r, c; - int low_r = y_offset_; - int hig_r = ccy_+y_offset_; - int low_c = x_offset_; - int hig_c = ccx_+x_offset_; - -// if (rx > ry) -// { - // x scan - for (c = (int) xc; c<=(int) (xc+rx); c++) - { - if (c>=low_c && c<hig_c) - { - r = bgRound(yc-ry*sqrt(1-(c-xc)*(c-xc)/(rx*rx))); - if (r>=low_r && r<hig_r) - { - dc.DrawPoint(c,r); - // +/- 1 - if ((r+1)<hig_r) dc.DrawPoint(c,r+1); - if ((r-1)>=low_r) dc.DrawPoint(c,r-1);; - } - } - } -// } -// else -// { - // y scan - for (r = (int)(yc-ry); r<=(int) yc; r++) - { - if (r>=low_r && r<hig_r) - { - c = bgRound(xc+rx*sqrt(1-(r-yc)*(r-yc)/(ry*ry))); - if (c>=low_c && c<hig_c) - { - dc.DrawPoint(c,r); - // +/- 1 - if ((c+1)<hig_c) dc.DrawPoint(c+1,r); - if ((c-1)>=low_c) dc.DrawPoint(c-1,r);; - } - } - } -// } -} - -void BgImCanvas::OnMouseRightDown(wxMouseEvent& event) -{ - wxClientDC dc(this); - PrepareDC(dc); - wxPoint pt(event.GetLogicalPosition(dc)); - static int x; - static int y; - x = pt.x-x_offset_; - y = pt.y-y_offset_; - if (x>=0 && x<ccx_ && y>=0 && y<ccy_) - { - if (curveClick_[x+y*ccx_]>0) - { - lmEventCurve_ = curveClick_[x+y*ccx_] - 1; - if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) - { - // determine if close to a node - int *tempx, *tempy, tempn; - double mindist, crtdist; - int i, minnode; - tempx = curveSet_[lmEventCurve_]->x_; - tempy = curveSet_[lmEventCurve_]->y_; - tempn = curveSet_[lmEventCurve_]->n_; - mindist = sqrt((x-tempx[0])*(x-tempx[0])+(y-tempy[0])*(y-tempy[0])); - minnode = 0; - for (i=1; i<tempn; i++) - { - crtdist = sqrt((x-tempx[i])*(x-tempx[i])+(y-tempy[i])*(y-tempy[i])); - if (crtdist < mindist) - { - mindist = crtdist; - minnode = i; - } - } - if (mindist <= 3) - { - // delete node option - lmEventNode_ = minnode; - localMenu_->Enable(BG_IMC_ADDNODE,FALSE); - localMenu_->Enable(BG_IMC_DELETENODE,TRUE); - } else - { - // add node option - localMenu_->Enable(BG_IMC_ADDNODE,TRUE); - localMenu_->Enable(BG_IMC_DELETENODE,FALSE); - } - } - else - { - localMenu_->Enable(BG_IMC_ADDNODE,FALSE); - localMenu_->Enable(BG_IMC_DELETENODE,FALSE); - } - lmEventX_ = x;//+x_offset_; - lmEventY_ = y;//+y_offset_; - PopupMenu(localMenu_, x+x_offset_, y+y_offset_); - } - } -} - -/* -//updates hover menu during scroll event -void BgImCanvas::OnScroll(wxScrollWinEvent& event) -{ - -} -*/ - -//attemtps to adjust scroll position of window according -//to current mouse position -void BgImCanvas::AdjustScroll(int x, int y, int action) -{ - if(zoom_level > 1) - { - - //get window width and height - int winWidth, winHeight; - GetSize(&winWidth, &winHeight); - - //get window vertical and horzontal scroll position - //and offset current mouse position to obtain mouse - //position relative to the image - x = x + GetScrollPos(wxHORIZONTAL); - y = y + GetScrollPos(wxVERTICAL); - - //re-location mouse position relative to new image width - //and height - if(action == ZOOM_IN) - { - x = zoom_level*(x/(zoom_level-1)); - y = zoom_level*(y/(zoom_level-1)); - } - else if(action == ZOOM_OUT) - { - x = zoom_level*(x/(zoom_level+1)); - y = zoom_level*(y/(zoom_level+1)); - } - - //resize scroll - int width = (pimage->GetHeight())*zoom_level; - int height = (pimage->GetWidth())*zoom_level; - SetScrollbars(1, 1, width, height); - - //set scroll position according to x and y - int offset_x = x/2; - int offset_y = y/2; - SetScrollPos(wxHORIZONTAL, offset_x, true); - SetScrollPos(wxVERTICAL, offset_y, true); - - //refresh window contents - Scroll(offset_x, offset_y); - } -} - -void BgImCanvas::OnEvent(wxMouseEvent& event) -{ -/* - wxClientDC dc(this); - PrepareDC(dc); - - wxPoint pt(event.GetLogicalPosition(dc)); - - if (g_xpos > -1 && g_ypos > -1 && event.Dragging()) - { - dc.SetPen(*wxBLACK_PEN); - dc.DrawLine(g_xpos, g_ypos, pt.x, pt.y); - - m_dirty = TRUE; - } - - g_xpos = pt.x; - g_ypos = pt.y; - */ - - - //store mouse pointer location... - m_x_ = event.m_x; - m_y_ = event.m_y; - - //keep track of menu window (hide/show)... - static bool hideWindow = true; - if((m_x_ >= menuXl_)&&(m_y_ >= menuYl_)&&(m_x_ <= menuXu_)&&(m_y_ <= menuYu_)) - hideWindow = false; - else if(!event.Leaving()) - hideWindow = true; - - wxClientDC dc(this); - PrepareDC(dc); - wxPoint pt(event.GetLogicalPosition(dc)); - static int x; - static int y; - static int curvedrag; - x = pt.x-x_offset_; - y = pt.y-y_offset_; -// x = event.GetX(); -// y = event.GetY(); - - if (isDragging_ == 0 && event.LeftDown()) - { - // check if over any line - if (x>=0 && x<ccx_ && y>=0 && y<ccy_) - { - if (curveClick_[x+y*ccx_]>0) - { - isDragging_ = 1; - curvedrag = curveClick_[x+y*ccx_]-1; - dragCurve_.SetCurve(curveSet_[curveClick_[x+y*ccx_]-1]); - dragCurve_.pen_.SetColour(wxColour(128,128,128)); - dragCurve_.StartDragging(x, y); - Refresh(); - } - } - } - else if (isDragging_ == 1 && event.Dragging()) - { - // modify curve to drag - dragCurve_.DragTo(x, y); - Refresh(false); - } - else if (isDragging_ == 1)// && event.LeftUp()) - { - isDragging_ = 0; - dragCurve_.EndDragging(x, y); - curveSet_[curvedrag]->SetCurve(&dragCurve_); - FillCurveClick(); - mouseModif_ = 1; - AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); - Refresh(); - } - else if (isDragging_ == 0 && event.Moving()) - { - // check if over any line - if (x>=0 && x<ccx_ && y>=0 && y<ccy_) - { - if (curveClick_[x+y*ccx_]>0 && crossCursor_ == 0) - { - crossCursor_ = 1; - SetCursor(*wxCROSS_CURSOR); - } - else if (crossCursor_ == 1) - { - SetCursor(*wxSTANDARD_CURSOR); - crossCursor_ = 0; - } - } - } - - //if zoom is enabled, set the cursor to the zoom icon - //otherwise leave it as default - if(event.Entering()) - { - //when parent is not the active child frame, set the cursor - //to wxCURSOR_ARROW - bool current_child = false; - wxMDIParentFrame *parent = (wxMDIParentFrame *)(child_frame_->GetParent()); - wxMDIChildFrame *activeChild = parent->GetActiveChild(); - if(activeChild == (wxMDIChildFrame *) child_frame_) - current_child = true; - - if((zoom_out || zoom_in)&&(current_child)) - SetCursor(wxCURSOR_MAGNIFIER); - else if((zoom_window)&&(current_child)) - SetCursor(wxCURSOR_CROSS); - else - SetCursor(wxCURSOR_ARROW); - - //indiciate that the window has acquired focus - has_focus = true; - - //show the menu window - if((menuWindow)&&(popup)) - menuWindow->Show(TRUE); - } - - //indicate that the window has lost focus - if(event.Leaving()) - { - //indicate that the window has lost focus - has_focus = false; - - //indicate that the mouse pointer is leaving - //this window - leaving = true; - - //refresh canvas upon using a zoom window - if(zoom_window) - Refresh(false); - - //hide the menu window - if((hideWindow)&&(popup)&&(menuWindow)) - menuWindow->Show(FALSE); - - } - - //check if the left mouse button has been clicked and zoom is activated - //if so zoom the image - if(event.LeftDown()&&zoom_in) - ZoomIn(m_x_, m_y_); - - if((event.LeftDown())&&zoom_out) - ZoomOut(m_x_, m_y_); - - if(zoom_window) - DisplayZoomWindow(m_x_, m_y_); - -} - -void BgImCanvas::AddHoverWindow(wxWindow* hoverWindow, int pp) -{ - popup = pp; - menuWindow = hoverWindow; - if(popup) menuWindow->Show(FALSE); - else menuWindow->Show(TRUE); - int width, height; - menuWindow->GetSize(&width, &height); - menuXl_ = HOVER_MENU_X - HOVER_MENU_BOUND; - menuYl_ = HOVER_MENU_Y - HOVER_MENU_BOUND; - menuXu_ = menuXl_ + width + HOVER_MENU_BOUND; - menuYu_ = menuXu_ + width + HOVER_MENU_BOUND; - menuWindow->SetSize(HOVER_MENU_X, HOVER_MENU_Y, width, height); -} - -void BgImCanvas::SetHoverWindowLocation(int x, int y) -{ - int width, height; - menuWindow->GetSize(&width, &height); - if((x < 0)||(x >= width)||(y < 0)||(y >= height)) return; - menuWindow->SetSize(x, y, width, height); -} - -// --------------------------------------------------------------------------- -// BgMdiEdgeChild -// --------------------------------------------------------------------------- - -BgMdiEdgeChild::BgMdiEdgeChild(wxMDIParentFrame *parent, const wxString& title, - const wxPoint& pos, const wxSize& size, - const long style) - : wxMDIChildFrame(parent, BG_EDGE_WINDOW, title, pos, size, style) -{ - - //set window number - window_number_ = gs_nFrames; - - //assume image is not yet loaded into segmentation window - filename_ = NULL; - - bpsize_ = 160; - - imagePlotSplitter_ = new wxSplitterWindow(this, -1, wxPoint(bpsize_, 0), wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); - plotSplitter_ = new wxSplitterWindow(imagePlotSplitter_, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); - origEdgeImage_ = new BgImCanvas(this, imagePlotSplitter_, wxDefaultPosition, wxDefaultSize); - origEdgeImage_->SetScrollbars(20, 20, 50, 50); - plotNmxImage_ = new BgImCanvas(this, plotSplitter_, wxDefaultPosition, wxDefaultSize); - - plotNmxImage_->SetScrollbars(20, 20, 50, 50); - plotTotImage_ = new BgImCanvas(this, plotSplitter_, wxDefaultPosition, wxDefaultSize); - - plotTotImage_->SetScrollbars(20, 20, 50, 50); - - g_children.Append(this); - //imagePlotSplitter_->SetClientSize(GetClientSize()); - imagePlotSplitter_->SplitVertically(origEdgeImage_, plotSplitter_,256); - plotSplitter_->SplitHorizontally(plotNmxImage_, plotTotImage_,256); - - // panel stuff - buttonPanel_ = new wxPanel(this, -1, wxPoint(0, 0)); - edButton_ = new wxButton(buttonPanel_, BG_EDGE_DETECT, "Edge Detect", wxPoint(40,10)); - cpButton_ = new wxButton(buttonPanel_, BG_CHANGE_PARAM_EDGE, "Change...", wxPoint(40,155)); - - wxStaticBox* viewSB = new wxStaticBox(buttonPanel_, -1, "View", wxPoint(35, 45), wxSize(85, 65)); - viewOrigCheck_ = new wxCheckBox(buttonPanel_, BG_EDGE_CVIEW_ORIG, "Image", wxPoint(45,65));//, wxPoint(10,85)); - viewEdgeCheck_ = new wxCheckBox(buttonPanel_, BG_EDGE_CVIEW_EDGE, "Edges", wxPoint(45,85));//, wxPoint(10,105)); - - int deltal = 45; - // put the parameters - wxStaticText* stParam = new wxStaticText(buttonPanel_, -1, "PARAMETERS:", wxPoint(C_PARAMX-5, 105 + C_PARAMY)); - - txtKernelSize_ = new wxStaticText(buttonPanel_, -1, "Grad Win.", wxPoint(C_PARAMX-5,deltal+125+C_PARAMY+0*C_PARAMDY)); - valKernelSize_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX+35,deltal+125+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX-20,C_PARAMSY)); - - txtMinPt_ = new wxStaticText(buttonPanel_, -1, "Min. length", wxPoint(C_PARAMX-5,deltal+125+C_PARAMY+1*C_PARAMDY)); - valMinPt_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX+35,deltal+125+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX-20,C_PARAMSY)); - - wxStaticBox* nmxSB = new wxStaticBox(buttonPanel_, -1, "Nonmaxima supp.", wxPoint(5, deltal+205+0), wxSize(140,4*C_PARAMDY-5)); - txtNmxType_ = new wxStaticText(buttonPanel_, -1, "Type", wxPoint(C_PARAMX, deltal+205+C_PARAMY+0*C_PARAMDY)); - valNmxType_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+205+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - txtNmxR_ = new wxStaticText(buttonPanel_, -1, "Rank", wxPoint(C_PARAMX,deltal+205+C_PARAMY+1*C_PARAMDY)); - valNmxR_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+205+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - txtNmxC_ = new wxStaticText(buttonPanel_, -1, "Conf", wxPoint(C_PARAMX,deltal+205+C_PARAMY+2*C_PARAMDY)); - valNmxC_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+205+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - - wxStaticBox* hhSB = new wxStaticBox(buttonPanel_, -1, "Hyst. High Tr.", wxPoint(5, deltal+325+0), wxSize(140,4*C_PARAMDY-5)); - txtHHType_ = new wxStaticText(buttonPanel_, -1, "Type", wxPoint(C_PARAMX,deltal+325+C_PARAMY+0*C_PARAMDY)); - txtHHR_ = new wxStaticText(buttonPanel_, -1, "Rank", wxPoint(C_PARAMX,deltal+325+C_PARAMY+1*C_PARAMDY)); - txtHHC_ = new wxStaticText(buttonPanel_, -1, "Conf", wxPoint(C_PARAMX,deltal+325+C_PARAMY+2*C_PARAMDY)); - valHHType_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+325+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - valHHR_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+325+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - valHHC_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+325+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - - wxStaticBox* hlSB = new wxStaticBox(buttonPanel_, -1, "Hyst. Low Tr.", wxPoint(5, deltal+445+0), wxSize(140, 4*C_PARAMDY-5)); - txtHLType_ = new wxStaticText(buttonPanel_, -1, "Type", wxPoint(C_PARAMX,deltal+445+C_PARAMY+0*C_PARAMDY)); - txtHLR_ = new wxStaticText(buttonPanel_, -1, "Rank", wxPoint(C_PARAMX,deltal+445+C_PARAMY+1*C_PARAMDY)); - txtHLC_ = new wxStaticText(buttonPanel_, -1, "Conf", wxPoint(C_PARAMX,deltal+445+C_PARAMY+2*C_PARAMDY)); - valHLType_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+445+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - valHLR_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+445+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - valHLC_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+445+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - - - //set lower bound zoom limit on display image - //to the size of the original image - origEdgeImage_->SetMinZoomLevel(1); - - // set default parameters for edge detection - rankNmx_ = RANK_NMX; - confNmx_ = CONF_NMX; - rankH_ = RANK_H; - confH_ = CONF_H; - rankL_ = RANK_L; - confL_ = CONF_L; - nMin_ = NMIN; - nmxType_ = FC_ELLIPSE; - hystHighType_ = FC_SQUARE_BOX; - hystLowType_ = FC_ELLIPSE; - kernelSize_ = KERNEL_SIZE; - - //set params - SetParametersNum(); - SetParametersStr(); - - // also default custom parameters - nCustH_ = 3; - nCustL_ = 3; - custHx_[0] = 0; - custHx_[1] = 0.7; - custHx_[2] = 1; - custHy_[0] = 1; - custHy_[1] = 0.7; - custHy_[2] = 0; - - custLx_[0] = 0; - custLx_[1] = 0.5; - custLx_[2] = 0.7; - custLy_[0] = 0.7; - custLy_[1] = 0.5; - custLy_[2] = 0; - - // set the values in the boxes - -// cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); - cbgEdgeDetect_ = 0; - cbgImage_ = new BgImage(); - cbgEdgeList_ = 0; - hasEdge_ = 0; - hasImage_ = 0; - - int w, h; - GetClientSize(&w, &h); - buttonPanel_->SetSize(0, 0, bpsize_, h); - imagePlotSplitter_->SetSize(bpsize_, 0, w-bpsize_, h); - imagePlotSplitter_->SetSashPosition(bpsize_+(w-bpsize_)/2,TRUE); - plotSplitter_->SetSashPosition(h/2,TRUE); - rightsize_ = (w-bpsize_)/2; - viewOrigCheck_->SetValue(TRUE); - viewEdgeCheck_->SetValue(TRUE); - - plotTotImage_->AddCurveSet(&nmxCurve_); - plotNmxImage_->AddCurveSet(&highCurve_); - plotNmxImage_->AddCurveSet(&lowCurve_); - lowCurve_.pen_.SetColour(255,0,0); - - //add margin to plots - plotNmxImage_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); - plotTotImage_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); - - //add title to each individual plot - BgText bgText(1, " Diagram after Non-Maxima Supression", *wxSWISS_FONT, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2-10); - - plotNmxImage_->AddText(&bgText); - bgText.SetText(" Diagram before Non-Maxima Supression"); - plotTotImage_->AddText(&bgText); - - //add x and y axis - plotNmxImage_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); - plotNmxImage_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); - plotTotImage_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); - plotTotImage_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); - - //label x and y axis - bgText.SetText("Rank ( )"); - plotNmxImage_->LabelHorizontalAxis(&bgText); - plotTotImage_->LabelHorizontalAxis(&bgText); - bgText.SetText("Confidence ( )"); - plotNmxImage_->LabelVerticalAxis(&bgText); - plotTotImage_->LabelVerticalAxis(&bgText); - - //place greek symbols - wxBitmap ro("ro", wxBITMAP_TYPE_RESOURCE), eta("eta", wxBITMAP_TYPE_RESOURCE); - BgBitmap ro_bmp(&ro, 1, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2 - 3); - BgBitmap eta_bmp(&eta, 2, RANK_CONF_MARGINX, RANK_CONF_MARGINY/2 - 3); - plotNmxImage_->AddBitmap(&ro_bmp); - plotNmxImage_->AddBitmap(&eta_bmp); - plotTotImage_->AddBitmap(&ro_bmp); - plotTotImage_->AddBitmap(&eta_bmp); - ro_bmp.SetPlotLocation(RANK_CONF_MARGINX+137,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY+35); - ro_bmp.SetId(3); - plotNmxImage_->AddBitmap(&ro_bmp); - plotTotImage_->AddBitmap(&ro_bmp); - wxBitmap rotated_eta("rotated_eta", wxBITMAP_TYPE_RESOURCE); - BgBitmap rotated_eta_bmp(&rotated_eta, 4, RANK_CONF_MARGINX-55,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY-162); - plotNmxImage_->AddBitmap(&rotated_eta_bmp); - plotTotImage_->AddBitmap(&rotated_eta_bmp); - - //indicate that the edge window is now open - window_open = true; - - //disable edge detection button - edButton_->Enable(false); - - //get parent tool bar and update it - toolbar = parent->GetToolBar(); - UpdateToolBar(); - - //set max/min zoom - maxZoom_ = 0; - minZoom_ = 1; - -} - -/* -BgMdiEdgeChild::BgMdiEdgeChild(wxMDIParentFrame *parent, const wxString& title, - const wxPoint& pos, const wxSize& size, - const long style) - : wxMDIChildFrame(parent, BG_EDGE_WINDOW, title, pos, size, style) -{ - - //set window number - window_number_ = gs_nFrames; - - //assume image is not yet loaded into segmentation window - filename_ = NULL; - - bpsize_ = 100; - imagePlotSplitter_ = new wxSplitterWindow(this, -1,wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); - plotSplitter_ = new wxSplitterWindow(imagePlotSplitter_, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); - origEdgeImage_ = new BgImCanvas(this, imagePlotSplitter_, wxDefaultPosition, wxDefaultSize); - origEdgeImage_->SetScrollbars(20, 20, 50, 50); - plotNmxImage_ = new BgImCanvas(this, plotSplitter_, wxDefaultPosition, wxDefaultSize); - - plotNmxImage_->SetScrollbars(20, 20, 50, 50); - plotTotImage_ = new BgImCanvas(this, plotSplitter_, wxDefaultPosition, wxDefaultSize); - - plotTotImage_->SetScrollbars(20, 20, 50, 50); - - g_children.Append(this); - //imagePlotSplitter_->SetClientSize(GetClientSize()); - imagePlotSplitter_->SplitVertically(origEdgeImage_, plotSplitter_,256); - plotSplitter_->SplitHorizontally(plotNmxImage_, plotTotImage_,256); - // panel stuff - buttonPanel_ = new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize); - edButton_ = new wxButton(buttonPanel_, BG_EDGE_DETECT, "Edge Detect", wxPoint(10,10)); - cpButton_ = new wxButton(buttonPanel_, BG_CHANGE_PARAM_EDGE, "Parameters...", wxPoint(10,45)); - viewOrigCheck_ = new wxCheckBox(buttonPanel_, BG_EDGE_CVIEW_ORIG, "View Image", wxPoint(10,85)); - viewEdgeCheck_ = new wxCheckBox(buttonPanel_, BG_EDGE_CVIEW_EDGE, "View Edges", wxPoint(10,105)); - - //set lower bound zoom limit on display image - //to the size of the original image - origEdgeImage_->SetMinZoomLevel(1); - - // set default parameters for edge detection - rankNmx_ = RANK_NMX; - confNmx_ = CONF_NMX; - rankH_ = RANK_H; - confH_ = CONF_H; - rankL_ = RANK_L; - confL_ = CONF_L; - nMin_ = NMIN; - nmxType_ = FC_ELLIPSE; - hystHighType_ = FC_SQUARE_BOX; - hystLowType_ = FC_ELLIPSE; - kernelSize_ = KERNEL_SIZE; - - // also default custom parameters - nCustH_ = 3; - nCustL_ = 3; - custHx_[0] = 0; - custHx_[1] = 0.7; - custHx_[2] = 1; - custHy_[0] = 1; - custHy_[1] = 0.7; - custHy_[2] = 0; - - custLx_[0] = 0; - custLx_[1] = 0.5; - custLx_[2] = 0.7; - custLy_[0] = 0.7; - custLy_[1] = 0.5; - custLy_[2] = 0; - - - -// cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); - cbgEdgeDetect_ = 0; - cbgImage_ = new BgImage(); - cbgEdgeList_ = 0; - hasEdge_ = 0; - hasImage_ = 0; - - int w, h; - GetClientSize(&w, &h); - buttonPanel_->SetSize(w-bpsize_, 0, bpsize_, h); - imagePlotSplitter_->SetSize(0, 0, w-bpsize_, h); - imagePlotSplitter_->SetSashPosition((w-bpsize_)/2,TRUE); - plotSplitter_->SetSashPosition(h/2,TRUE); - rightsize_ = (w-bpsize_)/2; - viewOrigCheck_->SetValue(TRUE); - viewEdgeCheck_->SetValue(TRUE); - - plotTotImage_->AddCurveSet(&nmxCurve_); - plotNmxImage_->AddCurveSet(&highCurve_); - plotNmxImage_->AddCurveSet(&lowCurve_); - lowCurve_.pen_.SetColour(255,0,0); - - //add margin to plots - plotNmxImage_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); - plotTotImage_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); - - //add title to each individual plot - BgText bgText(1, " Diagram after Non-Maxima Supression", *wxSWISS_FONT, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2-10); - - plotNmxImage_->AddText(&bgText); - bgText.SetText(" Diagram before Non-Maxima Supression"); - plotTotImage_->AddText(&bgText); - - //add x and y axis - plotNmxImage_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); - plotNmxImage_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); - plotTotImage_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); - plotTotImage_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); - - //label x and y axis - bgText.SetText("Rank ( )"); - plotNmxImage_->LabelHorizontalAxis(&bgText); - plotTotImage_->LabelHorizontalAxis(&bgText); - bgText.SetText("Confidence ( )"); - plotNmxImage_->LabelVerticalAxis(&bgText); - plotTotImage_->LabelVerticalAxis(&bgText); - - //place greek symbols - wxBitmap ro("ro", wxBITMAP_TYPE_RESOURCE), eta("eta", wxBITMAP_TYPE_RESOURCE); - BgBitmap ro_bmp(&ro, 1, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2 - 3); - BgBitmap eta_bmp(&eta, 2, RANK_CONF_MARGINX, RANK_CONF_MARGINY/2 - 3); - plotNmxImage_->AddBitmap(&ro_bmp); - plotNmxImage_->AddBitmap(&eta_bmp); - plotTotImage_->AddBitmap(&ro_bmp); - plotTotImage_->AddBitmap(&eta_bmp); - ro_bmp.SetPlotLocation(RANK_CONF_MARGINX+137,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY+35); - ro_bmp.SetId(3); - plotNmxImage_->AddBitmap(&ro_bmp); - plotTotImage_->AddBitmap(&ro_bmp); - wxBitmap rotated_eta("rotated_eta", wxBITMAP_TYPE_RESOURCE); - BgBitmap rotated_eta_bmp(&rotated_eta, 4, RANK_CONF_MARGINX-55,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY-162); - plotNmxImage_->AddBitmap(&rotated_eta_bmp); - plotTotImage_->AddBitmap(&rotated_eta_bmp); - - //indicate that the edge window is now open - window_open = true; - - //disable edge detection button - edButton_->Enable(false); - - //get parent tool bar and update it - toolbar = parent->GetToolBar(); - UpdateToolBar(); - - //set max/min zoom - maxZoom_ = 0; - minZoom_ = 1; - -} -*/ - -BgMdiEdgeChild::~BgMdiEdgeChild() -{ - if(filename_) delete [] filename_; - - if (hasEdge_ == 1) - origEdgeImage_->RemovePointSet(&cbgPointSet_); - - if (cbgEdgeList_ != 0) - delete cbgEdgeList_; - delete cbgImage_; - if (cbgEdgeDetect_ != 0) - delete cbgEdgeDetect_; - - delete viewEdgeCheck_; - delete viewOrigCheck_; - delete cpButton_; - delete edButton_; - delete buttonPanel_; - - - - delete origEdgeImage_; - delete plotNmxImage_; - delete plotTotImage_; - - delete plotSplitter_; - delete imagePlotSplitter_; - g_children.DeleteObject(this); -} - -void BgMdiEdgeChild::OnUpdateNum(wxCommandEvent& WXUNUSED(event)) -{ - double tx[MAX_CUSTOM_NODES]; - double ty[MAX_CUSTOM_NODES]; - int ttype,i; - int npoints,modif=0; - if (plotNmxImage_->mouseModif_ == 1) - { - modif = 1; - // get new hyst params - highCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - hystHighType_ = ttype; - rankH_ = tx[0]; - confH_ = ty[0]; - } else - { - hystHighType_ = ttype; - for (i=0; i<npoints; i++) - { - custHx_[i] = tx[i]; - custHy_[i] = ty[i]; - } - nCustH_ = npoints; - } - lowCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - hystLowType_ = ttype; - rankL_ = tx[0]; - confL_ = ty[0]; - } else - { - hystLowType_ = ttype; - for (i=0; i<npoints; i++) - { - custLx_[i] = tx[i]; - custLy_[i] = ty[i]; - } - nCustL_ = npoints; - } - plotNmxImage_->mouseModif_ = 0; - } - if (plotTotImage_->mouseModif_ == 1) - { - modif = 1; - // get new nmx params - nmxCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - nmxType_ = ttype; - rankNmx_ = tx[0]; - confNmx_ = ty[0]; - } - plotTotImage_->mouseModif_ = 0; - } - if (modif == 1) - { - SetParametersNum(); - SetParametersStr(); - } -} - -void BgMdiEdgeChild::SetParametersNum() -{ - wxString ts; - ts = wxString::Format("%.3g", rankH_); - valHHR_->SetLabel(ts); - ts = wxString::Format("%.3g", confH_); - valHHC_->SetLabel(ts); - ts = wxString::Format("%.3g", rankL_); - valHLR_->SetLabel(ts); - ts = wxString::Format("%.3g", confL_); - valHLC_->SetLabel(ts); - ts = wxString::Format("%.3g", rankNmx_); - valNmxR_->SetLabel(ts); - ts = wxString::Format("%.3g", confNmx_); - valNmxC_->SetLabel(ts); -} -void BgMdiEdgeChild::SetParametersStr() -{ - switch(hystHighType_) - { - case FC_ELLIPSE: - valHHType_->SetLabel("arc"); - break; - case FC_VERT_LINE: - valHHType_->SetLabel("vertical line"); - break; - case FC_HORIZ_LINE: - valHHType_->SetLabel("horizontal line"); - break; - case FC_SQUARE_BOX: - valHHType_->SetLabel("box"); - break; - case FC_LINE: - valHHType_->SetLabel("line"); - break; - case FC_CUSTOM: - valHHType_->SetLabel("custom"); - break; - } - - switch(hystLowType_) - { - case FC_ELLIPSE: - valHLType_->SetLabel("arc"); - break; - case FC_VERT_LINE: - valHLType_->SetLabel("vertical line"); - break; - case FC_HORIZ_LINE: - valHLType_->SetLabel("horizontal line"); - break; - case FC_SQUARE_BOX: - valHLType_->SetLabel("box"); - break; - case FC_LINE: - valHLType_->SetLabel("line"); - break; - case FC_CUSTOM: - valHLType_->SetLabel("custom"); - break; - } - - switch(nmxType_) - { - case FC_ELLIPSE: - valNmxType_->SetLabel("arc"); - break; - case FC_VERT_LINE: - valNmxType_->SetLabel("vertical line"); - break; - case FC_HORIZ_LINE: - valNmxType_->SetLabel("horizontal line"); - break; - case FC_SQUARE_BOX: - valNmxType_->SetLabel("box"); - break; - case FC_LINE: - valNmxType_->SetLabel("line"); - break; - case FC_CUSTOM: - valNmxType_->SetLabel("custom"); - break; - } - wxString ts; - ts = wxString::Format("%d", nMin_); - valMinPt_->SetLabel(ts); - ts = wxString::Format("%d", kernelSize_); - valKernelSize_->SetLabel(ts); - - -} - -void BgMdiEdgeChild::OnViewEdge(wxCommandEvent& WXUNUSED(event)) -{ - viewEdgeCheck_->SetValue(miViewEdge_->IsChecked()); - - if (hasEdge_ == false) - return; - - if (miViewEdge_->IsChecked() == TRUE) - { - // show edges - origEdgeImage_->AddPointSet(&cbgPointSet_); - - } - else - { - // hide edges - origEdgeImage_->RemovePointSet(&cbgPointSet_); - } - -} - -void BgMdiEdgeChild::OnViewOrig(wxCommandEvent& WXUNUSED(event)) -{ - viewOrigCheck_->SetValue(miViewOrig_->IsChecked()); - - if (hasImage_ == false) - return; - - if (miViewOrig_->IsChecked() == TRUE) - { - // show edges - //canvas->AddPointSet(edgesSeq_[crtImage_]); - origEdgeImage_->ShowBitmap(true); - } - else - { - // hide edges - //canvas->RemovePointSet(edgesSeq_[crtImage_]); - origEdgeImage_->ShowBitmap(false); - } - origEdgeImage_->Refresh(); - -} - -void BgMdiEdgeChild::OnCViewEdge(wxCommandEvent& WXUNUSED(event)) -{ - miViewEdge_->Check(viewEdgeCheck_->GetValue()); - if (hasEdge_ == false) - return; - - if (viewEdgeCheck_->GetValue() == TRUE) - { - // show edges - origEdgeImage_->AddPointSet(&cbgPointSet_); - - } - else - { - // hide edges - origEdgeImage_->RemovePointSet(&cbgPointSet_); - } -} - -void BgMdiEdgeChild::OnCViewOrig(wxCommandEvent& WXUNUSED(event)) -{ - miViewOrig_->Check(viewOrigCheck_->GetValue()); - - if (hasImage_ == false) - return; - - if (viewOrigCheck_->GetValue() == TRUE) - { - // show edges - //canvas->AddPointSet(edgesSeq_[crtImage_]); - origEdgeImage_->ShowBitmap(true); - } - else - { - // hide edges - //canvas->RemovePointSet(edgesSeq_[crtImage_]); - origEdgeImage_->ShowBitmap(false); - } - -} - - -void BgMdiEdgeChild::OnSize(wxSizeEvent& WXUNUSED(event)) -{ - int w, h; - GetClientSize(&w, &h); - buttonPanel_->SetSize(0, 0, bpsize_, h); - imagePlotSplitter_->SetSize(bpsize_, 0, w-bpsize_, h); - plotSplitter_->SetSashPosition(h/2,TRUE); - h = w-bpsize_-rightsize_; - h = (h<0)? 0:h; - imagePlotSplitter_->SetSashPosition(h,TRUE); -} - -void BgMdiEdgeChild::OnQuit(wxCommandEvent& WXUNUSED(event)) -{ - Close(TRUE); -} - -void BgMdiEdgeChild::OnClose(wxCloseEvent& event) -{ - gs_nFrames--; - //indicate that the window is closed (used by OnFocus) - window_open = false; - //reset toolbar - if(gs_nFrames == 0) ResetToolBar(); - event.Skip(); -} - -void BgMdiEdgeChild::OnFocus(wxFocusEvent& WXUNUSED(event)) -{ - //update toolbar - if(!on_exit) UpdateToolBar(); - return; -} - -void BgMdiEdgeChild::ZoomWindow(void) -{ - //display zoom window - origEdgeImage_->zoom_window = true; - origEdgeImage_->zoom_in = false; - origEdgeImage_->zoom_out = false; -} - -void BgMdiEdgeChild::ZoomIn(void) -{ - //zoom into display image - origEdgeImage_->zoom_window = false; - origEdgeImage_->zoom_in = true; - origEdgeImage_->zoom_out = false; - return; -} - -void BgMdiEdgeChild::ZoomOut(void) -{ - //zoom out of display image - origEdgeImage_->zoom_window = false; - origEdgeImage_->zoom_in = false; - origEdgeImage_->zoom_out = true; - return; -} - -void BgMdiEdgeChild::NoZoom(void) -{ - //do not zoom display image - origEdgeImage_->zoom_window = false; - origEdgeImage_->zoom_in = false; - origEdgeImage_->zoom_out = false; - return; -} - -void BgMdiEdgeChild::UpdateZoomControl(void) -{ - //determine whether to enable zoom in control based on maximum zoom - if(maxZoom_ || minZoom_) - UpdateToolBar(); - else - { -// toolbar->Realize(); - toolbar->EnableTool(BG_ZOOM_IN, true); - toolbar->EnableTool(BG_ZOOM_OUT, true); - } -} - -void BgMdiEdgeChild::RunEnable(void) -{ - edButton_->Enable(true); - wxMenuBar *menubar = GetMenuBar(); - menubar->Enable(BG_EDGE_DETECT, true); -} - -void BgMdiEdgeChild::SaveEnable(void) -{ -// toolbar->Realize(); - toolbar->EnableTool(BG_SAVE_RESULT, true); -} - -void BgMdiEdgeChild::UpdateToolBar(void) -{ - //update toolbar - if(window_open) - { - //determine whether to enable save based on whether segmentation - //has occurred - bool save_enable; - if(hasEdge_) - save_enable = true; - else - save_enable = false; - - //determine whether to enable zoom controls based on whether image - //has been loaded - bool load_enable; - if(hasImage_) - load_enable = true; - else - load_enable = false; - - //determine whether to enable zoom in control based on maximum zoom - bool max_zoom; - if(maxZoom_) - max_zoom = true; - else - max_zoom = false; - - //determine whether to enable zoom out control based on minimum zoom - bool min_zoom; - if(minZoom_) - min_zoom = true; - else - min_zoom = false; - - //adjust toolbar - toolbar->SetToolShortHelp(BG_LOAD_IMAGE, "Load image to perform edge detection"); - toolbar->SetToolShortHelp(BG_SAVE_RESULT, "Save edge map"); - toolbar->EnableTool(BG_SAVE_RESULT, save_enable); - toolbar->EnableTool(BG_CROSS, load_enable); - toolbar->EnableTool(BG_ZOOM_IN, ((load_enable)&&(!max_zoom))); - toolbar->EnableTool(BG_ZOOM_OUT, ((load_enable)&&(!min_zoom))); - toolbar->EnableTool(BG_POINTER, true); - - //set to no zoom - toolbar->ToggleTool(BG_CROSS, false); - toolbar->ToggleTool(BG_ZOOM_IN, false); - toolbar->ToggleTool(BG_ZOOM_OUT, false); - toolbar->ToggleTool(BG_POINTER, true); - origEdgeImage_->SetCursor(wxCURSOR_ARROW); - NoZoom(); - -// toolbar->Realize(); - } - return; -} - -void BgMdiEdgeChild::ResetToolBar(void) -{ - //update toolbar - toolbar->SetToolShortHelp(BG_LOAD_IMAGE, "Load image to process"); - toolbar->SetToolShortHelp(BG_SAVE_RESULT, "Save result"); - toolbar->EnableTool(BG_SAVE_RESULT, false); - toolbar->EnableTool(BG_CROSS, false); - toolbar->EnableTool(BG_ZOOM_IN, false); - toolbar->EnableTool(BG_ZOOM_OUT, false); - toolbar->EnableTool(BG_POINTER, false); - toolbar->ToggleTool(BG_CROSS, false); - toolbar->ToggleTool(BG_ZOOM_IN, false); - toolbar->ToggleTool(BG_ZOOM_OUT, false); - toolbar->ToggleTool(BG_POINTER, false); -// toolbar->Realize(); - return; -} - -void BgMdiEdgeChild::ReadImage(char *pathname, char *filename) -{ - plotTotImage_->ClearData(1); - plotNmxImage_->ClearData(1); - - if (origEdgeImage_->SetImage(pathname) == 0) - return; - bgLog("Image %s loaded\n",pathname); - - //obtain and store image filename - if(filename_) delete [] filename_; - filename_ = new char [strlen(filename) + 1]; - strcpy(filename_, filename); - - miViewOrig_->Check(TRUE); - viewOrigCheck_->SetValue(TRUE); - origEdgeImage_->showbitmap_ = true; - - if (hasEdge_ == 1) - origEdgeImage_->RemovePointSet(&cbgPointSet_); - // set cbgImage - cbgImage_->SetImageFromRGB(origEdgeImage_->pimage->GetData(), origEdgeImage_->pimage->GetWidth(), origEdgeImage_->pimage->GetHeight()); - if (cbgEdgeDetect_ != 0) - delete cbgEdgeDetect_; - cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); - hasImage_ = 1; - hasEdge_ = 0; - - //get image dimension - width_ = origEdgeImage_->pimage->GetWidth(); - height_ = origEdgeImage_->pimage->GetHeight(); - - //reset the zoom level of the original edge image - origEdgeImage_->Zoom(1); - - //reset max/min zoom flags - maxZoom_ = 0; - minZoom_ = 1; - - //update interface... - - /***********************************************/ - - //enable run - RunEnable(); - - //update the tool bar - UpdateToolBar(); - - //set window title - wxString statusname; - statusname.Printf(_T("Edge Detection Frame %d - %s (%d x %d) [Original Image]"), window_number_, filename_, width_, height_); - SetTitle(statusname); - - /***********************************************/ -} - -void BgMdiEdgeChild::OnLoadImage(wxCommandEvent& WXUNUSED(event)) -{ - // get the file name -// wxFileDialog filedialog(this,"Choose an image file","","", -// "All files (*.*)|*.*|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm", -// wxOPEN); -#if defined(__WXGTK__) || defined(__WXMOTIF__) - wxFileDialog filedialog(this,"Choose an image file","","", - "*",wxOPEN); -#else - wxFileDialog filedialog(this,"Choose an image file","","", - "Common image files|*.png;*.bmp;*.gif;*.tif;*.tiff;*.jpg;*.pnm;*.pgm;*.ppm|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm|PGM/PPM files (*.pgm,*.ppm)|*.pgm;*.ppm", - wxOPEN); -#endif - if(filedialog.ShowModal()==wxID_OK) - { - plotTotImage_->ClearData(1); - plotNmxImage_->ClearData(1); - - if (hasEdge_ == 1) - origEdgeImage_->RemovePointSet(&cbgPointSet_); - - if (origEdgeImage_->SetImage(filedialog.GetPath().c_str()) == 0) - return; - bgLog("Image %s loaded\n",filedialog.GetPath().c_str()); - - //obtain and store image filename - if(filename_) delete [] filename_; - filename_ = new char [strlen(filedialog.GetFilename().c_str()) + 1]; - strcpy(filename_, filedialog.GetFilename().c_str()); - - miViewOrig_->Check(TRUE); - viewOrigCheck_->SetValue(TRUE); - origEdgeImage_->showbitmap_ = true; - - // set cbgImage - cbgImage_->SetImageFromRGB(origEdgeImage_->pimage->GetData(), origEdgeImage_->pimage->GetWidth(), origEdgeImage_->pimage->GetHeight()); - if (cbgEdgeDetect_ != 0) - delete cbgEdgeDetect_; - cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); - hasImage_ = 1; - hasEdge_ = 0; - - //get image dimension - width_ = origEdgeImage_->pimage->GetWidth(); - height_ = origEdgeImage_->pimage->GetHeight(); - - //reset the zoom level of the original edge image - origEdgeImage_->Zoom(1); - - //reset max/min zoom flags - maxZoom_ = 0; - minZoom_ = 1; - - //update interface... - - /***********************************************/ - //enable run - RunEnable(); - - //update the tool bar - UpdateToolBar(); - - //set window title - wxString statusname; - statusname.Printf(_T("Edge Detection Frame %d - %s (%d x %d) [Original Image]"), window_number_, filename_, width_, height_); - SetTitle(statusname); - - /***********************************************/ - } -} - -void BgMdiEdgeChild::OnSaveEdgeMap(wxCommandEvent& WXUNUSED(event)) -{ - if (hasEdge_ == 0) - { - bgLog("No edge map, run edge detection first!\n"); - return; - } - // get the file name - wxFileDialog filedialog(this,"Choose an image file","","", - "PGM files (*.pgm)|*.pgm", - wxSAVE); - - if(filedialog.ShowModal()==wxID_OK) - { - BgImage tempImage(cbgImage_->x_, cbgImage_->y_); - cbgEdgeList_->SetBinImage(&tempImage); - write_pgm_image(filedialog.GetPath().c_str(), tempImage.im_, tempImage.y_, tempImage.x_, "", 255); - bgLog("Edge map saved in: %s\n",filedialog.GetPath().c_str()); - - char tch[100]; - sprintf(tch,"%s.txt",filedialog.GetPath().c_str()); - cbgEdgeList_->SaveEdgeList(tch); - } -} - -void BgMdiEdgeChild::OnEdgeDetect(wxCommandEvent& WXUNUSED(event)) -{ - // determine if we have image - if (cbgImage_->hasIm_ == false) - { - //no image loaded - bgLog("No image loaded!\n"); - return; - } - if (hasEdge_ == 1) - origEdgeImage_->RemovePointSet(&cbgPointSet_); - - if (cbgEdgeList_ != 0) - delete cbgEdgeList_; - cbgEdgeList_ = new BgEdgeList(); - - // test if modif params - double tx[MAX_CUSTOM_NODES]; - double ty[MAX_CUSTOM_NODES]; - int ttype,i; - int npoints; - - if (plotTotImage_->mouseModif_ == 1) - { - // get new nmx params - nmxCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - nmxType_ = ttype; - rankNmx_ = tx[0]; - confNmx_ = ty[0]; - } - plotTotImage_->mouseModif_ = 0; - } - if (plotNmxImage_->mouseModif_ == 1) - { - // get new hyst params - highCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - hystHighType_ = ttype; - rankH_ = tx[0]; - confH_ = ty[0]; - } else - { - hystHighType_ = ttype; - for (i=0; i<npoints; i++) - { - custHx_[i] = tx[i]; - custHy_[i] = ty[i]; - } - nCustH_ = npoints; - } - lowCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - hystLowType_ = ttype; - rankL_ = tx[0]; - confL_ = ty[0]; - } else - { - hystLowType_ = ttype; - for (i=0; i<npoints; i++) - { - custLx_[i] = tx[i]; - custLy_[i] = ty[i]; - } - nCustL_ = npoints; - } - plotNmxImage_->mouseModif_ = 0; - } - - if (hystHighType_ == FC_CUSTOM) - cbgEdgeDetect_->SetCustomHigh(custHx_, custHy_, nCustH_); - if (hystLowType_ == FC_CUSTOM) - cbgEdgeDetect_->SetCustomLow(custLx_, custLy_, nCustL_); - - // determine if we have permanent data - if (cbgEdgeDetect_->havePerm_ == true) { - // compute only nmx and hyst - cbgEdgeDetect_->DoRecompute(cbgEdgeList_, rankNmx_, confNmx_, rankH_, confH_, rankL_, confL_, - nMin_, nmxType_, hystHighType_, hystLowType_); - // set only nmx image - SetNmxImage(); - } - else - { - // compute all steps - cbgEdgeDetect_->DoEdgeDetect(cbgImage_, cbgEdgeList_, rankNmx_, confNmx_, rankH_, confH_, rankL_, confL_, - nMin_, nmxType_, hystHighType_, hystLowType_); - // set total and nmx image - SetTotalImage(); - SetNmxImage(); - } - - // get binary edge image - BgImage tempImage(cbgImage_->x_, cbgImage_->y_); - cbgEdgeList_->SetBinImage(&tempImage); - - int* edgex; - int* edgey; - int nEdgep; - edgex = new int[(cbgImage_->x_) * (cbgImage_->y_)]; - edgey = new int[(cbgImage_->x_) * (cbgImage_->y_)]; - cbgPointSet_.type_ = 1; - - cbgEdgeList_->GetAllEdgePoints(edgex, edgey, &nEdgep); - cbgPointSet_.SetPoints(edgex, edgey, nEdgep); - hasEdge_ = 1; - delete [] edgey; - delete [] edgex; - - // update image canvas - if (miViewEdge_->IsChecked()) - origEdgeImage_->AddPointSet(&cbgPointSet_); - - //active save tool - SaveEnable(); - - //update menu bar - wxMenuBar *menubar = GetMenuBar(); - menubar->Enable(BG_EDGE_SAVE_MAP, true); - -} - -void BgMdiEdgeChild::SetTotalImage(void) -{ - unsigned char* buf; - int xsz = RANK_CONF_IMSIZEX; - int ysz = RANK_CONF_IMSIZEY; - int imsz = xsz*ysz; - buf = new unsigned char[imsz]; - int i; - for (i=0; i<imsz; i++) - buf[i] = 255; - - int l, c; - int xo = cbgEdgeDetect_->x_; - int yo = cbgEdgeDetect_->y_; - float* rank; - float* conf; - rank = cbgEdgeDetect_->permRank_; - conf = cbgEdgeDetect_->permConf_; - for (i=0; i<xo*yo; i++) - { - if (rank[i]>0 && conf[i]>0) - { - c = (int) (rank[i]*((double) xsz)); - c = (c>=xsz) ? xsz-1 : c; - l = (int) (conf[i]*((double) ysz)); - l = (l>=ysz) ? ysz-1 : l; - l = ysz-1-l; - buf[c+l*xsz]=80; - } - } - - nmxCurve_.SetParamCurve(nmxType_, &rankNmx_, &confNmx_, 1, xsz, ysz); - plotTotImage_->SetImageFromGray(buf, xsz, ysz); - plotTotImage_->FillCurveClick(); - - delete [] buf; - -} - -void BgMdiEdgeChild::SetNmxImage(void) -{ - unsigned char* buf; - int xsz = RANK_CONF_IMSIZEX; - int ysz = RANK_CONF_IMSIZEY; - int imsz = xsz*ysz; - buf = new unsigned char[imsz]; - int i; - for (i=0; i<imsz; i++) - buf[i] = 255; - - int l, c; - int xo = cbgEdgeDetect_->x_; - int yo = cbgEdgeDetect_->y_; - float* rank; - float* conf; - rank = cbgEdgeDetect_->permNmxRank_; - conf = cbgEdgeDetect_->permNmxConf_; - for (i=0; i<xo*yo; i++) - { - if (rank[i]>0 && conf[i]>0) - { - c = (int) (rank[i]*((double) xsz)); - c = (c>=xsz) ? xsz-1 : c; - l = (int) (conf[i]*((double) ysz)); - l = (l>=ysz) ? ysz-1 : l; - l = ysz-1-l; - buf[c+l*xsz]=80; - } - } - - if (hystHighType_ != FC_CUSTOM) - highCurve_.SetParamCurve(hystHighType_, &rankH_, &confH_, 1, xsz, ysz); - else - { - highCurve_.SetParamCurve(hystHighType_, custHx_, custHy_, nCustH_, xsz, ysz); - } - if (hystLowType_ != FC_CUSTOM) - lowCurve_.SetParamCurve(hystLowType_, &rankL_, &confL_, 1, xsz, ysz); - else - { - lowCurve_.SetParamCurve(hystLowType_, custLx_, custLy_, nCustL_, xsz, ysz); - } - plotNmxImage_->SetImageFromGray(buf, xsz, ysz); - plotNmxImage_->FillCurveClick(); - - delete [] buf; - -} - -void BgMdiEdgeChild::OnChangeParam(wxCommandEvent& WXUNUSED(event)) -{ - // show the parameters window and change it - double tx[20]; - double ty[20]; - int ttype,i; - int npoints; - if (plotTotImage_->mouseModif_ == 1) - { - // get new nmx params - nmxCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - nmxType_ = ttype; - rankNmx_ = tx[0]; - confNmx_ = ty[0]; - } - plotTotImage_->mouseModif_ = 0; - } - if (plotNmxImage_->mouseModif_ == 1) - { - // get new hyst params - highCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - hystHighType_ = ttype; - rankH_ = tx[0]; - confH_ = ty[0]; - } else - { - hystHighType_ = ttype; - for (i=0; i<npoints; i++) - { - custHx_[i] = tx[i]; - custHy_[i] = ty[i]; - } - rankH_ = tx[npoints-1]; - confH_ = ty[0]; - nCustH_ = npoints; - } - lowCurve_.GetParamCurve(tx, ty, ttype,npoints); - if ((ttype!=FC_CUSTOM) && (ttype!=-1)) - { - hystLowType_ = ttype; - rankL_ = tx[0]; - confL_ = ty[0]; - } else - { - hystLowType_ = ttype; - for (i=0; i<npoints; i++) - { - custLx_[i] = tx[i]; - custLy_[i] = ty[i]; - } - rankL_ = tx[npoints-1]; - confL_ = ty[0]; - nCustL_ = npoints; - } - plotNmxImage_->mouseModif_ = 0; - } - BgParamDialog paramDialog(this, -1, "Change Parameters", wxDefaultPosition, wxSize(250,510), - wxDEFAULT_DIALOG_STYLE | wxDIALOG_MODAL); - paramDialog.SetValues(rankNmx_, confNmx_, rankH_, confH_, rankL_, confL_, nMin_, - nmxType_, hystHighType_, hystLowType_, kernelSize_); - if (paramDialog.ShowModal()==wxID_OK) - { - // do change param stuff - int tempKernelSize; - tempKernelSize = kernelSize_; - paramDialog.GetValues(rankNmx_, confNmx_, rankH_, confH_, rankL_, confL_, nMin_, - nmxType_, hystHighType_, hystLowType_, tempKernelSize); - if (tempKernelSize != kernelSize_) - { - kernelSize_ = tempKernelSize; - if (cbgEdgeDetect_ != 0) { - delete cbgEdgeDetect_; - cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); - } - } - - // change image param - int xsz = RANK_CONF_IMSIZEX; - int ysz = RANK_CONF_IMSIZEY; - - if (hystHighType_ != FC_CUSTOM) - highCurve_.SetParamCurve(hystHighType_, &rankH_, &confH_, 1, xsz, ysz); - else - { - highCurve_.SetParamCurve(hystHighType_, custHx_, custHy_, nCustH_, xsz, ysz); - } - if (hystLowType_ != FC_CUSTOM) - lowCurve_.SetParamCurve(hystLowType_, &rankL_, &confL_, 1, xsz, ysz); - else - { - lowCurve_.SetParamCurve(hystLowType_, custLx_, custLy_, nCustL_, xsz, ysz); - } - - nmxCurve_.SetParamCurve(nmxType_, &rankNmx_, &confNmx_, 1, xsz, ysz); - - plotNmxImage_->FillCurveClick(); - plotTotImage_->FillCurveClick(); - - SetParametersStr(); - SetParametersNum(); - } -} - - -// --------------------------------------------------------------------------- -// BgParamDialog -// --------------------------------------------------------------------------- - -BgParamDialog::BgParamDialog(wxWindow* parent, wxWindowID id, const wxString& title, - const wxPoint& pos, const wxSize& size, - long style, const wxString& name) -: wxDialog(parent, id, title, pos, size, style, name) -{ - okButton_ = new wxButton(this, BG_PARAMD_OK, "Ok", wxPoint(20+C_PARAMX+10,450)); - cancelButton_ = new wxButton(this, BG_PARAMD_CANCEL, "Cancel", wxPoint(20+C_PARAMX+10+C_PARAMDX+60,450)); - - /* - txtNmxR_ = new wxStaticText(this, -1, "Nmx. rank: ", wxPoint(C_PARAMX,C_PARAMY+0*C_PARAMDY)); - txtNmxC_ = new wxStaticText(this, -1, "Nmx. conf: ", wxPoint(C_PARAMX,C_PARAMY+1*C_PARAMDY)); - txtHHR_ = new wxStaticText(this, -1, "Hyst. high rank: ", wxPoint(C_PARAMX,C_PARAMY+2*C_PARAMDY)); - txtHHC_ = new wxStaticText(this, -1, "Hyst. high conf: ", wxPoint(C_PARAMX,C_PARAMY+3*C_PARAMDY)); - txtHLR_ = new wxStaticText(this, -1, "Hyst. low rank: ", wxPoint(C_PARAMX,C_PARAMY+4*C_PARAMDY)); - txtHLC_ = new wxStaticText(this, -1, "Hyst. low conf: ", wxPoint(C_PARAMX,C_PARAMY+5*C_PARAMDY)); - txtMinPt_ = new wxStaticText(this, -1, "Min. points: ", wxPoint(C_PARAMX,C_PARAMY+6*C_PARAMDY)); - txtNmxType_ = new wxStaticText(this, -1, "Nmx. type: ", wxPoint(C_PARAMX,C_PARAMY+7*C_PARAMDY)); - txtHHType_ = new wxStaticText(this, -1, "Hyst. high type: ", wxPoint(C_PARAMX,C_PARAMY+8*C_PARAMDY)); - txtHLType_ = new wxStaticText(this, -1, "Hyst. low: ", wxPoint(C_PARAMX,C_PARAMY+9*C_PARAMDY)); - txtKernelSize_ = new wxStaticText(this, -1, "Kernel radius: ", wxPoint(C_PARAMX,C_PARAMY+10*C_PARAMDY)); - - valNmxR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+0*C_PARAMDY)); - valNmxC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+1*C_PARAMDY)); - valHHR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+2*C_PARAMDY)); - valHHC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+3*C_PARAMDY)); - valHLR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+4*C_PARAMDY)); - valHLC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+5*C_PARAMDY)); - valMinPt_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+6*C_PARAMDY)); - valNmxType_ = new wxChoice(this, -1, wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+7*C_PARAMDY), wxDefaultSize); - valHHType_ = new wxChoice(this, -1, wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+8*C_PARAMDY), wxDefaultSize); - valHLType_ = new wxChoice(this, -1, wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+9*C_PARAMDY), wxDefaultSize); - valKernelSize_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+10*C_PARAMDY)); - */ - - txtKernelSize_ = new wxStaticText(this, -1, "Grad Win.", wxPoint(20+C_PARAMX-5,0+C_PARAMY+0*C_PARAMDY)); - valKernelSize_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX+35,0+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX-20,C_PARAMSY)); - - txtMinPt_ = new wxStaticText(this, -1, "Min. length", wxPoint(20+C_PARAMX-5,0+C_PARAMY+1*C_PARAMDY)); - valMinPt_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX+35,0+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX-20,C_PARAMSY)); - - wxStaticBox* nmxSB = new wxStaticBox(this, -1, "Nonmaxima supp.", wxPoint(20+5, 80+0), wxSize(140,4*C_PARAMDY-5)); - txtNmxType_ = new wxStaticText(this, -1, "Type", wxPoint(20+C_PARAMX, 80+C_PARAMY+0*C_PARAMDY)); - valNmxType_ = new wxChoice(this, -1, wxPoint(20+C_PARAMX+C_PARAMDX,80+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - txtNmxR_ = new wxStaticText(this, -1, "Rank", wxPoint(20+C_PARAMX,80+C_PARAMY+1*C_PARAMDY)); - valNmxR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,80+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - txtNmxC_ = new wxStaticText(this, -1, "Conf", wxPoint(20+C_PARAMX,80+C_PARAMY+2*C_PARAMDY)); - valNmxC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,80+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - - wxStaticBox* hhSB = new wxStaticBox(this, -1, "Hyst. High Tr.", wxPoint(20+5, 200+0), wxSize(140,4*C_PARAMDY-5)); - txtHHType_ = new wxStaticText(this, -1, "Type", wxPoint(20+C_PARAMX,200+C_PARAMY+0*C_PARAMDY)); - txtHHR_ = new wxStaticText(this, -1, "Rank", wxPoint(20+C_PARAMX,200+C_PARAMY+1*C_PARAMDY)); - txtHHC_ = new wxStaticText(this, -1, "Conf", wxPoint(20+C_PARAMX,200+C_PARAMY+2*C_PARAMDY)); - valHHType_ = new wxChoice(this, -1, wxPoint(20+C_PARAMX+C_PARAMDX,200+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - valHHR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,200+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - valHHC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,200+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - - wxStaticBox* hlSB = new wxStaticBox(this, -1, "Hyst. Low Tr.", wxPoint(20+5, 320+0), wxSize(140, 4*C_PARAMDY-5)); - txtHLType_ = new wxStaticText(this, -1, "Type", wxPoint(20+C_PARAMX,320+C_PARAMY+0*C_PARAMDY)); - txtHLR_ = new wxStaticText(this, -1, "Rank", wxPoint(20+C_PARAMX,320+C_PARAMY+1*C_PARAMDY)); - txtHLC_ = new wxStaticText(this, -1, "Conf", wxPoint(20+C_PARAMX,320+C_PARAMY+2*C_PARAMDY)); - valHLType_ = new wxChoice(this, -1, wxPoint(20+C_PARAMX+C_PARAMDX,320+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - valHLR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,320+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - valHLC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,320+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); - - - - // put choices - valNmxType_->Append("Arc"); - valNmxType_->Append("Vertical Line"); - valNmxType_->Append("Horizontal Line"); - valNmxType_->Append("Line"); - valNmxType_->Append("Box"); - - valHHType_->Append("Arc"); - valHHType_->Append("Vertical Line"); - valHHType_->Append("Horizontal Line"); - valHHType_->Append("Line"); - valHHType_->Append("Box"); - valHHType_->Append("Custom"); - - valHLType_->Append("Arc"); - valHLType_->Append("Vertical Line"); - valHLType_->Append("Horizontal Line"); - valHLType_->Append("Line"); - valHLType_->Append("Box"); - valHLType_->Append("Custom"); - -} - -BgParamDialog::~BgParamDialog() -{ - delete txtNmxR_; - delete txtNmxC_; - delete txtHHR_; - delete txtHHC_; - delete txtHLR_; - delete txtHLC_; - delete txtMinPt_; - delete txtNmxType_; - delete txtHHType_; - delete txtHLType_; - delete txtKernelSize_; - - delete valNmxR_; - delete valNmxC_; - delete valHHR_; - delete valHHC_; - delete valHLR_; - delete valHLC_; - delete valMinPt_; - delete valNmxType_; - delete valHHType_; - delete valHLType_; - delete valKernelSize_; - - delete okButton_; - delete cancelButton_; -} - -void BgParamDialog::OnOk(wxCommandEvent& WXUNUSED(event)) -{ - EndModal(wxID_OK); -} - -void BgParamDialog::OnCancel(wxCommandEvent& WXUNUSED(event)) -{ - EndModal(wxID_CANCEL); -} - -void BgParamDialog::SetValues(double nmxR, double nmxC, double hhR, double hhC, double hlR, double hlC, - int nMin, int nmxT, int hhT, int hlT, int ks) -{ - wxString ts; - ts = wxString::Format("%.3g", nmxR); - valNmxR_->SetValue(ts); - ts = wxString::Format("%.3g", nmxC); - valNmxC_->SetValue(ts); - ts = wxString::Format("%.3g", hhR); - valHHR_->SetValue(ts); - ts = wxString::Format("%.3g", hhC); - valHHC_->SetValue(ts); - ts = wxString::Format("%.3g", hlR); - valHLR_->SetValue(ts); - ts = wxString::Format("%.3g", hlC); - valHLC_->SetValue(ts); - ts = wxString::Format("%d", nMin); - valMinPt_->SetValue(ts); - valNmxType_->SetSelection(nmxT); - valHHType_->SetSelection(hhT); - valHLType_->SetSelection(hlT); - ts = wxString::Format("%d", ks); - valKernelSize_->SetValue(ts); - -} - -void BgParamDialog::GetValues(double& nmxR, double& nmxC, double& hhR, double& hhC, double& hlR, double& hlC, - int& nMin, int& nmxT, int& hhT, int& hlT, int& ks) -{ - double td; - long tl; - int ti; - - td = -1; - tl = -1; - ti = -1; - if ((valNmxR_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) - nmxR = td; - else - bgLog("nmx. rank value out of range.\n"); - - if ((valNmxC_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) - nmxC = td; - else - bgLog("nmx. conf. value out of range.\n"); - - if ((valHHR_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) - hhR = td; - else - bgLog("hyst. high rank value out of range.\n"); - - if ((valHHC_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) - hhC = td; - else - bgLog("hyst. high conf. value out of range.\n"); - - if ((valHLR_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) - hlR = td; - else - bgLog("hyst. low rank value out of range.\n"); - - if ((valHLC_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) - hlC = td; - else - bgLog("hyst. low conf. value out of range.\n"); - - if ((valMinPt_->GetValue().ToLong(&tl) == TRUE) && (tl>=0)) - nMin = (int) tl; - else - bgLog("min. edge points value out of range.\n"); - - if ((ti=valNmxType_->GetSelection()) != -1) - nmxT = ti; - - if ((ti=valHHType_->GetSelection()) != -1) - hhT = ti; - - if ((ti=valHLType_->GetSelection()) != -1) - hlT = ti; - - if ((valKernelSize_->GetValue().ToLong(&tl) == TRUE) && (tl>0) && ((2*tl+1)<=MAX_FILTS)) - ks = (int) tl; - else - bgLog("kernel radius value out of range.\n"); - - -} - -// --------------------------------------------------------------------------- -// BgSpeedSelect -// --------------------------------------------------------------------------- - -BgSpeedSelect::BgSpeedSelect(wxWindow* parent, wxWindowID id, const wxString& title, - const wxPoint& pos, const wxSize& size, - long style, const wxString& name) -: wxDialog(parent, id, title, pos, size, style, name) -{ - okButton_ = new wxButton(this, BG_SPEEDSEL_OK, "Ok", wxPoint(30,80)); - cancelButton_ = new wxButton(this, BG_SPEEDSEL_CANCEL, "Cancel", wxPoint(120,80)); - - txtQuality_ = new wxStaticText(this, -1, "Speed", wxPoint(160, 10)); - txtSpeed_ = new wxStaticText(this, -1, "Quality", wxPoint(40, 10)); - - sldSpeed_ = new wxSlider(this, BG_SPEEDSEL_SLD, 0, 0, 100, wxPoint(18,40), wxSize(155,-1), - wxSL_AUTOTICKS | wxSL_LABELS); - sldSpeed_->SetTickFreq(20, 0); -} - -BgSpeedSelect::~BgSpeedSelect() -{ - delete sldSpeed_; - - delete okButton_; - delete cancelButton_; -} - -void BgSpeedSelect::OnOk(wxCommandEvent& WXUNUSED(event)) -{ - EndModal(wxID_OK); -} - -void BgSpeedSelect::OnCancel(wxCommandEvent& WXUNUSED(event)) -{ - EndModal(wxID_CANCEL); -} - -void BgSpeedSelect::SetSliderValue(float sliderV) -{ - sldSpeed_->SetValue((int) (sliderV*100)); -} - -void BgSpeedSelect::GetSliderValue(float& sliderV) -{ - sliderV = (float) (sldSpeed_->GetValue() / 100.0); -} - -// --------------------------------------------------------------------------- -// BgMdiSegmentChild -// --------------------------------------------------------------------------- - -BgMdiSegmentChild::BgMdiSegmentChild(wxMDIParentFrame *parent, const wxString& title, - const wxPoint& pos, const wxSize& size, - const long style) - : wxMDIChildFrame(parent, BG_SEGM_WINDOW, title, pos, size, style) -{ - - //set window number - window_number_ = gs_nFrames; - - //assume image is not yet loaded into segmentation window - filename_ = NULL; - - //split window to display the segmented image on the left hand side, - //and the ph diagram on the right hand side - imagePlotSplitter_ = new wxSplitterWindow(this, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); - plotMapSplitter_ = new wxSplitterWindow(imagePlotSplitter_, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); - mapSplitter_ = new wxSplitterWindow(plotMapSplitter_, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); - - //create option panels - winPanel1_ = new BgMenuPanel(mapSplitter_, -1, BG_CANVAS_VIEW1_GRADMAP, BG_CANVAS_VIEW1_CONFMAP, BG_CANVAS_VIEW1_WEITMAP, BG_CANVAS_VIEW1_CUSTMAP, - BG_CANVAS_SAVE_GRADMAP, BG_CANVAS_SAVE_CONFMAP, BG_CANVAS_SAVE_WEITMAP); - winPanel2_ = new BgMenuPanel(mapSplitter_, -1, BG_CANVAS_VIEW2_GRADMAP, BG_CANVAS_VIEW2_CONFMAP, BG_CANVAS_VIEW2_WEITMAP, BG_CANVAS_VIEW2_CUSTMAP, - BG_CANVAS_SAVE_GRADMAP, BG_CANVAS_SAVE_CONFMAP, BG_CANVAS_SAVE_WEITMAP); - winPanel1_->view_menu->Enable(BG_CANVAS_VIEW1_CUSTMAP, false); - winPanel2_->view_menu->Enable(BG_CANVAS_VIEW2_CUSTMAP, false); - winPanel1_->CheckViewItem(BG_CANVAS_VIEW1_CONFMAP); - winPanel2_->CheckViewItem(BG_CANVAS_VIEW2_GRADMAP); - winPanel1_->EnableMenu(false); - winPanel2_->EnableMenu(false); - - //define ph diagram and segmented display image - phDiagram_ = new BgImCanvas(this, plotMapSplitter_, wxDefaultPosition, wxDefaultSize); - phDiagram_->SetScrollbars(20, 20, 50, 50); - plotWindow1_ = new BgImCanvas(this, winPanel1_, wxPoint(0,PLOT_MENU_HEIGHT), wxDefaultSize); - plotWindow1_->SetScrollbars(20, 20, 50, 50); - plotWindow2_ = new BgImCanvas(this, winPanel2_, wxPoint(0,PLOT_MENU_HEIGHT), wxDefaultSize); - plotWindow2_->SetScrollbars(20, 20, 50, 50); - displayImage_ = new BgImCanvas(this, imagePlotSplitter_, wxDefaultPosition, wxDefaultSize); - displayImage_->SetScrollbars(20, 20, 50, 50); - - //set the scroll window of each panel - winPanel1_->SetScrollWindow((wxWindow *) plotWindow1_); - winPanel2_->SetScrollWindow((wxWindow *) plotWindow2_); - - //set lower bound zoom limit on display image - //to the size of the original image - displayImage_->SetMinZoomLevel(1); - - //place each image object into their corresponding positions in the split - //window - imagePlotSplitter_->SplitVertically(displayImage_, plotMapSplitter_,256); - plotMapSplitter_->SplitHorizontally(phDiagram_, mapSplitter_, 256); - mapSplitter_->SplitVertically(winPanel1_, winPanel2_, 256); - - //inititalize segmentation parameters - sigmaS = 7; - sigmaR = float(6.5); - aij = float(0.3); - epsilon = float(0.3); - minRegion = 20; - kernelSize = 2; - - //set text size - wxSize txtSize(50, 20); - - //allocate memory for display images - cbgImage_ = new BgImage(); - filtImage_ = new BgImage(); - segmImage_ = new BgImage(); - whiteImage_ = new BgImage(); - - //allocate memory to store boundary pixel locations - boundaries_ = new BgPointSet(); - - hasImage_ = 0; - hasFilter_ = 0; - hasSegment_ = 0; - hasBoundaries_ = 0; - - //shut off text box monitoring - checkTextBoxes_ = false; - - optionsPanel_ = new wxPanel(this, -1, wxPoint(0, 0), wxSize(BG_SEGM_OP_SIZEX, BG_SEGM_OP_SIZEY)); - - wxBoxSizer *toplayout = new wxBoxSizer(wxVERTICAL); - - loadButton_ = new wxButton(optionsPanel_, BG_SEGM_LOAD_IMAGE, "Load Image"); - toplayout->Add(loadButton_, 0, wxCENTER | wxBOTTOM | wxTOP, 5); - - wxString operations[] = {"Segment", "Filter Only", "Fusion Only"}; - operationRadio_ = new wxRadioBox(optionsPanel_, BG_SEGM_OPERATION, "Operation", wxDefaultPosition, wxSize(BG_SP_WIDTH, -1), 3, operations, 3 ,wxRA_SPECIFY_ROWS); - toplayout->Add(operationRadio_, 0, wxCENTER | wxBOTTOM, 5); - - runButton_ = new wxButton(optionsPanel_, BG_SEGM_SEGMENT, "Run"); - toplayout->Add(runButton_, 0, wxCENTER | wxBOTTOM, 5); - - wxString choices[] = {"Original", "Filtered", "Segmented", "No Image"}; - viewImSegRadio_ = new wxRadioBox(optionsPanel_, BG_SEGM_VIEW_IMSEG, "View Image", wxDefaultPosition, wxSize(BG_SP_WIDTH, -1), 4, choices, 4, wxRA_SPECIFY_ROWS); - toplayout->Add(viewImSegRadio_, 0, wxCENTER | wxBOTTOM, 5); - - viewBoundariesCheck_ = new wxCheckBox(optionsPanel_, BG_SEGM_VIEW_EDGES, "Overlay Boundaries"); - toplayout->Add(viewBoundariesCheck_, 0, wxALIGN_LEFT | wxLEFT | wxBOTTOM, 10); - - //add bandwidth parameters... - subPanel1_ = new wxPanel(optionsPanel_, -1, wxDefaultPosition, wxSize(BG_SP_WIDTH, BG_SP_HEIGHT)); - subPanelBox1_ = new wxStaticBox(subPanel1_, -1, "Bandwidth", wxPoint(0, 0), wxSize(BG_SP_WIDTH, BG_SP_TOP_HEIGHT), wxSIMPLE_BORDER, "staticBox"); - subPanelBox2_ = new wxStaticBox(subPanel1_, -1, "", wxPoint(0, BG_SP_TOP_HEIGHT-8), wxSize(BG_SP_WIDTH, BG_SP_HEIGHT-BG_SP_TOP_HEIGHT), wxSIMPLE_BORDER, "staticBox"); - textSigmaS_ = new wxStaticText(subPanel1_, -1, "Spatial [2h+1]", wxPoint(BG_LEFT_CELL, 18)); - txtSigmaS_ = new wxTextCtrl(subPanel1_, BG_SEGM_TEXT_SIGMAS, "7", wxPoint(BG_RIGHT_CELL, 15), txtSize); - textSigmaR_ = new wxStaticText(subPanel1_, -1, "Color [2h]", wxPoint(BG_LEFT_CELL, 43)); - txtSigmaR_ = new wxTextCtrl(subPanel1_, BG_SEGM_TEXT_SIGMAR, "6.5", wxPoint(BG_RIGHT_CELL, 40), txtSize); - textMinRegion_ = new wxStaticText(subPanel1_, -1, "Minimum Region", wxPoint(BG_LEFT_CELL, 78)); - txtMinRegion_ = new wxTextCtrl(subPanel1_, BG_SEGM_TEXT_MINREG, "20", wxPoint(BG_RIGHT_CELL, 75), txtSize); - toplayout->Add(subPanel1_, 0, wxCENTER | wxBOTTOM | wxTOP, 5); - - useWeightMap_ = new wxCheckBox(optionsPanel_, BG_SEGM_USE_EDGE_MAP, "Use Weight Map"); - toplayout->Add(useWeightMap_, 0, wxALIGN_LEFT | wxLEFT | wxBOTTOM, 10); - - //add weight map parameters... - subPanel2_ = new wxPanel(optionsPanel_, -1, wxDefaultPosition, wxSize(BG_SP_WIDTH, BG_SP_HEIGHT_2)); - subPanelBox3_ = new wxStaticBox(subPanel2_, -1, "", wxPoint(0, 0), wxSize(BG_SP_WIDTH, BG_SP_HEIGHT_2), wxSIMPLE_BORDER, "staticBox"); - textKernelSize_ = new wxStaticText(subPanel2_, -1, "Grad. Window (2n+1)", wxPoint(BG_LEFT_CELL, 18)); - txtKernelSize_ = new wxTextCtrl(subPanel2_, BG_SEGM_TEXT_GRADWIN, "2", wxPoint(BG_RIGHT_CELL, 15), txtSize); - textA_ = new wxStaticText(subPanel2_, -1, "Mixture Parameter", wxPoint(BG_LEFT_CELL, 43)); - txtA_ = new wxTextCtrl(subPanel2_, BG_SEGM_TEXT_AIJ, "0.3", wxPoint(BG_RIGHT_CELL, 40), txtSize); - textEpsilon_ = new wxStaticText(subPanel2_, -1, "Threshold", wxPoint(BG_LEFT_CELL, 68)); - txtEpsilon_ = new wxTextCtrl(subPanel2_, BG_SEGM_TEXT_EPSILON, "0.3", wxPoint(BG_RIGHT_CELL, 65), txtSize); - toplayout->Add(subPanel2_, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_TOP, 5); - - //add parameter history control - subPanel3_ = new wxPanel(optionsPanel_, -1, wxDefaultPosition, wxSize(BG_SP_WIDTH, 43)); - subPanelBox4_ = new wxStaticBox(subPanel3_, -1, "", wxPoint(0, 0), wxSize(BG_SP_WIDTH, 43), wxSIMPLE_BORDER, "staticBox"); - textParamBox_ = new wxStaticText(subPanel3_, -1, "History", wxPoint(BG_LEFT_CELL, 18)); - paramComboBox_ = new BgParameterHistoryBox(subPanel3_, BG_SEGM_CHANGE_PARAMS, "", wxPoint(BG_RIGHT_CELL-50, 15), wxSize(100,20), 5, 0, wxDefaultValidator, "comboBox"); - toplayout->Add(subPanel3_, 0, wxALIGN_CENTER | wxCENTER | wxBOTTOM, 10); - - optionsPanel_->SetAutoLayout(TRUE); - toplayout->Fit(optionsPanel_); - optionsPanel_->SetSizer(toplayout); - - g_children.Append(this); - - //set the size and sash position of the splitters - int w, h; - GetClientSize(&w, &h); - imagePlotSplitter_->SetSize(BG_SEGM_OP_SIZEX, 0, w-BG_SEGM_OP_SIZEX, h); - imagePlotSplitter_->SetSashPosition((w-BG_SEGM_OP_SIZEX)/2, TRUE); - plotMapSplitter_->SetSashPosition(h/2, TRUE); - mapSplitter_->SetSashPosition((w-BG_SEGM_OP_SIZEX)/4, TRUE); - - //initalize edge maps... - customMap_ = (float *) NULL; - confMap_ = (float *) NULL; - gradMap_ = (float *) NULL; - weightMap_ = (float *) NULL; - - //indicate that the edge parameters have not changed - edgeParamsHaveChanged_ = false; - - //add margin to plots - phDiagram_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); - plotWindow1_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); - plotWindow2_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); - - //add title to each individual plot - BgText bgText(1," Diagram of Region Boundary Data Points", *wxSWISS_FONT, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2-10); - phDiagram_->AddText(&bgText); - bgText.SetText("Confidence Map"); - plotWindow1_->AddText(&bgText); - bgText.SetText("Gradient Map"); - plotWindow2_->AddText(&bgText); - - //add x and y axis - phDiagram_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); - phDiagram_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); - - //label x and y axis - bgText.SetText("Rank ( )"); - phDiagram_->LabelHorizontalAxis(&bgText); - bgText.SetText("Confidence ( )"); - phDiagram_->LabelVerticalAxis(&bgText); - - //place greek symbols - wxBitmap ro("ro", wxBITMAP_TYPE_RESOURCE), eta("eta", wxBITMAP_TYPE_RESOURCE); - BgBitmap ro_bmp(&ro, 1, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2 - 3); - BgBitmap eta_bmp(&eta, 2, RANK_CONF_MARGINX, RANK_CONF_MARGINY/2 - 3); - phDiagram_->AddBitmap(&ro_bmp); - phDiagram_->AddBitmap(&eta_bmp); - ro_bmp.SetPlotLocation(RANK_CONF_MARGINX+137,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY+35); - ro_bmp.SetId(3); - phDiagram_->AddBitmap(&ro_bmp); - wxBitmap rotated_eta("rotated_eta", wxBITMAP_TYPE_RESOURCE); - BgBitmap rotated_eta_bmp(&rotated_eta, 4, RANK_CONF_MARGINX-55,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY-162); - phDiagram_->AddBitmap(&rotated_eta_bmp); - - //declare that segmentation window is open - window_open = true; - - //get parent tool bar and update it - toolbar = parent->GetToolBar(); - UpdateToolBar(); - - //disable confidence map text boxes - txtA_->Enable(false); - txtEpsilon_->Enable(false); - txtKernelSize_->Enable(false); - textA_->Enable(false); - textEpsilon_->Enable(false); - textKernelSize_->Enable(false); - - //disable run button - runButton_->Enable(false); - - //disable radio boxes - viewImSegRadio_->Enable(false); - operationRadio_->Enable(false); - - //disable view boundaries check box - viewBoundariesCheck_->Enable(false); - - //intialize parameter combo box - float *myParameters = new float [6]; - myParameters[0] = sigmaS; - myParameters[1] = sigmaR; - myParameters[2] = aij; - myParameters[3] = epsilon; - myParameters[4] = minRegion; - myParameters[5] = kernelSize; - paramComboBox_->SetCurrentList((void *) myParameters, 6); - isCurrentHistory_ = true; - - //turn on text box monitoring - checkTextBoxes_ = true; - - //initialize speedup level to medium - speedUpLevel_ = MED_SPEEDUP; - speedUpThreshold_ = (float) 0.1; - - //initialize max/min zoom - maxZoom_ = 0; - minZoom_ = 1; - -} - - -BgMdiSegmentChild::~BgMdiSegmentChild() -{ - if (hasBoundaries_ == 1) - displayImage_->RemovePointSet(boundaries_); - - if(filename_) delete [] filename_; - - delete optionsPanel_; - delete displayImage_; - - delete boundaries_; - delete whiteImage_; - delete segmImage_; - delete filtImage_; - delete cbgImage_; - - if (customMap_) delete [] customMap_; - if (confMap_) delete [] confMap_; - if (gradMap_) delete [] gradMap_; - if (weightMap_) delete [] weightMap_; - - g_children.DeleteObject(this); -} - -void BgMdiSegmentChild::OnViewImSeg(wxCommandEvent& WXUNUSED(event)) -{ - //if an image has not been loaded then exit this method... - if (hasImage_ == 0) - return; - - switch(viewImSegRadio_->GetSelection()) - { - - //view original image - case 0: - boundaries_->pen_.SetColour(*wxWHITE); - displayImage_->SetImage(cbgImage_->im_, cbgImage_->x_, cbgImage_->y_, cbgImage_->colorIm_); - break; - - //view filtered image - case 1: - if (hasFilter_ == 0) - { - viewImSegRadio_->SetSelection(0); - bgLog("Filter the image first!\n"); - return; - } else - { - boundaries_->pen_.SetColour(*wxWHITE); - displayImage_->SetImage(filtImage_->im_, filtImage_->x_, filtImage_->y_, filtImage_->colorIm_); - } - break; - - //view segmented image - case 2: - if (hasSegment_ == 0) - { - viewImSegRadio_->SetSelection(0); - bgLog("Segment the image first!\n"); - return; - } else - { - boundaries_->pen_.SetColour(*wxWHITE); - displayImage_->SetImage(segmImage_->im_, segmImage_->x_, segmImage_->y_, segmImage_->colorIm_); - } - break; - - //view boundaries - default: - if (hasBoundaries_ == 0) - { - viewImSegRadio_->SetSelection(0); - bgLog("Process the image first!\n"); - return; - } else - { - boundaries_->pen_.SetColour(*wxBLACK); - displayImage_->SetImage(whiteImage_->im_, whiteImage_->x_, whiteImage_->y_, whiteImage_->colorIm_); - } - } -} - -//specifies image operation(i.e. segment, filter or fuse regions) -void BgMdiSegmentChild::OnChangeOperation(wxCommandEvent& WXUNUSED(event)) -{ - - wxMenuBar *menubar = GetMenuBar(); - switch(operationRadio_->GetSelection()) - { - //segment the image - case 0: - menubar->SetLabel(BG_SEGM_SEGMENT, "Segment Image\tShift-R"); - break; - //filter the image - case 1: - menubar->SetLabel(BG_SEGM_SEGMENT, "Filter Image\tShift-R"); - break; - //fuse regions - default: - menubar->SetLabel(BG_SEGM_SEGMENT, "Fuse Regions\tShift-R"); - break; - } - - //done. - return; - -} - -//changes the paramters depending on the parameter list -void BgMdiSegmentChild::OnChangeParameters(wxCommandEvent& WXUNUSED(event)) -{ - float *myParameters; - - //get current selection index... - int selIndex = paramComboBox_->GetSelection(); - - //aquire current parameters and store them in "current parameter" slot... - if(isCurrentHistory_) - { - int csigmaS, cminRegion, ckernelSize; - float csigmaR, caij, cepsilon; - GetParameters(csigmaS, csigmaR, caij, cepsilon, cminRegion, ckernelSize, 0); - myParameters = (float *) paramComboBox_->GetCurrentListData(); - myParameters[0] = csigmaS; - myParameters[1] = csigmaR; - myParameters[2] = caij; - myParameters[3] = cepsilon; - myParameters[4] = cminRegion; - myParameters[5] = ckernelSize; - } - - //check to see if the "current parameter" slot has been selected, - //if so set the current history flag and use the parameters from - //current history slot - if(selIndex == 0) - { - isCurrentHistory_ = true; - myParameters = (float *) paramComboBox_->GetCurrentListData(); - } - //otherwise indicate that the current slot has not just been selected - //and get parameters from current parameter list - else - { - isCurrentHistory_ = false; - myParameters = (float *) paramComboBox_->GetParameterListData(selIndex-1); - } - - //set the text boxes... - char str[10]; - checkTextBoxes_ = false; - sprintf(str, "%d", bgRoundSign(myParameters[0])); - txtSigmaS_->SetValue(str); - sprintf(str, "%3.1f", myParameters[1]); - txtSigmaR_->SetValue(str); - sprintf(str, "%3.1f", myParameters[2]); - txtA_->SetValue(str); - sprintf(str, "%3.1f", myParameters[3]); - txtEpsilon_->SetValue(str); - sprintf(str, "%d", bgRoundSign(myParameters[4])); - txtMinRegion_->SetValue(str); - sprintf(str, "%d", bgRoundSign(myParameters[5])); - txtKernelSize_->SetValue(str); - checkTextBoxes_ = true; - -} - -void BgMdiSegmentChild::OnUpdateTextBoxes(wxCommandEvent& event) -{ - //update parameter history.... - if(checkTextBoxes_) - { - paramComboBox_->SetSelection(0); - isCurrentHistory_ = true; - } - - //check if a edge parameter has been changed - int id = event.GetId(); - if((id == BG_SEGM_TEXT_GRADWIN)||(id == BG_SEGM_TEXT_AIJ)||(id == BG_SEGM_TEXT_EPSILON)) - edgeParamsHaveChanged_ = true; - -} - -void BgMdiSegmentChild::OnUpdateSpeedUpLevel(wxCommandEvent& event) -{ - long menuItemId = event.GetId(); - wxMenuBar* myMenuBar = GetMenuBar(); - switch(menuItemId) - { - case BG_SEGM_SPEEDUP_MEDM: - speedUpLevel_ = MED_SPEEDUP; - myMenuBar->Check(BG_SEGM_SPEEDUP_NONE, false); - myMenuBar->Check(BG_SEGM_SPEEDUP_HIGH, false); - break; - case BG_SEGM_SPEEDUP_HIGH: - speedUpLevel_ = HIGH_SPEEDUP; - myMenuBar->Check(BG_SEGM_SPEEDUP_NONE, false); - myMenuBar->Check(BG_SEGM_SPEEDUP_MEDM, false); - { - BgSpeedSelect speedSelect(this, -1, "Select speed/quality", wxDefaultPosition, wxSize(220,150), - wxDEFAULT_DIALOG_STYLE | wxDIALOG_MODAL); - speedSelect.SetSliderValue(speedUpThreshold_); - if (speedSelect.ShowModal()==wxID_OK) - { - speedSelect.GetSliderValue(speedUpThreshold_); - } - } - - break; - default: - speedUpLevel_ = NO_SPEEDUP; - myMenuBar->Check(BG_SEGM_SPEEDUP_MEDM, false); - myMenuBar->Check(BG_SEGM_SPEEDUP_HIGH, false); - } -} - -void BgMdiSegmentChild::OnViewBoundaries(wxCommandEvent& WXUNUSED(event)) -{ - - if (hasBoundaries_ == false) - return; - - bool isChecked; - isChecked = viewBoundariesCheck_->GetValue(); - - if (isChecked) - { - // show edges - displayImage_->AddPointSet(boundaries_); - - } - else - { - // hide edges - displayImage_->RemovePointSet(boundaries_); - } - -} - - -//activates/de-activates the text boxes used for -//synergistic segmentation based on the use confidence -//map checkbox -void BgMdiSegmentChild::OnUseWeightMap(wxCommandEvent& WXUNUSED(event)) -{ - - //depending on use confidence map checkbox, activate/de-activate - //text boxes - if(useWeightMap_->GetValue()) - { - //enable text boxes - txtA_->Enable(true); - txtEpsilon_->Enable(true); - txtKernelSize_->Enable(true); - textA_->Enable(true); - textEpsilon_->Enable(true); - textKernelSize_->Enable(true); - } - else - { - //disable text boxes - txtA_->Enable(false); - txtEpsilon_->Enable(false); - txtKernelSize_->Enable(false); - textA_->Enable(false); - textEpsilon_->Enable(false); - textKernelSize_->Enable(false); - } - - //done. - return; -} - -void BgMdiSegmentChild::OnUpdatePlotWindow1(wxCommandEvent& event) -{ - int menuItemId = event.GetId(); - - //update checkmarks - winPanel1_->CheckViewItem(menuItemId); - - //change plot... - int i; - int data_length = width_*height_; - unsigned char *buffer = new unsigned char[data_length]; - BgText bgText(1,"ConfidenceMap", *wxSWISS_FONT, 0, 0); - switch(menuItemId) - { - case BG_CANVAS_VIEW1_GRADMAP: - bgText.SetText("Gradient Map"); - bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-40,RANK_CONF_MARGINY/2-10); - plotWindow1_->AddText(&bgText); - for(i = 0; i < data_length; i++) - buffer[i] = (unsigned char)(255*gradMap_[i] + 0.5); - plotWindow1_->SetImageFromGray(buffer, width_, height_); - break; - case BG_CANVAS_VIEW1_CONFMAP: - bgText.SetText("Confidence Map"); - bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-45,RANK_CONF_MARGINY/2-10); - plotWindow1_->AddText(&bgText); - for(i = 0; i < data_length; i++) - buffer[i] = (unsigned char)(255*confMap_[i] + 0.5); - plotWindow1_->SetImageFromGray(buffer, width_, height_); - break; - case BG_CANVAS_VIEW1_WEITMAP: - bgText.SetText("Weight Map"); - bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-35,RANK_CONF_MARGINY/2-10); - plotWindow1_->AddText(&bgText); - for(i = 0; i < data_length; i++) - buffer[i] = (unsigned char)(255*weightMap_[i] + 0.5); - plotWindow1_->SetImageFromGray(buffer, width_, height_); - break; - case BG_CANVAS_VIEW1_CUSTMAP: - bgText.SetText("Custom Weight Map"); - bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-60,RANK_CONF_MARGINY/2-10); - plotWindow1_->AddText(&bgText); - for(i = 0; i < data_length; i++) - buffer[i] = (unsigned char)(255*customMap_[i] + 0.5); - plotWindow1_->SetImageFromGray(buffer, width_, height_); - break; - } - - //de-allocate memory used by conf/gradient map buffer - delete [] buffer; -} - -void BgMdiSegmentChild::OnUpdatePlotWindow2(wxCommandEvent& event) -{ - int menuItemId = event.GetId(); - - //update checkmarks - winPanel2_->CheckViewItem(menuItemId); - - //change plot... - int i; - int data_length = width_*height_; - unsigned char *buffer = new unsigned char[data_length]; - BgText bgText(1,"ConfidenceMap", *wxSWISS_FONT, 0, 0); - switch(menuItemId) - { - case BG_CANVAS_VIEW2_GRADMAP: - bgText.SetText("Gradient Map"); - bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-40,RANK_CONF_MARGINY/2-10); - plotWindow2_->AddText(&bgText); - for(i = 0; i < data_length; i++) - buffer[i] = (unsigned char)(255*gradMap_[i] + 0.5); - plotWindow2_->SetImageFromGray(buffer, width_, height_); - break; - case BG_CANVAS_VIEW2_CONFMAP: - bgText.SetText("Confidence Map"); - bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-45,RANK_CONF_MARGINY/2-10); - plotWindow2_->AddText(&bgText); - for(i = 0; i < data_length; i++) - buffer[i] = (unsigned char)(255*confMap_[i] + 0.5); - plotWindow2_->SetImageFromGray(buffer, width_, height_); - break; - case BG_CANVAS_VIEW2_WEITMAP: - bgText.SetText("Weight Map"); - bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-35,RANK_CONF_MARGINY/2-10); - plotWindow2_->AddText(&bgText); - for(i = 0; i < data_length; i++) - buffer[i] = (unsigned char)(255*weightMap_[i] + 0.5); - plotWindow2_->SetImageFromGray(buffer, width_, height_); - break; - case BG_CANVAS_VIEW2_CUSTMAP: - bgText.SetText("Custom Weight Map"); - bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-60,RANK_CONF_MARGINY/2-10); - plotWindow2_->AddText(&bgText); - for(i = 0; i < data_length; i++) - buffer[i] = (unsigned char)(255*customMap_[i] + 0.5); - plotWindow2_->SetImageFromGray(buffer, width_, height_); - break; - } - - //de-allocate memory used by conf/gradient map buffer - delete [] buffer; -} - - -void BgMdiSegmentChild::OnSaveEdgeInformation(wxCommandEvent& event) -{ - -#if defined(__WXGTK__) || defined(__WXMOTIF__) - wxFileDialog filedialog(this,"Save Edge Information","","", - "*",wxSAVE); -#else - wxFileDialog filedialog(this,"Save Edge Information","","", - "Matlab ASCII data files (*.dat)|*.dat|PGM Files (*.pgm)|*.pgm", - wxSAVE); -#endif - - if(filedialog.ShowModal()==wxID_OK) - { - - //get the image type - int dtype = filedialog.GetFilterIndex(); - - //obtain pointer to data - float *myData; - switch(event.GetId()) - { - case BG_CANVAS_SAVE_GRADMAP: - myData = gradMap_; - break; - case BG_CANVAS_SAVE_CONFMAP: - myData = confMap_; - break; - case BG_CANVAS_SAVE_WEITMAP: - myData = weightMap_; - break; - } - - //get the filename and path - char* path = (char*) filedialog.GetPath().c_str(); - char* filename = (char*) filedialog.GetFilename().c_str(); - - //PGM Image - if(dtype) - { - unsigned char *buf = new unsigned char [height_*width_]; - int i; - for(i = 0; i < height_*width_; i++) - buf[i] = myData[i]*255 + 0.5; - write_pgm_image(path, buf, height_, width_, "", 255); - delete [] buf; - } - else - //Matlab Data File - { - write_MATLAB_ASCII(path, myData, height_, width_); - } - } - -} - -void BgMdiSegmentChild::OnSize(wxSizeEvent& WXUNUSED(event)) -{ - int w, h; - GetClientSize(&w, &h); - optionsPanel_->SetSize(0, 0, BG_SEGM_OP_SIZEX, h); - imagePlotSplitter_->SetSize(BG_SEGM_OP_SIZEX, 0, w-BG_SEGM_OP_SIZEX, h); - imagePlotSplitter_->SetSashPosition((w-BG_SEGM_OP_SIZEX)/2, TRUE); - plotMapSplitter_->SetSashPosition(h/2, TRUE); - mapSplitter_->SetSashPosition((w-BG_SEGM_OP_SIZEX)/4, TRUE); -} - -//clears display of ph diagram and rank and confidence maps -void BgMdiSegmentChild::ClearDisplay( void ) -{ - phDiagram_->ClearDisplay(); - plotWindow1_->ClearDisplay(); - plotWindow2_->ClearDisplay(); -} - -//turns plotting capability on/off -void BgMdiSegmentChild::UpdateDisplay(bool update) -{ - if(update) - { - phDiagram_->noUpdate_ = false; - plotWindow1_->noUpdate_ = false; - plotWindow2_->noUpdate_ = false; - } - else - { - phDiagram_->noUpdate_ = true; - plotWindow1_->noUpdate_ = true; - plotWindow2_->noUpdate_ = true; - } -} - -void BgMdiSegmentChild::OnQuit(wxCommandEvent& WXUNUSED(event)) -{ - Close(TRUE); -} - -void BgMdiSegmentChild::OnClose(wxCloseEvent& event) -{ - //decrement global counter indicating number of frames open - gs_nFrames--; - //indicate that the window is now close (used by OnFocus) - window_open = false; - //reset the toolbar - if(gs_nFrames == 0) ResetToolBar(); - event.Skip(); -} - -void BgMdiSegmentChild::OnFocus(wxFocusEvent& WXUNUSED(event)) -{ - //update toolbar - if(!on_exit) UpdateToolBar(); - return; -} - -void BgMdiSegmentChild::ZoomWindow(void) -{ - //display zoom window - displayImage_->zoom_window = true; - displayImage_->zoom_in = false; - displayImage_->zoom_out = false; -} - -void BgMdiSegmentChild::ZoomIn(void) -{ - //zoom into display image - displayImage_->zoom_window = false; - displayImage_->zoom_in = true; - displayImage_->zoom_out = false; - return; -} - -void BgMdiSegmentChild::ZoomOut(void) -{ - //zoom out of display image - displayImage_->zoom_window = false; - displayImage_->zoom_in = false; - displayImage_->zoom_out = true; - return; -} - -void BgMdiSegmentChild::NoZoom(void) -{ - //do not zoom display image - displayImage_->zoom_window = false; - displayImage_->zoom_in = false; - displayImage_->zoom_out = false; - return; -} - -void BgMdiSegmentChild::UpdateZoomControl(void) -{ - //determine whether to enable zoom in control based on maximum zoom - if(maxZoom_ || minZoom_) - UpdateToolBar(); - else - { - toolbar->EnableTool(BG_ZOOM_IN, true); - toolbar->EnableTool(BG_ZOOM_OUT, true); -// toolbar->Realize(); - } -} - -void BgMdiSegmentChild::RunEnable(void) -{ - wxMenuBar *menubar = GetMenuBar(); - menubar->Enable(BG_SEGM_LOAD_MAP, true); - menubar->Enable(BG_SEGM_SEGMENT, true); - runButton_->Enable(true); - viewImSegRadio_->Enable(true); - viewImSegRadio_->Enable(1, false); - viewImSegRadio_->Enable(2, false); - viewImSegRadio_->Enable(3, false); -} - -void BgMdiSegmentChild::SaveEnable(void) -{ - toolbar->EnableTool(BG_SAVE_RESULT, true); -} - -void BgMdiSegmentChild::UpdateToolBar(void) -{ - //update toolbar (except during close) - if(window_open) - { - //determine whether to enable save based on whether segmentation - //has occurred - bool save_enable; - if(hasSegment_) - save_enable = true; - else - save_enable = false; - - //determine whether to enable zoom controls based on whether image - //has been loaded - bool load_enable; - if(hasImage_) - load_enable = true; - else - load_enable = false; - - //determine whether to enable zoom in control based on maximum zoom - bool max_zoom; - if(maxZoom_) - max_zoom = true; - else - max_zoom = false; - - //determine whether to enable zoom out control based on minimum zoom - bool min_zoom; - if(minZoom_) - min_zoom = true; - else - min_zoom = false; - - //adjust toolbar - toolbar->SetToolShortHelp(BG_LOAD_IMAGE, "Load image to perform image segmentation"); - toolbar->SetToolShortHelp(BG_SAVE_RESULT, "Save segmented image"); - toolbar->EnableTool(BG_SAVE_RESULT, save_enable); - toolbar->EnableTool(BG_CROSS, load_enable); - toolbar->EnableTool(BG_ZOOM_IN, ((load_enable)&&(!max_zoom))); - toolbar->EnableTool(BG_ZOOM_OUT, ((load_enable)&&(!min_zoom))); - toolbar->EnableTool(BG_POINTER, true); - - //set to no zoom - toolbar->ToggleTool(BG_CROSS, false); - toolbar->ToggleTool(BG_ZOOM_IN, false); - toolbar->ToggleTool(BG_ZOOM_OUT, false); - toolbar->ToggleTool(BG_POINTER, true); - displayImage_->SetCursor(wxCURSOR_ARROW); - NoZoom(); - } - return; -} - -void BgMdiSegmentChild::ResetToolBar(void) -{ - //update toolbar - toolbar->SetToolShortHelp(BG_LOAD_IMAGE, "Load image to process"); - toolbar->SetToolShortHelp(BG_SAVE_RESULT, "Save result"); - toolbar->EnableTool(BG_SAVE_RESULT, false); - toolbar->EnableTool(BG_CROSS, false); - toolbar->EnableTool(BG_ZOOM_IN, false); - toolbar->EnableTool(BG_ZOOM_OUT, false); - toolbar->EnableTool(BG_POINTER, false); - toolbar->ToggleTool(BG_CROSS, false); - toolbar->ToggleTool(BG_ZOOM_IN, false); - toolbar->ToggleTool(BG_ZOOM_OUT, false); - toolbar->ToggleTool(BG_POINTER, false); - return; -} - -void BgMdiSegmentChild::ReadImage(char *pathname, char *filename) -{ - //take away point set if boundaries have been calculated - if(hasBoundaries_) - { - hasBoundaries_ = false; - displayImage_->RemovePointSet(boundaries_); - boundaries_->CleanData(); - } - - if(displayImage_->SetImage(pathname) == 0) - return; - - //obtain and store image filename - if(filename_) delete [] filename_; - filename_ = new char [strlen(filename) + 1]; - strcpy(filename_, filename); - - displayImage_->showbitmap_ = true; - - //set value of view boundaries control - viewBoundariesCheck_->SetValue(0); - - //set image view option to original - viewImSegRadio_->SetSelection(0); - - //get image dimension - width_ = displayImage_->pimage->GetWidth(); - height_ = displayImage_->pimage->GetHeight(); - - //reset zoom level of display image - displayImage_->Zoom(1); - - //reset max/min zoom flags - maxZoom_ = 0; - minZoom_ = 1; - - //set cbgImage - cbgImage_->SetImageFromRGB(displayImage_->pimage->GetData(), width_, height_, true); - hasImage_ = 1; - hasSegment_ = 0; - hasBoundaries_ = 0; - - //adjust titles - BgText title(1, "Confidence Map", *wxSWISS_FONT, RANK_CONF_MARGINX+width_/2-45,RANK_CONF_MARGINY/2-10); - plotWindow1_->AddText(&title); - title.SetText("Gradient Map"); - title.SetPlotLocation(RANK_CONF_MARGINX+width_/2-40,RANK_CONF_MARGINY/2-10); - plotWindow2_->AddText(&title); - - //add axis - plotWindow1_->ClearAxis(); - plotWindow2_->ClearAxis(); - plotWindow1_->AddHorizontalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, width_, 5, 0, width_-1); - plotWindow1_->AddVerticalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, height_, 5, 0, height_-1); - plotWindow2_->AddHorizontalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, width_, 5, 0, width_-1); - plotWindow2_->AddVerticalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, height_, 5, 0, height_-1); - - //label axis - BgText label(1, "x", *wxSWISS_FONT, 0, 0); - plotWindow1_->LabelHorizontalAxis(&label); - plotWindow2_->LabelHorizontalAxis(&label); - label.SetText("y"); - plotWindow1_->LabelVerticalAxis(&label); - plotWindow2_->LabelVerticalAxis(&label); - plotWindow1_->RotateVerticalAxisLabel(-90); - plotWindow2_->RotateVerticalAxisLabel(-90); - - //set white image - unsigned char *img = new unsigned char [(width_)*(height_)*3]; - memset(img, 255, (width_)*(height_)*3); - whiteImage_->SetImageFromRGB(img, width_, height_, true); - delete [] img; - - //clear the plot window displays - ClearDisplay(); - - //do no update the plot windows - UpdateDisplay(false); - - //delete edge maps if they exists... - if(customMap_) delete [] customMap_; - if(gradMap_ ) delete [] gradMap_; - if(confMap_ ) delete [] confMap_; - if(weightMap_) delete [] weightMap_; - - //set edge maps to NULL... - customMap_ = (float *) NULL; - gradMap_ = (float *) NULL; - confMap_ = (float *) NULL; - weightMap_ = (float *) NULL; - - //update interface... - - /***********************************************/ - - //enable run - RunEnable(); - - //enable operations radio box - operationRadio_->Enable(true); - - //update the tool bar - UpdateToolBar(); - - //set window title - wxString statusname; - statusname.Printf(_T("Segmentation Frame %d - %s (%d x %d) [Original Image]"), window_number_, filename_, width_, height_); - SetTitle(statusname); - - //update the menubar - wxMenuBar *menubar = GetMenuBar(); - menubar->Enable(BG_SEGM_SAVE_SEGMENTED, false); - menubar->Enable(BG_SEGM_USE_MAP, false); - - //update window menus - winPanel1_->view_menu->Enable(BG_CANVAS_VIEW1_CUSTMAP, false); - winPanel2_->view_menu->Enable(BG_CANVAS_VIEW2_CUSTMAP, false); - winPanel1_->EnableMenu(false); - winPanel2_->EnableMenu(false); - - /***********************************************/ - -} - -void BgMdiSegmentChild::OnLoadImage(wxCommandEvent& WXUNUSED(event)) -{ -// get the file name -// wxFileDialog filedialog(this,"Choose an image file","","", -// "All files (*.*)|*.*|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm", -// wxOPEN); -#if defined(__WXGTK__) || defined(__WXMOTIF__) - wxFileDialog filedialog(this,"Choose an image file","","", - "*",wxOPEN); -#else - wxFileDialog filedialog(this,"Choose an image file","","", - "Common image files|*.png;*.bmp;*.gif;*.tif;*.tiff;*.jpg;*.pnm;*.pgm;*.ppm|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm|PGM/PPM files (*.pgm,*.ppm)|*.pgm;*.ppm", - wxOPEN); -#endif - - if(filedialog.ShowModal()==wxID_OK) - { - //take away point set if boundaries have been calculated - if(hasBoundaries_) - { - hasBoundaries_ = false; - displayImage_->RemovePointSet(boundaries_); - boundaries_->CleanData(); - } - - if (displayImage_->SetImage(filedialog.GetPath().c_str()) == 0) - return; - bgLog("Image %s loaded\n",filedialog.GetPath().c_str()); - - //obtain and store image filename - if(filename_) delete [] filename_; - filename_ = new char [strlen(filedialog.GetFilename().c_str()) + 1]; - strcpy(filename_, filedialog.GetFilename().c_str()); - - displayImage_->showbitmap_ = true; - - //set value of view boundaries control - viewBoundariesCheck_->SetValue(0); - - //set image view option to original - viewImSegRadio_->SetSelection(0); - - //set operation option to segment - operationRadio_->SetSelection(0); - - //get image dimension - width_ = displayImage_->pimage->GetWidth(); - height_ = displayImage_->pimage->GetHeight(); - - //reset zoom level of display image - displayImage_->Zoom(1); - - //reset max/min zoom flags - maxZoom_ = 0; - minZoom_ = 1; - - //set cbgImage - cbgImage_->SetImageFromRGB(displayImage_->pimage->GetData(), width_, height_, true); - hasImage_ = 1; - hasFilter_ = 0; - hasSegment_ = 0; - hasBoundaries_ = 0; - - //adjust titles - BgText title(1, "Confidence Map", *wxSWISS_FONT, RANK_CONF_MARGINX+width_/2-45,RANK_CONF_MARGINY/2-10); - plotWindow1_->AddText(&title); - title.SetText("Gradient Map"); - title.SetPlotLocation(RANK_CONF_MARGINX+width_/2-40,RANK_CONF_MARGINY/2-10); - plotWindow2_->AddText(&title); - - //add axis - plotWindow1_->ClearAxis(); - plotWindow2_->ClearAxis(); - plotWindow1_->AddHorizontalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, width_, 5, 0, width_-1); - plotWindow1_->AddVerticalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, height_, 5, 0, height_-1); - plotWindow2_->AddHorizontalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, width_, 5, 0, width_-1); - plotWindow2_->AddVerticalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, height_, 5, 0, height_-1); - - //label axis - BgText label(1, "x", *wxSWISS_FONT, 0, 0); - plotWindow1_->LabelHorizontalAxis(&label); - plotWindow2_->LabelHorizontalAxis(&label); - label.SetText("y"); - plotWindow1_->LabelVerticalAxis(&label); - plotWindow2_->LabelVerticalAxis(&label); - plotWindow1_->RotateVerticalAxisLabel(-90); - plotWindow2_->RotateVerticalAxisLabel(-90); - - //set white image - unsigned char *img = new unsigned char [(width_)*(height_)*3]; - memset(img, 255, (width_)*(height_)*3); - whiteImage_->SetImageFromRGB(img, width_, height_, true); - delete [] img; - - //clear the plot window displays - ClearDisplay(); - - //do not update plot windows - UpdateDisplay(false); - - //delete edge maps if they exists... - if(customMap_) delete [] customMap_; - if(gradMap_ ) delete [] gradMap_; - if(confMap_ ) delete [] confMap_; - if(weightMap_) delete [] weightMap_; - - //set edge maps to NULL... - customMap_ = (float *) NULL; - gradMap_ = (float *) NULL; - confMap_ = (float *) NULL; - weightMap_ = (float *) NULL; - - //update interface... - - /***********************************************/ - - //enable run - RunEnable(); - - //enable operations radio box - operationRadio_->Enable(true); - - //update the tool bar - UpdateToolBar(); - - //set window title - wxString statusname; - statusname.Printf(_T("Segmentation Frame %d - %s (%d x %d) [Original Image]"), window_number_, filename_, width_, height_); - SetTitle(statusname); - - //update the menubar - wxMenuBar *menubar = GetMenuBar(); - menubar->Enable(BG_SEGM_SAVE_SEGMENTED, false); - menubar->Enable(BG_SEGM_USE_MAP, false); - - //update window menus - winPanel1_->view_menu->Enable(BG_CANVAS_VIEW1_CUSTMAP, false); - winPanel2_->view_menu->Enable(BG_CANVAS_VIEW2_CUSTMAP, false); - winPanel1_->EnableMenu(false); - winPanel2_->EnableMenu(false); - - /***********************************************/ - - } -} - - -void BgMdiSegmentChild::LoadCustomWeightMap(wxCommandEvent& WXUNUSED(event)) -{ - - //make sure an image was read... - if(hasImage_ == 0) - { - bgLog("image has not been loaded, load image.\n"); - return; - } - - //compute data length - int xsz = cbgImage_->x_, ysz = cbgImage_->y_; - int data_length = (xsz)*(ysz); - -// get the file name -#if defined(__WXGTK__) || defined(__WXMOTIF__) - wxFileDialog filedialog(this,"Upload Custom Weight Map","","", - "*",wxOPEN); -#else - wxFileDialog filedialog(this,"Upload Custom Weight Map","","", - "Matlab ASCII data files (*.dat)|*.dat|All Files (*.*)|*.*", - wxOPEN); -#endif - if(filedialog.ShowModal()==wxID_OK) - { - - //de-allocate memory for customMap (if it exists) - if(customMap_) delete [] customMap_; - - //allocate memory for customMap - customMap_ = new float [data_length]; - - //get data file name - const char *filename = filedialog.GetPath().c_str(); - - //attempt to read in data - FILE *fp = fopen(filename, "rb"); - int i; - for(i = 0; i < data_length; i++) - { - if(!fscanf(fp, "%f", &customMap_[i])) - { - bgLog("Load Map Error: Data length does not match the size of the image."); - delete [] customMap_; - customMap_ = NULL; - return; - } - } - fclose(fp); - - //inform user of successful upload - bgLog("Weight map '%s' successfully uploaded.\n", filename); - - //enable use custom weight map menu items - wxMenuBar* myMenuBar = GetMenuBar(); - myMenuBar->Enable(BG_SEGM_USE_MAP, true); - winPanel1_->view_menu->Enable(BG_CANVAS_VIEW1_CUSTMAP, true); - winPanel2_->view_menu->Enable(BG_CANVAS_VIEW2_CUSTMAP, true); - - } -} - -void BgMdiSegmentChild::OnSaveSegmentedImage(wxCommandEvent& WXUNUSED(event)) -{ - if ((hasSegment_ == 0)&&(hasFilter_ == 0)) - { - bgLog("No result to save. Run segmenter.\n"); - return; - } - -#if defined(__WXGTK__) || defined(__WXMOTIF__) - wxFileDialog filedialog(this,"Choose an image file","","", - "*",wxSAVE); -#else - wxFileDialog filedialog(this,"Choose an image file","","", - "PNM files (*.pnm)|*.pnm|PNG files (*.png)|*.png|PCX files (*.pcx)|*.pcx|PGM files (*.pgm)|*.pgm|JPEG files (*.jpg) (not recommended)|*.jpg", - wxSAVE); -#endif - if(filedialog.ShowModal()==wxID_OK) - { - - //get the image type - int imtype; - switch (filedialog.GetFilterIndex()) - { - case 0: - imtype = wxBITMAP_TYPE_PNM; - break; - case 1: - imtype = wxBITMAP_TYPE_PNG; - break; - case 2: - imtype = wxBITMAP_TYPE_PCX; - break; - case 3: - imtype = wxBITMAP_TYPE_ANY; - break; - case 4: - imtype = wxBITMAP_TYPE_JPEG; - break; - default: - return; - } - - //if the filtered image is available then save it... - if(hasFilter_ == 1) - { - - //get path and add extension - char *path = new char [strlen(filedialog.GetPath()) + 1]; - strcpy(path, filedialog.GetPath()); - BgAddExtension(&path, "_filt"); - - //convert the image to wxImage format... - wxImage tmpIm(filtImage_->x_, filtImage_->y_); - unsigned char* tmpImData; - tmpImData = tmpIm.GetData(); - filtImage_->GetImageColor(tmpImData); - - //save the image... - tmpIm.SaveFile(path, imtype); - bgLog("Filtered image saved to:\t'%s'.\n", path); - - //de-allocate memory - delete path; - - } - - //if the segmented image is available then save it... - if(hasSegment_ == 1) - { - - //get path and add extension - char *path = new char [strlen(filedialog.GetPath()) + 1]; - strcpy(path, filedialog.GetPath()); - BgAddExtension(&path, "_segm"); - - //convert the image to wxImage format... - wxImage tmpIm(segmImage_->x_, segmImage_->y_); - unsigned char* tmpImData; - tmpImData = tmpIm.GetData(); - segmImage_->GetImageColor(tmpImData); - - //save the image... - tmpIm.SaveFile(path, imtype); - bgLog("Segmented image saved to:\t'%s'.\n", path); - - //de-allocate memory - delete [] path; - - } - - //save boundaries - OnSaveBoundaries((char*)filedialog.GetPath().c_str(), imtype); - - } -} - -//saves edge map -void BgMdiSegmentChild::OnSaveBoundaries(char *filename, int imtype) -{ - - //make sure boundaries exist before proceeding... - if(hasBoundaries_ == 0) - return; - - //create edge map - int width = cbgImage_->x_, height = cbgImage_->y_; - wxImage tmpImg(width, height); - unsigned char *buf = tmpImg.GetData(); - memset(buf, 255, width*height*3*sizeof(unsigned char)); - int n = boundaries_->n_; - int i, dp, x, y; - for(i = 0; i < n; i++) - { - x = boundaries_->x_[i]; - y = boundaries_->y_[i]; - dp = y*width+x; - buf[3*dp] = buf[3*dp+1] = buf[3*dp+2] = 0; - } - - //create new filename (add _em extension) - char *new_filename = new char [strlen(filename) + 1]; - strcpy(new_filename, filename); - BgAddExtension(&new_filename, "_bndy"); - - //save edgemap using specified filename and image format - tmpImg.SaveFile(new_filename, imtype); - bgLog("Boundaries saved to:\t'%s'.\n", new_filename); - - //de-allocate memory - delete [] new_filename; - - //done. - return; - -} - -//construct a ph diagram using the boundary pixels -//aquired from image segmentation (also outputs results -//to 'xyrc.txt' -void BgMdiSegmentChild::SetphDiagram(int width, float *confMap, float *rankMap) -{ - unsigned char* buf; - int xsz = RANK_CONF_IMSIZEX; - int ysz = RANK_CONF_IMSIZEY; - int imsz = xsz*ysz; - buf = new unsigned char[imsz]; - int i; - for (i=0; i<imsz; i++) - buf[i] = 255; - - int l, c, dpoint; - int n = boundaries_->n_; - int *xpos = boundaries_->x_, *ypos = boundaries_->y_; - for (i=0; i<n; i++) - { - dpoint = (ypos[i])*width+xpos[i]; - if ((rankMap[dpoint]>0) && (confMap[dpoint]>0)) - { - c = (int) (rankMap[dpoint]*((double) xsz)); - c = (c>=xsz) ? xsz-1 : c; - l = (int) (confMap[dpoint]*((double) ysz)); - l = (l>=ysz) ? ysz-1 : l; - l = ysz-1-l; - buf[c+l*xsz]=80; - - } - } - - phDiagram_->SetImageFromGray(buf, xsz, ysz); - - //adjust scroll bar... - phDiagram_->SetScrollbars(1, 1, xsz+2*RANK_CONF_MARGINX, ysz+2*RANK_CONF_MARGINY+40); - delete [] buf; -} - -void mySegment(void *Object) -{ - BgMdiSegmentChild *segmObj = (BgMdiSegmentChild *) Object; - segmObj->Segment(); -} - -void BgMdiSegmentChild::OnSegment(wxCommandEvent& WXUNUSED(event)) -{ - - //get parameters from GUI - int error = GetParameters(sigmaS, sigmaR, aij, epsilon, minRegion, kernelSize, 1); - if(error) - return; - - //create the working thread - BgThread *workingThread = new BgThread(wxTHREAD_DETACHED, mySegment, this); - stop_flag = false; - workingThread->Create(); - workingThread->Run(); - - //determine progress bar title and message - int operation = operationRadio_->GetSelection(); - char myMessage[80], myTitle[80]; - switch (operation) - { - //filter - case 1: - strcpy(myTitle, "Image Filtering Progress"); - strcpy(myMessage, "Filtering Image..."); - break; - //fuse regions - case 2: - strcpy(myTitle, "Region Fusing Progress"); - strcpy(myMessage, "Fusing Image Regions..."); - break; - //segment - default: - strcpy(myTitle, "Image Segmentation Progress"); - strcpy(myMessage, "Segmenting Image..."); - break; - } - - //call progress dialog - bool done; - percentDone = 0; - wxProgressDialog progressDialog(myTitle, myMessage, 100, this, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); - while((done = progressDialog.Update(percentDone))&&(percentDone != 100)) wxYield(); - if(!done) stop_flag = true; //if the algorithm is not done but the user aborted the operation - //then tell the thread to stop running - - //if its succesfully completed update the parameter history box - if(done) - { - int selIndex = paramComboBox_->GetSelection(); - if(selIndex) - { - paramComboBox_->UseParameterList(selIndex-1); - } - else - { - float *myParameters = new float [6]; - myParameters[0] = sigmaS; - myParameters[1] = sigmaR; - myParameters[2] = aij; - myParameters[3] = epsilon; - myParameters[4] = minRegion; - myParameters[5] = kernelSize; - paramComboBox_->AddParameterList((void *) myParameters, 6); - } - - //set the selection to the current parameter slot - paramComboBox_->SetSelection(0); - isCurrentHistory_ = true; - } - return; - -} - -void BgMdiSegmentChild::Segment( void ) -{ - // parameters - // sigma_s - // sigma_r - // a - // epsilon - // minRegion - // kernel radius - // filter - // speedup level - - if (hasImage_ == 0) - { - bgLog("No image loaded!\n"); - return; - } - - //if image segmentaiton is not synergistic clear - //display and disable it, otherwise enable it - if(!useWeightMap_->GetValue()) - { - ClearDisplay(); - UpdateDisplay(false); - } - else - { - UpdateDisplay(true); - } - - //display parameters to the user - if(useWeightMap_->GetValue()) - { - bgLog("Input parameters:\n"); - bgLog("\tSpatial Bandwidth\t\t= %4d\n\tColor Bandwidth\t\t= %4.1f\n", sigmaS, sigmaR); - bgLog("\tMinimum Region\t\t= %4d\n", minRegion); - bgLog("\tGradient Window Radius\t= %4d\n", kernelSize); - bgLog("\tMixing Parameter\t\t= %4.1f\n", aij); - bgLog("\tThreshold\t\t\t= %4.1f\n", epsilon); - } - else - { - bgLog("Input parameters:\n"); - bgLog("\tSpatial Bandwidth\t= %4d\n\tColor Bandwidth\t= %4.1f\n", sigmaS, sigmaR); - bgLog("\tMinimum Region\t= %4d\n", minRegion); - } - - //obtain image dimensions - int width, height; - width = cbgImage_->x_; - height = cbgImage_->y_; - - //obtain image type (color or grayscale) - imageType gtype; - if(cbgImage_->colorIm_) - gtype = COLOR; - else - gtype = GRAYSCALE; - - //if gradient and confidence maps are not defined, - //and synergistic segmentation is requested, then compute them; - //also compute them if the parameters have changed - if(useWeightMap_->GetValue()) - { - - //if the weight map has already been defined - //then find out if it needs to be recomputed - if((weightMap_)&&(edgeParamsHaveChanged_)) - { - delete [] confMap_; - delete [] gradMap_; - delete [] weightMap_; - weightMap_ = (float *) NULL; - //indicate that the change has been recognized... - edgeParamsHaveChanged_ = false; - } - - //if the weight map has not been computed or discarded - //then recompute it... - if(!weightMap_) - { - - //allocate memory for gradient and confidence maps - confMap_ = new float[width*height]; - gradMap_ = new float[width*height]; - - //compute gradient and confidence maps - BgEdgeDetect edgeDetector(kernelSize); - edgeDetector.ComputeEdgeInfo(cbgImage_, confMap_, gradMap_); - - //compute weight map... - - /******************************************************************/ - - //allocate memory for weight map - weightMap_ = new float[width*height]; - - //compute weight map using gradient and confidence maps - int i; - for (i=0; i<width*height; i++) - { - if (gradMap_[i] > 0.02) - weightMap_[i] = aij*gradMap_[i] + (1 - aij)*confMap_[i]; - else - weightMap_[i] = 0; - } - - /******************************************************************/ - } - - } - - //determine operation (filtering or segmentation) - int operation = operationRadio_->GetSelection(); - - //create instance of image processor class - msImageProcessor *iProc = new msImageProcessor(); - - //define an input image using the image under consideration - //(if filtering or segmentation has taken place, then use this - // result upon performing fusing...) - if((operation == 2)&&(hasFilter_)) - iProc->DefineImage(filtImage_->im_, gtype, height, width); - else - iProc->DefineImage(cbgImage_->im_, gtype, height, width); - - //determine if a custom weight map is to be used - wxMenuBar *menubar = GetMenuBar(); - bool useCustomMap = menubar->IsChecked(BG_SEGM_USE_MAP); - - //set the weight map (if one was specified and a custom map is not being utilized) - if((useWeightMap_->GetValue())&&(weightMap_)&&(!useCustomMap)) iProc->SetWeightMap(weightMap_, epsilon); - - //set the custom map (if one was provided) - if((useWeightMap_->GetValue())&&(customMap_)&&(useCustomMap)) iProc->SetWeightMap(customMap_, epsilon); - - //check for errors in image definition or in the setting - //of the confidence map... - if (iProc->ErrorStatus) - { - bgLog("%s\n", iProc->ErrorMessage); - return; - } - - //perform image segmentation or filtering.... - timer_start(); //start the timer - iProc->SetSpeedThreshold(speedUpThreshold_); - switch(operation) - { - //filter - case 1: - - iProc->Filter(sigmaS, sigmaR, speedUpLevel_); - if (iProc->ErrorStatus == EL_ERROR) - { - bgLog("%s\n", iProc->ErrorMessage); - return; - } else if (iProc->ErrorStatus == EL_HALT) - { - break; - } - - //obtain the filtered image.... - filtImage_->Resize(width, height, cbgImage_->colorIm_); - iProc->GetResults(filtImage_->im_); - if (iProc->ErrorStatus == EL_ERROR) - { - bgLog("%s\n", iProc->ErrorMessage); - return; - } - - //indicate that only the filtered image has been computed... - hasFilter_ = 1; - hasSegment_ = 0; - - break; - - //fuse - case 2: - - iProc->FuseRegions(sigmaR, minRegion); - if (iProc->ErrorStatus == EL_ERROR) - { - bgLog("%s\n", iProc->ErrorMessage); - return; - } else if (iProc->ErrorStatus == EL_HALT) - { - break; - } - - //obtain the segmented image... - segmImage_->Resize(width, height, cbgImage_->colorIm_); - iProc->GetResults(segmImage_->im_); - if (iProc->ErrorStatus == EL_ERROR) - { - bgLog("%s\n", iProc->ErrorMessage); - return; - } - - //indicate that the segmented image has been computed... - hasSegment_ = 1; - - break; - - //segment - default: - - //filter the image... - iProc->Filter(sigmaS, sigmaR, speedUpLevel_); - if (iProc->ErrorStatus == EL_ERROR) - { - bgLog("%s\n", iProc->ErrorMessage); - return; - } else if (iProc->ErrorStatus == EL_HALT) - { - break; - } - - //filter the image.... - int dim; - if(cbgImage_->colorIm_) - dim = 3; - else - dim = 1; - unsigned char *tempImage = new unsigned char [dim*height*width]; - iProc->GetResults(tempImage); - if (iProc->ErrorStatus == EL_ERROR) - { - bgLog("%s\n", iProc->ErrorMessage); - delete [] tempImage; - return; - } - - //fuse regions... - iProc->FuseRegions(sigmaR, minRegion); - if (iProc->ErrorStatus == EL_ERROR) - { - bgLog("%s\n", iProc->ErrorMessage); - delete [] tempImage; - return; - } else if (iProc->ErrorStatus == EL_HALT) - { - delete [] tempImage; - break; - } - - //obtain the segmented and filtered image... - filtImage_->Resize(width, height, cbgImage_->colorIm_); - memcpy(filtImage_->im_, tempImage, dim*height*width*sizeof(unsigned char)); - delete [] tempImage; - segmImage_->Resize(width, height, cbgImage_->colorIm_); - iProc->GetResults(segmImage_->im_); - if (iProc->ErrorStatus) - { - bgLog("%s\n", iProc->ErrorMessage); - return; - } - - //indicate that both the filtered and segmented image have been computed... - hasFilter_ = 1; - hasSegment_ = 1; - - } - - //check and see if the algorithm has been halted, if so - //then de-allocate the image processing object and - //indicate to the working thread that it is safe - //to exit at this point and exit - if(iProc->ErrorStatus == EL_HALT) - { - delete iProc; - stop_flag = false; - bgLog("Operation Canceled.\n"); - return; - } - - //set has boundaries to true - hasBoundaries_ = true; - - //clean boundary data if any exists - boundaries_->CleanData(); - - //get boundary indeces from region list object - //of the image processor object... - RegionList *regionList = iProc->GetBoundaries(); - int *regionIndeces = regionList->GetRegionIndeces(0); - int numRegions = regionList->GetNumRegions(); - int boundaryPointCount = 0; - - //calculate the number of boundary points stored by region list - //class - int i; - for(i = 0; i < numRegions; i++) - boundaryPointCount += regionList->GetRegionCount(i); - - //create a point set using calculated boundary point count... - boundaries_->x_ = new int [boundaryPointCount]; - boundaries_->y_ = new int [boundaryPointCount]; - boundaries_->n_ = boundaryPointCount; - for(i = 0; i < boundaryPointCount; i++) - { - boundaries_->x_[i] = regionIndeces[i]%width; - boundaries_->y_[i] = regionIndeces[i]/width; - } - - //set pen width, and style - boundaries_->pen_.SetWidth(1); - boundaries_->pen_.SetStyle(wxSOLID); - - //set point type to point (= 1) - boundaries_->type_ = 1; - - //construct the phDiagram - if(useWeightMap_->GetValue()) SetphDiagram(width, confMap_, gradMap_); - - //display the confidence and gradient maps respectively - if(useWeightMap_->GetValue()) - { - wxCommandEvent myevent; - myevent.m_id = BG_CANVAS_VIEW1_CONFMAP; - OnUpdatePlotWindow1(myevent); - myevent.m_id = BG_CANVAS_VIEW2_GRADMAP; - OnUpdatePlotWindow2(myevent); - } - - //delete the image processing object - delete iProc; - - //done. - - //stop the timer - timer_stop(); - - //update the GUI... - - /**********************************************************************************/ - - //update the menu bar - menubar->Enable(BG_SEGM_SAVE_SEGMENTED, true); - - //update tool bar - SaveEnable(); - - //update segmentation window.... - switch(operation) - { - - //the image has been filtered only.... - case 1: - viewImSegRadio_->Enable(1, true); - viewImSegRadio_->Enable(2, false); - viewImSegRadio_->SetSelection(1); - break; - - //the image has been segmented only... - case 2: - viewImSegRadio_->Enable(2, true); - viewImSegRadio_->SetSelection(2); - break; - - //image has been filtered and segmented... - default: - viewImSegRadio_->Enable(1, true); - viewImSegRadio_->Enable(2, true); - viewImSegRadio_->SetSelection(2); - break; - - } - viewImSegRadio_->Enable(3, true); - viewBoundariesCheck_->Enable(true); - wxCommandEvent zcev; - OnViewImSeg(zcev); - - //update the menu bars... - winPanel1_->EnableMenu(useWeightMap_->GetValue()); - winPanel2_->EnableMenu(useWeightMap_->GetValue()); - - /**********************************************************************************/ - - //set progress to 100% (need this for case of filtering) - percentDone = 100; - - //indicate that it is safe for the thread to stop executing - stop_flag = false; - - //done. - return; - -} - -int BgMdiSegmentChild::GetParameters(int &sigmaS, float &sigmaR, float &aij, float &epsilon, int &minRegion, int &kernelSize, int dataEntryCheck) -{ - - double tempd; - char str[10]; - - //do not perform data entry check - if(!dataEntryCheck) - { - //sigmaS - txtSigmaS_->GetValue().ToDouble(&tempd); - sigmaS = bgRoundSign(tempd); - - //sigmaR - txtSigmaR_->GetValue().ToDouble(&tempd); - sigmaR = (float) tempd; - - //minRegion - txtMinRegion_->GetValue().ToDouble(&tempd); - minRegion = bgRoundSign(tempd); - - //kernel size - txtKernelSize_->GetValue().ToDouble(&tempd); - kernelSize = bgRoundSign(tempd); - - //aij - txtA_->GetValue().ToDouble(&tempd); - aij = (float) tempd; - - //epsilon - txtEpsilon_->GetValue().ToDouble(&tempd); - epsilon = (float) tempd; - - //done. - return 0; - } - - //perform data entry check - if ((txtSigmaS_->GetValue().ToDouble(&tempd) == TRUE) && (tempd > 0)) - { - sigmaS = (int)(tempd + 0.5); - sprintf(str, "%d", sigmaS); - txtSigmaS_->SetValue(str); - } - else - { - bgLog("The value of the spatial bandwidth cannot be zero or negative.\n"); - return 1; - } - if ((txtSigmaR_->GetValue().ToDouble(&tempd) == TRUE) && (tempd > 0)) - sigmaR = tempd; - else - { - bgLog("The value of the range bandwidth cannot be zero or negative.\n"); - return 1; - } - if ((txtMinRegion_->GetValue().ToDouble(&tempd) == TRUE) && (tempd >= 0)) - { - minRegion = (int)(tempd + 0.5); - sprintf(str, "%d", minRegion); - txtMinRegion_->SetValue(str); - } - else - { - bgLog("The value of minimum region cannot be negative.\n"); - return 1; - } - if ((txtKernelSize_->GetValue().ToDouble(&tempd) == TRUE) && (tempd > 0)) - { - kernelSize = (int)(tempd + 0.5); - sprintf(str, "%d", kernelSize); - txtKernelSize_->SetValue(str); - } - else - { - bgLog("The gradient window radius cannot be zero or negative.\n"); - return 1; - } - if ((txtA_->GetValue().ToDouble(&tempd) == TRUE) && (tempd >= 0) && (tempd <= 1)) - { - aij = tempd; - if(aij < 0.01) txtA_->SetValue("0.0"); - } - else - { - bgLog("The value of the mixture parameter cannot be negative or greater than one.\n"); - return 1; - } - if ((txtEpsilon_->GetValue().ToDouble(&tempd) == TRUE) && (tempd >= 0) && (tempd <= 1)) - { - epsilon = tempd; - if(epsilon < 0.01) txtEpsilon_->SetValue("0.0"); - } - else - { - bgLog("The threshold value cannot be negative or greater than one.\n"); - return 1; - } - return 0; +///////////////////////////////////////////////////////////////////////////// +// Name: bgimsystem.cpp +// Purpose: Image processing system +// Author: Bogdan Georgescu, Chris M. Christoudias +// Modified by: +// Created: 06/22/2000 +// Copyright: (c) Bogdan Georgescu, Chris M. Christoudias +// Version: v0.1 +///////////////////////////////////////////////////////////////////////////// + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include <wx/toolbar.h> +#include <wx/progdlg.h> + +#if defined(__WXGTK__) || defined(__WXMOTIF__) + #include "icons/mondrian.xpm" + #include "icons/new.xpm" + #include "icons/open.xpm" + #include "icons/save.xpm" + #include "icons/copy.xpm" + #include "icons/cut.xpm" + #include "icons/paste.xpm" + #include "icons/print.xpm" + #include "icons/help.xpm" +#endif + +#include <wx/html/htmlwin.h> + +#include "BgImagPGM.h" +#include "BgImagPNM.h" + +// Edge detection include stuff +#include <math.h> +#include "BgImage.h" +#include "BgEdge.h" +#include "BgEdgeList.h" +#include "BgEdgeDetect.h" +#include "BgDefaults.h" + +#include "msImageProcessor.h" + +#include <stdio.h> +#include <string.h> +#include "bgimsystem.h" + +IMPLEMENT_APP(BgApp) +// --------------------------------------------------------------------------- +// global variables +// --------------------------------------------------------------------------- + +BgMdiFrame *g_frame = (BgMdiFrame *) NULL; +wxList g_children; + +// For drawing lines in a canvas +static long g_xpos = -1; +static long g_ypos = -1; + +static int gs_nFrames = 0; +static bool on_exit = false; +#define DEFAULT_LOG_SIZE 100 + +// --------------------------------------------------------------------------- +// event tables +// --------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(BgMdiFrame, wxMDIParentFrame) +EVT_MENU(BG_ABOUT, BgMdiFrame::OnAbout) +EVT_MENU(BG_HELP, BgMdiFrame::OnHelp) +EVT_MENU(BG_QUIT, BgMdiFrame::OnQuit) +EVT_MENU(BG_NEW_EDGE_WINDOW, BgMdiFrame::OnNewEdgeWindow) +EVT_MENU(BG_NEW_SEGM_WINDOW, BgMdiFrame::OnNewSegmWindow) +EVT_MENU(BG_LOAD_IMAGE, BgMdiFrame::OnLoadImage) +EVT_MENU(BG_LOAD_IMAGE_EDGE, BgMdiFrame::OnLoadImageEdge) +EVT_MENU(BG_SEGM_LOAD_IMAGE, BgMdiFrame::OnLoadImageSegm) +EVT_MENU(BG_SAVE_RESULT, BgMdiFrame::OnSaveResult) +EVT_MENU(BG_CROSS, BgMdiFrame::ZoomControl) +EVT_MENU(BG_ZOOM_IN, BgMdiFrame::ZoomControl) +EVT_MENU(BG_ZOOM_OUT, BgMdiFrame::ZoomControl) +EVT_MENU(BG_POINTER, BgMdiFrame::ZoomControl) +EVT_CLOSE(BgMdiFrame::OnClose) + +EVT_SIZE(BgMdiFrame::OnSize) +END_EVENT_TABLE() + +// Note that BG_NEW_WINDOW and BG_ABOUT commands get passed +// to the parent window for processing, so no need to +// duplicate event handlers here. + +BEGIN_EVENT_TABLE(BgMdiEdgeChild, wxMDIChildFrame) +EVT_MENU(BG_LOAD_IMAGE_EDGE, BgMdiEdgeChild::OnLoadImage) +EVT_MENU(BG_EDGE_DETECT, BgMdiEdgeChild::OnEdgeDetect) +EVT_MENU(BG_CHANGE_PARAM_EDGE, BgMdiEdgeChild::OnChangeParam) +EVT_MENU(BG_CHILD_EDGE_QUIT, BgMdiEdgeChild::OnQuit) +EVT_MENU(BG_EDGE_VIEW_ORIG, BgMdiEdgeChild::OnViewOrig) +EVT_MENU(BG_EDGE_VIEW_EDGE, BgMdiEdgeChild::OnViewEdge) +EVT_MENU(BG_EDGE_SAVE_MAP, BgMdiEdgeChild::OnSaveEdgeMap) + +EVT_SET_FOCUS(BgMdiEdgeChild::OnFocus) +EVT_CLOSE(BgMdiEdgeChild::OnClose) +EVT_SIZE(BgMdiEdgeChild::OnSize) + +EVT_BUTTON(BG_EDGE_DETECT, BgMdiEdgeChild::OnEdgeDetect) +EVT_BUTTON(BG_CHANGE_PARAM_EDGE, BgMdiEdgeChild::OnChangeParam) +EVT_CHECKBOX(BG_EDGE_CVIEW_ORIG, BgMdiEdgeChild::OnCViewOrig) +EVT_CHECKBOX(BG_EDGE_CVIEW_EDGE, BgMdiEdgeChild::OnCViewEdge) + +EVT_COMMAND(BG_EVENT_UPDATE_ID, BG_EVENT_UPDATE, BgMdiEdgeChild::OnUpdateNum) + +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(BgMdiSegmentChild, wxMDIChildFrame) +EVT_MENU(BG_SEGM_LOAD_IMAGE, BgMdiSegmentChild::OnLoadImage) +EVT_MENU(BG_SEGM_SAVE_SEGMENTED, BgMdiSegmentChild::OnSaveSegmentedImage) +EVT_MENU(BG_SEGM_SAVE_EDGEMAP, BgMdiSegmentChild::OnSaveBoundaries) +EVT_MENU(BG_CHILD_SEGM_QUIT, BgMdiSegmentChild::OnQuit) +EVT_MENU(BG_SEGM_SEGMENT, BgMdiSegmentChild::OnSegment) +EVT_MENU(BG_SEGM_LOAD_MAP, BgMdiSegmentChild::LoadCustomWeightMap) +EVT_MENU(BG_SEGM_SPEEDUP_NONE, BgMdiSegmentChild::OnUpdateSpeedUpLevel) +EVT_MENU(BG_SEGM_SPEEDUP_MEDM, BgMdiSegmentChild::OnUpdateSpeedUpLevel) +EVT_MENU(BG_SEGM_SPEEDUP_HIGH, BgMdiSegmentChild::OnUpdateSpeedUpLevel) +EVT_MENU(BG_CANVAS_VIEW1_GRADMAP, BgMdiSegmentChild::OnUpdatePlotWindow1) +EVT_MENU(BG_CANVAS_VIEW1_CONFMAP, BgMdiSegmentChild::OnUpdatePlotWindow1) +EVT_MENU(BG_CANVAS_VIEW1_WEITMAP, BgMdiSegmentChild::OnUpdatePlotWindow1) +EVT_MENU(BG_CANVAS_VIEW1_CUSTMAP, BgMdiSegmentChild::OnUpdatePlotWindow1) +EVT_MENU(BG_CANVAS_VIEW2_GRADMAP, BgMdiSegmentChild::OnUpdatePlotWindow2) +EVT_MENU(BG_CANVAS_VIEW2_CONFMAP, BgMdiSegmentChild::OnUpdatePlotWindow2) +EVT_MENU(BG_CANVAS_VIEW2_WEITMAP, BgMdiSegmentChild::OnUpdatePlotWindow2) +EVT_MENU(BG_CANVAS_VIEW2_CUSTMAP, BgMdiSegmentChild::OnUpdatePlotWindow2) +EVT_MENU(BG_CANVAS_SAVE_GRADMAP, BgMdiSegmentChild::OnSaveEdgeInformation) +EVT_MENU(BG_CANVAS_SAVE_CONFMAP, BgMdiSegmentChild::OnSaveEdgeInformation) +EVT_MENU(BG_CANVAS_SAVE_WEITMAP, BgMdiSegmentChild::OnSaveEdgeInformation) + +EVT_SET_FOCUS(BgMdiSegmentChild::OnFocus) +EVT_CLOSE(BgMdiSegmentChild::OnClose) +EVT_SIZE(BgMdiSegmentChild::OnSize) + +EVT_BUTTON(BG_SEGM_LOAD_IMAGE, BgMdiSegmentChild::OnLoadImage) +EVT_BUTTON(BG_SEGM_SEGMENT, BgMdiSegmentChild::OnSegment) +EVT_BUTTON(BG_SEGM_LOAD_MAP, BgMdiSegmentChild::LoadCustomWeightMap) +EVT_RADIOBOX(BG_SEGM_VIEW_IMSEG, BgMdiSegmentChild::OnViewImSeg) +EVT_RADIOBOX(BG_SEGM_OPERATION, BgMdiSegmentChild::OnChangeOperation) +EVT_CHECKBOX(BG_SEGM_VIEW_EDGES, BgMdiSegmentChild::OnViewBoundaries) +EVT_CHECKBOX(BG_SEGM_USE_EDGE_MAP, BgMdiSegmentChild::OnUseWeightMap) +EVT_COMBOBOX(BG_SEGM_CHANGE_PARAMS, BgMdiSegmentChild::OnChangeParameters) + +EVT_TEXT(BG_SEGM_TEXT_SIGMAS, BgMdiSegmentChild::OnUpdateTextBoxes) +EVT_TEXT(BG_SEGM_TEXT_SIGMAR, BgMdiSegmentChild::OnUpdateTextBoxes) +EVT_TEXT(BG_SEGM_TEXT_MINREG, BgMdiSegmentChild::OnUpdateTextBoxes) +EVT_TEXT(BG_SEGM_TEXT_GRADWIN, BgMdiSegmentChild::OnUpdateTextBoxes) +EVT_TEXT(BG_SEGM_TEXT_AIJ, BgMdiSegmentChild::OnUpdateTextBoxes) +EVT_TEXT(BG_SEGM_TEXT_EPSILON, BgMdiSegmentChild::OnUpdateTextBoxes) + +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(BgImCanvas, wxScrolledWindow) +EVT_RIGHT_DOWN(BgImCanvas::OnMouseRightDown) +EVT_MOUSE_EVENTS(BgImCanvas::OnEvent) + +EVT_MENU(BG_IMC_ADDNODE, BgImCanvas::OnCustomAddNode) +EVT_MENU(BG_IMC_DELETENODE, BgImCanvas::OnCustomDeleteNode) +EVT_MENU(BG_IMC_SELTYPE_ELLIPSE, BgImCanvas::OnCTypeEllipse) +EVT_MENU(BG_IMC_SELTYPE_VLINE, BgImCanvas::OnCTypeVLine) +EVT_MENU(BG_IMC_SELTYPE_HLINE, BgImCanvas::OnCTypeHLine) +EVT_MENU(BG_IMC_SELTYPE_LINE, BgImCanvas::OnCTypeLine) +EVT_MENU(BG_IMC_SELTYPE_BOX, BgImCanvas::OnCTypeBox) +EVT_MENU(BG_IMC_SELTYPE_CUSTOM, BgImCanvas::OnCTypeCustom) + +//EVT_SCROLLWIN(BgImCanvas::OnScroll) + +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(BgParamDialog, wxDialog) +EVT_BUTTON(BG_PARAMD_OK, BgParamDialog::OnOk) +EVT_BUTTON(BG_PARAMD_CANCEL, BgParamDialog::OnCancel) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(BgSpeedSelect, wxDialog) +EVT_BUTTON(BG_SPEEDSEL_OK, BgSpeedSelect::OnOk) +EVT_BUTTON(BG_SPEEDSEL_CANCEL, BgSpeedSelect::OnCancel) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(BgDialog, wxDialog) +EVT_BUTTON(BG_DIALOG_OK, BgDialog::OnExit) +EVT_PAINT(BgDialog::OnPaint) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(BgHoverBar, wxWindow) +EVT_BUTTON(BG_CANVAS_VIEW_BUTTON, BgHoverBar::ShowMenu) +EVT_BUTTON(BG_CANVAS_SAVE_BUTTON, BgHoverBar::ShowMenu) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(BgMenuPanel, wxPanel) +EVT_BUTTON(BG_CANVAS_VIEW_BUTTON, BgMenuPanel::ShowMenu) +EVT_BUTTON(BG_CANVAS_SAVE_BUTTON, BgMenuPanel::ShowMenu) +EVT_SIZE(BgMenuPanel::OnSize) +END_EVENT_TABLE() + +// =========================================================================== +// implementation +// =========================================================================== + +// --------------------------------------------------------------------------- +// Global Data used for Multi-Threaded Enviornment +// --------------------------------------------------------------------------- + +bool stop_flag; +int percentDone; + +// --------------------------------------------------------------------------- +// Log function +// --------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// wxLogTextCtrl implementation +// ---------------------------------------------------------------------------- + +bgLogTextCtrl::bgLogTextCtrl(wxTextCtrl *pTextCtrl) +{ + m_pTextCtrl = pTextCtrl; +} + +void bgLogTextCtrl::DoLogString(const wxChar *szString, time_t WXUNUSED(t)) +{ + wxString msg; + TimeStamp(&msg); + msg << szString; + + m_pTextCtrl->AppendText(msg); +} + +#define VAR_LOG_BUFFER_SIZE (4096) + +static wxChar varszBuf[VAR_LOG_BUFFER_SIZE]; + +FILE* glogfile; + +void bgLog(const char* szFormat, ...) +{ + va_list argptr; + va_start(argptr, szFormat); + wxVsnprintf(varszBuf, WXSIZEOF(varszBuf), szFormat, argptr); + va_end(argptr); + ::wxLogMessage(varszBuf); + bgLogFile(varszBuf); +} + +void bgLogVar(const char* first, va_list alist) +{ +// va_start(alist, first); + wxVsnprintf(varszBuf, WXSIZEOF(varszBuf), first, alist); +// va_end(alist); + ::wxLogMessage(varszBuf); + bgLogFile(varszBuf); +} + +void bgLogFile(const char* szFormat, ...) +{ + if (glogfile == 0) + glogfile = fopen("filelog.txt", "w"); + va_list argptr; + va_start(argptr, szFormat); + vfprintf(glogfile, szFormat, argptr); + va_end(argptr); + fflush(glogfile); +} + +inline int bgRound(double inline_x) +{ + return ((int) (inline_x+0.5)); +} + +// --------------------------------------------------------------------------- +// BgApp +// --------------------------------------------------------------------------- + +// Initialise this in OnInit, not statically +bool BgApp::OnInit() +{ + // Create the main frame window + + g_frame = new BgMdiFrame((wxFrame *)NULL, -1, "Edge Detection and Image SegmentatiON System (EDISON)", + wxPoint(10, 10), wxSize(1024, 768), + wxDEFAULT_FRAME_STYLE | wxHSCROLL | wxVSCROLL); +#ifdef __WXMSW__ +#if 0 + // Experimental: change the window menu + wxMenu* windowMenu = new wxMenu; + windowMenu->Append(5000, "My menu item!"); + frame->SetWindowMenu(windowMenu); +#endif +#endif + + // Give it an icon +#ifdef __WXMSW__ + g_frame->SetIcon(wxIcon("bg_icn")); +#else + g_frame->SetIcon(wxIcon( mondrian_xpm )); +#endif + + // Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(BG_NEW_EDGE_WINDOW, "New &edge window\tAlt-E", "Create a new edge detect window"); + file_menu->Append(BG_NEW_SEGM_WINDOW, "New &segment window\tAlt-S", "Create a new segmentation window"); + file_menu->Append(BG_LOAD_IMAGE_EDGE, "&Load edge image\tCtrl-L", "Load a new image to perform edge detection"); + file_menu->Append(BG_SEGM_LOAD_IMAGE, "&Load segment image\tShift-L", "Load a new image to perform segmentation"); + file_menu->Append(BG_QUIT, "E&xit\tAlt-X", "Quit the program"); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(BG_ABOUT, "&About"); + help_menu->Append(BG_HELP, "&Help\tCtrl-H"); + + wxMenuBar *menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, "&File"); + menu_bar->Append(help_menu, "&Help"); + + // Associate the menu bar with the frame + g_frame->SetMenuBar(menu_bar); + + g_frame->CreateStatusBar(); + + g_frame->Show(TRUE); + + SetTopWindow(g_frame); + +#if wxUSE_LIBPNG + wxImage::AddHandler( new wxPNGHandler ); +#endif + +#if wxUSE_LIBJPEG + wxImage::AddHandler( new wxJPEGHandler ); +#endif + +#if wxUSE_LIBTIFF + wxImage::AddHandler( new wxTIFFHandler ); +#endif + +#if wxUSE_GIF + wxImage::AddHandler( new wxGIFHandler ); +#endif + +#if wxUSE_PCX + wxImage::AddHandler( new wxPCXHandler ); +#endif + + wxImage::AddHandler( new bgPNMHandler ); + wxImage::AddHandler( new bgPGMHandler ); + return TRUE; +} + +// --------------------------------------------------------------------------- +// BgMdiFrame +// --------------------------------------------------------------------------- + +// Define my frame constructor +BgMdiFrame::BgMdiFrame(wxWindow *parent, + const wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + const long style) + : wxMDIParentFrame(parent, id, title, pos, size, style) +{ + logtext_ = new wxTextCtrl(this, -1, "Log window.\n", + wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY); + logtext_->SetBackgroundColour("wheat"); + bglogctrl_ = new bgLogTextCtrl(logtext_); + logTargetOld_ = wxLog::SetActiveTarget(bglogctrl_); + logsize_ = DEFAULT_LOG_SIZE; + + CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL); + InitToolBar(GetToolBar()); + + //get program location directory + strcpy(programDir_, wxGetCwd()); + + //get help directory location + //(NOTE: This code must be altered to function properly in UNIX.) + strcpy(helpDir_, programDir_); + strcat(helpDir_, "\\doc\\help.html"); + + // Accelerators + wxAcceleratorEntry entries[13]; + entries[0].Set(wxACCEL_ALT, (int) 'E', BG_NEW_EDGE_WINDOW); + entries[1].Set(wxACCEL_ALT, (int) 'S', BG_NEW_SEGM_WINDOW); + entries[2].Set(wxACCEL_ALT, (int) 'X', BG_QUIT); + entries[3].Set(wxACCEL_ALT, (int) 'C', BG_CHILD_EDGE_QUIT); + entries[4].Set(wxACCEL_SHIFT, (int) 'C', BG_CHILD_SEGM_QUIT); + entries[5].Set(wxACCEL_CTRL, (int) 'H', BG_HELP); + entries[6].Set(wxACCEL_CTRL, (int) 'S', BG_EDGE_SAVE_MAP); + entries[7].Set(wxACCEL_SHIFT, (int) 'S', BG_SEGM_SAVE_SEGMENTED); + entries[8].Set(wxACCEL_CTRL, (int) 'L', BG_LOAD_IMAGE_EDGE); + entries[9].Set(wxACCEL_SHIFT, (int) 'L', BG_SEGM_LOAD_IMAGE); + entries[10].Set(wxACCEL_SHIFT, (int) 'M', BG_SEGM_LOAD_MAP); + entries[11].Set(wxACCEL_CTRL, (int) 'R', BG_EDGE_DETECT); + entries[12].Set(wxACCEL_SHIFT, (int) 'R', BG_SEGM_SEGMENT); + wxAcceleratorTable accel(13, entries); + SetAcceleratorTable(accel); + + // bgFileLog + //glogfile = fopen("filelog.txt", "w"); + glogfile = 0; +} + +void BgMdiFrame::OnClose(wxCloseEvent& event) +{ + if ( event.CanVeto() && (gs_nFrames > 0) ) + { + wxString msg; + if (gs_nFrames == 1) + msg.Printf(_T("%d window still open, close anyhow?"), gs_nFrames); + else + msg.Printf(_T("%d windows still open, close anyhow?"), gs_nFrames); + if ( wxMessageBox(msg, "Please confirm", + wxICON_QUESTION | wxYES_NO) != wxYES ) + { + event.Veto(); + + return; + } + } + + //indicate that the system is exiting + on_exit = true; + + wxLog::SetActiveTarget(logTargetOld_); + delete bglogctrl_; + delete logtext_; + + // bgFileLog + if (glogfile != 0) + fclose(glogfile); + + event.Skip(); +} + +//sets the title of the active child frame +void BgMdiFrame::SetChildTitle(wxMDIChildFrame *activeChild, int zconst, int maxZoom, int minZoom) +{ + wxString title; + if(activeChild->GetId() == BG_EDGE_WINDOW) + { + BgMdiEdgeChild *edgeChild = (BgMdiEdgeChild *) activeChild; + if(maxZoom) + title.Printf(_T("Edge Detection Frame %d - %s (%d x %d) x %d [Maximum Zoom]"), edgeChild->window_number_, edgeChild->filename_, edgeChild->width_, edgeChild->height_, zconst); + else if(minZoom) + title.Printf(_T("Edge Detection Frame %d - %s (%d x %d) [Original Image]"), edgeChild->window_number_, edgeChild->filename_, edgeChild->width_, edgeChild->height_); + else + title.Printf(_T("Edge Detection Frame %d - %s (%d x %d) x %d [Zoom]"), edgeChild->window_number_, edgeChild->filename_, edgeChild->width_, edgeChild->height_, zconst); + } + else if(activeChild->GetId() == BG_SEGM_WINDOW) + { + BgMdiSegmentChild *segmChild = (BgMdiSegmentChild *) activeChild; + if(maxZoom) + title.Printf(_T("Segmentation Frame %d - %s (%d x %d) x %d [Maximum Zoom]"), segmChild->window_number_, segmChild->filename_, segmChild->width_, segmChild->height_, zconst); + else if(minZoom) + title.Printf(_T("Segmentation Frame %d - %s (%d x %d) [Original Image]"), segmChild->window_number_, segmChild->filename_, segmChild->width_, segmChild->height_); + else + title.Printf(_T("Segmentation Frame %d - %s (%d x %d) x %d [Zoom]"), segmChild->window_number_, segmChild->filename_, segmChild->width_, segmChild->height_, zconst); + } + activeChild->SetTitle(title); + return; +} + +//updates toolbar when maximum zoom occurs +void BgMdiFrame::UpdateZoomControl(wxMDIChildFrame *activeChild, int maxZoom, int minZoom) +{ + if(activeChild->GetId() == BG_EDGE_WINDOW) + { + if(maxZoom) + ((BgMdiEdgeChild *) activeChild)->maxZoom_ = true; + else + ((BgMdiEdgeChild *) activeChild)->maxZoom_ = false; + if(minZoom) + ((BgMdiEdgeChild *) activeChild)->minZoom_ = true; + else + ((BgMdiEdgeChild *) activeChild)->minZoom_ = false; + ((BgMdiEdgeChild *) activeChild)->UpdateZoomControl(); + } + else if (activeChild->GetId() == BG_SEGM_WINDOW) + { + if(maxZoom) + ((BgMdiSegmentChild *) activeChild)->maxZoom_ = true; + else + ((BgMdiSegmentChild *) activeChild)->maxZoom_ = false; + if(minZoom) + ((BgMdiSegmentChild *) activeChild)->minZoom_ = true; + else + ((BgMdiSegmentChild *) activeChild)->minZoom_ = false; + ((BgMdiSegmentChild *) activeChild)->UpdateZoomControl(); + } +} + +void BgMdiFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(); +} + +void BgMdiFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) +{ + const int BG_DIALOG_INDENT = 30, BG_DIALOG_TOP_MARGIN = 15; + BgDialog aboutDialog(this, -1, "About EDISON", wxPoint(-1,-1), wxSize(450, 300), wxDEFAULT_DIALOG_STYLE | wxDIALOG_MODAL | wxBORDER | wxSYSTEM_MENU, "aboutDialog"); + wxFont myFont(9, wxSWISS, wxNORMAL, wxBOLD, false); + BgText bgText(0, "Edge Detection and Image SegmentatiON System (EDISON) v1.1", myFont, BG_DIALOG_INDENT, BG_DIALOG_TOP_MARGIN); + aboutDialog.AddText(&bgText); + myFont.SetWeight(wxNORMAL); + myFont.SetUnderlined(true); + bgText.SetId(1); + bgText.SetFont(myFont); + bgText.SetText("Authors"); + bgText.SetPlotLocation(BG_DIALOG_INDENT, BG_DIALOG_TOP_MARGIN+15); + aboutDialog.AddText(&bgText); + myFont.SetUnderlined(false); + bgText.SetId(2); + bgText.SetFont(myFont); + bgText.SetText(": Bogdan Georgescu, Chris Christoudias (freeware) 2002"); + bgText.SetPlotLocation(BG_DIALOG_INDENT+44, BG_DIALOG_TOP_MARGIN+15); + aboutDialog.AddText(&bgText); + bgText.SetId(3); + bgText.SetText("Center for Advanced Information Processing (CAIP), Rutgers University"); + bgText.SetPlotLocation(BG_DIALOG_INDENT, BG_DIALOG_TOP_MARGIN+30); + aboutDialog.AddText(&bgText); + wxBitmap riul_logo("riul_logo", wxBITMAP_TYPE_RESOURCE), caip_logo("caip_logo", wxBITMAP_TYPE_RESOURCE), rutgers_logo("rutgers_logo", wxBITMAP_TYPE_RESOURCE); + BgBitmap myBitmap(&riul_logo, 0, BG_DIALOG_INDENT+20, BG_DIALOG_TOP_MARGIN+60); + aboutDialog.AddBitmap(&myBitmap); + myBitmap.SetId(1); + myBitmap.SetMap(&caip_logo); + myBitmap.SetPlotLocation(BG_DIALOG_INDENT+85, BG_DIALOG_TOP_MARGIN+170); + aboutDialog.AddBitmap(&myBitmap); + myBitmap.SetId(2); + myBitmap.SetMap(&rutgers_logo); + myBitmap.SetPlotLocation(BG_DIALOG_INDENT+145, BG_DIALOG_TOP_MARGIN+165); + aboutDialog.AddBitmap(&myBitmap); + aboutDialog.Centre(wxBOTH); + aboutDialog.ShowModal(); +} + +void BgMdiFrame::OnHelp(wxCommandEvent& WXUNUSED(event) ) +{ + wxDialog helpDialog(this, -1, "Help Window", wxPoint(10,10), wxSize(800,600), wxDEFAULT_DIALOG_STYLE | wxDIALOG_MODAL | wxBORDER | wxSYSTEM_MENU); + wxHtmlWindow helpWind(&helpDialog, -1, wxPoint(10,10), wxSize(770,550)); + helpWind.LoadPage(helpDir_); + helpDialog.ShowModal(); + bgLog("\n"); +} + +void BgMdiFrame::OnLoadImage(wxCommandEvent& WXUNUSED(event)) +{ + + wxMDIChildFrame *activeChild = GetActiveChild(); + wxCommandEvent zcev; + if(activeChild) + { + if(activeChild->GetId() == BG_EDGE_WINDOW) + ((BgMdiEdgeChild*) activeChild)->OnLoadImage(zcev); + else if(activeChild->GetId() == BG_SEGM_WINDOW) + ((BgMdiSegmentChild*) activeChild)->OnLoadImage(zcev); + } else + { + //read an image + char *pathname, *filename; + GetImageFileInfo(&pathname, &filename); + if(pathname) + { + + //get current width and height of this window + int width, height; + GetSize(&width, &height); + + //half window width + width = width/2; + + //create an edge window + OnNewEdgeWindow(zcev); + + //load read image into edge window + activeChild = GetActiveChild(); + ((BgMdiEdgeChild*) activeChild)->ReadImage(pathname, filename); + ((BgMdiEdgeChild*) activeChild)->RunEnable(); + + //set position and size of edge detection window + activeChild->SetSize(0,-30,width,height); + + //create a segmentation window + OnNewSegmWindow(zcev); + + //load read image into segment window + activeChild = GetActiveChild(); + ((BgMdiSegmentChild*) activeChild)->ReadImage(pathname, filename); + ((BgMdiSegmentChild*) activeChild)->RunEnable(); + + //set position and size of segmnetation window + activeChild->SetSize(width,-30,width,height); + + //de-allocate memory used by filename + delete [] filename; + } + } + +} + +void BgMdiFrame::OnLoadImageEdge(wxCommandEvent& WXUNUSED(event)) +{ + BgMdiEdgeChild* activeChild; + activeChild = 0; + activeChild = (BgMdiEdgeChild*) GetActiveChild(); + wxCommandEvent zcev; + if (activeChild != 0) + { + activeChild->OnLoadImage(zcev); + } else + { + OnNewEdgeWindow(zcev); + activeChild = (BgMdiEdgeChild*) GetActiveChild(); + activeChild->OnLoadImage(zcev); + } +} + +void BgMdiFrame::OnLoadImageSegm(wxCommandEvent& WXUNUSED(event)) +{ + BgMdiSegmentChild* activeChild; + activeChild = 0; + activeChild = (BgMdiSegmentChild*) GetActiveChild(); + wxCommandEvent zcev; + if (activeChild != 0) + { + activeChild->OnLoadImage(zcev); + } else + { + OnNewSegmWindow(zcev); + activeChild = (BgMdiSegmentChild*) GetActiveChild(); + activeChild->OnLoadImage(zcev); + } +} + +void BgMdiFrame::OnSaveResult(wxCommandEvent& WXUNUSED(event)) +{ + wxMDIChildFrame* activeChild = GetActiveChild(); + if(activeChild) + { + wxCommandEvent zcev; + if (activeChild->GetId() == BG_EDGE_WINDOW) + ((BgMdiEdgeChild *) activeChild)->OnSaveEdgeMap(zcev); + else if (activeChild->GetId() == BG_SEGM_WINDOW) + ((BgMdiSegmentChild *) activeChild)->OnSaveSegmentedImage(zcev); + } +} + +void BgMdiFrame::OnNewEdgeWindow(wxCommandEvent& WXUNUSED(event) ) +{ + + //indicate that another child frame will be created + gs_nFrames++; + + // Make another frame, containing a edge processing window + BgMdiEdgeChild *subframe = new BgMdiEdgeChild(g_frame, "Edge Detection Frame", + wxPoint(-1, -1), wxSize(-1, -1), + wxDEFAULT_FRAME_STYLE); + + wxString title; + title.Printf(_T("Edge Detection Frame %d"), gs_nFrames); + + subframe->SetTitle(title); + + // Give it an icon +#ifdef __WXMSW__ + subframe->SetIcon(wxIcon("chrt_icn")); +#else + subframe->SetIcon(wxIcon( mondrian_xpm )); +#endif + + // Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(BG_NEW_EDGE_WINDOW, "New &edge window\tAlt-E", "Create a new edge detection window"); + file_menu->Append(BG_NEW_SEGM_WINDOW, "New &segment window\tAlt-S", "Create a new segmentation window"); + file_menu->Append(BG_LOAD_IMAGE_EDGE, "&Load image\tCtrl-L", "Load image to perform edge detection"); + file_menu->Append(BG_EDGE_SAVE_MAP, "&Save edge map\tCtrl-S"); + file_menu->Append(BG_CHILD_EDGE_QUIT, "&Close edge window\tAlt-C", "Close this window"); + file_menu->Append(BG_QUIT, "E&xit\tAlt-X"); + + wxMenu *edge_menu = new wxMenu; + + edge_menu->Append(BG_EDGE_DETECT, "Edge Detect\tCtrl-R"); + edge_menu->Append(BG_CHANGE_PARAM_EDGE, "Change Parameters..."); + + wxMenu *view_menu = new wxMenu; + + subframe->miViewOrig_ = new wxMenuItem(view_menu, BG_EDGE_VIEW_ORIG, "Original", "View original", TRUE); + subframe->miViewEdge_ = new wxMenuItem(view_menu, BG_EDGE_VIEW_EDGE, "Edge map", "View edge map", TRUE); + + view_menu->Append(subframe->miViewOrig_); + view_menu->Append(subframe->miViewEdge_); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(BG_ABOUT, "&About"); + help_menu->Append(BG_HELP, "&Help\tCtrl-H"); + + wxMenuBar *menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, "&File"); + menu_bar->Append(edge_menu, "&Edge Detect"); + menu_bar->Append(view_menu, "&View"); + menu_bar->Append(help_menu, "&Help"); + + //disable items on menu bar + menu_bar->Enable(BG_EDGE_DETECT, false); + menu_bar->Enable(BG_EDGE_SAVE_MAP, false); + + // Associate the menu bar with the frame + subframe->SetMenuBar(menu_bar); + + subframe->CreateStatusBar(); + subframe->SetStatusText(title); + + int width, height; + subframe->GetClientSize(&width, &height); + + subframe->Show(TRUE); + subframe->miViewOrig_->Check(TRUE); + subframe->miViewEdge_->Check(TRUE); +} + +void BgMdiFrame::OnNewSegmWindow(wxCommandEvent& WXUNUSED(event) ) +{ + + //indicate that another child frame will be created + gs_nFrames++; + + // Make another frame, containing a edge processing window + BgMdiSegmentChild *subframe = new BgMdiSegmentChild(g_frame, "Segmentation Frame", + wxPoint(-1, -1), wxSize(-1, -1), + wxDEFAULT_FRAME_STYLE); + + wxString title; + title.Printf(_T("Segmentation Frame %d"), gs_nFrames); + + subframe->SetTitle(title); + + // Give it an icon +#ifdef __WXMSW__ + subframe->SetIcon(wxIcon("chrt_icn")); +#else + subframe->SetIcon(wxIcon( mondrian_xpm )); +#endif + + // Make a menubar + wxMenu *file_menu = new wxMenu; + file_menu->Append(BG_NEW_EDGE_WINDOW, "New &edge window\tAlt-E", "Create a new edge detection window"); + file_menu->Append(BG_NEW_SEGM_WINDOW, "New &segment window\tAlt-S", "Create a new segmentation window"); + file_menu->Append(BG_SEGM_LOAD_IMAGE, "&Load image\tShift-L", "Load image to perform segmentation"); + file_menu->Append(BG_SEGM_SAVE_SEGMENTED, "&Save result\tShift-S"); + file_menu->Append(BG_CHILD_SEGM_QUIT, "&Close window\tShift-C", "Close this window"); + file_menu->Append(BG_QUIT, "E&xit\tAlt-X"); + + wxMenu *segm_menu = new wxMenu; + segm_menu->Append(BG_SEGM_SEGMENT, "Segment Image\tShift-R"); + segm_menu->AppendSeparator(); + wxMenu *speedup_menu = new wxMenu; + speedup_menu->Append(BG_SEGM_SPEEDUP_NONE, "&None", "", true); + speedup_menu->Append(BG_SEGM_SPEEDUP_MEDM, "&Medium", "", true); + speedup_menu->Append(BG_SEGM_SPEEDUP_HIGH, "&High", "", true); + wxMenuItem *segm_menu_item = new wxMenuItem(segm_menu, BG_SEGM_SPEEDUP, "Speedup", "", false, speedup_menu); + segm_menu->Append(segm_menu_item); + + wxMenu *weightmap_menu = new wxMenu; + weightmap_menu->Append(BG_SEGM_LOAD_MAP, "Load custom weight &map\tShift-M", "Load map images to perform segmentation"); + weightmap_menu->AppendSeparator(); + weightmap_menu->Append(BG_SEGM_USE_MAP, "&Use custom weight map", "", true); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(BG_ABOUT, "&About"); + help_menu->Append(BG_HELP, "&Help\tCtrl-H"); + + wxMenuBar *menu_bar = new wxMenuBar; + menu_bar->Append(file_menu, "&File"); + menu_bar->Append(segm_menu, "&Algorithm"); + menu_bar->Append(weightmap_menu, "&Weight Map"); + menu_bar->Append(help_menu, "&Help"); + + //disable items on menu bar + menu_bar->Enable(BG_SEGM_SEGMENT, false); + menu_bar->Enable(BG_SEGM_SAVE_SEGMENTED, false); + menu_bar->Enable(BG_SEGM_LOAD_MAP, false); + menu_bar->Enable(BG_SEGM_USE_MAP, false); + + //check speedup to medium + menu_bar->Check(BG_SEGM_SPEEDUP_MEDM, true); + + // Associate the menu bar with the frame + subframe->SetMenuBar(menu_bar); + subframe->CreateStatusBar(); + subframe->SetStatusText(title); + + subframe->Show(TRUE); + subframe->Fit(); +} + +void BgMdiFrame::GetImageFileInfo(char **pathname, char **filename) +{ + +// get the file name +#if defined(__WXGTK__) || defined(__WXMOTIF__) + wxFileDialog filedialog(this,"Choose an image file","","", + "*",wxOPEN); +#else + wxFileDialog filedialog(this,"Choose an image file","","", + "Common image files|*.png;*.bmp;*.gif;*.tif;*.tiff;*.jpg;*.pnm;*.pgm;*.ppm|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm|PGM/PPM files (*.pgm,*.ppm)|*.pgm;*.ppm", + wxOPEN); +#endif + + //retrieve and check filename + *filename = (char *) NULL; + *pathname = (char *) NULL; + BgImCanvas *temp = new BgImCanvas(this, this, wxDefaultPosition, wxDefaultSize); + if(filedialog.ShowModal()==wxID_OK) + { + char* temp_str = (char *) filedialog.GetPath().c_str(); + *pathname = new char [strlen(temp_str) + 1]; + strcpy(*pathname, temp_str); + temp_str = (char *) filedialog.GetFilename().c_str(); + *filename = new char [strlen(temp_str) + 1]; + strcpy(*filename, temp_str); + if (temp->SetImage(*pathname) == 0) + { + delete [] *pathname; + delete [] *filename; + *pathname = (char *) NULL; + *filename = (char *) NULL; + } + else + bgLog("Image %s loaded\n",filedialog.GetPath().c_str()); + } + + //de-allocate memory + delete temp; + + //done. + return; +} + +//manages toolbar zoom controls +void BgMdiFrame::ZoomControl(wxCommandEvent& event) +{ + //set display + wxToolBar *toolbar = GetToolBar(); + switch (event.m_id) + { + case BG_CROSS: + toolbar->ToggleTool(BG_CROSS, true); + toolbar->ToggleTool(BG_ZOOM_IN, false); + toolbar->ToggleTool(BG_ZOOM_OUT, false); + toolbar->ToggleTool(BG_POINTER, false); + break; + case BG_ZOOM_IN: + toolbar->ToggleTool(BG_CROSS, false); + toolbar->ToggleTool(BG_ZOOM_IN, true); + toolbar->ToggleTool(BG_ZOOM_OUT, false); + toolbar->ToggleTool(BG_POINTER, false); + break; + case BG_ZOOM_OUT: + toolbar->ToggleTool(BG_CROSS, false); + toolbar->ToggleTool(BG_ZOOM_IN, false); + toolbar->ToggleTool(BG_ZOOM_OUT, true); + toolbar->ToggleTool(BG_POINTER, false); + break; + //BG_POINTER: + default: + toolbar->ToggleTool(BG_CROSS, false); + toolbar->ToggleTool(BG_ZOOM_IN, false); + toolbar->ToggleTool(BG_ZOOM_OUT, false); + toolbar->ToggleTool(BG_POINTER, true); + break; + } + + //set zoom functionality + wxMDIChildFrame *activeChild = GetActiveChild(); + if(activeChild->GetId() == BG_EDGE_WINDOW) + { + switch (event.m_id) + { + case BG_CROSS: + ((BgMdiEdgeChild *) activeChild)->ZoomWindow(); + break; + case BG_ZOOM_IN: + ((BgMdiEdgeChild *) activeChild)->ZoomIn(); + break; + case BG_ZOOM_OUT: + ((BgMdiEdgeChild *) activeChild)->ZoomOut(); + break; + //BG_POINTER: + default: + ((BgMdiEdgeChild *) activeChild)->NoZoom(); + break; + } + } + else if(activeChild->GetId() == BG_SEGM_WINDOW) + { + switch (event.m_id) + { + case BG_CROSS: + ((BgMdiSegmentChild *) activeChild)->ZoomWindow(); + break; + case BG_ZOOM_IN: + ((BgMdiSegmentChild *) activeChild)->ZoomIn(); + break; + case BG_ZOOM_OUT: + ((BgMdiSegmentChild *) activeChild)->ZoomOut(); + break; + //BG_POINTER: + default: + ((BgMdiSegmentChild *) activeChild)->NoZoom(); + break; + } + } + + return; + +} + + +void BgMdiFrame::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + int w, h; + GetClientSize(&w, &h); + logtext_->SetSize(0, h-logsize_, w, logsize_); + GetClientWindow()->SetSize(0, 0, w, h-logsize_); +} + + +void BgMdiFrame::InitToolBar(wxToolBar* toolBar) +{ + const int BITMAP_COUNT = 9; + wxBitmap* bitmaps[BITMAP_COUNT]; + +#ifdef __WXMSW__ + bitmaps[0] = new wxBitmap( "icon1", wxBITMAP_TYPE_RESOURCE); + bitmaps[1] = new wxBitmap( "icon7", wxBITMAP_TYPE_RESOURCE); + bitmaps[2] = new wxBitmap( "icon8", wxBITMAP_TYPE_RESOURCE); + bitmaps[3] = new wxBitmap( "icon2", wxBITMAP_TYPE_RESOURCE); + bitmaps[4] = new wxBitmap( "icon3", wxBITMAP_TYPE_RESOURCE); + bitmaps[5] = new wxBitmap( "icon9", wxBITMAP_TYPE_RESOURCE); + bitmaps[6] = new wxBitmap("icon10", wxBITMAP_TYPE_RESOURCE); + bitmaps[7] = new wxBitmap("icon11", wxBITMAP_TYPE_RESOURCE); + bitmaps[8] = new wxBitmap("icon12", wxBITMAP_TYPE_RESOURCE); +#else + bitmaps[0] = new wxBitmap( bnew_xpm ); + bitmaps[1] = new wxBitmap( bnsg_xpm ); + bitmaps[2] = new wxBitmap( bhelp_xpm ); + bitmaps[3] = new wxBitmap( bopen_xpm ); + bitmaps[4] = new wxBitmap( bsave_xpm ); + bitmaps[5] = new wxBitmap( bcros_xpm ); + bitmaps[6] = new wxBitmap( bzin_xpm ); + bitmaps[7] = new wxBitmap( bzout_xpm ); + bitmaps[8] = new wxBitmap( bpoin_xpm ); + +#endif + +#ifdef __WXMSW__ + int width = 24; +#else + int width = 16; +#endif + int currentX = 5; + + //add tools to tool bar + toolBar->AddTool( BG_NEW_EDGE_WINDOW, *(bitmaps[0]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "New edge window"); + currentX += width + 5; + toolBar->AddTool( BG_NEW_SEGM_WINDOW, *(bitmaps[1]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "New segment window"); + currentX += width + 5; + toolBar->AddTool( BG_LOAD_IMAGE, *(bitmaps[3]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Load image for processing"); + currentX += width + 5; + toolBar->AddTool( BG_SAVE_RESULT, *(bitmaps[4]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Save result"); + currentX += width + 5; + toolBar->AddSeparator(); + toolBar->AddTool( BG_CROSS, *(bitmaps[5]), wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, "Zoom Window"); + currentX += width + 5; + toolBar->AddTool( BG_ZOOM_IN, *(bitmaps[6]), wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, "Zoom In"); + currentX += width + 5; + toolBar->AddTool( BG_ZOOM_OUT, *(bitmaps[7]), wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, "Zoom Out"); + currentX += width + 5; + toolBar->AddTool( BG_POINTER, *(bitmaps[8]), wxNullBitmap, TRUE, currentX, -1, (wxObject *) NULL, "Select"); + currentX += width + 5; + toolBar->AddSeparator(); + toolBar->AddTool( BG_HELP, *bitmaps[2], wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, "Help"); + + //set bitmap size of controls buttons to 20x20 + wxSize tool_size(20,20); + toolBar->SetToolBitmapSize(tool_size); + + toolBar->Realize(); + + //disable certain tools + toolBar->EnableTool(BG_SAVE_RESULT, false); + toolBar->EnableTool(BG_CROSS, false); + toolBar->EnableTool(BG_ZOOM_IN, false); + toolBar->EnableTool(BG_ZOOM_OUT, false); + toolBar->EnableTool(BG_POINTER, false); + + int i; + for (i = 0; i < BITMAP_COUNT; i++) + delete bitmaps[i]; +} + +// --------------------------------------------------------------------------- +// BgPointSet +// --------------------------------------------------------------------------- + +BgPointSet::BgPointSet() +{ + x_ = y_ = 0; + n_ = 0; + type_ = 0; + pen_.SetColour(*wxBLUE); + //pen_.SetColour(*wxWHITE); + pen_.SetWidth(1); + pen_.SetStyle(wxSOLID); +} + +BgPointSet::~BgPointSet() +{ + CleanData(); +} + +void BgPointSet::CleanData() +{ + if (n_ > 0) + { + delete [] x_; + delete [] y_; + x_ = y_ = 0; + n_ = 0; + } +} + +void BgPointSet::SetPoints(int* x, int* y, int n) +{ + CleanData(); + n_ = n; + x_ = new int[n_]; + y_ = new int[n_]; + for (int i=0; i<n; i++) + { + x_[i] = x[i]; + y_[i] = y[i]; + } +} + +// --------------------------------------------------------------------------- +// BgCurveSet +// --------------------------------------------------------------------------- + +BgCurveSet::BgCurveSet() +{ + x_ = y_ = 0; + xs_ = ys_ = 0; + n_ = 0; + type_ = -1; + pen_.SetColour(*wxBLUE); + pen_.SetWidth(3); + pen_.SetStyle(wxSOLID); + isDragging_ = 0; +} + +BgCurveSet::~BgCurveSet() +{ + CleanData(); +} + +void BgCurveSet::CleanData() +{ + if (n_ > 0) + { + delete [] x_; + delete [] y_; + x_ = y_ = 0; + n_ = 0; + } + type_ = -1; + xs_ = ys_ = 0; +} + +void BgCurveSet::SetCurve(BgCurveSet* bgc) +{ + CleanData(); + type_ = bgc->type_; + n_ = bgc->n_; + x_ = new int[n_]; + y_ = new int[n_]; + xs_ = bgc->xs_; + ys_ = bgc->ys_; + for (int i=0; i<n_; i++) + { + x_[i] = bgc->x_[i]; + y_[i] = bgc->y_[i]; + } +} + +void BgCurveSet::SetParamCurve(int type, double* x, double* y, int n, int xs, int ys) +{ + CleanData(); + type_ = type; + n_ = n; + x_ = new int[n_]; + y_ = new int[n_]; + xs_ = xs; + ys_ = ys; + for (int i=0; i<n; i++) + { + x_[i] = (int) (x[i]*xs); + y_[i] = (int) (ys-y[i]*ys); + } +} + +void BgCurveSet::GetParamCurve(double* x, double* y, int& type, int& n) +{ + for (int i=0; i<n_; i++) + { + x[i] = ((double)x_[i])/xs_; + y[i] = ((double)(ys_-y_[i]))/ys_; + } + type = type_; + n = n_; +} + +void BgCurveSet::DrawYourself(unsigned char* buf, int val) +{ + int j; + switch (type_) + { + case -1: + break; + case FC_ELLIPSE: + DrawEllipticArc(buf, val, -x_[0], y_[0], 2*x_[0], 2*(ys_-y_[0]), 0, 90); + break; + case FC_VERT_LINE: + DrawLine(buf, val, x_[0], 0, x_[0], ys_); + break; + case FC_HORIZ_LINE: + DrawLine(buf, val, 0, y_[0], xs_, y_[0]); + break; + case FC_LINE: + DrawLine(buf, val, 0, y_[0], x_[0], ys_); + break; + case FC_SQUARE_BOX: + DrawLine(buf, val, 0, y_[0], x_[0], y_[0]); + DrawLine(buf, val, x_[0], y_[0], x_[0], ys_); + break; + case FC_CUSTOM: + // lines + for (j=0; j<(n_-1); j++) + DrawLine(buf, val, x_[j], y_[j], x_[j+1], y_[j+1]); + // control points + for (j=0; j<n_; j++) + DrawPoint(buf, val ,x_[j], y_[j]); + break; + } + +} + +void BgCurveSet::DrawPoint(unsigned char* buf, int val, int x, int y) +{ + int r, c; + int dx, dy; + for (dx=-2; dx<=2; dx++) + { + for (dy=-2; dy<=2; dy++) + { + c=x+dx; + r=y+dy; + if ((c>=0) && (c<xs_) && (r>=0) && (r<ys_) && ((abs(dx)+abs(dy))<4)) + buf[c+r*ys_] = val; + } + } +} + +void BgCurveSet::DrawLine(unsigned char* buf, int val, int xs, int ys, int xe, int ye) +{ + int r, c; + double dsx, dsy, dex, dey; + if (abs(xs-xe)>abs(ys-ye)) + { + // x scan + if (xs > xe) + { + dsx = xe; + dsy = ye; + dex = xs; + dey = ys; + } + else + { + dex = xe; + dey = ye; + dsx = xs; + dsy = ys; + } + + for (c = (int) dsx; c<=(int)dex; c++) + { + if (c>=0 && c<xs_) + { + r = bgRound(dey-(dey-dsy)*(dex-c)/(dex-dsx)); + if (r>=0 && r<ys_) + { + buf[c+r*xs_] = val; + // +/- 1 + if ((r+1)<ys_) buf[c+(r+1)*xs_] = val; + if ((r-1)>=0) buf[c+(r-1)*xs_] = val; + // +/- 2 + if ((r+2)<ys_) buf[c+(r+2)*xs_] = val; + if ((r-2)>=0) buf[c+(r-2)*xs_] = val; + } + } + } + } + else + { + // y scan + if (ys > ye) + { + dsx = xe; + dsy = ye; + dex = xs; + dey = ys; + } + else + { + dex = xe; + dey = ye; + dsx = xs; + dsy = ys; + } + + // check bounds + + for (r = (int) dsy; r<=(int) dey; r++) + { + if (r>=0 && r<ys_) + { + c = bgRound(dex-(dex-dsx)*(dey-r)/(dey-dsy)); + if (c>=0 && c<xs_) + { + buf[c+r*xs_] = val; + // +/- 1 + if ((c+1)<xs_) buf[c+1+r*xs_] = val; + if ((c-1)>=0) buf[c-1+r*xs_] = val; + // +/- 2 + if ((c+2)<xs_) buf[c+2+r*xs_] = val; + if ((c-2)>=0) buf[c-2+r*xs_] = val; + } + } + } + } +} +void BgCurveSet::DrawEllipticArc(unsigned char* buf, int val, int x, int y, int w, int h, int sa, int ea) +{ + double xc, yc, rx, ry; + rx = w/2; + ry = h/2; + xc = x+rx; + yc = y+ry; + int r, c; + +// if (rx > ry) +// { + // x scan + for (c = (int) xc; c<=(int) (xc+rx); c++) + { + if (c>=0 && c<xs_) + { + r = bgRound(yc-ry*sqrt(1-(c-xc)*(c-xc)/(rx*rx))); + if (r>=0 && r<ys_) + { + buf[c+r*xs_] = val; + // +/- 1 + if ((r+1)<ys_) buf[c+(r+1)*xs_] = val; + if ((r-1)>=0) buf[c+(r-1)*xs_] = val; + // +/- 2 + if ((r+2)<ys_) buf[c+(r+2)*xs_] = val; + if ((r-2)>=0) buf[c+(r-2)*xs_] = val; + } + } + } +// } +// else +// { + // y scan + for (r = (int)(yc-ry); r<=(int) yc; r++) + { + if (r>=0 && r<ys_) + { + c = bgRound(xc+rx*sqrt(1-(r-yc)*(r-yc)/(ry*ry))); + if (c>=0 && c<xs_) + { + buf[c+r*xs_] = val; + // +/- 1 + if ((c+1)<xs_) buf[c+1+r*xs_] = val; + if ((c-1)>=0) buf[c-1+r*xs_] = val; + // +/- 2 + if ((c+2)<xs_) buf[c+2+r*xs_] = val; + if ((c-2)>=0) buf[c-2+r*xs_] = val; + } + } + } +// } +} + +void BgCurveSet::StartDragging(int x, int y) +{ + isDragging_ = 1; + int j; + switch (type_) + { + case -1: + break; + case FC_ELLIPSE: + if (abs(x)<3) + ltodrag_ = 1; + else if (abs(y-ys_)<3) + ltodrag_ = 2; + else + ltodrag_ = 0; + break; + case FC_VERT_LINE: + ltodrag_ = 0; + break; + case FC_HORIZ_LINE: + ltodrag_ = 0; + break; + case FC_LINE: + if (abs(x)<3) + ltodrag_ = 1; + else if (abs(y-ys_)<3) + ltodrag_ = 2; + else + ltodrag_ = 0; + break; + case FC_SQUARE_BOX: + if (abs((abs(x-x_[0])-abs(y-y_[0])))<3) + { + // drag corner + ltodrag_ = 2; + } + else if (abs(x-x_[0])>abs(y-y_[0])) + { + // drag horizontal + ltodrag_ = 0; + } + else + { + // drag vertical + ltodrag_ = 1; + } + break; + case FC_CUSTOM: + // find point to drag + int mind = abs(x-x_[0]) + abs(y-y_[0]); + int cmind, mj; + mj = 0; + for (j=1; j<n_; j++) + { + cmind = abs(x-x_[j]) + abs(y-y_[j]); + if (cmind < mind) + { + mind = cmind; + mj = j; + } + } + ltodrag_ = mj; + break; + } +} + +void BgCurveSet::DragTo(int x, int y) +{ + if ((x<0) || (y<0) || (x>=xs_) || (y>=ys_)) + return; + double k, ry; + switch (type_) + { + case -1: + break; + case FC_ELLIPSE: + // modify ellipse to drag + if (ltodrag_ == 0) + { + k = ((double)x_[0])/(ys_-y_[0]); + ry = sqrt(((double)x*x)/(k*k)+(y-ys_)*(y-ys_)); + x_[0] = bgRound(k*ry); + y_[0] = bgRound(ys_-ry); + } + else if (ltodrag_ == 1) + { + y_[0] = y; + } + else + { + x_[0] = x; + } + break; + case FC_VERT_LINE: + x_[0] = x; + break; + case FC_HORIZ_LINE: + y_[0] = y; + break; + case FC_LINE: + // modify line to drag + if (ltodrag_ == 0) + { + k = ((double) (ys_-y_[0])/x_[0]); + y_[0] = ys_-bgRound((double (ys_-y)+k*x)); + x_[0] = bgRound((double (ys_-y)+k*x)/(k)); + } + else if (ltodrag_ == 1) + { + y_[0] = y; + } + else + { + x_[0] = x; + } + break; + case FC_SQUARE_BOX: + if (ltodrag_ == 0) + y_[0] = y; + else if (ltodrag_ == 1) + x_[0] = x; + else + { + x_[0] = x; + y_[0] = y; + } + break; + case FC_CUSTOM: + // modify line to drag + if (ltodrag_ == 0) + { + y_[0] = y; + } else if (ltodrag_ == (n_-1)) + { + x_[n_-1] = x; + } else + { + x_[ltodrag_] = x; + y_[ltodrag_] = y; + } + break; + } +} + +void BgCurveSet::EndDragging(int x, int y) +{ + isDragging_ = 0; +} + +// --------------------------------------------------------------------------- +// BgParameterHistory +// --------------------------------------------------------------------------- + +BgParameterHistory::BgParameterHistory( void ) +{ + params_ = (void *) NULL; + listSize_ = 0; + next_ = (BgParameterHistory *) NULL; +} + +BgParameterHistory::BgParameterHistory(void *parameters, int itemCount) +{ + params_ = parameters; + listSize_ = itemCount; + next_ = (BgParameterHistory *) NULL; +} + + +BgParameterHistory::~BgParameterHistory( void ) +{ + if(params_) delete [] params_; +} + +// --------------------------------------------------------------------------- +// BgParameterHistoryBox +// --------------------------------------------------------------------------- + +BgParameterHistoryBox::BgParameterHistoryBox(wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, int n, long style, const wxValidator& validator, const wxString& name) + : wxComboBox(parent, id, value, pos, size, 0, (wxString*) NULL, style, validator, name) +{ + //initialize history list + maxCount_ = n; + listCount_ = 0; + historyList_ = (BgParameterHistory *) NULL; + + //initialize combo box + Append("Current"); + SetSelection(0); +} + +BgParameterHistoryBox::~BgParameterHistoryBox( void ) +{ + //delete history... + BgParameterHistory *temp; + while(historyList_) + { + temp = historyList_; + historyList_ = historyList_->next_; + delete temp; + } +} + +void BgParameterHistoryBox::AddParameterList(void *parameters, int itemCount) +{ + if(listCount_ < maxCount_) + { + BgParameterHistory *newHistory = new BgParameterHistory(parameters, itemCount); + newHistory->next_ = historyList_; + historyList_ = newHistory; + listCount_++; + char str[40]; + sprintf(str, "Parameter List -%d", listCount_); + Append(str); + } + else + { + BgParameterHistory *newHistory = historyList_; + while(newHistory->next_->next_) newHistory = newHistory->next_; + if(newHistory->next_->params_) delete newHistory->next_->params_; + newHistory->next_->params_ = parameters; + newHistory->next_->listSize_ = itemCount; + newHistory->next_->next_ = historyList_; + historyList_ = newHistory->next_; + newHistory->next_ = (BgParameterHistory *) NULL; + } +} + +void *BgParameterHistoryBox::GetParameterListData(int indexNumber) +{ + if(indexNumber < listCount_) + { + BgParameterHistory *currentHistory = historyList_; + int count = 0; + while(indexNumber != count) + { + currentHistory = currentHistory->next_; + count++; + } + return currentHistory->params_; + } + return (void *) NULL; +} + +int BgParameterHistoryBox::GetParameterListCount(int indexNumber) +{ + if(indexNumber < listCount_) + { + BgParameterHistory *currentHistory = historyList_; + int count = 0; + while(indexNumber != count) + { + currentHistory = currentHistory->next_; + count++; + } + return currentHistory->listSize_; + } + return -1; +} + +void BgParameterHistoryBox::UseParameterList(int indexNumber) +{ + if((indexNumber < listCount_) && (indexNumber != 0)) + { + BgParameterHistory *previousHistory = historyList_; + int count = 0; + while(count != indexNumber - 1) + { + previousHistory = previousHistory->next_; + count++; + } + BgParameterHistory *currentHistory = previousHistory->next_; + previousHistory->next_ = currentHistory->next_; + currentHistory->next_ = historyList_; + historyList_ = currentHistory; + } + return; +} + +void BgParameterHistoryBox::SetCurrentList(void *parameters, int itemCount) +{ + currentList_.params_ = parameters; + currentList_.listSize_ = itemCount; +} + +void *BgParameterHistoryBox::GetCurrentListData( void ) +{ + return currentList_.params_; +} + +int BgParameterHistoryBox::GetCurrentListCount( void ) +{ + return currentList_.listSize_; +} + +// --------------------------------------------------------------------------- +// BgText +// --------------------------------------------------------------------------- + +//default constructor +BgText::BgText(void) +{ + text_ = (char *) NULL; + font_ = (wxFont *) NULL; + id_ = 0; + x_ = 0; + y_ = 0; +} + +//overloaded constructor +BgText::BgText(int id, char *text, wxFont font, int x, int y) +{ + text_ = new char [strlen(text) + 1]; + strcpy(text_, text); + font_ = new wxFont; + (*font_) = font; + id_ = id; + x_ = x; + y_ = y; +} + +//destructor +BgText::~BgText(void) +{ + delete text_; + delete font_; +} + +//sets text string +//pre : text is a character string used to set the text +// field of the text object +//post: the text field of the text object has been set to text +void BgText::SetText(char *text) +{ + if((text_)&&(strlen(text) > strlen(text_))) + { + delete [] text_; + text_ = new char [strlen(text) + 1]; + } + strcpy(text_, text); + return; +} + +//sets font of text +//pre : font specifies the new font of the text object +//post: the font of the text object has been changed to font +void BgText::SetFont(wxFont font) +{ + if(!font_) font_ = new wxFont; + (*font_) = font; + return; +} + +//sets id of text +//pre : id is the new id of the text object +//post: the id of the text object has been set to id +void BgText::SetId(int id) +{ + id_ = id; +} + +//sets plot location of text +//pre : (x,y) determine the new plot location of the text object +//post: the plot location of the text object has been set to (x,y) +void BgText::SetPlotLocation(int x, int y) +{ + x_ = x; + y_ = y; +} + +// --------------------------------------------------------------------------- +// BgTextObj +// --------------------------------------------------------------------------- + +//constructor +BgTextObj::BgTextObj(BgText *text) +{ + text_ = new BgText(text->id_, text->text_, *(text->font_), text->x_, text->y_); + next_ = NULL; +} + +//destructor +BgTextObj::~BgTextObj(void) +{ + delete text_; +} + +// --------------------------------------------------------------------------- +// BgTextList +// --------------------------------------------------------------------------- + +// *** public methods *** // + +//constructor +BgTextList::BgTextList(void) +{ + head_ = cur_ = (BgTextObj *) NULL; + itemcount_ = 0; +} + +//destructor +BgTextList::~BgTextList(void) +{ + cur_ = head_; + while(cur_) + DeleteText(); +} + +//adds text object to list +//pre : text is a text object to be added to the list +//post: text has been added to the list +int BgTextList::AddText(BgText *text) +{ + //search for existsing text object + int id = text->id_; + cur_ = head_; + while((cur_)&&(cur_->text_->id_ != id)) + cur_ = cur_->next_; + + //if it exists change its contents + if(cur_) + { + BgText *tmp_text = cur_->text_; + tmp_text->SetText(text->text_); + tmp_text->SetFont(*(text->font_)); + tmp_text->SetPlotLocation(text->x_, text->y_); + } + //otherwise add it to existing list + else + { + BgTextObj *temp; + if((temp = new BgTextObj(text)) == NULL) + return 1; + + temp->next_ = head_; + if(head_ == NULL) + cur_ = temp; + head_ = temp; + itemcount_++; + } + + return 0; +} + +//removes text object from list +//pre : textId is the id of the text to be removed from the +// list +//post: text object having id textId has been removed from the +// list if it exists (1 is returned upon error) +int BgTextList::RemoveText(int textId) +{ + cur_ = head_; + while((cur_)&&(cur_->text_->id_ != textId)) + cur_ = cur_->next_; + + if(cur_) + { + DeleteText(); + return 0; + } + else + return 1; +} + +//returns text object from text list +//post: the text object pointed to by cur_ is returned +BgText *BgTextList::GetText(void) +{ + if(cur_) + { + BgText *text; + text = cur_->text_; + cur_ = cur_->next_; + return text; + } + else + return (BgText *) NULL; +} + +//resets cur_ pointer to head of the list +void BgTextList::ResetList(void) +{ + cur_ = head_; +} + +//returns the number of text objects contained +//within the list +//post: count of text objects contained by list is returned +int BgTextList::GetTextCount(void) +{ + return itemcount_; +} + +// *** private methods *** + +//deletes a text object node pointed to +//by cur_ +//post: text object has been deleted from the text list +void BgTextList::DeleteText(void) +{ + if(cur_ == head_) + { + head_ = head_->next_; + delete cur_; + cur_ = head_; + } + else + { + BgTextObj *temp = cur_; + cur_ = cur_->next_; + if(!cur_) cur_ = head_; + delete temp; + } +} + +// --------------------------------------------------------------------------- +// BgBitmap +// --------------------------------------------------------------------------- + +//default constructor +BgBitmap::BgBitmap(void) +{ + bitmap_ = (wxBitmap *) NULL; + location_x_ = location_y_ = 0; + id_ = 0; +} + +//overloaded constructor +BgBitmap::BgBitmap(wxBitmap *bitmap, int id, int location_x, int location_y) +{ + bitmap_ = new wxBitmap; + (*bitmap_) = (*bitmap); + id_ = id; + location_x_ = location_x; + location_y_ = location_y; +} + +//destructor +BgBitmap::~BgBitmap(void) +{ + if(bitmap_) delete bitmap_; +} + +//set bitmap content +//pre : bitmap is the new bitmap content +//post: bitmap content has been changed to that of bitmap +void BgBitmap::SetMap(wxBitmap *bitmap) +{ + if(!bitmap_) bitmap_ = new wxBitmap; + (*bitmap_) = (*bitmap); +} + +//set plot location +//pre : (location_x, location_y) define new plot location of bitmap +//post: plot location of bitmap has been set to (location_x, location_y) +void BgBitmap::SetPlotLocation(int location_x, int location_y) +{ + location_x_ = location_x; + location_y_ = location_y; +} + +//set bitmap id +//pre : id is the new bitmap id +//post: the bitmap id has been set to id +void BgBitmap::SetId(int id) +{ + id_ = id; +} + +// --------------------------------------------------------------------------- +// BgBitmapObj +// --------------------------------------------------------------------------- + +//default constructor +BgBitmapObj::BgBitmapObj(void) +{ + bitmap_ = (BgBitmap *) NULL; + next_ = (BgBitmapObj *) NULL; +} + +//overloaded constructor +BgBitmapObj::BgBitmapObj(BgBitmap* bitmap) +{ + bitmap_ = new BgBitmap(bitmap->bitmap_, bitmap->id_, + bitmap->location_x_, bitmap->location_y_); + next_ = (BgBitmapObj *) NULL; +} + +//destructor +BgBitmapObj::~BgBitmapObj(void) +{ + if(bitmap_) delete bitmap_; +} + +// --------------------------------------------------------------------------- +// BgBitmap +// --------------------------------------------------------------------------- + +//constructor +BgBitmapList::BgBitmapList(void) +{ + head_ = cur_ = (BgBitmapObj *) NULL; + itemcount_ = 0; +} + +//destuctor +BgBitmapList::~BgBitmapList(void) +{ + cur_ = head_; + while(cur_) + DeleteBitmap(); +} + +//add a bitmap object to the list +//pre : bitmap is a bitmap object to be added to the list +//post: bitmap has been added to the list +int BgBitmapList::AddBitmap(BgBitmap *bitmap) +{ + BgBitmapObj *temp; + if((temp = new BgBitmapObj(bitmap)) == NULL) + return 1; + + temp->next_ = head_; + if(head_ == NULL) + cur_ = temp; + head_ = temp; + itemcount_++; + + return 0; +} + +//remove bitmap from list +//pre : bitmap is to be removed from list +//post: bitmap has been removed from the list +void BgBitmapList::RemoveBitmap(BgBitmap *bitmap) +{ + int id = bitmap->id_; + cur_ = head_; + while((cur_)&&(cur_->bitmap_->id_ != id)) + cur_ = cur_->next_; + DeleteBitmap(); +} + +//get bitmap from the list pointed to by cur_ +//post: bitmap pointed to by cur_ has been returned +// and cur_ has been incremented to the next list +// item +BgBitmap *BgBitmapList::GetBitmap(void) +{ + BgBitmap *temp = (BgBitmap *) NULL; + if(cur_) + { + temp = cur_->bitmap_; + cur_ = cur_->next_; + } + + return temp; +} + +//reset bitmap list cur_ pointer +//post: cur_ has been set to the head of the list +void BgBitmapList::ResetList(void) +{ + cur_ = head_; +} + +//get the number of bitmaps stored by list +//post: bitmap count has been returned +int BgBitmapList::GetBitmapCount(void) +{ + return itemcount_; +} + +//delete bitmap object from list +//post: bitmap object pointed to by cur has been deleted +void BgBitmapList::DeleteBitmap(void) +{ + if(cur_) + { + BgBitmapObj *temp = cur_; + cur_ = cur_->next_; + delete temp; + itemcount_--; + } +} + +// --------------------------------------------------------------------------- +// BgAxis +// --------------------------------------------------------------------------- + +//default constructor +BgAxis::BgAxis(void) +{ + start_x_ = 0; start_y_ = 0; + length_ = 0; + ticknum_ = 0; + direction_ = 0; + start_val_ = 0; stop_val_ = 0; + label_ = (BgText *) NULL; + rotation_ = 0; +} + +//overloaded constructor +BgAxis::BgAxis(int start_x, int start_y, int length, int ticknum, int direction, float start_val, float stop_val) +{ + start_x_ = start_x; + start_y_ = start_y; + length_ = length; + ticknum_ = ticknum; + direction_ = direction; + start_val_ = start_val; + stop_val_ = stop_val; + label_ = (BgText *) NULL; + rotation_ = 0; +} + +//destuctor +BgAxis::~BgAxis(void) +{ + if(label_) delete label_; +} + +//set plotting origin +//pre : (start_x, start_y) specify the new axis plotting origin +//post: axis plotting origin has been set to (start_x, start_y) +void BgAxis::SetPlotOrigin(int start_x, int start_y) +{ + start_x_ = start_x; + start_y_ = start_y; +} + +//set axis length +//pre : length specifies the new length of the axis +//post: the axis lengh has been set to length +void BgAxis::SetLength(int length) +{ + length_ = length; +} + +//set axis tick number +//pre : ticknum is the new tick number of the axis +//post: the axis tick number has been set to ticknum +void BgAxis::SetTicknum(int ticknum) +{ + ticknum_ = ticknum; +} + +//set axis boundaries +//pre : (start_val, stop_val) define the new axis boundaries +//post: the axis boundaries have been set to (start_val, stop_val) +void BgAxis::SetBounds(float start_val, float stop_val) +{ + start_val_ = start_val; + stop_val_ = stop_val; +} + +//add axis label +//pre : label specifies the axis label +//post: the axis has been labeled using label +void BgAxis::Label(BgText *label) +{ + if(label_) delete label_; + char *text = label->text_; + int label_length = 3*strlen(text); + //horizontal axis + if(direction_ == 0) + { + label_x_ = start_x_ + length_/2 - label_length; + label_y_ = start_y_ + 30; + } + //vertical axis + else + { + label_x_ = start_x_ - 60; + label_y_ = start_y_ - length_/2 + label_length; + } + label_ = new BgText(label->id_, text, *(label->font_), label_x_, label_y_); +} + +//removes axis label +//post: the axis label has been removed +void BgAxis::RemoveLabel(void) +{ + if(label_) delete label_; + label_ = (BgText *) NULL; +} + +//sets label rotation +//pre : rotation specifies clockwise label rotation (rotation = 0 +// leaves the label parallel to the axis) +//post: label rotation has been set to rotation +void BgAxis::SetLabelRotation(int rotation) +{ + rotation_ = rotation; +} + +//draw axis object +//pre : dc is a dc object used to draw onto a window +//post: the axis has been drawn onto the window using +// using the dc object +void BgAxis::PlotAxis(wxDC *dc) +{ + //set tick length + int ticklength = 8; + + //calculate axis ending locations + int end_x = start_x_ + length_; + int end_y = start_y_ - length_; + + //define shift in x and y direction + int shift_x = 5; + int shift_y = 5; + + //create font + wxFont plotFont(7, wxSWISS, wxNORMAL, wxNORMAL, false, "", wxFONTENCODING_DEFAULT); + + //plot axis line + //horizontal axis + if(direction_ == 0) + { + //draw axis line + dc->DrawLine(start_x_, start_y_, end_x, start_y_); + dc->DrawLine(start_x_, start_y_+1, end_x, start_y_+1); + + //draw tick marks + int increment = length_/ticknum_; + if(length_%ticknum_ != 0) increment++; + int x_location = start_x_; + while(x_location < end_x) + { + dc->DrawLine(x_location, start_y_, x_location, start_y_+ticklength); + dc->DrawLine(x_location+1, start_y_, x_location+1, start_y_+ticklength); + x_location = x_location + increment; + } + dc->DrawLine(end_x-1, start_y_, end_x-1, start_y_+ticklength); + dc->DrawLine(end_x, start_y_, end_x, start_y_+ticklength); + + //draw floating point axis markers + x_location = start_x_ - shift_x; + float marker_x = start_val_; + float marker_increment = (stop_val_ - start_val_)/ticknum_; + char marker_str[8]; + int i = 0, fixed_y = start_y_ + 10; + char align[6]; + if(stop_val_ < 10) + strcpy(align, "%4.2f"); + else + { + strcpy(align, "%4.0f"); + x_location = x_location - shift_x; + shift_x = 2*shift_x; + } + dc->SetFont(plotFont); + for(i = 0; i < ticknum_; i++) + { + sprintf(marker_str, align, marker_x); + dc->DrawText(marker_str, x_location, fixed_y); + marker_x += marker_increment; + x_location += increment; + } + sprintf(marker_str, align, marker_x); + dc->DrawText(marker_str, end_x - shift_x, fixed_y); + + //add label + if(label_) + { + dc->SetFont(*(label_->font_)); + dc->DrawRotatedText(label_->text_, label_x_, label_y_, 0+rotation_); + } + } + //vertical axis + else + { + //draw axis line + dc->DrawLine(start_x_, start_y_, start_x_, end_y); + dc->DrawLine(start_x_-1, start_y_, start_x_-1, end_y); + + //draw tick marks + int increment = length_/ticknum_; + if(length_%ticknum_ != 0) increment++; + int y_location = end_y; + while(y_location < start_y_) + { + dc->DrawLine(start_x_, y_location, start_x_-ticklength, y_location); + dc->DrawLine(start_x_, y_location+1, start_x_-ticklength, y_location+1); + y_location = y_location + increment; + } + dc->DrawLine(start_x_, start_y_, start_x_-ticklength, start_y_); + dc->DrawLine(start_x_, start_y_+1, start_x_-ticklength, start_y_+1); + + //draw floating point axis markers + y_location = start_y_; + float marker_y = start_val_; + float marker_increment = (stop_val_ - start_val_)/ticknum_; + char marker_str[8]; + int i = 0, fixed_x = start_x_ - 30; + char align[6]; + if(stop_val_ < 10) + strcpy(align, "%4.2f"); + else + strcpy(align, "%4.0f"); + dc->SetFont(plotFont); + sprintf(marker_str, align, marker_y); + dc->DrawText(marker_str, fixed_x, y_location - shift_y); + marker_y += marker_increment; + y_location -= increment; + for(i = 1; i < ticknum_; i++) + { + sprintf(marker_str, align, marker_y); + dc->DrawText(marker_str, fixed_x, y_location); + marker_y += marker_increment; + y_location -= increment; + } + sprintf(marker_str, align, marker_y); + dc->DrawText(marker_str, fixed_x, end_y - shift_y); + + //add label + if(label_) + { + dc->SetFont(*(label_->font_)); + dc->DrawRotatedText(label_->text_, label_x_, label_y_, 90+rotation_); + } + } +} + +// --------------------------------------------------------------------------- +// BgThread +// --------------------------------------------------------------------------- + +BgThread::BgThread(wxThreadKind kind, void foo(void*), void *Object) : wxThread(kind) +{ + function_ = foo; + Object_ = Object; +} + +BgThread::~BgThread( void ) +{ + function_ = NULL; + Object_ = NULL; +} + +void *BgThread::Entry( void ) +{ + function_(Object_); + return (void *) NULL; +} + +// --------------------------------------------------------------------------- +// BgDialog +// --------------------------------------------------------------------------- + +BgDialog::BgDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name) + : wxDialog(parent, id, title, pos, size, style, name) +{ + + okButton_ = new wxButton(this, BG_DIALOG_OK, "OK", wxPoint(size.GetWidth()/2-40, size.GetHeight()-60)); +} + +BgDialog::~BgDialog( void ) +{ + delete okButton_; +} + +void BgDialog::AddText(BgText *text) +{ + tlist_.AddText(text); +} + +void BgDialog::AddBitmap(BgBitmap *bitmap) +{ + blist_.AddBitmap(bitmap); +} + +void BgDialog::RemoveText(int id) +{ + tlist_.RemoveText(id); +} + +void BgDialog::RemoveBitmap(BgBitmap *bitmap) +{ + blist_.RemoveBitmap(bitmap); +} + +void BgDialog::OnPaint(wxPaintEvent& WXUNUSED(event)) +{ + + wxPaintDC dc(this); + + //draw new text to the image from text object list + BgText *bgText; + tlist_.ResetList(); + while(bgText = tlist_.GetText()) + { + dc.SetFont(*(bgText->font_)); + dc.DrawText(bgText->text_, bgText->x_, bgText->y_); + } + + //draw bitmaps + blist_.ResetList(); + BgBitmap *bitmap; + while(bitmap = blist_.GetBitmap()) + dc.DrawBitmap(*(bitmap->bitmap_), bitmap->location_x_, bitmap->location_y_, true); + +} + +void BgDialog::OnExit(wxCommandEvent& WXUNUSED(event)) +{ + EndModal(wxID_OK); +} + +// --------------------------------------------------------------------------- +// BgHoverBar +// --------------------------------------------------------------------------- + +BgHoverBar::BgHoverBar(wxWindow* parent, wxWindowID id, int gradViewId, int confViewId, int weitViewId, int custViewId, int gradSaveId, int confSaveId, int weitSaveId) + : wxWindow(parent, id, wxDefaultPosition, wxDefaultSize, wxRAISED_BORDER) +{ + //set the size of the window + SetSize(120,30); + + //place a button using a bitmap + menuButton1_ = new wxBitmapButton(this, BG_CANVAS_VIEW_BUTTON, wxBitmap("down_arrow", wxBITMAP_TYPE_RESOURCE), wxPoint(33,2), wxSize(18,20)); + menuButton2_ = new wxBitmapButton(this, BG_CANVAS_SAVE_BUTTON, wxBitmap("down_arrow", wxBITMAP_TYPE_RESOURCE), wxPoint(92,2), wxSize(18,20)); + menuText1_ = new wxStaticText(this, -1, "View", wxPoint(5,5), wxSize(25,20)); + menuText2_ = new wxStaticText(this, -1, "Save", wxPoint(62,5), wxSize(25,20)); + + //get view menu identification constants + gradViewId_ = gradViewId; + confViewId_ = confViewId; + weitViewId_ = weitViewId; + custViewId_ = custViewId; + gradSaveId_ = gradSaveId; + confSaveId_ = confSaveId; + weitSaveId_ = weitSaveId; + + //create view menu + view_menu = new wxMenu; + view_menu->Append(gradViewId_, "&Gradient Map", "", true); + view_menu->Append(confViewId_, "&Confidence Map", "", true); + view_menu->Append(weitViewId_, "&Weight Map", "", true); + view_menu->Append(custViewId_, "C&ustom Weight Map", "", true); + + //create save menu + save_menu = new wxMenu; + save_menu->Append(gradSaveId_, "&Gradient Map"); + save_menu->Append(confSaveId_, "&Confidence Map"); + save_menu->Append(weitSaveId_, "&Weight Map"); + +} + +BgHoverBar::~BgHoverBar( void ) +{ + //de-allocate menus... + delete view_menu; + delete save_menu; +} + +void BgHoverBar::ShowMenu(wxCommandEvent& event) +{ + int buttonId = event.GetId(); + if(buttonId == BG_CANVAS_VIEW_BUTTON) + { + menuText1_->SetForegroundColour(wxColour(0,0,100)); + menuText2_->SetForegroundColour(wxColour(0,0,0)); + menuText1_->Refresh(); + menuText2_->Refresh(); + PopupMenu(view_menu, 0, 26); + } + else + { + menuText1_->SetForegroundColour(wxColour(0,0,0)); + menuText2_->SetForegroundColour(wxColour(0,0,100)); + menuText1_->Refresh(); + menuText2_->Refresh(); + PopupMenu(save_menu, 0, 26); + } + Update(); +} + +void BgHoverBar::CheckViewItem(long viewItemId) +{ + view_menu->Check(gradViewId_, false); + view_menu->Check(confViewId_, false); + view_menu->Check(weitViewId_, false); + view_menu->Check(custViewId_, false); + view_menu->Check(viewItemId, true); +} + +void BgHoverBar::Update( void ) +{ + menuText1_->SetForegroundColour(wxColour(0,0,0)); + menuText2_->SetForegroundColour(wxColour(0,0,0)); + menuText1_->Refresh(); + menuText2_->Refresh(); +} + +// --------------------------------------------------------------------------- +// BgMenuPanel +// --------------------------------------------------------------------------- + +BgMenuPanel::BgMenuPanel(wxWindow* parent, wxWindowID id, int gradViewId, int confViewId, int weitViewId, int custViewId, int gradSaveId, int confSaveId, int weitSaveId) + : wxPanel(parent, id, wxDefaultPosition, wxDefaultSize) +{ + //keep pointer to scroll window + scrollWindow_ = (wxWindow *) NULL; + + //set the position and size of the window + SetSize(0,0,120,30); + + //place a button using a bitmap + menuButton1_ = new wxBitmapButton(this, BG_CANVAS_VIEW_BUTTON, wxBitmap("down_arrow", wxBITMAP_TYPE_RESOURCE), wxPoint(33,2), wxSize(18,20)); + menuButton2_ = new wxBitmapButton(this, BG_CANVAS_SAVE_BUTTON, wxBitmap("down_arrow", wxBITMAP_TYPE_RESOURCE), wxPoint(92,2), wxSize(18,20)); + menuText1_ = new wxStaticText(this, -1, "View", wxPoint(5,5), wxSize(25,20)); + menuText2_ = new wxStaticText(this, -1, "Save", wxPoint(62,5), wxSize(25,20)); + + //get view menu identification constants + gradViewId_ = gradViewId; + confViewId_ = confViewId; + weitViewId_ = weitViewId; + custViewId_ = custViewId; + gradSaveId_ = gradSaveId; + confSaveId_ = confSaveId; + weitSaveId_ = weitSaveId; + + //create view menu + view_menu = new wxMenu; + view_menu->Append(gradViewId_, "&Gradient Map", "", true); + view_menu->Append(confViewId_, "&Confidence Map", "", true); + view_menu->Append(weitViewId_, "&Weight Map", "", true); + view_menu->Append(custViewId_, "C&ustom Weight Map", "", true); + + //create save menu + save_menu = new wxMenu; + save_menu->Append(gradSaveId_, "&Gradient Map"); + save_menu->Append(confSaveId_, "&Confidence Map"); + save_menu->Append(weitSaveId_, "&Weight Map"); + +} + +BgMenuPanel::~BgMenuPanel( void ) +{ + //de-allocate menus... + delete view_menu; + delete save_menu; +} + +void BgMenuPanel::ShowMenu(wxCommandEvent& event) +{ + int buttonId = event.GetId(); + if(buttonId == BG_CANVAS_VIEW_BUTTON) + { + menuText1_->SetForegroundColour(wxColour(0,0,200)); + menuText2_->SetForegroundColour(wxColour(0,0,0)); + menuText1_->Refresh(); + menuText2_->Refresh(); + PopupMenu(view_menu, 0, 26); + } + else + { + menuText1_->SetForegroundColour(wxColour(0,0,0)); + menuText2_->SetForegroundColour(wxColour(0,0,200)); + menuText1_->Refresh(); + menuText2_->Refresh(); + PopupMenu(save_menu, 0, 26); + } + Update(); +} + +void BgMenuPanel::CheckViewItem(long viewItemId) +{ + view_menu->Check(gradViewId_, false); + view_menu->Check(confViewId_, false); + view_menu->Check(weitViewId_, false); + view_menu->Check(custViewId_, false); + view_menu->Check(viewItemId, true); +} + +void BgMenuPanel::Update( void ) +{ + menuText1_->SetForegroundColour(wxColour(0,0,0)); + menuText2_->SetForegroundColour(wxColour(0,0,0)); + menuText1_->Refresh(); + menuText2_->Refresh(); +} + +void BgMenuPanel::EnableMenu(bool enable) +{ + menuText1_->Enable(enable); + menuText2_->Enable(enable); + menuButton1_->Enable(enable); + menuButton2_->Enable(enable); +} + +//adjusts size of scroll window +void BgMenuPanel::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + if(scrollWindow_) + { + int w, h; + GetClientSize(&w, &h); + scrollWindow_->SetSize(0,PLOT_MENU_HEIGHT,w,h-PLOT_MENU_HEIGHT); + } +} + +void BgMenuPanel::SetScrollWindow(wxWindow *scrollwindow) +{ + scrollWindow_ = scrollwindow; +} + +// --------------------------------------------------------------------------- +// BgLineSet +// --------------------------------------------------------------------------- + +BgLineSet::BgLineSet() +{ + xs_ = ys_ = xe_ = ye_ = 0; + lineParam_ = 0; + n_ = 0; + pen_.SetColour(*wxRED); + //pen_.SetColour(*wxWHITE); + pen_.SetWidth(2); + pen_.SetStyle(wxSOLID); +} + +BgLineSet::~BgLineSet() +{ + CleanData(); +} + +void BgLineSet::CleanData() +{ + if (n_ > 0) + { + delete [] xs_; + delete [] xe_; + delete [] ys_; + delete [] ye_; + delete [] lineParam_; + xs_ = ys_ = xe_ = ye_ = 0; + lineParam_ = 0; + n_ = 0; + } +} + +void BgLineSet::SetLines(int* xs, int* xe, int* ys, int* ye, double* lineParam, int n) +{ + CleanData(); + n_ = n; + xs_ = new int[n_]; + xe_ = new int[n_]; + ys_ = new int[n_]; + ye_ = new int[n_]; + lineParam_ = new double[n_*3]; + int i; + for (i=0; i<n; i++) + { + xs_[i] = xs[i]; + ys_[i] = ys[i]; + xe_[i] = xe[i]; + ye_[i] = ye[i]; + } + for (i=0; i<(3*n); i++) + lineParam_[i] = lineParam[i]; +} + +void BgLineSet::SetLines(double* startp, double* endp, double* lineParam, int n) +{ + CleanData(); + n_ = n; + xs_ = new int[n_]; + xe_ = new int[n_]; + ys_ = new int[n_]; + ye_ = new int[n_]; + lineParam_ = new double[n_*3]; + int i; + for (i=0; i<n; i++) + { + xs_[i] = (int) startp[2*i]; + ys_[i] = (int) startp[2*i+1]; + xe_[i] = (int) endp[2*i]; + ye_[i] = (int) endp[2*i+1]; + } + for (i=0; i<(3*n); i++) + lineParam_[i] = lineParam[i]; +} + +// --------------------------------------------------------------------------- +// BgImCanvas +// --------------------------------------------------------------------------- + +// Define a constructor for my canvas +BgImCanvas::BgImCanvas(wxWindow *child_frame, wxWindow *parent, const wxPoint& pos, const wxSize& size) +: wxScrolledWindow(parent, -1, pos, size, + wxSIMPLE_BORDER|wxVSCROLL|wxHSCROLL) +{ + SetBackgroundColour(wxColour("WHITE")); + pbitmap=(wxBitmap*) NULL; + pimage=(wxImage*) NULL; + hasbitmap=FALSE; + showbitmap_ = TRUE; + m_dirty = FALSE; + nLineSets_ = nPointSets_ = 0; + + //set pointer to child frame (e.g. used to update window title) + child_frame_ = child_frame; + + // clickable curve stuff + nCurveSets_ = 0; + ccx_ = RANK_CONF_IMSIZEX; + ccy_ = RANK_CONF_IMSIZEY; + curveClick_ = new unsigned char[ccx_*ccy_]; + isDragging_ = 0; + FillCurveClick(); + mouseModif_ = 0; + crossCursor_ = 0; + showtrack_ = 0; + + //initialize window events + has_focus = false; + leaving = false; + + //initialize plotting canvas + x_offset_ = 0; + y_offset_ = 0; + textObjectCount_ = 0; + xAxis = (BgAxis *) NULL; + yAxis = (BgAxis *) NULL; + clear_display_ = false; + + //initializing zooming parameters + zoom_in = false; + zoom_out = false; + zoom_window = false; + zoom_level = 1; + + //initialize empty zoom box and refresh box + zoombox = (wxImage *) NULL; + refresh_box = (wxImage *) NULL; + + //initialize point map + point_map = NULL; + point_colour = (wxColour *) NULL; + + //initialize zoomed image buffer + zImg = NULL; + + //initialize zoom window corner + cx = 0; + cy = 0; + + //initialize mouse pointer location + m_x_ = 0; + m_y_ = 0; + + //initialize zoom buffers + buf = (unsigned char *) NULL; + + //initialize hover window such that + //it does not popup + popup = 0; + + //initialize hover window + menuWindow = (wxWindow *) NULL; + + //pay attention to updates + noUpdate_ = false; + + //construct zoom cursors + //?????????????????????????????? + wxString str; + str.Printf(wxT("icon10")); + bgCURSOR_MAGNIFIER_PLUS = new wxCursor(str, wxBITMAP_TYPE_CUR_RESOURCE); + //bgCURSOR_MAGNIFIER_PLUS = new wxCursor("icon10", wxBITMAP_TYPE_RESOURCE, 0, 0); + str.Printf(wxT("icon11")); + bgCURSOR_MAGNIFIER_MINUS = new wxCursor(str, wxBITMAP_TYPE_CUR_RESOURCE); + //bgCURSOR_MAGNIFIER_MINUS = new wxCursor("icon11", wxBITMAP_TYPE_RESOURCE, 0, 0); + + //build local menu + localMenu_ = new wxMenu(); + localMenu_->Append(BG_IMC_ADDNODE,"Add node"); + localMenu_->Append(BG_IMC_DELETENODE,"Delete node"); + localMenu_->AppendSeparator(); + localMenu_->Append(BG_IMC_SELTYPE_ELLIPSE,"Arc"); + localMenu_->Append(BG_IMC_SELTYPE_VLINE,"Vertical line"); + localMenu_->Append(BG_IMC_SELTYPE_HLINE,"Horizontal line"); + localMenu_->Append(BG_IMC_SELTYPE_LINE,"Line"); + localMenu_->Append(BG_IMC_SELTYPE_BOX,"Box"); + localMenu_->Append(BG_IMC_SELTYPE_CUSTOM,"Custom"); +} + +BgImCanvas::~BgImCanvas() +{ + ClearData(); + if(xAxis) delete xAxis; + if(yAxis) delete yAxis; + delete [] curveClick_; + delete localMenu_; + delete bgCURSOR_MAGNIFIER_PLUS; + delete bgCURSOR_MAGNIFIER_MINUS; +} + +void BgImCanvas::OnCustomAddNode(wxCommandEvent& WXUNUSED(event)) +{ + if ((lmEventCurve_ < 0) || (lmEventCurve_ >= nCurveSets_) || + (curveSet_[lmEventCurve_]->type_!=FC_CUSTOM)) + { + return; + } + int n, type; + n = curveSet_[lmEventCurve_]->n_; + double *tx, *ty; + tx = new double[n+1]; + ty = new double[n+1]; + curveSet_[lmEventCurve_]->GetParamCurve(tx, ty, type, n); + double x, y; + x = ((double) lmEventX_)/ccx_; + y = (ccy_ - ((double) lmEventY_))/ccy_; + + // determine closest line + double cx, cy, cr, ax, ay, dx, dy; + double mny = 10; + int ci = -1; + int i; + for (i=0; i<(n-1); i++) + { + cx = tx[i+1]-tx[i]; + cy = ty[i+1]-ty[i]; + cr = sqrt(cx*cx+cy*cy); + if (cr <= 0) + continue; + ax = x-tx[i]; + ay = y-ty[i]; + dx = (cx*ax+cy*ay)/cr; + dy = fabs((-cy*ax+cx*ay)/cr); + if ((dx>=0) && (dx<=cr)) + { + if (dy<mny) + { + mny = dy; + ci = i; + } + } + } + if (ci >= 0) + { + // modify curve + for (i=n; i>ci; i--) + { + tx[i] = tx[i-1]; + ty[i] = ty[i-1]; + } + tx[ci+1] = x; + ty[ci+1] = y; + curveSet_[lmEventCurve_]->SetParamCurve(type, tx, ty, n+1, ccx_, ccy_); + } + + delete [] ty; + delete [] tx; + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + + FillCurveClick(); + return; +} +void BgImCanvas::OnCustomDeleteNode(wxCommandEvent& WXUNUSED(event)) +{ + if ((lmEventCurve_ < 0) || (lmEventCurve_ >= nCurveSets_) || + (lmEventNode_ < 0) || (lmEventNode_ >= (curveSet_[lmEventCurve_]->n_-1))) + { + return; + } + if (lmEventNode_ == 0) + { + bgLog("Cannot delete first node.\n"); + return; + } + if (lmEventNode_ == (curveSet_[lmEventCurve_]->n_-1)) + { + bgLog("Cannot delete last node.\n"); + return; + } + // delete the node + int i; + int n = curveSet_[lmEventCurve_]->n_; + int *tx, *ty; + tx = curveSet_[lmEventCurve_]->x_; + ty = curveSet_[lmEventCurve_]->y_; + for (i=lmEventNode_; i<(n-1); i++) + { + tx[i] = tx[i+1]; + ty[i] = ty[i+1]; + } + curveSet_[lmEventCurve_]->n_ = n-1; + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + FillCurveClick(); + return; +} +void BgImCanvas::OnCTypeEllipse(wxCommandEvent& WXUNUSED(event)) +{ + if (lmEventCurve_ < nCurveSets_) + { + if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) + { + curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; + curveSet_[lmEventCurve_]->n_ = 1; + } + curveSet_[lmEventCurve_]->type_ = FC_ELLIPSE; + FillCurveClick(); + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + } +} +void BgImCanvas::OnCTypeVLine(wxCommandEvent& WXUNUSED(event)) +{ + if (lmEventCurve_ < nCurveSets_) + { + if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) + { + curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; + curveSet_[lmEventCurve_]->n_ = 1; + } + curveSet_[lmEventCurve_]->type_ = FC_VERT_LINE; + FillCurveClick(); + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + } +} +void BgImCanvas::OnCTypeHLine(wxCommandEvent& WXUNUSED(event)) +{ + if (lmEventCurve_ < nCurveSets_) + { + if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) + { + curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; + curveSet_[lmEventCurve_]->n_ = 1; + } + curveSet_[lmEventCurve_]->type_ = FC_HORIZ_LINE; + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + FillCurveClick(); + } +} +void BgImCanvas::OnCTypeLine(wxCommandEvent& WXUNUSED(event)) +{ + if (lmEventCurve_ < nCurveSets_) + { + if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) + { + curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; + curveSet_[lmEventCurve_]->n_ = 1; + } + curveSet_[lmEventCurve_]->type_ = FC_LINE; + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + FillCurveClick(); + } +} +void BgImCanvas::OnCTypeBox(wxCommandEvent& WXUNUSED(event)) +{ + if (lmEventCurve_ < nCurveSets_) + { + if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) + { + curveSet_[lmEventCurve_]->x_[0] = curveSet_[lmEventCurve_]->x_[curveSet_[lmEventCurve_]->n_-1]; + curveSet_[lmEventCurve_]->n_ = 1; + } + curveSet_[lmEventCurve_]->type_ = FC_SQUARE_BOX; + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + FillCurveClick(); + } +} +void BgImCanvas::OnCTypeCustom(wxCommandEvent& WXUNUSED(event)) +{ + if (lmEventCurve_ < nCurveSets_) + { + if (curveSet_[lmEventCurve_]->type_ != FC_CUSTOM) + { + double x[3]; + double y[3]; + int n,type; + curveSet_[lmEventCurve_]->GetParamCurve(x,y,type,n); + n = 3; + type = FC_CUSTOM; + x[2] = x[0]; + x[0] = 0; + y[2] = 0; + x[2] = (x[2]>1) ? 1:x[2]; + x[2] = (x[2]<0) ? 0:x[2]; + y[0] = (y[0]>1) ? 1:y[0]; + y[0] = (y[0]<0) ? 0:y[0]; + x[1] = (x[0]+x[2])*2.0/3.0; + y[1] = (y[0]+y[2])*2.0/3.0; + curveSet_[lmEventCurve_]->SetParamCurve(type, x, y, n, ccx_, ccy_); + } + curveSet_[lmEventCurve_]->type_ = FC_CUSTOM; + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + FillCurveClick(); + } +} + +void BgImCanvas::AddPointSet(BgPointSet* ps) +{ + pointSet_[nPointSets_++] = ps; + + //update point map if the point set consists + //of data points (not circles) + if((ps->type_ == 1)&&(hasbitmap)) + { + int nt, *tx, *ty; + nt = ps->n_; + tx = ps->x_; + ty = ps->y_; + int i, dp, width = pimage->GetWidth(); + for(i=0; i<nt; i++) + { + dp = ty[i]*width+tx[i]; + point_map[dp] = true; + } + } + + //define new pen colour is yet defined, define it + if(point_colour) delete point_colour; + point_colour = new wxColour(ps->pen_.GetColour()); + + //add point data to zoomed image (if it has been defined, + //i.e. an image has been loaded into the image canvas) + if(zImg) AddPoints(zImg, ((pimage->GetWidth())*zoom_level)); + + Refresh(); +} + +void BgImCanvas::RemovePointSet(BgPointSet* ps) +{ + int i = 0; + while (i<nPointSets_ && pointSet_[i]!=ps) + i++; + if (i<nPointSets_) + { + i++; + while(i<nPointSets_) + { + pointSet_[i-1] = pointSet_[i]; + i++; + } + nPointSets_--; + } + + //adjust point map accordingly + if((point_map)&&(ps->type_ == 1)) //point + { + int width = pimage->GetWidth(); + int nt, *tx, *ty; + nt = ps->n_; + tx = ps->x_; + ty = ps->y_; + for(i=0; i<nt; i++) + point_map[ty[i]*width+tx[i]] = false; + } + + //delete pen colour if no more point sets exist + if(nPointSets_ == 0) + { + delete point_colour; + point_colour = (wxColour *) NULL; + } + + //remove this point set from the zoomed image... + + /*********************************************************/ + + if(zImg) + { + delete [] zImg; + int width, height; + width = (pimage->GetWidth())*zoom_level; + height = (pimage->GetHeight())*zoom_level; + zImg = new unsigned char [3*width*height]; + if(zoom_level > 1) + bgZoomIn(&zImg, pimage->GetData(), pimage->GetWidth(), pimage->GetHeight(), zoom_level, false); + else if(zoom_level == 1) + memcpy(zImg, pimage->GetData(), 3*width*height*sizeof(unsigned char)); + + //add any other point sets that may exist + AddPoints(zImg, width); + } + + /*********************************************************/ + + Refresh(false); + +} + +void BgImCanvas::AddLineSet(BgLineSet* ls) +{ + lineSet_[nLineSets_++] = ls; + Refresh(); +} + +void BgImCanvas::AddTrackSet(int x, int y, int hx, int hy) +{ + trackval_[0] = x; + trackval_[1] = y; + hx_ = hx; + hy_ = hy; + showtrack_ = 1; + Refresh(); + +} + +void BgImCanvas::RemoveTrackSet() +{ + showtrack_ = 0; + Refresh(); +} + + +void BgImCanvas::RemoveLineSet(BgLineSet* ls) +{ + int i = 0; + while (i<nLineSets_ && lineSet_[i]!=ls) + i++; + if (i<nLineSets_) + { + i++; + while(i<nLineSets_) + { + lineSet_[i-1] = lineSet_[i]; + i++; + } + nLineSets_--; + } + Refresh(); +} + +void BgImCanvas::AddCurveSet(BgCurveSet* cs) +{ + curveSet_[nCurveSets_++] = cs; + Refresh(); +} + +void BgImCanvas::RemoveCurveSet(BgCurveSet* cs) +{ + int i = 0; + while (i<nCurveSets_ && curveSet_[i]!=cs) + i++; + if (i<nCurveSets_) + { + i++; + while(i<nCurveSets_) + { + curveSet_[i-1] = curveSet_[i]; + i++; + } + nCurveSets_--; + } + Refresh(); +} + +//adds text object to be dran to the image +//pre : bgText is the text object to be plotted +//post: bgText has been added to the image +void BgImCanvas::AddText(BgText *bgText) +{ + //add text to text list + if(tlist_.AddText(bgText)) + { + bgLog("BgImCanvas::AddText Error: Out of memory.\n"); + return; + } + + //obtain new text object count + textObjectCount_ = tlist_.GetTextCount(); +} + +//clears all text object from text list +void BgImCanvas::RemoveText(int text_id) +{ + tlist_.RemoveText(text_id); + return; +} + +//adds horizontal axis +void BgImCanvas::AddHorizontalAxis(int start_x, int start_y, int length, int ticknum, float start_val, float stop_val) +{ + if(xAxis) delete xAxis; + xAxis = new BgAxis(start_x, start_y, length, ticknum, 0, start_val, stop_val); +} + +//adds horizontal axis +void BgImCanvas::AddVerticalAxis(int start_x, int start_y, int length, int ticknum, float start_val, float stop_val) +{ + if(yAxis) delete yAxis; + yAxis = new BgAxis(start_x, start_y, length, ticknum, 1, start_val, stop_val); +} + +//clears axis +void BgImCanvas::ClearAxis( void ) +{ + if(xAxis) delete xAxis; + if(yAxis) delete yAxis; + xAxis = yAxis = (BgAxis *) NULL; +} + +//labels horizontal axis +void BgImCanvas::LabelHorizontalAxis(BgText *bgText) +{ + if(xAxis) xAxis->Label(bgText); +} + +//labels vertical axis +void BgImCanvas::LabelVerticalAxis(BgText *bgText) +{ + if(yAxis) yAxis->Label(bgText); +} + +//removes label on horizontal axis +void BgImCanvas::RemoveHorizontalAxisLabel(void) +{ + if(xAxis) xAxis->RemoveLabel(); +} + +//removes lable on vertical axis +void BgImCanvas::RemoveVerticalAxisLabel(void) +{ + if(yAxis) yAxis->RemoveLabel(); +} + +//rotates horizontal axis label clockwise from default position +void BgImCanvas::RotateHorizontalAxisLabel(int rotation) +{ + if(xAxis) xAxis->SetLabelRotation(rotation); +} + +//rotates vertical axis label clockwise from default position +void BgImCanvas::RotateVerticalAxisLabel(int rotation) +{ + if(yAxis) yAxis->SetLabelRotation(rotation); +} + +//plot bitmap at specified location +void BgImCanvas::AddBitmap(BgBitmap *bitmap) +{ + blist_.AddBitmap(bitmap); +} + +//remove bitmap from plot +void BgImCanvas::RemoveBitmap(BgBitmap *bitmap) +{ + blist_.RemoveBitmap(bitmap); +} + +//clears display +void BgImCanvas::ClearDisplay(void) +{ + clear_display_ = true; + Refresh(); +} + +void BgImCanvas::ClearData(int refresh) +{ + if(hasbitmap==TRUE) { + delete pbitmap; + delete pimage; + } + if(zoombox) delete zoombox; + if(refresh_box) delete refresh_box; + if(zImg) delete zImg; + if(point_map) delete [] point_map; + if(buf) delete [] buf; + hasbitmap=FALSE; + pbitmap=(wxBitmap*) NULL; + pimage=(wxImage*) NULL; + zoombox=(wxImage*) NULL; + refresh_box=(wxImage*) NULL; + zImg=NULL; + point_map=NULL; + showtrack_ = 0; + if (refresh > 0) + Refresh(); +} + +int BgImCanvas::SetImage(wxString imname) +{ + ClearData(); + pimage=new wxImage(); + if (!pimage->LoadFile(imname)) + { + delete pimage; + wxLogError("Can't load image "+imname); + return 0; + } + else + { + SetScrollbars(1, 1, (pimage->GetWidth())/1, (pimage->GetHeight())/1); +#if wxCHECK_VERSION(2, 3, 0) + pbitmap = new wxBitmap(pimage); +#else + pbitmap = new wxBitmap(pimage->ConvertToBitmap()); +#endif + hasbitmap=TRUE; + m_dirty=TRUE; + + //create point map + CreatePointMap(pimage->GetWidth(), pimage->GetHeight()); + + //take account for zoom (takes care of refresh) + Zoom(zoom_level); + } + return 1; +} + +void BgImCanvas::SetImage(wxImage& image) +{ + ClearData(); + pimage=new wxImage(); + *pimage = image; + SetScrollbars(1, 1, (pimage->GetWidth())/1, (pimage->GetHeight())/1); + +#if wxCHECK_VERSION(2, 3, 0) + pbitmap = new wxBitmap(pimage); +#else + pbitmap = new wxBitmap(pimage->ConvertToBitmap()); +#endif + hasbitmap=TRUE; + m_dirty=TRUE; + + //create point map + CreatePointMap(image.GetWidth(), image.GetHeight()); + + //take account for zoom (takes care of refresh) + Zoom(zoom_level); + +} + +void BgImCanvas::SetSameImage(wxImage& image) +{ + *pimage = image; +#if wxCHECK_VERSION(2, 3, 0) + *pbitmap = wxBitmap(image); +#else + *pbitmap = image.ConvertToBitmap(); +#endif + + //create point map + CreatePointMap(image.GetWidth(), image.GetHeight()); + + //take account for zoom (takes care of refresh) + Zoom(zoom_level); +} + +void BgImCanvas::SetImageFromGray(unsigned char* data, int w, int h) +{ + ClearData(); + + pimage = new wxImage(w, h); + + int i; + unsigned char* itTData; + itTData = pimage->GetData(); + + for (i=0; i<w*h; i++) + { + *(itTData++)=data[i]; + *(itTData++)=data[i]; + *(itTData++)=data[i]; + } + SetScrollbars(1, 1, (pimage->GetWidth())/1, (pimage->GetHeight())/1); + +#if wxCHECK_VERSION(2, 3, 0) + pbitmap = new wxBitmap(pimage); +#else + pbitmap = new wxBitmap(pimage->ConvertToBitmap()); +#endif + hasbitmap=TRUE; + m_dirty=TRUE; + + //create point map + CreatePointMap(w, h); + + //take account for zoom (takes care of refresh) + Zoom(zoom_level); +} + +void BgImCanvas::SetImage(unsigned char* data, int w, int h, bool colorim) +{ + ClearData(); + + pimage = new wxImage(w, h); + + int i; + unsigned char* itTData; + itTData = pimage->GetData(); + + if (colorim == false) + { + for (i=0; i<w*h; i++) + { + *(itTData++)=data[i]; + *(itTData++)=data[i]; + *(itTData++)=data[i]; + } + } else + { + for (i=0; i<(3*w*h); i++) + { + *(itTData++)=data[i]; + } + } + SetScrollbars(1, 1, (pimage->GetWidth())/1, (pimage->GetHeight())/1); + +#if wxCHECK_VERSION(2, 3, 0) + pbitmap = new wxBitmap(pimage); +#else + pbitmap = new wxBitmap(pimage->ConvertToBitmap()); +#endif + hasbitmap=TRUE; + m_dirty=TRUE; + + + //create point map + CreatePointMap(w, h); + + //take account for zoom (takes care of refresh) + Zoom(zoom_level); +} + +/* +Still needs work!!!!!! +*/ + +void BgImCanvas::ShowBitmap(bool showbitmap) +{ + showbitmap_ = showbitmap; + if(hasbitmap) + { + //compute height and width of original image + int width = pimage->GetWidth(); + int height = pimage->GetHeight(); + + //paint zoom image + if(!showbitmap_) + memset(zImg, 255, 3*zoom_level*zoom_level*width*height*sizeof(unsigned char)); + else + bgZoomIn(&zImg, pimage->GetData(), width, height, zoom_level, false); + + //plot points from point set onto zoom image + AddPoints(zImg, width*zoom_level); + + //re-draw image onto canvas + Refresh(); + } + return; +} + + +// Define the repainting behaviour +void BgImCanvas::OnDraw(wxDC& dc) +{ + //clear the display + if(clear_display_) + { + clear_display_ = false; + dc.Clear(); + return; + } + + //do not update the display (good for keeping + //a display clear in light of onSize() events + //for example) + if(noUpdate_) return; + + //catch leaving event + if((zoom_window)&&(leaving)) + { + //if a refresh window remains, plot it and delete it + if(refresh_box) + { +#if wxCHECK_VERSION(2, 3, 0) + dc.DrawBitmap(wxBitmap(refresh_box), cx, cy); +#else + dc.DrawBitmap(refresh_box->ConvertToBitmap(), cx, cy); +#endif + delete refresh_box; + refresh_box = (wxImage*) NULL; + } + + //retrieve leaving event + leaving = false; + + //exit + return; + } + + + if (hasbitmap==false) + { + dc.Clear(); + return; + } + //re-plot image bitmap + if(hasbitmap==true && showbitmap_==true) + { + if((!zoom_window)||(!has_focus)) + dc.DrawBitmap(*pbitmap,0+x_offset_,0+y_offset_); + } + else if(!zoom_window) + { + dc.Clear(); + } + if (showtrack_ == 1) + { + wxPen tPen=dc.GetPen(); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.SetPen(*wxRED_PEN); + //+x_offset_+y_offset_ + dc.DrawEllipse(trackval_[0]-2, trackval_[1]-2, 5,5); + dc.DrawEllipse(trackval_[0]-hx_, trackval_[1]-hy_, 2*hx_+1, 2*hy_+1); + dc.SetPen(tPen); + dc.SetBrush(wxNullBrush); + } + if ((nPointSets_ > 0)&&((!zoom_window)||(!has_focus))) + { + int i,j; + int* tx; + int* ty; + int x, xc; + int y, yc; + int nt; + wxPen tPen=dc.GetPen(); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + for (i=0; i<nPointSets_; i++) + { + dc.SetPen(pointSet_[i]->pen_); + nt = pointSet_[i]->n_; + tx = pointSet_[i]->x_; + ty = pointSet_[i]->y_; + if(pointSet_[i]->type_ == 0) // circle + { + for (j=0; j<nt; j++) + { + dc.DrawEllipse(tx[j]-2+x_offset_, ty[j]-2+y_offset_, 5,5); + } + } + else if(pointSet_[i]->type_ == 1) // point + { + for (j=0; j<nt; j++) + { + xc = zoom_level*(tx[j] + x_offset_); + yc = zoom_level*(ty[j] + y_offset_); + for(y=0; y<zoom_level; y++) + { + for(x=0; x<zoom_level; x++) + { + dc.DrawPoint(xc+x, yc+y); + } + } + } + } + } + dc.SetPen(tPen); + dc.SetBrush(wxNullBrush); + } + + if (nLineSets_ > 0) + { + int i,j; + int* tsx; + int* tsy; + int* tex; + int* tey; + int nt; + wxPen tPen=dc.GetPen(); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + for (i=0; i<nLineSets_; i++) + { + dc.SetPen(lineSet_[i]->pen_); + nt = lineSet_[i]->n_; + tsx = lineSet_[i]->xs_; + tsy = lineSet_[i]->ys_; + tex = lineSet_[i]->xe_; + tey = lineSet_[i]->ye_; + for (j=0; j<nt; j++) + { + dc.DrawLine(tsx[j]+x_offset_, tsy[j]+y_offset_, tex[j]+x_offset_, tey[j]+y_offset_); + } + } + dc.SetPen(tPen); + dc.SetBrush(wxNullBrush); + } + int txs,tys,txe,tye; + + if (nCurveSets_ > 0) + { + int i,j; + int* tx; + int* ty; + int xs, ys; + int nt; + wxPen tPen=dc.GetPen(); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + for (i=0; i<nCurveSets_; i++) + { + dc.SetPen(curveSet_[i]->pen_); + tx = curveSet_[i]->x_; + ty = curveSet_[i]->y_; + nt = curveSet_[i]->n_; + xs = curveSet_[i]->xs_; + ys = curveSet_[i]->ys_; + + switch (curveSet_[i]->type_) + { + case -1: + break; + case FC_ELLIPSE: + MyDrawEllipticArc(dc,-tx[0]+x_offset_, ty[0]+y_offset_, 2*tx[0], 2*(ys-ty[0]), 0, 90); + break; + case FC_VERT_LINE: + // if ((tx[0]>=0) && (tx[0]<xs)) + dc.DrawLine(tx[0]+x_offset_, 0+y_offset_, tx[0]+x_offset_, ys+y_offset_); + break; + case FC_HORIZ_LINE: + if ((ty[0]>=0) && (ty[0]<ys)) + dc.DrawLine(0+x_offset_, ty[0]+y_offset_, xs+x_offset_, ty[0]+y_offset_); + break; + case FC_LINE: + // determine clipping + tye = ys; + txe = tx[0]; + txe = (txe<=0)?1:txe; + txs = 0; + tys = ty[0]; + tys = (tys>ys)?ys:tys; + if (txe>xs) + { + tye = ccy_-((ccy_-tys)*(txe-xs))/txe; + txe = xs; + } + if (tys<0) + { + txs= (txe*(-tys))/(tye-tys); + tys= 0; + } + + dc.DrawLine(0+x_offset_, ty[0]+y_offset_, tx[0]+x_offset_, ys+y_offset_); + break; + case FC_SQUARE_BOX: + txs = (tx[0]<0)?0:tx[0]; + txs = (txs>=xs)?xs-1:txs; + tys = (ty[0]<0)?0:ty[0]; + tys = (tys>=ys)?ys-1:tys; + dc.DrawLine(0+x_offset_, tys+y_offset_, txs+x_offset_, tys+y_offset_); + dc.DrawLine(txs+x_offset_, tys+y_offset_, txs+x_offset_, ys+y_offset_); + break; + case FC_CUSTOM: + for (j=0; j<(nt-1); j++) + dc.DrawLine(tx[j]+x_offset_, ty[j]+y_offset_, tx[j+1]+x_offset_, ty[j+1]+y_offset_); + break; + } + // wxPen pPen=dc.GetPen(); + // pPen.SetWidth(17); + // pPen.SetColour(64,64,64); + // dc.SetPen(pPen); + switch (curveSet_[i]->type_) + { + case -1: + break; + case FC_ELLIPSE: + case FC_LINE: + // dc.DrawPoint(0,ty[0]); + // dc.DrawPoint(tx[0],ys); + dc.DrawRectangle(0-2+x_offset_,ty[0]-2+y_offset_,5,5); + dc.DrawRectangle(tx[0]-2+x_offset_,ys-2+y_offset_,5,5); + break; + case FC_SQUARE_BOX: + // dc.DrawPoint(0,ty[0]); + // dc.DrawPoint(tx[0],ys); + // dc.DrawPoint(tx[0],ty[0]); + dc.DrawRectangle(0-2+x_offset_,ty[0]-2+y_offset_,5,5); + dc.DrawRectangle(tx[0]-2+x_offset_,ys-2+y_offset_,5,5); + dc.DrawRectangle(tx[0]-2+x_offset_,ty[0]-2+y_offset_,5,5); + break; + case FC_CUSTOM: + for (j=0; j<nt; j++) + dc.DrawRectangle(tx[j]-2+x_offset_,ty[j]-2+y_offset_,5,5); + // dc.DrawPoint(tx[j],ty[j]); + break; + } + } + dc.SetPen(tPen); + dc.SetBrush(wxNullBrush); + } + + if (isDragging_ == 1) + { + int j; + int* tx; + int* ty; + int xs, ys; + int nt; + wxPen tPen=dc.GetPen(); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.SetPen(dragCurve_.pen_); + tx = dragCurve_.x_; + ty = dragCurve_.y_; + nt = dragCurve_.n_; + xs = dragCurve_.xs_; + ys = dragCurve_.ys_; + + switch (dragCurve_.type_) + { + case -1: + break; + case FC_ELLIPSE: + MyDrawEllipticArc(dc,-tx[0]+x_offset_, ty[0]+y_offset_, 2*tx[0], 2*(ys-ty[0]), 0, 90); + break; + case FC_VERT_LINE: + // if ((tx[0]>=0) && (tx[0]<xs)) + dc.DrawLine(tx[0]+x_offset_, 0+y_offset_, tx[0]+x_offset_, ys+y_offset_); + break; + case FC_HORIZ_LINE: + if ((ty[0]>=0) && (ty[0]<ys)) + dc.DrawLine(0+x_offset_, ty[0]+y_offset_, xs+x_offset_, ty[0]+y_offset_); + break; + case FC_LINE: + // determine clipping + tye = ys; + txe = tx[0]; + txe = (txe<=0)?1:txe; + txs = 0; + tys = ty[0]; + tys = (tys>ys)?ys:tys; + if (txe>xs) + { + tye = ccy_-((ccy_-tys)*(txe-xs))/txe; + txe = xs; + } + if (tys<0) + { + txs= (txe*(-tys))/(tye-tys); + tys= 0; + } + + dc.DrawLine(0+x_offset_, ty[0]+y_offset_, tx[0]+x_offset_, ys+y_offset_); + break; + case FC_SQUARE_BOX: + txs = (tx[0]<0)?0:tx[0]; + txs = (txs>=xs)?xs-1:txs; + tys = (ty[0]<0)?0:ty[0]; + tys = (tys>=ys)?ys-1:tys; + dc.DrawLine(0+x_offset_, tys+y_offset_, txs+x_offset_, tys+y_offset_); + dc.DrawLine(txs+x_offset_, tys+y_offset_, txs+x_offset_, ys+y_offset_); + break; + case FC_CUSTOM: + for (j=0; j<(nt-1); j++) + dc.DrawLine(tx[j]+x_offset_, ty[j]+y_offset_, tx[j+1]+x_offset_, ty[j+1]+y_offset_); + break; + } + + dc.SetPen(tPen); + dc.SetBrush(wxNullBrush); + + } + + //draw horizontal and vertical axis + if(xAxis) xAxis->PlotAxis(&dc); + if(yAxis) yAxis->PlotAxis(&dc); + + //draw new text to the image from text object list + BgText *bgText; + tlist_.ResetList(); + while(bgText = tlist_.GetText()) + { + dc.SetFont(*(bgText->font_)); + dc.DrawText(bgText->text_, bgText->x_, bgText->y_); + } + + //draw bitmaps + blist_.ResetList(); + BgBitmap *bitmap; + while(bitmap = blist_.GetBitmap()) + dc.DrawBitmap(*(bitmap->bitmap_), bitmap->location_x_, bitmap->location_y_, true); + + //draw zoom window box + if((zoom_window)&&(has_focus)) + { + //draw refresh window +#if wxCHECK_VERSION(2, 3, 0) + if(refresh_box) dc.DrawBitmap(wxBitmap(refresh_box), cx, cy); +#else + if(refresh_box) dc.DrawBitmap(refresh_box->ConvertToBitmap(), cx, cy); +#endif + + //compute height and width of zoom box and window + int zWidth, zHeight; + int dWidth, dHeight; + zWidth = zoombox->GetWidth(); + zHeight = zoombox->GetHeight(); + GetSize(&dWidth, &dHeight); + + //compute upper corner of window + cx = m_x_ - zWidth/2; + cy = m_y_ - zHeight/2; + + //check bounds.... + if(cx < 0) cx = 0; + if(cy < 0) cy = 0; + if(cx >= dWidth - zWidth) cx = dWidth - zWidth - 1; + if(cy >= dHeight - zHeight) cy = dHeight - zHeight - 1; + + //place in image coordinate frame + cx = cx + GetScrollPos(wxHORIZONTAL); + cy = cy + GetScrollPos(wxVERTICAL); + + //check bounds + int width = pimage->GetWidth()*zoom_level, height = pimage->GetHeight()*zoom_level; + if(cx >= width - zWidth) cx = width - zWidth - 1; + if(cy >= height - zHeight) cy = height - zHeight - 1; + + //draw zoom window +#if wxCHECK_VERSION(2, 3, 0) + dc.DrawBitmap(wxBitmap(zoombox), cx, cy); +#else + dc.DrawBitmap(zoombox->ConvertToBitmap(), cx, cy); +#endif + + //create refresh box for next iteration + DefineRefreshBox(); + } + +} + +//adds an image margin to the image +//pre : (x_margin, y_margin) define the margins in the +// x and y direction respectively +//post: an image margin has been added +void BgImCanvas::AddMargin(int x_margin, int y_margin) +{ + //shift the image + x_offset_ = x_margin; + y_offset_ = y_margin; + + //redraw the image + Refresh(); + +} + +//overloaded zoom function that does not use current mouse position +int BgImCanvas::Zoom(int zconst) +{ + return Zoom(zconst, 0, 0); +} + +//allows one to zoom into/out of the image dispalyed by the image canvas +//pre : zconst is the zoom constant +// (m_x, m_y) is the current position of the mouse +//post: the image has been zoomed in by a factor of zconst +// returns 1 when zoom not possible due to image constraints, +// zoom at maximum or minimum image dimensions, or possible error +int BgImCanvas::Zoom(int zconst, int m_x, int m_y) +{ + //must have bitmap to zoom + if(hasbitmap) + { + //determine zooming action + int action; + if(zconst < zoom_level) + action = ZOOM_OUT; + else if(zconst > zoom_level) + action = ZOOM_IN; + + //check bounds + int width = pimage->GetWidth(), height = pimage->GetHeight(); + if(zconst < 0) + { + //take absolute value of zoom constant + int pos_zc = -zconst; + + //compute new width + if(width%pos_zc) + width = width/pos_zc+1; + else + width /= pos_zc; + + //compute new height + if(height%pos_zc) + height = height/pos_zc+1; + else + height /= -zconst; + + //make sure width and height are above minimum + //before continuing + if((width < MIN_WIDTH)||(height < MIN_HEIGHT)) + return 1; + } + else if (zconst > 0) + { + width *= zconst; + height *= zconst; + if((width > MAX_WIDTH)||(height > MAX_HEIGHT)) + return 1; + } + else + { + //zconst equals zero (ambiguous so exit) + return 1; + } + + //set zoom_level + zoom_level = zconst; + + if(zoom_level == 1) + { + delete pbitmap; +#if wxCHECK_VERSION(2, 3, 0) + pbitmap = new wxBitmap(pimage); +#else + pbitmap = new wxBitmap(pimage->ConvertToBitmap()); +#endif + if(zImg) delete zImg; + zImg = new unsigned char [3*height*width]; + memcpy(zImg, pimage->GetData(), 3*height*width); + } + else if(zoom_level > 1) + { + //zoom into image using zoom level + wxImage tempIm(width, height); + if(zImg) delete [] zImg; + zImg = new unsigned char [3*width*height]; + bgZoomIn(&zImg, pimage->GetData(), pimage->GetWidth(), pimage->GetHeight(), zoom_level, false); + memcpy(tempIm.GetData(), zImg, 3*width*height*sizeof(unsigned char)); + + //reset the bitmap using zoomed image + delete pbitmap; +#if wxCHECK_VERSION(2, 3, 0) + pbitmap = new wxBitmap(tempIm); +#else + pbitmap = new wxBitmap(tempIm.ConvertToBitmap()); +#endif + } + else if(zoom_level < -1) + { + //zoom out of image using zoom level + wxImage tempIm(width, height); + if(zImg) delete [] zImg; + zImg = new unsigned char [3*width*height]; + bgZoomOut(&zImg, pimage->GetData(), pimage->GetWidth(), pimage->GetHeight(), (-zoom_level), false); + memcpy(tempIm.GetData(), zImg, 3*width*height*sizeof(unsigned char)); + + //reset the bitmap using zoomed image + delete pbitmap; +#if wxCHECK_VERSION(2, 3, 0) + pbitmap = new wxBitmap(tempIm); +#else + pbitmap = new wxBitmap(tempIm.ConvertToBitmap()); +#endif + } + + //if a bitmap is not to be shown, clear (make white) the + //zoomed image + if(!showbitmap_) + memset(zImg, 255, 3*width*height*sizeof(unsigned char)); + + //add point data to zoomed image + AddPoints(zImg, width); + + //re-display image + Refresh(); + + //set scroll bars according to current mouse position and zooming action + AdjustScroll(m_x, m_y, action); + + //return 1 when maximum or minimum image dimension has occured + if((width == MAX_WIDTH)||(width == MIN_WIDTH)||(height == MAX_HEIGHT)||(height == MIN_HEIGHT)) + return 1; + + //return 1 when close to maximum or minimum image dimension... + /*********************************************************************/ + + if(zconst > 0) + { + width += pimage->GetWidth(); + height += pimage->GetHeight(); + if((width > MAX_WIDTH)||(height > MAX_HEIGHT)) + return 1; + } + else if(zconst < 0) + { + + //obtain width and height of original image + width = pimage->GetWidth(); + height = pimage->GetHeight(); + + //take absolute value of zoom constant + int pos_zc = -zconst; + + //compute new width + if(width%pos_zc) + width = width/pos_zc+1; + else + width /= pos_zc; + + //compute new height + if(height%pos_zc) + height = height/pos_zc+1; + else + height /= -zconst; + width = (pimage->GetWidth()); + + //check image bounds... + if((width < MIN_WIDTH)||(height < MIN_HEIGHT)) + return 1; + } + + /*********************************************************************/ + } + + //done. + return 0; + +} + +//allows one to zoom into the image stored by the image canvas +//pre : (m_x, m_y) is the current mouse position +//post: the image has been zoomed in by a factor of zoom_level+1 +// 1 is returned when max zoom level is reached +int BgImCanvas::ZoomIn(int m_x, int m_y) +{ + //must have bitmap to zoom into + if(hasbitmap) + { + //make sure zoom level is not at maximum before proceeding - + //max_zoom_level has value 0 when unspecified + if((max_zoom_level)&&(zoom_level == max_zoom_level)) + { + wxWindow *parent = child_frame_->GetParent(); + ((BgMdiFrame *) parent)->UpdateZoomControl((wxMDIChildFrame *) child_frame_, true, false); + return 1; + } + + //zoom image + int zconst = zoom_level + 1; + if(zconst == -1) zconst = 1; + int maxZoom = Zoom(zconst, m_x, m_y); + + //take into account maximum zoom level + maxZoom = (maxZoom || ((max_zoom_level)&&(zoom_level == max_zoom_level))); + + //set title of child frame + wxWindow *parent = child_frame_->GetParent(); + ((BgMdiFrame *) parent)->SetChildTitle((wxMDIChildFrame *) child_frame_, zoom_level, maxZoom, false); + + //update zoom control of child frame + ((BgMdiFrame *) parent)->UpdateZoomControl((wxMDIChildFrame *) child_frame_, maxZoom, false); + + //indicate if max zoom has occured + return maxZoom; + } + + //done. + return 0; +} + +//allows one to zoom out of the image stored by the image canvas +//pre : (m_x, m_y) is the current mouse position +//post: the image has been zoomed out by a factor of zoom_level-1 +// returns 1 if minimum zoom has occured +int BgImCanvas::ZoomOut(int m_x, int m_y) +{ + //must have bitmap to zoom into + if(hasbitmap) + { + //make sure zoom level is not at minimum before proceeding - + //min_zoom_level has value 0 when unspecified + if((min_zoom_level)&&(zoom_level == min_zoom_level)) + { + wxWindow *parent = child_frame_->GetParent(); + ((BgMdiFrame *) parent)->UpdateZoomControl((wxMDIChildFrame *) child_frame_, false, true); + return 1; + } + + //zoom image + int zconst = zoom_level - 1; + if(zconst == 0) zconst = -2; + int minZoom = Zoom(zconst, m_x, m_y); + + //take into account mininimum zoom level; + minZoom = (int)(minZoom ||((min_zoom_level)&&(zoom_level == min_zoom_level))); + + //set title of child frame + wxWindow *parent = child_frame_->GetParent(); + ((BgMdiFrame *) parent)->SetChildTitle((wxMDIChildFrame *) child_frame_, zoom_level, false, minZoom); + + //update zoom control of child frame + ((BgMdiFrame *) parent)->UpdateZoomControl((wxMDIChildFrame *) child_frame_, false, minZoom); + + //indicate if min zoom has occured + return minZoom; + } + + //done. + return 0; +} + +//sets max zoom level +void BgImCanvas::SetMaxZoomLevel(int mzl) +{ + max_zoom_level = mzl; +} + +//sets min zoom level +void BgImCanvas::SetMinZoomLevel(int mzl) +{ + min_zoom_level = mzl; +} + + +#define WIN_PERC 16 + +void BgImCanvas::DefineZoomBox(int l_x, int h_x, int l_y, int h_y) +{ + + //obtain image height and width + int iWidth = pimage->GetWidth(), iHeight = pimage->GetHeight(); + + //calculate box height and width + static int bWidth = h_x-l_x+1, bHeight = h_y-l_y+1; + + //allocate/deallocate memory + if((bWidth != h_x-l_x+1)||(!buf)) + { + bWidth = h_x-l_x+1; + bHeight = h_y-l_y+1; + if(buf) delete buf; + buf = new unsigned char [3*bWidth*bHeight]; + } + + //get point pen colour + unsigned char r, g, b; + if(point_colour) + { + r = point_colour->Red(); + g = point_colour->Green(); + b = point_colour->Blue(); + } + + //crop image data and store it into buf (if the bitmap is being displayed...) + unsigned char *imData = pimage->GetData(); + int bx, by, ix, iy, idp, bdp; + if(showbitmap_) + { + for(by=0; by<bHeight; by++) + { + for(bx=0; bx<bWidth; bx++) + { + ix = bx + l_x; + iy = by + l_y; + idp = 3*(iy*iWidth + ix); + bdp = 3*(by*bWidth + bx); + buf[bdp ] = imData[idp ]; + buf[bdp+1] = imData[idp+1]; + buf[bdp+2] = imData[idp+2]; + + //account for point sets using point map + if(point_map[idp/3]) + { + buf[bdp] = r; + buf[bdp+1] = g; + buf[bdp+2] = b; + } + } + } + } + //create blank (white) image and plot point set onto it + //prior to zoom + else + { + memset(buf, 255, 3*bWidth*bHeight*sizeof(unsigned char)); + for(by=0; by<bHeight; by++) + { + for(bx=0; bx<bWidth; bx++) + { + ix = bx + l_x; + iy = by + l_y; + idp = 3*(iy*iWidth + ix); + bdp = 3*(by*bWidth + bx); + + //account for point sets using point map + if(point_map[idp/3]) + { + buf[bdp] = r; + buf[bdp+1] = g; + buf[bdp+2] = b; + } + } + } + } + + //zoom the data in buf... + + //set zoom window size and allocate memory + static int zWidth = bWidth*zoom_level*2; + static int zHeight = bHeight*zoom_level*2; + if((zWidth != bWidth*zoom_level*2)||(!zoombox)) + { + zWidth = bWidth*zoom_level*2; + zHeight = bHeight*zoom_level*2; + if(zoombox) delete zoombox; + zoombox = new wxImage(zWidth, zHeight); + + } + + //create a zoom box image using buf + unsigned char *zbData = zoombox->GetData(); + bgZoomIn(&zbData, buf, bWidth, bHeight, zoom_level*2, false); + + //done. + return; +} + +void BgImCanvas::DefineRefreshBox(void) +{ + + //obtain image height and width + int iWidth = pimage->GetWidth()*zoom_level, iHeight = pimage->GetHeight()*zoom_level; + + //calculate box height and width + static int bWidth = zoombox->GetWidth(), bHeight = zoombox->GetHeight(); + + //allocate/de-allocate memory for refresh box + if((bWidth != zoombox->GetWidth())||(!refresh_box)) + { + bWidth = zoombox->GetWidth(); + bHeight = zoombox->GetHeight(); + if(refresh_box) delete [] refresh_box; + refresh_box = new wxImage(bWidth, bHeight); + } + unsigned char *rBuf = refresh_box->GetData(); + + //get point pen colour + unsigned char r, g, b; + if(point_colour) + { + r = point_colour->Red(); + g = point_colour->Green(); + b = point_colour->Blue(); + } + + //define refresh box... + + //crop image data and store it into rBuf... + unsigned char *imData = pimage->GetData(); + int bx, by, ix, iy, bdp, idp; + for(by=0; by<bHeight; by++) + { + for(bx=0; bx<bWidth; bx++) + { + ix = bx + cx; + iy = by + cy; + idp = 3*(iy*iWidth + ix); + bdp = 3*(by*bWidth + bx); + rBuf[bdp ] = zImg[idp ]; + rBuf[bdp+1] = zImg[idp+1]; + rBuf[bdp+2] = zImg[idp+2]; + } + } + + //done. + return; +} + +//creates point map used by zoom and refresh windows +void BgImCanvas::CreatePointMap(int w, int h) +{ + + //initialze point map + if(point_map) delete [] point_map; + point_map = new bool [w*h]; + memset(point_map, 0, w*h*sizeof(bool)); + + //if point sets already exist then add the, + if (nPointSets_ > 0) + { + //adjust point pen colour to be that of the last + //point set added + if(point_colour) delete point_colour; + point_colour = new wxColour(pointSet_[nPointSets_-1]->pen_.GetColour()); + + int nt, *tx, *ty, i, j; + for (i=0; i<nPointSets_; i++) + { + nt = pointSet_[i]->n_; + tx = pointSet_[i]->x_; + ty = pointSet_[i]->y_; + if(pointSet_[i]->type_ == 1) // point + { + for(j=0; j<nt; j++) + point_map[ty[j]*w+tx[j]] = true; + } + } + } +} + +//adds points from point sets onto specified image +void BgImCanvas::AddPoints(unsigned char *im, int width) +{ + //if point sets have been defined add point data to image + if(nPointSets_ > 0) + { + unsigned char r, g, b; + wxColour pen_colour; + int nt, *tx, *ty, i, j, x, y, dp, offset; + for(i=0; i < nPointSets_; i++) + { + if(pointSet_[i]->type_ == 1) //point + { + //get pen colour + pen_colour = pointSet_[i]->pen_.GetColour(); + r = pen_colour.Red(); + g = pen_colour.Green(); + b = pen_colour.Blue(); + + //place points + nt = pointSet_[i]->n_; + tx = pointSet_[i]->x_; + ty = pointSet_[i]->y_; + for(j=0; j<nt; j++) + { + dp = 3*(ty[j]*width+tx[j])*zoom_level; + for(y=0; y<zoom_level; y++) + { + for(x=0; x<zoom_level; x++) + { + offset = 3*(y*width+x); + im[dp+offset ] = r; + im[dp+offset+1] = g; + im[dp+offset+2] = b; + } + } + } + } + } + } +} + +//displays zoom window at cursor position +void BgImCanvas::DisplayZoomWindow(int m_x, int m_y) +{ + + //set mouse position... + m_x_ = m_x; + m_y_ = m_y; + + //compute width and height of window.... + + /***********************************************************/ + + //obtain image height and width + int w = pimage->GetWidth(), h = pimage->GetHeight(); + + //take percentage of height and width to compute + //box half-width and half-height + int hw, hh; + int wp = WIN_PERC; + if(w%wp) + hw = w/wp + 1; + else + hw = w/wp; + + if(h%wp) + hh = h/wp + 1; + else + hh = h/wp; + + /***********************************************************/ + + //normalize mouse coordinates to image coordinate frame + + /***********************************************************/ + + if(zoom_level > 0) + { + m_x = (m_x + GetScrollPos(wxHORIZONTAL))/zoom_level; + m_y = (m_y + GetScrollPos(wxVERTICAL))/zoom_level; + } + else if(zoom_level < 0) + { + m_x = (m_x + GetScrollPos(wxHORIZONTAL))*(-zoom_level); + m_y = (m_y + GetScrollPos(wxVERTICAL))*(-zoom_level); + } + + /***********************************************************/ + + //make sure x_m and y_m are with bounds before proceeding... + + /***********************************************************/ + + if((m_x < 0)||(m_x >= w)||(m_y < 0)||(m_y >= h)) + return; + + /***********************************************************/ + + //compute zoom window bounds... + + /***********************************************************/ + + //define window bounds based on current mouse position + int low_x, hi_x, low_y, hi_y; + if((low_x = m_x - hw) < 0) low_x = 0; + if((hi_x = m_x + hw) >= w) hi_x = w-1; + if((low_y = m_y - hh) < 0) low_y = 0; + if((hi_y = m_y + hh) >= h) hi_y = h-1; + + //make window larger according to current mouse position + if(m_x <= hw) hi_x += hw-m_x; + if((w-m_x-1) <= hw) low_x -= hw-(w-m_x-1); + if(m_y <= hh) hi_y += hh-m_y; + if((h-m_y-1) <= hh) low_y -= hh-(h-m_y-1); + + /***********************************************************/ + + //define zoom box... + + /***********************************************************/ + + DefineZoomBox(low_x, hi_x, low_y, hi_y); + + /***********************************************************/ + + //display zoomed image over current mouse position... + + /***********************************************************/ + + Refresh(false); + + /***********************************************************/ + + //done. + return; + +} + +/* +void BgImCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event)) +{ +} +*/ +void BgImCanvas::FillCurveClick() +{ + int i; + for (i=0; i<ccx_*ccy_; i++) + curveClick_[i] = 0; + + for (i=0; i<nCurveSets_; i++) + curveSet_[i]->DrawYourself(curveClick_, i+1); + + Refresh(); +// write_pgm_image("curveclick.pgm", curveClick_, 256, 256, "", 4); +} + +/* +void BgImCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) +{ + wxClientDC dc(this); + PrepareDC(dc); + if(hasbitmap==TRUE) + { + dc.DrawBitmap(*pbitmap,0,0); + } + else + { + dc.Clear(); + } +} +*/ + +void BgImCanvas::MyDrawEllipticArc(wxDC& dc, int x, int y, int w, int h, int sa, int ea) +{ + double xc, yc, rx, ry; + rx = w/2; + ry = h/2; + xc = x+rx; + yc = y+ry; + int r, c; + int low_r = y_offset_; + int hig_r = ccy_+y_offset_; + int low_c = x_offset_; + int hig_c = ccx_+x_offset_; + +// if (rx > ry) +// { + // x scan + for (c = (int) xc; c<=(int) (xc+rx); c++) + { + if (c>=low_c && c<hig_c) + { + r = bgRound(yc-ry*sqrt(1-(c-xc)*(c-xc)/(rx*rx))); + if (r>=low_r && r<hig_r) + { + dc.DrawPoint(c,r); + // +/- 1 + if ((r+1)<hig_r) dc.DrawPoint(c,r+1); + if ((r-1)>=low_r) dc.DrawPoint(c,r-1);; + } + } + } +// } +// else +// { + // y scan + for (r = (int)(yc-ry); r<=(int) yc; r++) + { + if (r>=low_r && r<hig_r) + { + c = bgRound(xc+rx*sqrt(1-(r-yc)*(r-yc)/(ry*ry))); + if (c>=low_c && c<hig_c) + { + dc.DrawPoint(c,r); + // +/- 1 + if ((c+1)<hig_c) dc.DrawPoint(c+1,r); + if ((c-1)>=low_c) dc.DrawPoint(c-1,r);; + } + } + } +// } +} + +void BgImCanvas::OnMouseRightDown(wxMouseEvent& event) +{ + wxClientDC dc(this); + PrepareDC(dc); + wxPoint pt(event.GetLogicalPosition(dc)); + static int x; + static int y; + x = pt.x-x_offset_; + y = pt.y-y_offset_; + if (x>=0 && x<ccx_ && y>=0 && y<ccy_) + { + if (curveClick_[x+y*ccx_]>0) + { + lmEventCurve_ = curveClick_[x+y*ccx_] - 1; + if (curveSet_[lmEventCurve_]->type_ == FC_CUSTOM) + { + // determine if close to a node + int *tempx, *tempy, tempn; + double mindist, crtdist; + int i, minnode; + tempx = curveSet_[lmEventCurve_]->x_; + tempy = curveSet_[lmEventCurve_]->y_; + tempn = curveSet_[lmEventCurve_]->n_; + mindist = sqrt((x-tempx[0])*(x-tempx[0])+(y-tempy[0])*(y-tempy[0])); + minnode = 0; + for (i=1; i<tempn; i++) + { + crtdist = sqrt((x-tempx[i])*(x-tempx[i])+(y-tempy[i])*(y-tempy[i])); + if (crtdist < mindist) + { + mindist = crtdist; + minnode = i; + } + } + if (mindist <= 3) + { + // delete node option + lmEventNode_ = minnode; + localMenu_->Enable(BG_IMC_ADDNODE,FALSE); + localMenu_->Enable(BG_IMC_DELETENODE,TRUE); + } else + { + // add node option + localMenu_->Enable(BG_IMC_ADDNODE,TRUE); + localMenu_->Enable(BG_IMC_DELETENODE,FALSE); + } + } + else + { + localMenu_->Enable(BG_IMC_ADDNODE,FALSE); + localMenu_->Enable(BG_IMC_DELETENODE,FALSE); + } + lmEventX_ = x;//+x_offset_; + lmEventY_ = y;//+y_offset_; + PopupMenu(localMenu_, x+x_offset_, y+y_offset_); + } + } +} + +/* +//updates hover menu during scroll event +void BgImCanvas::OnScroll(wxScrollWinEvent& event) +{ + +} +*/ + +//attemtps to adjust scroll position of window according +//to current mouse position +void BgImCanvas::AdjustScroll(int x, int y, int action) +{ + if(zoom_level > 1) + { + + //get window width and height + int winWidth, winHeight; + GetSize(&winWidth, &winHeight); + + //get window vertical and horzontal scroll position + //and offset current mouse position to obtain mouse + //position relative to the image + x = x + GetScrollPos(wxHORIZONTAL); + y = y + GetScrollPos(wxVERTICAL); + + //re-location mouse position relative to new image width + //and height + if(action == ZOOM_IN) + { + x = zoom_level*(x/(zoom_level-1)); + y = zoom_level*(y/(zoom_level-1)); + } + else if(action == ZOOM_OUT) + { + x = zoom_level*(x/(zoom_level+1)); + y = zoom_level*(y/(zoom_level+1)); + } + + //resize scroll + int width = (pimage->GetHeight())*zoom_level; + int height = (pimage->GetWidth())*zoom_level; + SetScrollbars(1, 1, width, height); + + //set scroll position according to x and y + int offset_x = x/2; + int offset_y = y/2; + SetScrollPos(wxHORIZONTAL, offset_x, true); + SetScrollPos(wxVERTICAL, offset_y, true); + + //refresh window contents + Scroll(offset_x, offset_y); + } +} + +void BgImCanvas::OnEvent(wxMouseEvent& event) +{ +/* + wxClientDC dc(this); + PrepareDC(dc); + + wxPoint pt(event.GetLogicalPosition(dc)); + + if (g_xpos > -1 && g_ypos > -1 && event.Dragging()) + { + dc.SetPen(*wxBLACK_PEN); + dc.DrawLine(g_xpos, g_ypos, pt.x, pt.y); + + m_dirty = TRUE; + } + + g_xpos = pt.x; + g_ypos = pt.y; + */ + + + //store mouse pointer location... + m_x_ = event.m_x; + m_y_ = event.m_y; + + //keep track of menu window (hide/show)... + static bool hideWindow = true; + if((m_x_ >= menuXl_)&&(m_y_ >= menuYl_)&&(m_x_ <= menuXu_)&&(m_y_ <= menuYu_)) + hideWindow = false; + else if(!event.Leaving()) + hideWindow = true; + + wxClientDC dc(this); + PrepareDC(dc); + wxPoint pt(event.GetLogicalPosition(dc)); + static int x; + static int y; + static int curvedrag; + x = pt.x-x_offset_; + y = pt.y-y_offset_; +// x = event.GetX(); +// y = event.GetY(); + + if (isDragging_ == 0 && event.LeftDown()) + { + // check if over any line + if (x>=0 && x<ccx_ && y>=0 && y<ccy_) + { + if (curveClick_[x+y*ccx_]>0) + { + isDragging_ = 1; + curvedrag = curveClick_[x+y*ccx_]-1; + dragCurve_.SetCurve(curveSet_[curveClick_[x+y*ccx_]-1]); + dragCurve_.pen_.SetColour(wxColour(128,128,128)); + dragCurve_.StartDragging(x, y); + Refresh(); + } + } + } + else if (isDragging_ == 1 && event.Dragging()) + { + // modify curve to drag + dragCurve_.DragTo(x, y); + Refresh(false); + } + else if (isDragging_ == 1)// && event.LeftUp()) + { + isDragging_ = 0; + dragCurve_.EndDragging(x, y); + curveSet_[curvedrag]->SetCurve(&dragCurve_); + FillCurveClick(); + mouseModif_ = 1; + AddPendingEvent(wxCommandEvent(BG_EVENT_UPDATE, BG_EVENT_UPDATE_ID)); + Refresh(); + } + else if (isDragging_ == 0 && event.Moving()) + { + // check if over any line + if (x>=0 && x<ccx_ && y>=0 && y<ccy_) + { + if (curveClick_[x+y*ccx_]>0 && crossCursor_ == 0) + { + crossCursor_ = 1; + SetCursor(*wxCROSS_CURSOR); + } + else if (crossCursor_ == 1) + { + SetCursor(*wxSTANDARD_CURSOR); + crossCursor_ = 0; + } + } + } + + //if zoom is enabled, set the cursor to the zoom icon + //otherwise leave it as default + if(event.Entering()) + { + //when parent is not the active child frame, set the cursor + //to wxCURSOR_ARROW + bool current_child = false; + wxMDIParentFrame *parent = (wxMDIParentFrame *)(child_frame_->GetParent()); + wxMDIChildFrame *activeChild = parent->GetActiveChild(); + if(activeChild == (wxMDIChildFrame *) child_frame_) + current_child = true; + + if((zoom_out || zoom_in)&&(current_child)) + SetCursor(wxCURSOR_MAGNIFIER); + else if((zoom_window)&&(current_child)) + SetCursor(wxCURSOR_CROSS); + else + SetCursor(wxCURSOR_ARROW); + + //indiciate that the window has acquired focus + has_focus = true; + + //show the menu window + if((menuWindow)&&(popup)) + menuWindow->Show(TRUE); + } + + //indicate that the window has lost focus + if(event.Leaving()) + { + //indicate that the window has lost focus + has_focus = false; + + //indicate that the mouse pointer is leaving + //this window + leaving = true; + + //refresh canvas upon using a zoom window + if(zoom_window) + Refresh(false); + + //hide the menu window + if((hideWindow)&&(popup)&&(menuWindow)) + menuWindow->Show(FALSE); + + } + + //check if the left mouse button has been clicked and zoom is activated + //if so zoom the image + if(event.LeftDown()&&zoom_in) + ZoomIn(m_x_, m_y_); + + if((event.LeftDown())&&zoom_out) + ZoomOut(m_x_, m_y_); + + if(zoom_window) + DisplayZoomWindow(m_x_, m_y_); + +} + +void BgImCanvas::AddHoverWindow(wxWindow* hoverWindow, int pp) +{ + popup = pp; + menuWindow = hoverWindow; + if(popup) menuWindow->Show(FALSE); + else menuWindow->Show(TRUE); + int width, height; + menuWindow->GetSize(&width, &height); + menuXl_ = HOVER_MENU_X - HOVER_MENU_BOUND; + menuYl_ = HOVER_MENU_Y - HOVER_MENU_BOUND; + menuXu_ = menuXl_ + width + HOVER_MENU_BOUND; + menuYu_ = menuXu_ + width + HOVER_MENU_BOUND; + menuWindow->SetSize(HOVER_MENU_X, HOVER_MENU_Y, width, height); +} + +void BgImCanvas::SetHoverWindowLocation(int x, int y) +{ + int width, height; + menuWindow->GetSize(&width, &height); + if((x < 0)||(x >= width)||(y < 0)||(y >= height)) return; + menuWindow->SetSize(x, y, width, height); +} + +// --------------------------------------------------------------------------- +// BgMdiEdgeChild +// --------------------------------------------------------------------------- + +BgMdiEdgeChild::BgMdiEdgeChild(wxMDIParentFrame *parent, const wxString& title, + const wxPoint& pos, const wxSize& size, + const long style) + : wxMDIChildFrame(parent, BG_EDGE_WINDOW, title, pos, size, style) +{ + + //set window number + window_number_ = gs_nFrames; + + //assume image is not yet loaded into segmentation window + filename_ = NULL; + + bpsize_ = 160; + + imagePlotSplitter_ = new wxSplitterWindow(this, -1, wxPoint(bpsize_, 0), wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); + plotSplitter_ = new wxSplitterWindow(imagePlotSplitter_, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); + origEdgeImage_ = new BgImCanvas(this, imagePlotSplitter_, wxDefaultPosition, wxDefaultSize); + origEdgeImage_->SetScrollbars(20, 20, 50, 50); + plotNmxImage_ = new BgImCanvas(this, plotSplitter_, wxDefaultPosition, wxDefaultSize); + + plotNmxImage_->SetScrollbars(20, 20, 50, 50); + plotTotImage_ = new BgImCanvas(this, plotSplitter_, wxDefaultPosition, wxDefaultSize); + + plotTotImage_->SetScrollbars(20, 20, 50, 50); + + g_children.Append(this); + //imagePlotSplitter_->SetClientSize(GetClientSize()); + imagePlotSplitter_->SplitVertically(origEdgeImage_, plotSplitter_,256); + plotSplitter_->SplitHorizontally(plotNmxImage_, plotTotImage_,256); + + // panel stuff + buttonPanel_ = new wxPanel(this, -1, wxPoint(0, 0)); + edButton_ = new wxButton(buttonPanel_, BG_EDGE_DETECT, "Edge Detect", wxPoint(40,10)); + cpButton_ = new wxButton(buttonPanel_, BG_CHANGE_PARAM_EDGE, "Change...", wxPoint(40,155)); + + wxStaticBox* viewSB = new wxStaticBox(buttonPanel_, -1, "View", wxPoint(35, 45), wxSize(85, 65)); + viewOrigCheck_ = new wxCheckBox(buttonPanel_, BG_EDGE_CVIEW_ORIG, "Image", wxPoint(45,65));//, wxPoint(10,85)); + viewEdgeCheck_ = new wxCheckBox(buttonPanel_, BG_EDGE_CVIEW_EDGE, "Edges", wxPoint(45,85));//, wxPoint(10,105)); + + int deltal = 45; + // put the parameters + wxStaticText* stParam = new wxStaticText(buttonPanel_, -1, "PARAMETERS:", wxPoint(C_PARAMX-5, 105 + C_PARAMY)); + + txtKernelSize_ = new wxStaticText(buttonPanel_, -1, "Grad Win.", wxPoint(C_PARAMX-5,deltal+125+C_PARAMY+0*C_PARAMDY)); + valKernelSize_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX+35,deltal+125+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX-20,C_PARAMSY)); + + txtMinPt_ = new wxStaticText(buttonPanel_, -1, "Min. length", wxPoint(C_PARAMX-5,deltal+125+C_PARAMY+1*C_PARAMDY)); + valMinPt_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX+35,deltal+125+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX-20,C_PARAMSY)); + + wxStaticBox* nmxSB = new wxStaticBox(buttonPanel_, -1, "Nonmaxima supp.", wxPoint(5, deltal+205+0), wxSize(140,4*C_PARAMDY-5)); + txtNmxType_ = new wxStaticText(buttonPanel_, -1, "Type", wxPoint(C_PARAMX, deltal+205+C_PARAMY+0*C_PARAMDY)); + valNmxType_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+205+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + txtNmxR_ = new wxStaticText(buttonPanel_, -1, "Rank", wxPoint(C_PARAMX,deltal+205+C_PARAMY+1*C_PARAMDY)); + valNmxR_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+205+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + txtNmxC_ = new wxStaticText(buttonPanel_, -1, "Conf", wxPoint(C_PARAMX,deltal+205+C_PARAMY+2*C_PARAMDY)); + valNmxC_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+205+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + + wxStaticBox* hhSB = new wxStaticBox(buttonPanel_, -1, "Hyst. High Tr.", wxPoint(5, deltal+325+0), wxSize(140,4*C_PARAMDY-5)); + txtHHType_ = new wxStaticText(buttonPanel_, -1, "Type", wxPoint(C_PARAMX,deltal+325+C_PARAMY+0*C_PARAMDY)); + txtHHR_ = new wxStaticText(buttonPanel_, -1, "Rank", wxPoint(C_PARAMX,deltal+325+C_PARAMY+1*C_PARAMDY)); + txtHHC_ = new wxStaticText(buttonPanel_, -1, "Conf", wxPoint(C_PARAMX,deltal+325+C_PARAMY+2*C_PARAMDY)); + valHHType_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+325+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + valHHR_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+325+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + valHHC_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+325+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + + wxStaticBox* hlSB = new wxStaticBox(buttonPanel_, -1, "Hyst. Low Tr.", wxPoint(5, deltal+445+0), wxSize(140, 4*C_PARAMDY-5)); + txtHLType_ = new wxStaticText(buttonPanel_, -1, "Type", wxPoint(C_PARAMX,deltal+445+C_PARAMY+0*C_PARAMDY)); + txtHLR_ = new wxStaticText(buttonPanel_, -1, "Rank", wxPoint(C_PARAMX,deltal+445+C_PARAMY+1*C_PARAMDY)); + txtHLC_ = new wxStaticText(buttonPanel_, -1, "Conf", wxPoint(C_PARAMX,deltal+445+C_PARAMY+2*C_PARAMDY)); + valHLType_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+445+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + valHLR_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+445+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + valHLC_ = new wxStaticText(buttonPanel_, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,deltal+445+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + + + //set lower bound zoom limit on display image + //to the size of the original image + origEdgeImage_->SetMinZoomLevel(1); + + // set default parameters for edge detection + rankNmx_ = RANK_NMX; + confNmx_ = CONF_NMX; + rankH_ = RANK_H; + confH_ = CONF_H; + rankL_ = RANK_L; + confL_ = CONF_L; + nMin_ = NMIN; + nmxType_ = FC_ELLIPSE; + hystHighType_ = FC_SQUARE_BOX; + hystLowType_ = FC_ELLIPSE; + kernelSize_ = KERNEL_SIZE; + + //set params + SetParametersNum(); + SetParametersStr(); + + // also default custom parameters + nCustH_ = 3; + nCustL_ = 3; + custHx_[0] = 0; + custHx_[1] = 0.7; + custHx_[2] = 1; + custHy_[0] = 1; + custHy_[1] = 0.7; + custHy_[2] = 0; + + custLx_[0] = 0; + custLx_[1] = 0.5; + custLx_[2] = 0.7; + custLy_[0] = 0.7; + custLy_[1] = 0.5; + custLy_[2] = 0; + + // set the values in the boxes + +// cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); + cbgEdgeDetect_ = 0; + cbgImage_ = new BgImage(); + cbgEdgeList_ = 0; + hasEdge_ = 0; + hasImage_ = 0; + + int w, h; + GetClientSize(&w, &h); + buttonPanel_->SetSize(0, 0, bpsize_, h); + imagePlotSplitter_->SetSize(bpsize_, 0, w-bpsize_, h); + imagePlotSplitter_->SetSashPosition(bpsize_+(w-bpsize_)/2,TRUE); + plotSplitter_->SetSashPosition(h/2,TRUE); + rightsize_ = (w-bpsize_)/2; + viewOrigCheck_->SetValue(TRUE); + viewEdgeCheck_->SetValue(TRUE); + + plotTotImage_->AddCurveSet(&nmxCurve_); + plotNmxImage_->AddCurveSet(&highCurve_); + plotNmxImage_->AddCurveSet(&lowCurve_); + lowCurve_.pen_.SetColour(255,0,0); + + //add margin to plots + plotNmxImage_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); + plotTotImage_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); + + //add title to each individual plot + BgText bgText(1, " Diagram after Non-Maxima Supression", *wxSWISS_FONT, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2-10); + + plotNmxImage_->AddText(&bgText); + bgText.SetText(" Diagram before Non-Maxima Supression"); + plotTotImage_->AddText(&bgText); + + //add x and y axis + plotNmxImage_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); + plotNmxImage_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); + plotTotImage_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); + plotTotImage_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); + + //label x and y axis + bgText.SetText("Rank ( )"); + plotNmxImage_->LabelHorizontalAxis(&bgText); + plotTotImage_->LabelHorizontalAxis(&bgText); + bgText.SetText("Confidence ( )"); + plotNmxImage_->LabelVerticalAxis(&bgText); + plotTotImage_->LabelVerticalAxis(&bgText); + + //place greek symbols + wxBitmap ro("ro", wxBITMAP_TYPE_RESOURCE), eta("eta", wxBITMAP_TYPE_RESOURCE); + BgBitmap ro_bmp(&ro, 1, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2 - 3); + BgBitmap eta_bmp(&eta, 2, RANK_CONF_MARGINX, RANK_CONF_MARGINY/2 - 3); + plotNmxImage_->AddBitmap(&ro_bmp); + plotNmxImage_->AddBitmap(&eta_bmp); + plotTotImage_->AddBitmap(&ro_bmp); + plotTotImage_->AddBitmap(&eta_bmp); + ro_bmp.SetPlotLocation(RANK_CONF_MARGINX+137,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY+35); + ro_bmp.SetId(3); + plotNmxImage_->AddBitmap(&ro_bmp); + plotTotImage_->AddBitmap(&ro_bmp); + wxBitmap rotated_eta("rotated_eta", wxBITMAP_TYPE_RESOURCE); + BgBitmap rotated_eta_bmp(&rotated_eta, 4, RANK_CONF_MARGINX-55,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY-162); + plotNmxImage_->AddBitmap(&rotated_eta_bmp); + plotTotImage_->AddBitmap(&rotated_eta_bmp); + + //indicate that the edge window is now open + window_open = true; + + //disable edge detection button + edButton_->Enable(false); + + //get parent tool bar and update it + toolbar = parent->GetToolBar(); + UpdateToolBar(); + + //set max/min zoom + maxZoom_ = 0; + minZoom_ = 1; + +} + +/* +BgMdiEdgeChild::BgMdiEdgeChild(wxMDIParentFrame *parent, const wxString& title, + const wxPoint& pos, const wxSize& size, + const long style) + : wxMDIChildFrame(parent, BG_EDGE_WINDOW, title, pos, size, style) +{ + + //set window number + window_number_ = gs_nFrames; + + //assume image is not yet loaded into segmentation window + filename_ = NULL; + + bpsize_ = 100; + imagePlotSplitter_ = new wxSplitterWindow(this, -1,wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); + plotSplitter_ = new wxSplitterWindow(imagePlotSplitter_, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); + origEdgeImage_ = new BgImCanvas(this, imagePlotSplitter_, wxDefaultPosition, wxDefaultSize); + origEdgeImage_->SetScrollbars(20, 20, 50, 50); + plotNmxImage_ = new BgImCanvas(this, plotSplitter_, wxDefaultPosition, wxDefaultSize); + + plotNmxImage_->SetScrollbars(20, 20, 50, 50); + plotTotImage_ = new BgImCanvas(this, plotSplitter_, wxDefaultPosition, wxDefaultSize); + + plotTotImage_->SetScrollbars(20, 20, 50, 50); + + g_children.Append(this); + //imagePlotSplitter_->SetClientSize(GetClientSize()); + imagePlotSplitter_->SplitVertically(origEdgeImage_, plotSplitter_,256); + plotSplitter_->SplitHorizontally(plotNmxImage_, plotTotImage_,256); + // panel stuff + buttonPanel_ = new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize); + edButton_ = new wxButton(buttonPanel_, BG_EDGE_DETECT, "Edge Detect", wxPoint(10,10)); + cpButton_ = new wxButton(buttonPanel_, BG_CHANGE_PARAM_EDGE, "Parameters...", wxPoint(10,45)); + viewOrigCheck_ = new wxCheckBox(buttonPanel_, BG_EDGE_CVIEW_ORIG, "View Image", wxPoint(10,85)); + viewEdgeCheck_ = new wxCheckBox(buttonPanel_, BG_EDGE_CVIEW_EDGE, "View Edges", wxPoint(10,105)); + + //set lower bound zoom limit on display image + //to the size of the original image + origEdgeImage_->SetMinZoomLevel(1); + + // set default parameters for edge detection + rankNmx_ = RANK_NMX; + confNmx_ = CONF_NMX; + rankH_ = RANK_H; + confH_ = CONF_H; + rankL_ = RANK_L; + confL_ = CONF_L; + nMin_ = NMIN; + nmxType_ = FC_ELLIPSE; + hystHighType_ = FC_SQUARE_BOX; + hystLowType_ = FC_ELLIPSE; + kernelSize_ = KERNEL_SIZE; + + // also default custom parameters + nCustH_ = 3; + nCustL_ = 3; + custHx_[0] = 0; + custHx_[1] = 0.7; + custHx_[2] = 1; + custHy_[0] = 1; + custHy_[1] = 0.7; + custHy_[2] = 0; + + custLx_[0] = 0; + custLx_[1] = 0.5; + custLx_[2] = 0.7; + custLy_[0] = 0.7; + custLy_[1] = 0.5; + custLy_[2] = 0; + + + +// cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); + cbgEdgeDetect_ = 0; + cbgImage_ = new BgImage(); + cbgEdgeList_ = 0; + hasEdge_ = 0; + hasImage_ = 0; + + int w, h; + GetClientSize(&w, &h); + buttonPanel_->SetSize(w-bpsize_, 0, bpsize_, h); + imagePlotSplitter_->SetSize(0, 0, w-bpsize_, h); + imagePlotSplitter_->SetSashPosition((w-bpsize_)/2,TRUE); + plotSplitter_->SetSashPosition(h/2,TRUE); + rightsize_ = (w-bpsize_)/2; + viewOrigCheck_->SetValue(TRUE); + viewEdgeCheck_->SetValue(TRUE); + + plotTotImage_->AddCurveSet(&nmxCurve_); + plotNmxImage_->AddCurveSet(&highCurve_); + plotNmxImage_->AddCurveSet(&lowCurve_); + lowCurve_.pen_.SetColour(255,0,0); + + //add margin to plots + plotNmxImage_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); + plotTotImage_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); + + //add title to each individual plot + BgText bgText(1, " Diagram after Non-Maxima Supression", *wxSWISS_FONT, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2-10); + + plotNmxImage_->AddText(&bgText); + bgText.SetText(" Diagram before Non-Maxima Supression"); + plotTotImage_->AddText(&bgText); + + //add x and y axis + plotNmxImage_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); + plotNmxImage_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); + plotTotImage_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); + plotTotImage_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); + + //label x and y axis + bgText.SetText("Rank ( )"); + plotNmxImage_->LabelHorizontalAxis(&bgText); + plotTotImage_->LabelHorizontalAxis(&bgText); + bgText.SetText("Confidence ( )"); + plotNmxImage_->LabelVerticalAxis(&bgText); + plotTotImage_->LabelVerticalAxis(&bgText); + + //place greek symbols + wxBitmap ro("ro", wxBITMAP_TYPE_RESOURCE), eta("eta", wxBITMAP_TYPE_RESOURCE); + BgBitmap ro_bmp(&ro, 1, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2 - 3); + BgBitmap eta_bmp(&eta, 2, RANK_CONF_MARGINX, RANK_CONF_MARGINY/2 - 3); + plotNmxImage_->AddBitmap(&ro_bmp); + plotNmxImage_->AddBitmap(&eta_bmp); + plotTotImage_->AddBitmap(&ro_bmp); + plotTotImage_->AddBitmap(&eta_bmp); + ro_bmp.SetPlotLocation(RANK_CONF_MARGINX+137,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY+35); + ro_bmp.SetId(3); + plotNmxImage_->AddBitmap(&ro_bmp); + plotTotImage_->AddBitmap(&ro_bmp); + wxBitmap rotated_eta("rotated_eta", wxBITMAP_TYPE_RESOURCE); + BgBitmap rotated_eta_bmp(&rotated_eta, 4, RANK_CONF_MARGINX-55,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY-162); + plotNmxImage_->AddBitmap(&rotated_eta_bmp); + plotTotImage_->AddBitmap(&rotated_eta_bmp); + + //indicate that the edge window is now open + window_open = true; + + //disable edge detection button + edButton_->Enable(false); + + //get parent tool bar and update it + toolbar = parent->GetToolBar(); + UpdateToolBar(); + + //set max/min zoom + maxZoom_ = 0; + minZoom_ = 1; + +} +*/ + +BgMdiEdgeChild::~BgMdiEdgeChild() +{ + if(filename_) delete [] filename_; + + if (hasEdge_ == 1) + origEdgeImage_->RemovePointSet(&cbgPointSet_); + + if (cbgEdgeList_ != 0) + delete cbgEdgeList_; + delete cbgImage_; + if (cbgEdgeDetect_ != 0) + delete cbgEdgeDetect_; + + delete viewEdgeCheck_; + delete viewOrigCheck_; + delete cpButton_; + delete edButton_; + delete buttonPanel_; + + + + delete origEdgeImage_; + delete plotNmxImage_; + delete plotTotImage_; + + delete plotSplitter_; + delete imagePlotSplitter_; + g_children.DeleteObject(this); +} + +void BgMdiEdgeChild::OnUpdateNum(wxCommandEvent& WXUNUSED(event)) +{ + double tx[MAX_CUSTOM_NODES]; + double ty[MAX_CUSTOM_NODES]; + int ttype,i; + int npoints,modif=0; + if (plotNmxImage_->mouseModif_ == 1) + { + modif = 1; + // get new hyst params + highCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + hystHighType_ = ttype; + rankH_ = tx[0]; + confH_ = ty[0]; + } else + { + hystHighType_ = ttype; + for (i=0; i<npoints; i++) + { + custHx_[i] = tx[i]; + custHy_[i] = ty[i]; + } + nCustH_ = npoints; + } + lowCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + hystLowType_ = ttype; + rankL_ = tx[0]; + confL_ = ty[0]; + } else + { + hystLowType_ = ttype; + for (i=0; i<npoints; i++) + { + custLx_[i] = tx[i]; + custLy_[i] = ty[i]; + } + nCustL_ = npoints; + } + plotNmxImage_->mouseModif_ = 0; + } + if (plotTotImage_->mouseModif_ == 1) + { + modif = 1; + // get new nmx params + nmxCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + nmxType_ = ttype; + rankNmx_ = tx[0]; + confNmx_ = ty[0]; + } + plotTotImage_->mouseModif_ = 0; + } + if (modif == 1) + { + SetParametersNum(); + SetParametersStr(); + } +} + +void BgMdiEdgeChild::SetParametersNum() +{ + wxString ts; + ts = wxString::Format("%.3g", rankH_); + valHHR_->SetLabel(ts); + ts = wxString::Format("%.3g", confH_); + valHHC_->SetLabel(ts); + ts = wxString::Format("%.3g", rankL_); + valHLR_->SetLabel(ts); + ts = wxString::Format("%.3g", confL_); + valHLC_->SetLabel(ts); + ts = wxString::Format("%.3g", rankNmx_); + valNmxR_->SetLabel(ts); + ts = wxString::Format("%.3g", confNmx_); + valNmxC_->SetLabel(ts); +} +void BgMdiEdgeChild::SetParametersStr() +{ + switch(hystHighType_) + { + case FC_ELLIPSE: + valHHType_->SetLabel("arc"); + break; + case FC_VERT_LINE: + valHHType_->SetLabel("vertical line"); + break; + case FC_HORIZ_LINE: + valHHType_->SetLabel("horizontal line"); + break; + case FC_SQUARE_BOX: + valHHType_->SetLabel("box"); + break; + case FC_LINE: + valHHType_->SetLabel("line"); + break; + case FC_CUSTOM: + valHHType_->SetLabel("custom"); + break; + } + + switch(hystLowType_) + { + case FC_ELLIPSE: + valHLType_->SetLabel("arc"); + break; + case FC_VERT_LINE: + valHLType_->SetLabel("vertical line"); + break; + case FC_HORIZ_LINE: + valHLType_->SetLabel("horizontal line"); + break; + case FC_SQUARE_BOX: + valHLType_->SetLabel("box"); + break; + case FC_LINE: + valHLType_->SetLabel("line"); + break; + case FC_CUSTOM: + valHLType_->SetLabel("custom"); + break; + } + + switch(nmxType_) + { + case FC_ELLIPSE: + valNmxType_->SetLabel("arc"); + break; + case FC_VERT_LINE: + valNmxType_->SetLabel("vertical line"); + break; + case FC_HORIZ_LINE: + valNmxType_->SetLabel("horizontal line"); + break; + case FC_SQUARE_BOX: + valNmxType_->SetLabel("box"); + break; + case FC_LINE: + valNmxType_->SetLabel("line"); + break; + case FC_CUSTOM: + valNmxType_->SetLabel("custom"); + break; + } + wxString ts; + ts = wxString::Format("%d", nMin_); + valMinPt_->SetLabel(ts); + ts = wxString::Format("%d", kernelSize_); + valKernelSize_->SetLabel(ts); + + +} + +void BgMdiEdgeChild::OnViewEdge(wxCommandEvent& WXUNUSED(event)) +{ + viewEdgeCheck_->SetValue(miViewEdge_->IsChecked()); + + if (hasEdge_ == false) + return; + + if (miViewEdge_->IsChecked() == TRUE) + { + // show edges + origEdgeImage_->AddPointSet(&cbgPointSet_); + + } + else + { + // hide edges + origEdgeImage_->RemovePointSet(&cbgPointSet_); + } + +} + +void BgMdiEdgeChild::OnViewOrig(wxCommandEvent& WXUNUSED(event)) +{ + viewOrigCheck_->SetValue(miViewOrig_->IsChecked()); + + if (hasImage_ == false) + return; + + if (miViewOrig_->IsChecked() == TRUE) + { + // show edges + //canvas->AddPointSet(edgesSeq_[crtImage_]); + origEdgeImage_->ShowBitmap(true); + } + else + { + // hide edges + //canvas->RemovePointSet(edgesSeq_[crtImage_]); + origEdgeImage_->ShowBitmap(false); + } + origEdgeImage_->Refresh(); + +} + +void BgMdiEdgeChild::OnCViewEdge(wxCommandEvent& WXUNUSED(event)) +{ + miViewEdge_->Check(viewEdgeCheck_->GetValue()); + if (hasEdge_ == false) + return; + + if (viewEdgeCheck_->GetValue() == TRUE) + { + // show edges + origEdgeImage_->AddPointSet(&cbgPointSet_); + + } + else + { + // hide edges + origEdgeImage_->RemovePointSet(&cbgPointSet_); + } +} + +void BgMdiEdgeChild::OnCViewOrig(wxCommandEvent& WXUNUSED(event)) +{ + miViewOrig_->Check(viewOrigCheck_->GetValue()); + + if (hasImage_ == false) + return; + + if (viewOrigCheck_->GetValue() == TRUE) + { + // show edges + //canvas->AddPointSet(edgesSeq_[crtImage_]); + origEdgeImage_->ShowBitmap(true); + } + else + { + // hide edges + //canvas->RemovePointSet(edgesSeq_[crtImage_]); + origEdgeImage_->ShowBitmap(false); + } + +} + + +void BgMdiEdgeChild::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + int w, h; + GetClientSize(&w, &h); + buttonPanel_->SetSize(0, 0, bpsize_, h); + imagePlotSplitter_->SetSize(bpsize_, 0, w-bpsize_, h); + plotSplitter_->SetSashPosition(h/2,TRUE); + h = w-bpsize_-rightsize_; + h = (h<0)? 0:h; + imagePlotSplitter_->SetSashPosition(h,TRUE); +} + +void BgMdiEdgeChild::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(TRUE); +} + +void BgMdiEdgeChild::OnClose(wxCloseEvent& event) +{ + gs_nFrames--; + //indicate that the window is closed (used by OnFocus) + window_open = false; + //reset toolbar + if(gs_nFrames == 0) ResetToolBar(); + event.Skip(); +} + +void BgMdiEdgeChild::OnFocus(wxFocusEvent& WXUNUSED(event)) +{ + //update toolbar + if(!on_exit) UpdateToolBar(); + return; +} + +void BgMdiEdgeChild::ZoomWindow(void) +{ + //display zoom window + origEdgeImage_->zoom_window = true; + origEdgeImage_->zoom_in = false; + origEdgeImage_->zoom_out = false; +} + +void BgMdiEdgeChild::ZoomIn(void) +{ + //zoom into display image + origEdgeImage_->zoom_window = false; + origEdgeImage_->zoom_in = true; + origEdgeImage_->zoom_out = false; + return; +} + +void BgMdiEdgeChild::ZoomOut(void) +{ + //zoom out of display image + origEdgeImage_->zoom_window = false; + origEdgeImage_->zoom_in = false; + origEdgeImage_->zoom_out = true; + return; +} + +void BgMdiEdgeChild::NoZoom(void) +{ + //do not zoom display image + origEdgeImage_->zoom_window = false; + origEdgeImage_->zoom_in = false; + origEdgeImage_->zoom_out = false; + return; +} + +void BgMdiEdgeChild::UpdateZoomControl(void) +{ + //determine whether to enable zoom in control based on maximum zoom + if(maxZoom_ || minZoom_) + UpdateToolBar(); + else + { +// toolbar->Realize(); + toolbar->EnableTool(BG_ZOOM_IN, true); + toolbar->EnableTool(BG_ZOOM_OUT, true); + } +} + +void BgMdiEdgeChild::RunEnable(void) +{ + edButton_->Enable(true); + wxMenuBar *menubar = GetMenuBar(); + menubar->Enable(BG_EDGE_DETECT, true); +} + +void BgMdiEdgeChild::SaveEnable(void) +{ +// toolbar->Realize(); + toolbar->EnableTool(BG_SAVE_RESULT, true); +} + +void BgMdiEdgeChild::UpdateToolBar(void) +{ + //update toolbar + if(window_open) + { + //determine whether to enable save based on whether segmentation + //has occurred + bool save_enable; + if(hasEdge_) + save_enable = true; + else + save_enable = false; + + //determine whether to enable zoom controls based on whether image + //has been loaded + bool load_enable; + if(hasImage_) + load_enable = true; + else + load_enable = false; + + //determine whether to enable zoom in control based on maximum zoom + bool max_zoom; + if(maxZoom_) + max_zoom = true; + else + max_zoom = false; + + //determine whether to enable zoom out control based on minimum zoom + bool min_zoom; + if(minZoom_) + min_zoom = true; + else + min_zoom = false; + + //adjust toolbar + toolbar->SetToolShortHelp(BG_LOAD_IMAGE, "Load image to perform edge detection"); + toolbar->SetToolShortHelp(BG_SAVE_RESULT, "Save edge map"); + toolbar->EnableTool(BG_SAVE_RESULT, save_enable); + toolbar->EnableTool(BG_CROSS, load_enable); + toolbar->EnableTool(BG_ZOOM_IN, ((load_enable)&&(!max_zoom))); + toolbar->EnableTool(BG_ZOOM_OUT, ((load_enable)&&(!min_zoom))); + toolbar->EnableTool(BG_POINTER, true); + + //set to no zoom + toolbar->ToggleTool(BG_CROSS, false); + toolbar->ToggleTool(BG_ZOOM_IN, false); + toolbar->ToggleTool(BG_ZOOM_OUT, false); + toolbar->ToggleTool(BG_POINTER, true); + origEdgeImage_->SetCursor(wxCURSOR_ARROW); + NoZoom(); + +// toolbar->Realize(); + } + return; +} + +void BgMdiEdgeChild::ResetToolBar(void) +{ + //update toolbar + toolbar->SetToolShortHelp(BG_LOAD_IMAGE, "Load image to process"); + toolbar->SetToolShortHelp(BG_SAVE_RESULT, "Save result"); + toolbar->EnableTool(BG_SAVE_RESULT, false); + toolbar->EnableTool(BG_CROSS, false); + toolbar->EnableTool(BG_ZOOM_IN, false); + toolbar->EnableTool(BG_ZOOM_OUT, false); + toolbar->EnableTool(BG_POINTER, false); + toolbar->ToggleTool(BG_CROSS, false); + toolbar->ToggleTool(BG_ZOOM_IN, false); + toolbar->ToggleTool(BG_ZOOM_OUT, false); + toolbar->ToggleTool(BG_POINTER, false); +// toolbar->Realize(); + return; +} + +void BgMdiEdgeChild::ReadImage(char *pathname, char *filename) +{ + plotTotImage_->ClearData(1); + plotNmxImage_->ClearData(1); + + if (origEdgeImage_->SetImage(pathname) == 0) + return; + bgLog("Image %s loaded\n",pathname); + + //obtain and store image filename + if(filename_) delete [] filename_; + filename_ = new char [strlen(filename) + 1]; + strcpy(filename_, filename); + + miViewOrig_->Check(TRUE); + viewOrigCheck_->SetValue(TRUE); + origEdgeImage_->showbitmap_ = true; + + if (hasEdge_ == 1) + origEdgeImage_->RemovePointSet(&cbgPointSet_); + // set cbgImage + cbgImage_->SetImageFromRGB(origEdgeImage_->pimage->GetData(), origEdgeImage_->pimage->GetWidth(), origEdgeImage_->pimage->GetHeight()); + if (cbgEdgeDetect_ != 0) + delete cbgEdgeDetect_; + cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); + hasImage_ = 1; + hasEdge_ = 0; + + //get image dimension + width_ = origEdgeImage_->pimage->GetWidth(); + height_ = origEdgeImage_->pimage->GetHeight(); + + //reset the zoom level of the original edge image + origEdgeImage_->Zoom(1); + + //reset max/min zoom flags + maxZoom_ = 0; + minZoom_ = 1; + + //update interface... + + /***********************************************/ + + //enable run + RunEnable(); + + //update the tool bar + UpdateToolBar(); + + //set window title + wxString statusname; + statusname.Printf(_T("Edge Detection Frame %d - %s (%d x %d) [Original Image]"), window_number_, filename_, width_, height_); + SetTitle(statusname); + + /***********************************************/ +} + +void BgMdiEdgeChild::OnLoadImage(wxCommandEvent& WXUNUSED(event)) +{ + // get the file name +// wxFileDialog filedialog(this,"Choose an image file","","", +// "All files (*.*)|*.*|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm", +// wxOPEN); +#if defined(__WXGTK__) || defined(__WXMOTIF__) + wxFileDialog filedialog(this,"Choose an image file","","", + "*",wxOPEN); +#else + wxFileDialog filedialog(this,"Choose an image file","","", + "Common image files|*.png;*.bmp;*.gif;*.tif;*.tiff;*.jpg;*.pnm;*.pgm;*.ppm|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm|PGM/PPM files (*.pgm,*.ppm)|*.pgm;*.ppm", + wxOPEN); +#endif + if(filedialog.ShowModal()==wxID_OK) + { + plotTotImage_->ClearData(1); + plotNmxImage_->ClearData(1); + + if (hasEdge_ == 1) + origEdgeImage_->RemovePointSet(&cbgPointSet_); + + if (origEdgeImage_->SetImage(filedialog.GetPath().c_str()) == 0) + return; + bgLog("Image %s loaded\n",filedialog.GetPath().c_str()); + + //obtain and store image filename + if(filename_) delete [] filename_; + filename_ = new char [strlen(filedialog.GetFilename().c_str()) + 1]; + strcpy(filename_, filedialog.GetFilename().c_str()); + + miViewOrig_->Check(TRUE); + viewOrigCheck_->SetValue(TRUE); + origEdgeImage_->showbitmap_ = true; + + // set cbgImage + cbgImage_->SetImageFromRGB(origEdgeImage_->pimage->GetData(), origEdgeImage_->pimage->GetWidth(), origEdgeImage_->pimage->GetHeight()); + if (cbgEdgeDetect_ != 0) + delete cbgEdgeDetect_; + cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); + hasImage_ = 1; + hasEdge_ = 0; + + //get image dimension + width_ = origEdgeImage_->pimage->GetWidth(); + height_ = origEdgeImage_->pimage->GetHeight(); + + //reset the zoom level of the original edge image + origEdgeImage_->Zoom(1); + + //reset max/min zoom flags + maxZoom_ = 0; + minZoom_ = 1; + + //update interface... + + /***********************************************/ + //enable run + RunEnable(); + + //update the tool bar + UpdateToolBar(); + + //set window title + wxString statusname; + statusname.Printf(_T("Edge Detection Frame %d - %s (%d x %d) [Original Image]"), window_number_, filename_, width_, height_); + SetTitle(statusname); + + /***********************************************/ + } +} + +void BgMdiEdgeChild::OnSaveEdgeMap(wxCommandEvent& WXUNUSED(event)) +{ + if (hasEdge_ == 0) + { + bgLog("No edge map, run edge detection first!\n"); + return; + } + // get the file name + wxFileDialog filedialog(this,"Choose an image file","","", + "PGM files (*.pgm)|*.pgm", + wxSAVE); + + if(filedialog.ShowModal()==wxID_OK) + { + BgImage tempImage(cbgImage_->x_, cbgImage_->y_); + cbgEdgeList_->SetBinImage(&tempImage); + write_pgm_image(filedialog.GetPath().c_str(), tempImage.im_, tempImage.y_, tempImage.x_, "", 255); + bgLog("Edge map saved in: %s\n",filedialog.GetPath().c_str()); + + char tch[100]; + sprintf(tch,"%s.txt",filedialog.GetPath().c_str()); + cbgEdgeList_->SaveEdgeList(tch); + } +} + +void BgMdiEdgeChild::OnEdgeDetect(wxCommandEvent& WXUNUSED(event)) +{ + // determine if we have image + if (cbgImage_->hasIm_ == false) + { + //no image loaded + bgLog("No image loaded!\n"); + return; + } + if (hasEdge_ == 1) + origEdgeImage_->RemovePointSet(&cbgPointSet_); + + if (cbgEdgeList_ != 0) + delete cbgEdgeList_; + cbgEdgeList_ = new BgEdgeList(); + + // test if modif params + double tx[MAX_CUSTOM_NODES]; + double ty[MAX_CUSTOM_NODES]; + int ttype,i; + int npoints; + + if (plotTotImage_->mouseModif_ == 1) + { + // get new nmx params + nmxCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + nmxType_ = ttype; + rankNmx_ = tx[0]; + confNmx_ = ty[0]; + } + plotTotImage_->mouseModif_ = 0; + } + if (plotNmxImage_->mouseModif_ == 1) + { + // get new hyst params + highCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + hystHighType_ = ttype; + rankH_ = tx[0]; + confH_ = ty[0]; + } else + { + hystHighType_ = ttype; + for (i=0; i<npoints; i++) + { + custHx_[i] = tx[i]; + custHy_[i] = ty[i]; + } + nCustH_ = npoints; + } + lowCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + hystLowType_ = ttype; + rankL_ = tx[0]; + confL_ = ty[0]; + } else + { + hystLowType_ = ttype; + for (i=0; i<npoints; i++) + { + custLx_[i] = tx[i]; + custLy_[i] = ty[i]; + } + nCustL_ = npoints; + } + plotNmxImage_->mouseModif_ = 0; + } + + if (hystHighType_ == FC_CUSTOM) + cbgEdgeDetect_->SetCustomHigh(custHx_, custHy_, nCustH_); + if (hystLowType_ == FC_CUSTOM) + cbgEdgeDetect_->SetCustomLow(custLx_, custLy_, nCustL_); + + // determine if we have permanent data + if (cbgEdgeDetect_->havePerm_ == true) { + // compute only nmx and hyst + cbgEdgeDetect_->DoRecompute(cbgEdgeList_, rankNmx_, confNmx_, rankH_, confH_, rankL_, confL_, + nMin_, nmxType_, hystHighType_, hystLowType_); + // set only nmx image + SetNmxImage(); + } + else + { + // compute all steps + cbgEdgeDetect_->DoEdgeDetect(cbgImage_, cbgEdgeList_, rankNmx_, confNmx_, rankH_, confH_, rankL_, confL_, + nMin_, nmxType_, hystHighType_, hystLowType_); + // set total and nmx image + SetTotalImage(); + SetNmxImage(); + } + + // get binary edge image + BgImage tempImage(cbgImage_->x_, cbgImage_->y_); + cbgEdgeList_->SetBinImage(&tempImage); + + int* edgex; + int* edgey; + int nEdgep; + edgex = new int[(cbgImage_->x_) * (cbgImage_->y_)]; + edgey = new int[(cbgImage_->x_) * (cbgImage_->y_)]; + cbgPointSet_.type_ = 1; + + cbgEdgeList_->GetAllEdgePoints(edgex, edgey, &nEdgep); + cbgPointSet_.SetPoints(edgex, edgey, nEdgep); + hasEdge_ = 1; + delete [] edgey; + delete [] edgex; + + // update image canvas + if (miViewEdge_->IsChecked()) + origEdgeImage_->AddPointSet(&cbgPointSet_); + + //active save tool + SaveEnable(); + + //update menu bar + wxMenuBar *menubar = GetMenuBar(); + menubar->Enable(BG_EDGE_SAVE_MAP, true); + +} + +void BgMdiEdgeChild::SetTotalImage(void) +{ + unsigned char* buf; + int xsz = RANK_CONF_IMSIZEX; + int ysz = RANK_CONF_IMSIZEY; + int imsz = xsz*ysz; + buf = new unsigned char[imsz]; + int i; + for (i=0; i<imsz; i++) + buf[i] = 255; + + int l, c; + int xo = cbgEdgeDetect_->x_; + int yo = cbgEdgeDetect_->y_; + float* rank; + float* conf; + rank = cbgEdgeDetect_->permRank_; + conf = cbgEdgeDetect_->permConf_; + for (i=0; i<xo*yo; i++) + { + if (rank[i]>0 && conf[i]>0) + { + c = (int) (rank[i]*((double) xsz)); + c = (c>=xsz) ? xsz-1 : c; + l = (int) (conf[i]*((double) ysz)); + l = (l>=ysz) ? ysz-1 : l; + l = ysz-1-l; + buf[c+l*xsz]=80; + } + } + + nmxCurve_.SetParamCurve(nmxType_, &rankNmx_, &confNmx_, 1, xsz, ysz); + plotTotImage_->SetImageFromGray(buf, xsz, ysz); + plotTotImage_->FillCurveClick(); + + delete [] buf; + +} + +void BgMdiEdgeChild::SetNmxImage(void) +{ + unsigned char* buf; + int xsz = RANK_CONF_IMSIZEX; + int ysz = RANK_CONF_IMSIZEY; + int imsz = xsz*ysz; + buf = new unsigned char[imsz]; + int i; + for (i=0; i<imsz; i++) + buf[i] = 255; + + int l, c; + int xo = cbgEdgeDetect_->x_; + int yo = cbgEdgeDetect_->y_; + float* rank; + float* conf; + rank = cbgEdgeDetect_->permNmxRank_; + conf = cbgEdgeDetect_->permNmxConf_; + for (i=0; i<xo*yo; i++) + { + if (rank[i]>0 && conf[i]>0) + { + c = (int) (rank[i]*((double) xsz)); + c = (c>=xsz) ? xsz-1 : c; + l = (int) (conf[i]*((double) ysz)); + l = (l>=ysz) ? ysz-1 : l; + l = ysz-1-l; + buf[c+l*xsz]=80; + } + } + + if (hystHighType_ != FC_CUSTOM) + highCurve_.SetParamCurve(hystHighType_, &rankH_, &confH_, 1, xsz, ysz); + else + { + highCurve_.SetParamCurve(hystHighType_, custHx_, custHy_, nCustH_, xsz, ysz); + } + if (hystLowType_ != FC_CUSTOM) + lowCurve_.SetParamCurve(hystLowType_, &rankL_, &confL_, 1, xsz, ysz); + else + { + lowCurve_.SetParamCurve(hystLowType_, custLx_, custLy_, nCustL_, xsz, ysz); + } + plotNmxImage_->SetImageFromGray(buf, xsz, ysz); + plotNmxImage_->FillCurveClick(); + + delete [] buf; + +} + +void BgMdiEdgeChild::OnChangeParam(wxCommandEvent& WXUNUSED(event)) +{ + // show the parameters window and change it + double tx[20]; + double ty[20]; + int ttype,i; + int npoints; + if (plotTotImage_->mouseModif_ == 1) + { + // get new nmx params + nmxCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + nmxType_ = ttype; + rankNmx_ = tx[0]; + confNmx_ = ty[0]; + } + plotTotImage_->mouseModif_ = 0; + } + if (plotNmxImage_->mouseModif_ == 1) + { + // get new hyst params + highCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + hystHighType_ = ttype; + rankH_ = tx[0]; + confH_ = ty[0]; + } else + { + hystHighType_ = ttype; + for (i=0; i<npoints; i++) + { + custHx_[i] = tx[i]; + custHy_[i] = ty[i]; + } + rankH_ = tx[npoints-1]; + confH_ = ty[0]; + nCustH_ = npoints; + } + lowCurve_.GetParamCurve(tx, ty, ttype,npoints); + if ((ttype!=FC_CUSTOM) && (ttype!=-1)) + { + hystLowType_ = ttype; + rankL_ = tx[0]; + confL_ = ty[0]; + } else + { + hystLowType_ = ttype; + for (i=0; i<npoints; i++) + { + custLx_[i] = tx[i]; + custLy_[i] = ty[i]; + } + rankL_ = tx[npoints-1]; + confL_ = ty[0]; + nCustL_ = npoints; + } + plotNmxImage_->mouseModif_ = 0; + } + BgParamDialog paramDialog(this, -1, "Change Parameters", wxDefaultPosition, wxSize(250,510), + wxDEFAULT_DIALOG_STYLE | wxDIALOG_MODAL); + paramDialog.SetValues(rankNmx_, confNmx_, rankH_, confH_, rankL_, confL_, nMin_, + nmxType_, hystHighType_, hystLowType_, kernelSize_); + if (paramDialog.ShowModal()==wxID_OK) + { + // do change param stuff + int tempKernelSize; + tempKernelSize = kernelSize_; + paramDialog.GetValues(rankNmx_, confNmx_, rankH_, confH_, rankL_, confL_, nMin_, + nmxType_, hystHighType_, hystLowType_, tempKernelSize); + if (tempKernelSize != kernelSize_) + { + kernelSize_ = tempKernelSize; + if (cbgEdgeDetect_ != 0) { + delete cbgEdgeDetect_; + cbgEdgeDetect_ = new BgEdgeDetect(kernelSize_); + } + } + + // change image param + int xsz = RANK_CONF_IMSIZEX; + int ysz = RANK_CONF_IMSIZEY; + + if (hystHighType_ != FC_CUSTOM) + highCurve_.SetParamCurve(hystHighType_, &rankH_, &confH_, 1, xsz, ysz); + else + { + highCurve_.SetParamCurve(hystHighType_, custHx_, custHy_, nCustH_, xsz, ysz); + } + if (hystLowType_ != FC_CUSTOM) + lowCurve_.SetParamCurve(hystLowType_, &rankL_, &confL_, 1, xsz, ysz); + else + { + lowCurve_.SetParamCurve(hystLowType_, custLx_, custLy_, nCustL_, xsz, ysz); + } + + nmxCurve_.SetParamCurve(nmxType_, &rankNmx_, &confNmx_, 1, xsz, ysz); + + plotNmxImage_->FillCurveClick(); + plotTotImage_->FillCurveClick(); + + SetParametersStr(); + SetParametersNum(); + } +} + + +// --------------------------------------------------------------------------- +// BgParamDialog +// --------------------------------------------------------------------------- + +BgParamDialog::BgParamDialog(wxWindow* parent, wxWindowID id, const wxString& title, + const wxPoint& pos, const wxSize& size, + long style, const wxString& name) +: wxDialog(parent, id, title, pos, size, style, name) +{ + okButton_ = new wxButton(this, BG_PARAMD_OK, "Ok", wxPoint(20+C_PARAMX+10,450)); + cancelButton_ = new wxButton(this, BG_PARAMD_CANCEL, "Cancel", wxPoint(20+C_PARAMX+10+C_PARAMDX+60,450)); + + /* + txtNmxR_ = new wxStaticText(this, -1, "Nmx. rank: ", wxPoint(C_PARAMX,C_PARAMY+0*C_PARAMDY)); + txtNmxC_ = new wxStaticText(this, -1, "Nmx. conf: ", wxPoint(C_PARAMX,C_PARAMY+1*C_PARAMDY)); + txtHHR_ = new wxStaticText(this, -1, "Hyst. high rank: ", wxPoint(C_PARAMX,C_PARAMY+2*C_PARAMDY)); + txtHHC_ = new wxStaticText(this, -1, "Hyst. high conf: ", wxPoint(C_PARAMX,C_PARAMY+3*C_PARAMDY)); + txtHLR_ = new wxStaticText(this, -1, "Hyst. low rank: ", wxPoint(C_PARAMX,C_PARAMY+4*C_PARAMDY)); + txtHLC_ = new wxStaticText(this, -1, "Hyst. low conf: ", wxPoint(C_PARAMX,C_PARAMY+5*C_PARAMDY)); + txtMinPt_ = new wxStaticText(this, -1, "Min. points: ", wxPoint(C_PARAMX,C_PARAMY+6*C_PARAMDY)); + txtNmxType_ = new wxStaticText(this, -1, "Nmx. type: ", wxPoint(C_PARAMX,C_PARAMY+7*C_PARAMDY)); + txtHHType_ = new wxStaticText(this, -1, "Hyst. high type: ", wxPoint(C_PARAMX,C_PARAMY+8*C_PARAMDY)); + txtHLType_ = new wxStaticText(this, -1, "Hyst. low: ", wxPoint(C_PARAMX,C_PARAMY+9*C_PARAMDY)); + txtKernelSize_ = new wxStaticText(this, -1, "Kernel radius: ", wxPoint(C_PARAMX,C_PARAMY+10*C_PARAMDY)); + + valNmxR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+0*C_PARAMDY)); + valNmxC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+1*C_PARAMDY)); + valHHR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+2*C_PARAMDY)); + valHHC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+3*C_PARAMDY)); + valHLR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+4*C_PARAMDY)); + valHLC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+5*C_PARAMDY)); + valMinPt_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+6*C_PARAMDY)); + valNmxType_ = new wxChoice(this, -1, wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+7*C_PARAMDY), wxDefaultSize); + valHHType_ = new wxChoice(this, -1, wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+8*C_PARAMDY), wxDefaultSize); + valHLType_ = new wxChoice(this, -1, wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+9*C_PARAMDY), wxDefaultSize); + valKernelSize_ = new wxTextCtrl(this, -1, "NA ", wxPoint(C_PARAMX+C_PARAMDX,C_PARAMY+10*C_PARAMDY)); + */ + + txtKernelSize_ = new wxStaticText(this, -1, "Grad Win.", wxPoint(20+C_PARAMX-5,0+C_PARAMY+0*C_PARAMDY)); + valKernelSize_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX+35,0+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX-20,C_PARAMSY)); + + txtMinPt_ = new wxStaticText(this, -1, "Min. length", wxPoint(20+C_PARAMX-5,0+C_PARAMY+1*C_PARAMDY)); + valMinPt_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX+35,0+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX-20,C_PARAMSY)); + + wxStaticBox* nmxSB = new wxStaticBox(this, -1, "Nonmaxima supp.", wxPoint(20+5, 80+0), wxSize(140,4*C_PARAMDY-5)); + txtNmxType_ = new wxStaticText(this, -1, "Type", wxPoint(20+C_PARAMX, 80+C_PARAMY+0*C_PARAMDY)); + valNmxType_ = new wxChoice(this, -1, wxPoint(20+C_PARAMX+C_PARAMDX,80+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + txtNmxR_ = new wxStaticText(this, -1, "Rank", wxPoint(20+C_PARAMX,80+C_PARAMY+1*C_PARAMDY)); + valNmxR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,80+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + txtNmxC_ = new wxStaticText(this, -1, "Conf", wxPoint(20+C_PARAMX,80+C_PARAMY+2*C_PARAMDY)); + valNmxC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,80+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + + wxStaticBox* hhSB = new wxStaticBox(this, -1, "Hyst. High Tr.", wxPoint(20+5, 200+0), wxSize(140,4*C_PARAMDY-5)); + txtHHType_ = new wxStaticText(this, -1, "Type", wxPoint(20+C_PARAMX,200+C_PARAMY+0*C_PARAMDY)); + txtHHR_ = new wxStaticText(this, -1, "Rank", wxPoint(20+C_PARAMX,200+C_PARAMY+1*C_PARAMDY)); + txtHHC_ = new wxStaticText(this, -1, "Conf", wxPoint(20+C_PARAMX,200+C_PARAMY+2*C_PARAMDY)); + valHHType_ = new wxChoice(this, -1, wxPoint(20+C_PARAMX+C_PARAMDX,200+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + valHHR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,200+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + valHHC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,200+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + + wxStaticBox* hlSB = new wxStaticBox(this, -1, "Hyst. Low Tr.", wxPoint(20+5, 320+0), wxSize(140, 4*C_PARAMDY-5)); + txtHLType_ = new wxStaticText(this, -1, "Type", wxPoint(20+C_PARAMX,320+C_PARAMY+0*C_PARAMDY)); + txtHLR_ = new wxStaticText(this, -1, "Rank", wxPoint(20+C_PARAMX,320+C_PARAMY+1*C_PARAMDY)); + txtHLC_ = new wxStaticText(this, -1, "Conf", wxPoint(20+C_PARAMX,320+C_PARAMY+2*C_PARAMDY)); + valHLType_ = new wxChoice(this, -1, wxPoint(20+C_PARAMX+C_PARAMDX,320+C_PARAMY+0*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + valHLR_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,320+C_PARAMY+1*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + valHLC_ = new wxTextCtrl(this, -1, "NA ", wxPoint(20+C_PARAMX+C_PARAMDX,320+C_PARAMY+2*C_PARAMDY), wxSize(C_PARAMSX,C_PARAMSY)); + + + + // put choices + valNmxType_->Append("Arc"); + valNmxType_->Append("Vertical Line"); + valNmxType_->Append("Horizontal Line"); + valNmxType_->Append("Line"); + valNmxType_->Append("Box"); + + valHHType_->Append("Arc"); + valHHType_->Append("Vertical Line"); + valHHType_->Append("Horizontal Line"); + valHHType_->Append("Line"); + valHHType_->Append("Box"); + valHHType_->Append("Custom"); + + valHLType_->Append("Arc"); + valHLType_->Append("Vertical Line"); + valHLType_->Append("Horizontal Line"); + valHLType_->Append("Line"); + valHLType_->Append("Box"); + valHLType_->Append("Custom"); + +} + +BgParamDialog::~BgParamDialog() +{ + delete txtNmxR_; + delete txtNmxC_; + delete txtHHR_; + delete txtHHC_; + delete txtHLR_; + delete txtHLC_; + delete txtMinPt_; + delete txtNmxType_; + delete txtHHType_; + delete txtHLType_; + delete txtKernelSize_; + + delete valNmxR_; + delete valNmxC_; + delete valHHR_; + delete valHHC_; + delete valHLR_; + delete valHLC_; + delete valMinPt_; + delete valNmxType_; + delete valHHType_; + delete valHLType_; + delete valKernelSize_; + + delete okButton_; + delete cancelButton_; +} + +void BgParamDialog::OnOk(wxCommandEvent& WXUNUSED(event)) +{ + EndModal(wxID_OK); +} + +void BgParamDialog::OnCancel(wxCommandEvent& WXUNUSED(event)) +{ + EndModal(wxID_CANCEL); +} + +void BgParamDialog::SetValues(double nmxR, double nmxC, double hhR, double hhC, double hlR, double hlC, + int nMin, int nmxT, int hhT, int hlT, int ks) +{ + wxString ts; + ts = wxString::Format("%.3g", nmxR); + valNmxR_->SetValue(ts); + ts = wxString::Format("%.3g", nmxC); + valNmxC_->SetValue(ts); + ts = wxString::Format("%.3g", hhR); + valHHR_->SetValue(ts); + ts = wxString::Format("%.3g", hhC); + valHHC_->SetValue(ts); + ts = wxString::Format("%.3g", hlR); + valHLR_->SetValue(ts); + ts = wxString::Format("%.3g", hlC); + valHLC_->SetValue(ts); + ts = wxString::Format("%d", nMin); + valMinPt_->SetValue(ts); + valNmxType_->SetSelection(nmxT); + valHHType_->SetSelection(hhT); + valHLType_->SetSelection(hlT); + ts = wxString::Format("%d", ks); + valKernelSize_->SetValue(ts); + +} + +void BgParamDialog::GetValues(double& nmxR, double& nmxC, double& hhR, double& hhC, double& hlR, double& hlC, + int& nMin, int& nmxT, int& hhT, int& hlT, int& ks) +{ + double td; + long tl; + int ti; + + td = -1; + tl = -1; + ti = -1; + if ((valNmxR_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) + nmxR = td; + else + bgLog("nmx. rank value out of range.\n"); + + if ((valNmxC_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) + nmxC = td; + else + bgLog("nmx. conf. value out of range.\n"); + + if ((valHHR_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) + hhR = td; + else + bgLog("hyst. high rank value out of range.\n"); + + if ((valHHC_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) + hhC = td; + else + bgLog("hyst. high conf. value out of range.\n"); + + if ((valHLR_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) + hlR = td; + else + bgLog("hyst. low rank value out of range.\n"); + + if ((valHLC_->GetValue().ToDouble(&td) == TRUE) && (td>=0)) + hlC = td; + else + bgLog("hyst. low conf. value out of range.\n"); + + if ((valMinPt_->GetValue().ToLong(&tl) == TRUE) && (tl>=0)) + nMin = (int) tl; + else + bgLog("min. edge points value out of range.\n"); + + if ((ti=valNmxType_->GetSelection()) != -1) + nmxT = ti; + + if ((ti=valHHType_->GetSelection()) != -1) + hhT = ti; + + if ((ti=valHLType_->GetSelection()) != -1) + hlT = ti; + + if ((valKernelSize_->GetValue().ToLong(&tl) == TRUE) && (tl>0) && ((2*tl+1)<=MAX_FILTS)) + ks = (int) tl; + else + bgLog("kernel radius value out of range.\n"); + + +} + +// --------------------------------------------------------------------------- +// BgSpeedSelect +// --------------------------------------------------------------------------- + +BgSpeedSelect::BgSpeedSelect(wxWindow* parent, wxWindowID id, const wxString& title, + const wxPoint& pos, const wxSize& size, + long style, const wxString& name) +: wxDialog(parent, id, title, pos, size, style, name) +{ + okButton_ = new wxButton(this, BG_SPEEDSEL_OK, "Ok", wxPoint(30,80)); + cancelButton_ = new wxButton(this, BG_SPEEDSEL_CANCEL, "Cancel", wxPoint(120,80)); + + txtQuality_ = new wxStaticText(this, -1, "Speed", wxPoint(160, 10)); + txtSpeed_ = new wxStaticText(this, -1, "Quality", wxPoint(40, 10)); + + sldSpeed_ = new wxSlider(this, BG_SPEEDSEL_SLD, 0, 0, 100, wxPoint(18,40), wxSize(155,-1), + wxSL_AUTOTICKS | wxSL_LABELS); + sldSpeed_->SetTickFreq(20, 0); +} + +BgSpeedSelect::~BgSpeedSelect() +{ + delete sldSpeed_; + + delete okButton_; + delete cancelButton_; +} + +void BgSpeedSelect::OnOk(wxCommandEvent& WXUNUSED(event)) +{ + EndModal(wxID_OK); +} + +void BgSpeedSelect::OnCancel(wxCommandEvent& WXUNUSED(event)) +{ + EndModal(wxID_CANCEL); +} + +void BgSpeedSelect::SetSliderValue(float sliderV) +{ + sldSpeed_->SetValue((int) (sliderV*100)); +} + +void BgSpeedSelect::GetSliderValue(float& sliderV) +{ + sliderV = (float) (sldSpeed_->GetValue() / 100.0); +} + +// --------------------------------------------------------------------------- +// BgMdiSegmentChild +// --------------------------------------------------------------------------- + +BgMdiSegmentChild::BgMdiSegmentChild(wxMDIParentFrame *parent, const wxString& title, + const wxPoint& pos, const wxSize& size, + const long style) + : wxMDIChildFrame(parent, BG_SEGM_WINDOW, title, pos, size, style) +{ + + //set window number + window_number_ = gs_nFrames; + + //assume image is not yet loaded into segmentation window + filename_ = NULL; + + //split window to display the segmented image on the left hand side, + //and the ph diagram on the right hand side + imagePlotSplitter_ = new wxSplitterWindow(this, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); + plotMapSplitter_ = new wxSplitterWindow(imagePlotSplitter_, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); + mapSplitter_ = new wxSplitterWindow(plotMapSplitter_, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH); + + //create option panels + winPanel1_ = new BgMenuPanel(mapSplitter_, -1, BG_CANVAS_VIEW1_GRADMAP, BG_CANVAS_VIEW1_CONFMAP, BG_CANVAS_VIEW1_WEITMAP, BG_CANVAS_VIEW1_CUSTMAP, + BG_CANVAS_SAVE_GRADMAP, BG_CANVAS_SAVE_CONFMAP, BG_CANVAS_SAVE_WEITMAP); + winPanel2_ = new BgMenuPanel(mapSplitter_, -1, BG_CANVAS_VIEW2_GRADMAP, BG_CANVAS_VIEW2_CONFMAP, BG_CANVAS_VIEW2_WEITMAP, BG_CANVAS_VIEW2_CUSTMAP, + BG_CANVAS_SAVE_GRADMAP, BG_CANVAS_SAVE_CONFMAP, BG_CANVAS_SAVE_WEITMAP); + winPanel1_->view_menu->Enable(BG_CANVAS_VIEW1_CUSTMAP, false); + winPanel2_->view_menu->Enable(BG_CANVAS_VIEW2_CUSTMAP, false); + winPanel1_->CheckViewItem(BG_CANVAS_VIEW1_CONFMAP); + winPanel2_->CheckViewItem(BG_CANVAS_VIEW2_GRADMAP); + winPanel1_->EnableMenu(false); + winPanel2_->EnableMenu(false); + + //define ph diagram and segmented display image + phDiagram_ = new BgImCanvas(this, plotMapSplitter_, wxDefaultPosition, wxDefaultSize); + phDiagram_->SetScrollbars(20, 20, 50, 50); + plotWindow1_ = new BgImCanvas(this, winPanel1_, wxPoint(0,PLOT_MENU_HEIGHT), wxDefaultSize); + plotWindow1_->SetScrollbars(20, 20, 50, 50); + plotWindow2_ = new BgImCanvas(this, winPanel2_, wxPoint(0,PLOT_MENU_HEIGHT), wxDefaultSize); + plotWindow2_->SetScrollbars(20, 20, 50, 50); + displayImage_ = new BgImCanvas(this, imagePlotSplitter_, wxDefaultPosition, wxDefaultSize); + displayImage_->SetScrollbars(20, 20, 50, 50); + + //set the scroll window of each panel + winPanel1_->SetScrollWindow((wxWindow *) plotWindow1_); + winPanel2_->SetScrollWindow((wxWindow *) plotWindow2_); + + //set lower bound zoom limit on display image + //to the size of the original image + displayImage_->SetMinZoomLevel(1); + + //place each image object into their corresponding positions in the split + //window + imagePlotSplitter_->SplitVertically(displayImage_, plotMapSplitter_,256); + plotMapSplitter_->SplitHorizontally(phDiagram_, mapSplitter_, 256); + mapSplitter_->SplitVertically(winPanel1_, winPanel2_, 256); + + //inititalize segmentation parameters + sigmaS = 7; + sigmaR = float(6.5); + aij = float(0.3); + epsilon = float(0.3); + minRegion = 20; + kernelSize = 2; + + //set text size + wxSize txtSize(50, 20); + + //allocate memory for display images + cbgImage_ = new BgImage(); + filtImage_ = new BgImage(); + segmImage_ = new BgImage(); + whiteImage_ = new BgImage(); + + //allocate memory to store boundary pixel locations + boundaries_ = new BgPointSet(); + + hasImage_ = 0; + hasFilter_ = 0; + hasSegment_ = 0; + hasBoundaries_ = 0; + + //shut off text box monitoring + checkTextBoxes_ = false; + + optionsPanel_ = new wxPanel(this, -1, wxPoint(0, 0), wxSize(BG_SEGM_OP_SIZEX, BG_SEGM_OP_SIZEY)); + + wxBoxSizer *toplayout = new wxBoxSizer(wxVERTICAL); + + loadButton_ = new wxButton(optionsPanel_, BG_SEGM_LOAD_IMAGE, "Load Image"); + toplayout->Add(loadButton_, 0, wxCENTER | wxBOTTOM | wxTOP, 5); + + wxString operations[] = {"Segment", "Filter Only", "Fusion Only"}; + operationRadio_ = new wxRadioBox(optionsPanel_, BG_SEGM_OPERATION, "Operation", wxDefaultPosition, wxSize(BG_SP_WIDTH, -1), 3, operations, 3 ,wxRA_SPECIFY_ROWS); + toplayout->Add(operationRadio_, 0, wxCENTER | wxBOTTOM, 5); + + runButton_ = new wxButton(optionsPanel_, BG_SEGM_SEGMENT, "Run"); + toplayout->Add(runButton_, 0, wxCENTER | wxBOTTOM, 5); + + wxString choices[] = {"Original", "Filtered", "Segmented", "No Image"}; + viewImSegRadio_ = new wxRadioBox(optionsPanel_, BG_SEGM_VIEW_IMSEG, "View Image", wxDefaultPosition, wxSize(BG_SP_WIDTH, -1), 4, choices, 4, wxRA_SPECIFY_ROWS); + toplayout->Add(viewImSegRadio_, 0, wxCENTER | wxBOTTOM, 5); + + viewBoundariesCheck_ = new wxCheckBox(optionsPanel_, BG_SEGM_VIEW_EDGES, "Overlay Boundaries"); + toplayout->Add(viewBoundariesCheck_, 0, wxALIGN_LEFT | wxLEFT | wxBOTTOM, 10); + + //add bandwidth parameters... + subPanel1_ = new wxPanel(optionsPanel_, -1, wxDefaultPosition, wxSize(BG_SP_WIDTH, BG_SP_HEIGHT)); + subPanelBox1_ = new wxStaticBox(subPanel1_, -1, "Bandwidth", wxPoint(0, 0), wxSize(BG_SP_WIDTH, BG_SP_TOP_HEIGHT), wxSIMPLE_BORDER, "staticBox"); + subPanelBox2_ = new wxStaticBox(subPanel1_, -1, "", wxPoint(0, BG_SP_TOP_HEIGHT-8), wxSize(BG_SP_WIDTH, BG_SP_HEIGHT-BG_SP_TOP_HEIGHT), wxSIMPLE_BORDER, "staticBox"); + textSigmaS_ = new wxStaticText(subPanel1_, -1, "Spatial [2h+1]", wxPoint(BG_LEFT_CELL, 18)); + txtSigmaS_ = new wxTextCtrl(subPanel1_, BG_SEGM_TEXT_SIGMAS, "7", wxPoint(BG_RIGHT_CELL, 15), txtSize); + textSigmaR_ = new wxStaticText(subPanel1_, -1, "Color [2h]", wxPoint(BG_LEFT_CELL, 43)); + txtSigmaR_ = new wxTextCtrl(subPanel1_, BG_SEGM_TEXT_SIGMAR, "6.5", wxPoint(BG_RIGHT_CELL, 40), txtSize); + textMinRegion_ = new wxStaticText(subPanel1_, -1, "Minimum Region", wxPoint(BG_LEFT_CELL, 78)); + txtMinRegion_ = new wxTextCtrl(subPanel1_, BG_SEGM_TEXT_MINREG, "20", wxPoint(BG_RIGHT_CELL, 75), txtSize); + toplayout->Add(subPanel1_, 0, wxCENTER | wxBOTTOM | wxTOP, 5); + + useWeightMap_ = new wxCheckBox(optionsPanel_, BG_SEGM_USE_EDGE_MAP, "Use Weight Map"); + toplayout->Add(useWeightMap_, 0, wxALIGN_LEFT | wxLEFT | wxBOTTOM, 10); + + //add weight map parameters... + subPanel2_ = new wxPanel(optionsPanel_, -1, wxDefaultPosition, wxSize(BG_SP_WIDTH, BG_SP_HEIGHT_2)); + subPanelBox3_ = new wxStaticBox(subPanel2_, -1, "", wxPoint(0, 0), wxSize(BG_SP_WIDTH, BG_SP_HEIGHT_2), wxSIMPLE_BORDER, "staticBox"); + textKernelSize_ = new wxStaticText(subPanel2_, -1, "Grad. Window (2n+1)", wxPoint(BG_LEFT_CELL, 18)); + txtKernelSize_ = new wxTextCtrl(subPanel2_, BG_SEGM_TEXT_GRADWIN, "2", wxPoint(BG_RIGHT_CELL, 15), txtSize); + textA_ = new wxStaticText(subPanel2_, -1, "Mixture Parameter", wxPoint(BG_LEFT_CELL, 43)); + txtA_ = new wxTextCtrl(subPanel2_, BG_SEGM_TEXT_AIJ, "0.3", wxPoint(BG_RIGHT_CELL, 40), txtSize); + textEpsilon_ = new wxStaticText(subPanel2_, -1, "Threshold", wxPoint(BG_LEFT_CELL, 68)); + txtEpsilon_ = new wxTextCtrl(subPanel2_, BG_SEGM_TEXT_EPSILON, "0.3", wxPoint(BG_RIGHT_CELL, 65), txtSize); + toplayout->Add(subPanel2_, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_TOP, 5); + + //add parameter history control + subPanel3_ = new wxPanel(optionsPanel_, -1, wxDefaultPosition, wxSize(BG_SP_WIDTH, 43)); + subPanelBox4_ = new wxStaticBox(subPanel3_, -1, "", wxPoint(0, 0), wxSize(BG_SP_WIDTH, 43), wxSIMPLE_BORDER, "staticBox"); + textParamBox_ = new wxStaticText(subPanel3_, -1, "History", wxPoint(BG_LEFT_CELL, 18)); + paramComboBox_ = new BgParameterHistoryBox(subPanel3_, BG_SEGM_CHANGE_PARAMS, "", wxPoint(BG_RIGHT_CELL-50, 15), wxSize(100,20), 5, 0, wxDefaultValidator, "comboBox"); + toplayout->Add(subPanel3_, 0, wxALIGN_CENTER | wxCENTER | wxBOTTOM, 10); + + optionsPanel_->SetAutoLayout(TRUE); + toplayout->Fit(optionsPanel_); + optionsPanel_->SetSizer(toplayout); + + g_children.Append(this); + + //set the size and sash position of the splitters + int w, h; + GetClientSize(&w, &h); + imagePlotSplitter_->SetSize(BG_SEGM_OP_SIZEX, 0, w-BG_SEGM_OP_SIZEX, h); + imagePlotSplitter_->SetSashPosition((w-BG_SEGM_OP_SIZEX)/2, TRUE); + plotMapSplitter_->SetSashPosition(h/2, TRUE); + mapSplitter_->SetSashPosition((w-BG_SEGM_OP_SIZEX)/4, TRUE); + + //initalize edge maps... + customMap_ = (float *) NULL; + confMap_ = (float *) NULL; + gradMap_ = (float *) NULL; + weightMap_ = (float *) NULL; + + //indicate that the edge parameters have not changed + edgeParamsHaveChanged_ = false; + + //add margin to plots + phDiagram_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); + plotWindow1_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); + plotWindow2_->AddMargin(RANK_CONF_MARGINX,RANK_CONF_MARGINY); + + //add title to each individual plot + BgText bgText(1," Diagram of Region Boundary Data Points", *wxSWISS_FONT, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2-10); + phDiagram_->AddText(&bgText); + bgText.SetText("Confidence Map"); + plotWindow1_->AddText(&bgText); + bgText.SetText("Gradient Map"); + plotWindow2_->AddText(&bgText); + + //add x and y axis + phDiagram_->AddHorizontalAxis(RANK_CONF_MARGINX-2,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX+2,10,0.0,1.0); + phDiagram_->AddVerticalAxis (RANK_CONF_MARGINX-1,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY,RANK_CONF_IMSIZEX,10,0.0,1.0); + + //label x and y axis + bgText.SetText("Rank ( )"); + phDiagram_->LabelHorizontalAxis(&bgText); + bgText.SetText("Confidence ( )"); + phDiagram_->LabelVerticalAxis(&bgText); + + //place greek symbols + wxBitmap ro("ro", wxBITMAP_TYPE_RESOURCE), eta("eta", wxBITMAP_TYPE_RESOURCE); + BgBitmap ro_bmp(&ro, 1, RANK_CONF_MARGINX - 10, RANK_CONF_MARGINY/2 - 3); + BgBitmap eta_bmp(&eta, 2, RANK_CONF_MARGINX, RANK_CONF_MARGINY/2 - 3); + phDiagram_->AddBitmap(&ro_bmp); + phDiagram_->AddBitmap(&eta_bmp); + ro_bmp.SetPlotLocation(RANK_CONF_MARGINX+137,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY+35); + ro_bmp.SetId(3); + phDiagram_->AddBitmap(&ro_bmp); + wxBitmap rotated_eta("rotated_eta", wxBITMAP_TYPE_RESOURCE); + BgBitmap rotated_eta_bmp(&rotated_eta, 4, RANK_CONF_MARGINX-55,RANK_CONF_IMSIZEY+RANK_CONF_MARGINY-162); + phDiagram_->AddBitmap(&rotated_eta_bmp); + + //declare that segmentation window is open + window_open = true; + + //get parent tool bar and update it + toolbar = parent->GetToolBar(); + UpdateToolBar(); + + //disable confidence map text boxes + txtA_->Enable(false); + txtEpsilon_->Enable(false); + txtKernelSize_->Enable(false); + textA_->Enable(false); + textEpsilon_->Enable(false); + textKernelSize_->Enable(false); + + //disable run button + runButton_->Enable(false); + + //disable radio boxes + viewImSegRadio_->Enable(false); + operationRadio_->Enable(false); + + //disable view boundaries check box + viewBoundariesCheck_->Enable(false); + + //intialize parameter combo box + float *myParameters = new float [6]; + myParameters[0] = sigmaS; + myParameters[1] = sigmaR; + myParameters[2] = aij; + myParameters[3] = epsilon; + myParameters[4] = minRegion; + myParameters[5] = kernelSize; + paramComboBox_->SetCurrentList((void *) myParameters, 6); + isCurrentHistory_ = true; + + //turn on text box monitoring + checkTextBoxes_ = true; + + //initialize speedup level to medium + speedUpLevel_ = MED_SPEEDUP; + speedUpThreshold_ = (float) 0.1; + + //initialize max/min zoom + maxZoom_ = 0; + minZoom_ = 1; + +} + + +BgMdiSegmentChild::~BgMdiSegmentChild() +{ + if (hasBoundaries_ == 1) + displayImage_->RemovePointSet(boundaries_); + + if(filename_) delete [] filename_; + + delete optionsPanel_; + delete displayImage_; + + delete boundaries_; + delete whiteImage_; + delete segmImage_; + delete filtImage_; + delete cbgImage_; + + if (customMap_) delete [] customMap_; + if (confMap_) delete [] confMap_; + if (gradMap_) delete [] gradMap_; + if (weightMap_) delete [] weightMap_; + + g_children.DeleteObject(this); +} + +void BgMdiSegmentChild::OnViewImSeg(wxCommandEvent& WXUNUSED(event)) +{ + //if an image has not been loaded then exit this method... + if (hasImage_ == 0) + return; + + switch(viewImSegRadio_->GetSelection()) + { + + //view original image + case 0: + boundaries_->pen_.SetColour(*wxWHITE); + displayImage_->SetImage(cbgImage_->im_, cbgImage_->x_, cbgImage_->y_, cbgImage_->colorIm_); + break; + + //view filtered image + case 1: + if (hasFilter_ == 0) + { + viewImSegRadio_->SetSelection(0); + bgLog("Filter the image first!\n"); + return; + } else + { + boundaries_->pen_.SetColour(*wxWHITE); + displayImage_->SetImage(filtImage_->im_, filtImage_->x_, filtImage_->y_, filtImage_->colorIm_); + } + break; + + //view segmented image + case 2: + if (hasSegment_ == 0) + { + viewImSegRadio_->SetSelection(0); + bgLog("Segment the image first!\n"); + return; + } else + { + boundaries_->pen_.SetColour(*wxWHITE); + displayImage_->SetImage(segmImage_->im_, segmImage_->x_, segmImage_->y_, segmImage_->colorIm_); + } + break; + + //view boundaries + default: + if (hasBoundaries_ == 0) + { + viewImSegRadio_->SetSelection(0); + bgLog("Process the image first!\n"); + return; + } else + { + boundaries_->pen_.SetColour(*wxBLACK); + displayImage_->SetImage(whiteImage_->im_, whiteImage_->x_, whiteImage_->y_, whiteImage_->colorIm_); + } + } +} + +//specifies image operation(i.e. segment, filter or fuse regions) +void BgMdiSegmentChild::OnChangeOperation(wxCommandEvent& WXUNUSED(event)) +{ + + wxMenuBar *menubar = GetMenuBar(); + switch(operationRadio_->GetSelection()) + { + //segment the image + case 0: + menubar->SetLabel(BG_SEGM_SEGMENT, "Segment Image\tShift-R"); + break; + //filter the image + case 1: + menubar->SetLabel(BG_SEGM_SEGMENT, "Filter Image\tShift-R"); + break; + //fuse regions + default: + menubar->SetLabel(BG_SEGM_SEGMENT, "Fuse Regions\tShift-R"); + break; + } + + //done. + return; + +} + +//changes the paramters depending on the parameter list +void BgMdiSegmentChild::OnChangeParameters(wxCommandEvent& WXUNUSED(event)) +{ + float *myParameters; + + //get current selection index... + int selIndex = paramComboBox_->GetSelection(); + + //aquire current parameters and store them in "current parameter" slot... + if(isCurrentHistory_) + { + int csigmaS, cminRegion, ckernelSize; + float csigmaR, caij, cepsilon; + GetParameters(csigmaS, csigmaR, caij, cepsilon, cminRegion, ckernelSize, 0); + myParameters = (float *) paramComboBox_->GetCurrentListData(); + myParameters[0] = csigmaS; + myParameters[1] = csigmaR; + myParameters[2] = caij; + myParameters[3] = cepsilon; + myParameters[4] = cminRegion; + myParameters[5] = ckernelSize; + } + + //check to see if the "current parameter" slot has been selected, + //if so set the current history flag and use the parameters from + //current history slot + if(selIndex == 0) + { + isCurrentHistory_ = true; + myParameters = (float *) paramComboBox_->GetCurrentListData(); + } + //otherwise indicate that the current slot has not just been selected + //and get parameters from current parameter list + else + { + isCurrentHistory_ = false; + myParameters = (float *) paramComboBox_->GetParameterListData(selIndex-1); + } + + //set the text boxes... + char str[10]; + checkTextBoxes_ = false; + sprintf(str, "%d", bgRoundSign(myParameters[0])); + txtSigmaS_->SetValue(str); + sprintf(str, "%3.1f", myParameters[1]); + txtSigmaR_->SetValue(str); + sprintf(str, "%3.1f", myParameters[2]); + txtA_->SetValue(str); + sprintf(str, "%3.1f", myParameters[3]); + txtEpsilon_->SetValue(str); + sprintf(str, "%d", bgRoundSign(myParameters[4])); + txtMinRegion_->SetValue(str); + sprintf(str, "%d", bgRoundSign(myParameters[5])); + txtKernelSize_->SetValue(str); + checkTextBoxes_ = true; + +} + +void BgMdiSegmentChild::OnUpdateTextBoxes(wxCommandEvent& event) +{ + //update parameter history.... + if(checkTextBoxes_) + { + paramComboBox_->SetSelection(0); + isCurrentHistory_ = true; + } + + //check if a edge parameter has been changed + int id = event.GetId(); + if((id == BG_SEGM_TEXT_GRADWIN)||(id == BG_SEGM_TEXT_AIJ)||(id == BG_SEGM_TEXT_EPSILON)) + edgeParamsHaveChanged_ = true; + +} + +void BgMdiSegmentChild::OnUpdateSpeedUpLevel(wxCommandEvent& event) +{ + long menuItemId = event.GetId(); + wxMenuBar* myMenuBar = GetMenuBar(); + switch(menuItemId) + { + case BG_SEGM_SPEEDUP_MEDM: + speedUpLevel_ = MED_SPEEDUP; + myMenuBar->Check(BG_SEGM_SPEEDUP_NONE, false); + myMenuBar->Check(BG_SEGM_SPEEDUP_HIGH, false); + break; + case BG_SEGM_SPEEDUP_HIGH: + speedUpLevel_ = HIGH_SPEEDUP; + myMenuBar->Check(BG_SEGM_SPEEDUP_NONE, false); + myMenuBar->Check(BG_SEGM_SPEEDUP_MEDM, false); + { + BgSpeedSelect speedSelect(this, -1, "Select speed/quality", wxDefaultPosition, wxSize(220,150), + wxDEFAULT_DIALOG_STYLE | wxDIALOG_MODAL); + speedSelect.SetSliderValue(speedUpThreshold_); + if (speedSelect.ShowModal()==wxID_OK) + { + speedSelect.GetSliderValue(speedUpThreshold_); + } + } + + break; + default: + speedUpLevel_ = NO_SPEEDUP; + myMenuBar->Check(BG_SEGM_SPEEDUP_MEDM, false); + myMenuBar->Check(BG_SEGM_SPEEDUP_HIGH, false); + } +} + +void BgMdiSegmentChild::OnViewBoundaries(wxCommandEvent& WXUNUSED(event)) +{ + + if (hasBoundaries_ == false) + return; + + bool isChecked; + isChecked = viewBoundariesCheck_->GetValue(); + + if (isChecked) + { + // show edges + displayImage_->AddPointSet(boundaries_); + + } + else + { + // hide edges + displayImage_->RemovePointSet(boundaries_); + } + +} + + +//activates/de-activates the text boxes used for +//synergistic segmentation based on the use confidence +//map checkbox +void BgMdiSegmentChild::OnUseWeightMap(wxCommandEvent& WXUNUSED(event)) +{ + + //depending on use confidence map checkbox, activate/de-activate + //text boxes + if(useWeightMap_->GetValue()) + { + //enable text boxes + txtA_->Enable(true); + txtEpsilon_->Enable(true); + txtKernelSize_->Enable(true); + textA_->Enable(true); + textEpsilon_->Enable(true); + textKernelSize_->Enable(true); + } + else + { + //disable text boxes + txtA_->Enable(false); + txtEpsilon_->Enable(false); + txtKernelSize_->Enable(false); + textA_->Enable(false); + textEpsilon_->Enable(false); + textKernelSize_->Enable(false); + } + + //done. + return; +} + +void BgMdiSegmentChild::OnUpdatePlotWindow1(wxCommandEvent& event) +{ + int menuItemId = event.GetId(); + + //update checkmarks + winPanel1_->CheckViewItem(menuItemId); + + //change plot... + int i; + int data_length = width_*height_; + unsigned char *buffer = new unsigned char[data_length]; + BgText bgText(1,"ConfidenceMap", *wxSWISS_FONT, 0, 0); + switch(menuItemId) + { + case BG_CANVAS_VIEW1_GRADMAP: + bgText.SetText("Gradient Map"); + bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-40,RANK_CONF_MARGINY/2-10); + plotWindow1_->AddText(&bgText); + for(i = 0; i < data_length; i++) + buffer[i] = (unsigned char)(255*gradMap_[i] + 0.5); + plotWindow1_->SetImageFromGray(buffer, width_, height_); + break; + case BG_CANVAS_VIEW1_CONFMAP: + bgText.SetText("Confidence Map"); + bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-45,RANK_CONF_MARGINY/2-10); + plotWindow1_->AddText(&bgText); + for(i = 0; i < data_length; i++) + buffer[i] = (unsigned char)(255*confMap_[i] + 0.5); + plotWindow1_->SetImageFromGray(buffer, width_, height_); + break; + case BG_CANVAS_VIEW1_WEITMAP: + bgText.SetText("Weight Map"); + bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-35,RANK_CONF_MARGINY/2-10); + plotWindow1_->AddText(&bgText); + for(i = 0; i < data_length; i++) + buffer[i] = (unsigned char)(255*weightMap_[i] + 0.5); + plotWindow1_->SetImageFromGray(buffer, width_, height_); + break; + case BG_CANVAS_VIEW1_CUSTMAP: + bgText.SetText("Custom Weight Map"); + bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-60,RANK_CONF_MARGINY/2-10); + plotWindow1_->AddText(&bgText); + for(i = 0; i < data_length; i++) + buffer[i] = (unsigned char)(255*customMap_[i] + 0.5); + plotWindow1_->SetImageFromGray(buffer, width_, height_); + break; + } + + //de-allocate memory used by conf/gradient map buffer + delete [] buffer; +} + +void BgMdiSegmentChild::OnUpdatePlotWindow2(wxCommandEvent& event) +{ + int menuItemId = event.GetId(); + + //update checkmarks + winPanel2_->CheckViewItem(menuItemId); + + //change plot... + int i; + int data_length = width_*height_; + unsigned char *buffer = new unsigned char[data_length]; + BgText bgText(1,"ConfidenceMap", *wxSWISS_FONT, 0, 0); + switch(menuItemId) + { + case BG_CANVAS_VIEW2_GRADMAP: + bgText.SetText("Gradient Map"); + bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-40,RANK_CONF_MARGINY/2-10); + plotWindow2_->AddText(&bgText); + for(i = 0; i < data_length; i++) + buffer[i] = (unsigned char)(255*gradMap_[i] + 0.5); + plotWindow2_->SetImageFromGray(buffer, width_, height_); + break; + case BG_CANVAS_VIEW2_CONFMAP: + bgText.SetText("Confidence Map"); + bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-45,RANK_CONF_MARGINY/2-10); + plotWindow2_->AddText(&bgText); + for(i = 0; i < data_length; i++) + buffer[i] = (unsigned char)(255*confMap_[i] + 0.5); + plotWindow2_->SetImageFromGray(buffer, width_, height_); + break; + case BG_CANVAS_VIEW2_WEITMAP: + bgText.SetText("Weight Map"); + bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-35,RANK_CONF_MARGINY/2-10); + plotWindow2_->AddText(&bgText); + for(i = 0; i < data_length; i++) + buffer[i] = (unsigned char)(255*weightMap_[i] + 0.5); + plotWindow2_->SetImageFromGray(buffer, width_, height_); + break; + case BG_CANVAS_VIEW2_CUSTMAP: + bgText.SetText("Custom Weight Map"); + bgText.SetPlotLocation(RANK_CONF_MARGINX+width_/2-60,RANK_CONF_MARGINY/2-10); + plotWindow2_->AddText(&bgText); + for(i = 0; i < data_length; i++) + buffer[i] = (unsigned char)(255*customMap_[i] + 0.5); + plotWindow2_->SetImageFromGray(buffer, width_, height_); + break; + } + + //de-allocate memory used by conf/gradient map buffer + delete [] buffer; +} + + +void BgMdiSegmentChild::OnSaveEdgeInformation(wxCommandEvent& event) +{ + +#if defined(__WXGTK__) || defined(__WXMOTIF__) + wxFileDialog filedialog(this,"Save Edge Information","","", + "*",wxSAVE); +#else + wxFileDialog filedialog(this,"Save Edge Information","","", + "Matlab ASCII data files (*.dat)|*.dat|PGM Files (*.pgm)|*.pgm", + wxSAVE); +#endif + + if(filedialog.ShowModal()==wxID_OK) + { + + //get the image type + int dtype = filedialog.GetFilterIndex(); + + //obtain pointer to data + float *myData; + switch(event.GetId()) + { + case BG_CANVAS_SAVE_GRADMAP: + myData = gradMap_; + break; + case BG_CANVAS_SAVE_CONFMAP: + myData = confMap_; + break; + case BG_CANVAS_SAVE_WEITMAP: + myData = weightMap_; + break; + } + + //get the filename and path + char* path = (char*) filedialog.GetPath().c_str(); + char* filename = (char*) filedialog.GetFilename().c_str(); + + //PGM Image + if(dtype) + { + unsigned char *buf = new unsigned char [height_*width_]; + int i; + for(i = 0; i < height_*width_; i++) + buf[i] = myData[i]*255 + 0.5; + write_pgm_image(path, buf, height_, width_, "", 255); + delete [] buf; + } + else + //Matlab Data File + { + write_MATLAB_ASCII(path, myData, height_, width_); + } + } + +} + +void BgMdiSegmentChild::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + int w, h; + GetClientSize(&w, &h); + optionsPanel_->SetSize(0, 0, BG_SEGM_OP_SIZEX, h); + imagePlotSplitter_->SetSize(BG_SEGM_OP_SIZEX, 0, w-BG_SEGM_OP_SIZEX, h); + imagePlotSplitter_->SetSashPosition((w-BG_SEGM_OP_SIZEX)/2, TRUE); + plotMapSplitter_->SetSashPosition(h/2, TRUE); + mapSplitter_->SetSashPosition((w-BG_SEGM_OP_SIZEX)/4, TRUE); +} + +//clears display of ph diagram and rank and confidence maps +void BgMdiSegmentChild::ClearDisplay( void ) +{ + phDiagram_->ClearDisplay(); + plotWindow1_->ClearDisplay(); + plotWindow2_->ClearDisplay(); +} + +//turns plotting capability on/off +void BgMdiSegmentChild::UpdateDisplay(bool update) +{ + if(update) + { + phDiagram_->noUpdate_ = false; + plotWindow1_->noUpdate_ = false; + plotWindow2_->noUpdate_ = false; + } + else + { + phDiagram_->noUpdate_ = true; + plotWindow1_->noUpdate_ = true; + plotWindow2_->noUpdate_ = true; + } +} + +void BgMdiSegmentChild::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(TRUE); +} + +void BgMdiSegmentChild::OnClose(wxCloseEvent& event) +{ + //decrement global counter indicating number of frames open + gs_nFrames--; + //indicate that the window is now close (used by OnFocus) + window_open = false; + //reset the toolbar + if(gs_nFrames == 0) ResetToolBar(); + event.Skip(); +} + +void BgMdiSegmentChild::OnFocus(wxFocusEvent& WXUNUSED(event)) +{ + //update toolbar + if(!on_exit) UpdateToolBar(); + return; +} + +void BgMdiSegmentChild::ZoomWindow(void) +{ + //display zoom window + displayImage_->zoom_window = true; + displayImage_->zoom_in = false; + displayImage_->zoom_out = false; +} + +void BgMdiSegmentChild::ZoomIn(void) +{ + //zoom into display image + displayImage_->zoom_window = false; + displayImage_->zoom_in = true; + displayImage_->zoom_out = false; + return; +} + +void BgMdiSegmentChild::ZoomOut(void) +{ + //zoom out of display image + displayImage_->zoom_window = false; + displayImage_->zoom_in = false; + displayImage_->zoom_out = true; + return; +} + +void BgMdiSegmentChild::NoZoom(void) +{ + //do not zoom display image + displayImage_->zoom_window = false; + displayImage_->zoom_in = false; + displayImage_->zoom_out = false; + return; +} + +void BgMdiSegmentChild::UpdateZoomControl(void) +{ + //determine whether to enable zoom in control based on maximum zoom + if(maxZoom_ || minZoom_) + UpdateToolBar(); + else + { + toolbar->EnableTool(BG_ZOOM_IN, true); + toolbar->EnableTool(BG_ZOOM_OUT, true); +// toolbar->Realize(); + } +} + +void BgMdiSegmentChild::RunEnable(void) +{ + wxMenuBar *menubar = GetMenuBar(); + menubar->Enable(BG_SEGM_LOAD_MAP, true); + menubar->Enable(BG_SEGM_SEGMENT, true); + runButton_->Enable(true); + viewImSegRadio_->Enable(true); + viewImSegRadio_->Enable(1, false); + viewImSegRadio_->Enable(2, false); + viewImSegRadio_->Enable(3, false); +} + +void BgMdiSegmentChild::SaveEnable(void) +{ + toolbar->EnableTool(BG_SAVE_RESULT, true); +} + +void BgMdiSegmentChild::UpdateToolBar(void) +{ + //update toolbar (except during close) + if(window_open) + { + //determine whether to enable save based on whether segmentation + //has occurred + bool save_enable; + if(hasSegment_) + save_enable = true; + else + save_enable = false; + + //determine whether to enable zoom controls based on whether image + //has been loaded + bool load_enable; + if(hasImage_) + load_enable = true; + else + load_enable = false; + + //determine whether to enable zoom in control based on maximum zoom + bool max_zoom; + if(maxZoom_) + max_zoom = true; + else + max_zoom = false; + + //determine whether to enable zoom out control based on minimum zoom + bool min_zoom; + if(minZoom_) + min_zoom = true; + else + min_zoom = false; + + //adjust toolbar + toolbar->SetToolShortHelp(BG_LOAD_IMAGE, "Load image to perform image segmentation"); + toolbar->SetToolShortHelp(BG_SAVE_RESULT, "Save segmented image"); + toolbar->EnableTool(BG_SAVE_RESULT, save_enable); + toolbar->EnableTool(BG_CROSS, load_enable); + toolbar->EnableTool(BG_ZOOM_IN, ((load_enable)&&(!max_zoom))); + toolbar->EnableTool(BG_ZOOM_OUT, ((load_enable)&&(!min_zoom))); + toolbar->EnableTool(BG_POINTER, true); + + //set to no zoom + toolbar->ToggleTool(BG_CROSS, false); + toolbar->ToggleTool(BG_ZOOM_IN, false); + toolbar->ToggleTool(BG_ZOOM_OUT, false); + toolbar->ToggleTool(BG_POINTER, true); + displayImage_->SetCursor(wxCURSOR_ARROW); + NoZoom(); + } + return; +} + +void BgMdiSegmentChild::ResetToolBar(void) +{ + //update toolbar + toolbar->SetToolShortHelp(BG_LOAD_IMAGE, "Load image to process"); + toolbar->SetToolShortHelp(BG_SAVE_RESULT, "Save result"); + toolbar->EnableTool(BG_SAVE_RESULT, false); + toolbar->EnableTool(BG_CROSS, false); + toolbar->EnableTool(BG_ZOOM_IN, false); + toolbar->EnableTool(BG_ZOOM_OUT, false); + toolbar->EnableTool(BG_POINTER, false); + toolbar->ToggleTool(BG_CROSS, false); + toolbar->ToggleTool(BG_ZOOM_IN, false); + toolbar->ToggleTool(BG_ZOOM_OUT, false); + toolbar->ToggleTool(BG_POINTER, false); + return; +} + +void BgMdiSegmentChild::ReadImage(char *pathname, char *filename) +{ + //take away point set if boundaries have been calculated + if(hasBoundaries_) + { + hasBoundaries_ = false; + displayImage_->RemovePointSet(boundaries_); + boundaries_->CleanData(); + } + + if(displayImage_->SetImage(pathname) == 0) + return; + + //obtain and store image filename + if(filename_) delete [] filename_; + filename_ = new char [strlen(filename) + 1]; + strcpy(filename_, filename); + + displayImage_->showbitmap_ = true; + + //set value of view boundaries control + viewBoundariesCheck_->SetValue(0); + + //set image view option to original + viewImSegRadio_->SetSelection(0); + + //get image dimension + width_ = displayImage_->pimage->GetWidth(); + height_ = displayImage_->pimage->GetHeight(); + + //reset zoom level of display image + displayImage_->Zoom(1); + + //reset max/min zoom flags + maxZoom_ = 0; + minZoom_ = 1; + + //set cbgImage + cbgImage_->SetImageFromRGB(displayImage_->pimage->GetData(), width_, height_, true); + hasImage_ = 1; + hasSegment_ = 0; + hasBoundaries_ = 0; + + //adjust titles + BgText title(1, "Confidence Map", *wxSWISS_FONT, RANK_CONF_MARGINX+width_/2-45,RANK_CONF_MARGINY/2-10); + plotWindow1_->AddText(&title); + title.SetText("Gradient Map"); + title.SetPlotLocation(RANK_CONF_MARGINX+width_/2-40,RANK_CONF_MARGINY/2-10); + plotWindow2_->AddText(&title); + + //add axis + plotWindow1_->ClearAxis(); + plotWindow2_->ClearAxis(); + plotWindow1_->AddHorizontalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, width_, 5, 0, width_-1); + plotWindow1_->AddVerticalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, height_, 5, 0, height_-1); + plotWindow2_->AddHorizontalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, width_, 5, 0, width_-1); + plotWindow2_->AddVerticalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, height_, 5, 0, height_-1); + + //label axis + BgText label(1, "x", *wxSWISS_FONT, 0, 0); + plotWindow1_->LabelHorizontalAxis(&label); + plotWindow2_->LabelHorizontalAxis(&label); + label.SetText("y"); + plotWindow1_->LabelVerticalAxis(&label); + plotWindow2_->LabelVerticalAxis(&label); + plotWindow1_->RotateVerticalAxisLabel(-90); + plotWindow2_->RotateVerticalAxisLabel(-90); + + //set white image + unsigned char *img = new unsigned char [(width_)*(height_)*3]; + memset(img, 255, (width_)*(height_)*3); + whiteImage_->SetImageFromRGB(img, width_, height_, true); + delete [] img; + + //clear the plot window displays + ClearDisplay(); + + //do no update the plot windows + UpdateDisplay(false); + + //delete edge maps if they exists... + if(customMap_) delete [] customMap_; + if(gradMap_ ) delete [] gradMap_; + if(confMap_ ) delete [] confMap_; + if(weightMap_) delete [] weightMap_; + + //set edge maps to NULL... + customMap_ = (float *) NULL; + gradMap_ = (float *) NULL; + confMap_ = (float *) NULL; + weightMap_ = (float *) NULL; + + //update interface... + + /***********************************************/ + + //enable run + RunEnable(); + + //enable operations radio box + operationRadio_->Enable(true); + + //update the tool bar + UpdateToolBar(); + + //set window title + wxString statusname; + statusname.Printf(_T("Segmentation Frame %d - %s (%d x %d) [Original Image]"), window_number_, filename_, width_, height_); + SetTitle(statusname); + + //update the menubar + wxMenuBar *menubar = GetMenuBar(); + menubar->Enable(BG_SEGM_SAVE_SEGMENTED, false); + menubar->Enable(BG_SEGM_USE_MAP, false); + + //update window menus + winPanel1_->view_menu->Enable(BG_CANVAS_VIEW1_CUSTMAP, false); + winPanel2_->view_menu->Enable(BG_CANVAS_VIEW2_CUSTMAP, false); + winPanel1_->EnableMenu(false); + winPanel2_->EnableMenu(false); + + /***********************************************/ + +} + +void BgMdiSegmentChild::OnLoadImage(wxCommandEvent& WXUNUSED(event)) +{ +// get the file name +// wxFileDialog filedialog(this,"Choose an image file","","", +// "All files (*.*)|*.*|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm", +// wxOPEN); +#if defined(__WXGTK__) || defined(__WXMOTIF__) + wxFileDialog filedialog(this,"Choose an image file","","", + "*",wxOPEN); +#else + wxFileDialog filedialog(this,"Choose an image file","","", + "Common image files|*.png;*.bmp;*.gif;*.tif;*.tiff;*.jpg;*.pnm;*.pgm;*.ppm|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|TIFF files (*.tif)|*.tif|JPEG files (*.jpg)|*.jpg|PNM files (*.pnm)|*.pnm|PGM/PPM files (*.pgm,*.ppm)|*.pgm;*.ppm", + wxOPEN); +#endif + + if(filedialog.ShowModal()==wxID_OK) + { + //take away point set if boundaries have been calculated + if(hasBoundaries_) + { + hasBoundaries_ = false; + displayImage_->RemovePointSet(boundaries_); + boundaries_->CleanData(); + } + + if (displayImage_->SetImage(filedialog.GetPath().c_str()) == 0) + return; + bgLog("Image %s loaded\n",filedialog.GetPath().c_str()); + + //obtain and store image filename + if(filename_) delete [] filename_; + filename_ = new char [strlen(filedialog.GetFilename().c_str()) + 1]; + strcpy(filename_, filedialog.GetFilename().c_str()); + + displayImage_->showbitmap_ = true; + + //set value of view boundaries control + viewBoundariesCheck_->SetValue(0); + + //set image view option to original + viewImSegRadio_->SetSelection(0); + + //set operation option to segment + operationRadio_->SetSelection(0); + + //get image dimension + width_ = displayImage_->pimage->GetWidth(); + height_ = displayImage_->pimage->GetHeight(); + + //reset zoom level of display image + displayImage_->Zoom(1); + + //reset max/min zoom flags + maxZoom_ = 0; + minZoom_ = 1; + + //set cbgImage + cbgImage_->SetImageFromRGB(displayImage_->pimage->GetData(), width_, height_, true); + hasImage_ = 1; + hasFilter_ = 0; + hasSegment_ = 0; + hasBoundaries_ = 0; + + //adjust titles + BgText title(1, "Confidence Map", *wxSWISS_FONT, RANK_CONF_MARGINX+width_/2-45,RANK_CONF_MARGINY/2-10); + plotWindow1_->AddText(&title); + title.SetText("Gradient Map"); + title.SetPlotLocation(RANK_CONF_MARGINX+width_/2-40,RANK_CONF_MARGINY/2-10); + plotWindow2_->AddText(&title); + + //add axis + plotWindow1_->ClearAxis(); + plotWindow2_->ClearAxis(); + plotWindow1_->AddHorizontalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, width_, 5, 0, width_-1); + plotWindow1_->AddVerticalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, height_, 5, 0, height_-1); + plotWindow2_->AddHorizontalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, width_, 5, 0, width_-1); + plotWindow2_->AddVerticalAxis(RANK_CONF_MARGINX, RANK_CONF_MARGINY+height_, height_, 5, 0, height_-1); + + //label axis + BgText label(1, "x", *wxSWISS_FONT, 0, 0); + plotWindow1_->LabelHorizontalAxis(&label); + plotWindow2_->LabelHorizontalAxis(&label); + label.SetText("y"); + plotWindow1_->LabelVerticalAxis(&label); + plotWindow2_->LabelVerticalAxis(&label); + plotWindow1_->RotateVerticalAxisLabel(-90); + plotWindow2_->RotateVerticalAxisLabel(-90); + + //set white image + unsigned char *img = new unsigned char [(width_)*(height_)*3]; + memset(img, 255, (width_)*(height_)*3); + whiteImage_->SetImageFromRGB(img, width_, height_, true); + delete [] img; + + //clear the plot window displays + ClearDisplay(); + + //do not update plot windows + UpdateDisplay(false); + + //delete edge maps if they exists... + if(customMap_) delete [] customMap_; + if(gradMap_ ) delete [] gradMap_; + if(confMap_ ) delete [] confMap_; + if(weightMap_) delete [] weightMap_; + + //set edge maps to NULL... + customMap_ = (float *) NULL; + gradMap_ = (float *) NULL; + confMap_ = (float *) NULL; + weightMap_ = (float *) NULL; + + //update interface... + + /***********************************************/ + + //enable run + RunEnable(); + + //enable operations radio box + operationRadio_->Enable(true); + + //update the tool bar + UpdateToolBar(); + + //set window title + wxString statusname; + statusname.Printf(_T("Segmentation Frame %d - %s (%d x %d) [Original Image]"), window_number_, filename_, width_, height_); + SetTitle(statusname); + + //update the menubar + wxMenuBar *menubar = GetMenuBar(); + menubar->Enable(BG_SEGM_SAVE_SEGMENTED, false); + menubar->Enable(BG_SEGM_USE_MAP, false); + + //update window menus + winPanel1_->view_menu->Enable(BG_CANVAS_VIEW1_CUSTMAP, false); + winPanel2_->view_menu->Enable(BG_CANVAS_VIEW2_CUSTMAP, false); + winPanel1_->EnableMenu(false); + winPanel2_->EnableMenu(false); + + /***********************************************/ + + } +} + + +void BgMdiSegmentChild::LoadCustomWeightMap(wxCommandEvent& WXUNUSED(event)) +{ + + //make sure an image was read... + if(hasImage_ == 0) + { + bgLog("image has not been loaded, load image.\n"); + return; + } + + //compute data length + int xsz = cbgImage_->x_, ysz = cbgImage_->y_; + int data_length = (xsz)*(ysz); + +// get the file name +#if defined(__WXGTK__) || defined(__WXMOTIF__) + wxFileDialog filedialog(this,"Upload Custom Weight Map","","", + "*",wxOPEN); +#else + wxFileDialog filedialog(this,"Upload Custom Weight Map","","", + "Matlab ASCII data files (*.dat)|*.dat|All Files (*.*)|*.*", + wxOPEN); +#endif + if(filedialog.ShowModal()==wxID_OK) + { + + //de-allocate memory for customMap (if it exists) + if(customMap_) delete [] customMap_; + + //allocate memory for customMap + customMap_ = new float [data_length]; + + //get data file name + const char *filename = filedialog.GetPath().c_str(); + + //attempt to read in data + FILE *fp = fopen(filename, "rb"); + int i; + for(i = 0; i < data_length; i++) + { + if(!fscanf(fp, "%f", &customMap_[i])) + { + bgLog("Load Map Error: Data length does not match the size of the image."); + delete [] customMap_; + customMap_ = NULL; + return; + } + } + fclose(fp); + + //inform user of successful upload + bgLog("Weight map '%s' successfully uploaded.\n", filename); + + //enable use custom weight map menu items + wxMenuBar* myMenuBar = GetMenuBar(); + myMenuBar->Enable(BG_SEGM_USE_MAP, true); + winPanel1_->view_menu->Enable(BG_CANVAS_VIEW1_CUSTMAP, true); + winPanel2_->view_menu->Enable(BG_CANVAS_VIEW2_CUSTMAP, true); + + } +} + +void BgMdiSegmentChild::OnSaveSegmentedImage(wxCommandEvent& WXUNUSED(event)) +{ + if ((hasSegment_ == 0)&&(hasFilter_ == 0)) + { + bgLog("No result to save. Run segmenter.\n"); + return; + } + +#if defined(__WXGTK__) || defined(__WXMOTIF__) + wxFileDialog filedialog(this,"Choose an image file","","", + "*",wxSAVE); +#else + wxFileDialog filedialog(this,"Choose an image file","","", + "PNM files (*.pnm)|*.pnm|PNG files (*.png)|*.png|PCX files (*.pcx)|*.pcx|PGM files (*.pgm)|*.pgm|JPEG files (*.jpg) (not recommended)|*.jpg", + wxSAVE); +#endif + if(filedialog.ShowModal()==wxID_OK) + { + + //get the image type + int imtype; + switch (filedialog.GetFilterIndex()) + { + case 0: + imtype = wxBITMAP_TYPE_PNM; + break; + case 1: + imtype = wxBITMAP_TYPE_PNG; + break; + case 2: + imtype = wxBITMAP_TYPE_PCX; + break; + case 3: + imtype = wxBITMAP_TYPE_ANY; + break; + case 4: + imtype = wxBITMAP_TYPE_JPEG; + break; + default: + return; + } + + //if the filtered image is available then save it... + if(hasFilter_ == 1) + { + + //get path and add extension + char *path = new char [strlen(filedialog.GetPath()) + 1]; + strcpy(path, filedialog.GetPath()); + BgAddExtension(&path, "_filt"); + + //convert the image to wxImage format... + wxImage tmpIm(filtImage_->x_, filtImage_->y_); + unsigned char* tmpImData; + tmpImData = tmpIm.GetData(); + filtImage_->GetImageColor(tmpImData); + + //save the image... + tmpIm.SaveFile(path, imtype); + bgLog("Filtered image saved to:\t'%s'.\n", path); + + //de-allocate memory + delete path; + + } + + //if the segmented image is available then save it... + if(hasSegment_ == 1) + { + + //get path and add extension + char *path = new char [strlen(filedialog.GetPath()) + 1]; + strcpy(path, filedialog.GetPath()); + BgAddExtension(&path, "_segm"); + + //convert the image to wxImage format... + wxImage tmpIm(segmImage_->x_, segmImage_->y_); + unsigned char* tmpImData; + tmpImData = tmpIm.GetData(); + segmImage_->GetImageColor(tmpImData); + + //save the image... + tmpIm.SaveFile(path, imtype); + bgLog("Segmented image saved to:\t'%s'.\n", path); + + //de-allocate memory + delete [] path; + + } + + //save boundaries + OnSaveBoundaries((char*)filedialog.GetPath().c_str(), imtype); + + } +} + +//saves edge map +void BgMdiSegmentChild::OnSaveBoundaries(char *filename, int imtype) +{ + + //make sure boundaries exist before proceeding... + if(hasBoundaries_ == 0) + return; + + //create edge map + int width = cbgImage_->x_, height = cbgImage_->y_; + wxImage tmpImg(width, height); + unsigned char *buf = tmpImg.GetData(); + memset(buf, 255, width*height*3*sizeof(unsigned char)); + int n = boundaries_->n_; + int i, dp, x, y; + for(i = 0; i < n; i++) + { + x = boundaries_->x_[i]; + y = boundaries_->y_[i]; + dp = y*width+x; + buf[3*dp] = buf[3*dp+1] = buf[3*dp+2] = 0; + } + + //create new filename (add _em extension) + char *new_filename = new char [strlen(filename) + 1]; + strcpy(new_filename, filename); + BgAddExtension(&new_filename, "_bndy"); + + //save edgemap using specified filename and image format + tmpImg.SaveFile(new_filename, imtype); + bgLog("Boundaries saved to:\t'%s'.\n", new_filename); + + //de-allocate memory + delete [] new_filename; + + //done. + return; + +} + +//construct a ph diagram using the boundary pixels +//aquired from image segmentation (also outputs results +//to 'xyrc.txt' +void BgMdiSegmentChild::SetphDiagram(int width, float *confMap, float *rankMap) +{ + unsigned char* buf; + int xsz = RANK_CONF_IMSIZEX; + int ysz = RANK_CONF_IMSIZEY; + int imsz = xsz*ysz; + buf = new unsigned char[imsz]; + int i; + for (i=0; i<imsz; i++) + buf[i] = 255; + + int l, c, dpoint; + int n = boundaries_->n_; + int *xpos = boundaries_->x_, *ypos = boundaries_->y_; + for (i=0; i<n; i++) + { + dpoint = (ypos[i])*width+xpos[i]; + if ((rankMap[dpoint]>0) && (confMap[dpoint]>0)) + { + c = (int) (rankMap[dpoint]*((double) xsz)); + c = (c>=xsz) ? xsz-1 : c; + l = (int) (confMap[dpoint]*((double) ysz)); + l = (l>=ysz) ? ysz-1 : l; + l = ysz-1-l; + buf[c+l*xsz]=80; + + } + } + + phDiagram_->SetImageFromGray(buf, xsz, ysz); + + //adjust scroll bar... + phDiagram_->SetScrollbars(1, 1, xsz+2*RANK_CONF_MARGINX, ysz+2*RANK_CONF_MARGINY+40); + delete [] buf; +} + +void mySegment(void *Object) +{ + BgMdiSegmentChild *segmObj = (BgMdiSegmentChild *) Object; + segmObj->Segment(); +} + +void BgMdiSegmentChild::OnSegment(wxCommandEvent& WXUNUSED(event)) +{ + + //get parameters from GUI + int error = GetParameters(sigmaS, sigmaR, aij, epsilon, minRegion, kernelSize, 1); + if(error) + return; + + //create the working thread + BgThread *workingThread = new BgThread(wxTHREAD_DETACHED, mySegment, this); + stop_flag = false; + workingThread->Create(); + workingThread->Run(); + + //determine progress bar title and message + int operation = operationRadio_->GetSelection(); + char myMessage[80], myTitle[80]; + switch (operation) + { + //filter + case 1: + strcpy(myTitle, "Image Filtering Progress"); + strcpy(myMessage, "Filtering Image..."); + break; + //fuse regions + case 2: + strcpy(myTitle, "Region Fusing Progress"); + strcpy(myMessage, "Fusing Image Regions..."); + break; + //segment + default: + strcpy(myTitle, "Image Segmentation Progress"); + strcpy(myMessage, "Segmenting Image..."); + break; + } + + //call progress dialog + bool done; + percentDone = 0; + wxProgressDialog progressDialog(myTitle, myMessage, 100, this, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); + while((done = progressDialog.Update(percentDone))&&(percentDone != 100)) wxYield(); + if(!done) stop_flag = true; //if the algorithm is not done but the user aborted the operation + //then tell the thread to stop running + + //if its succesfully completed update the parameter history box + if(done) + { + int selIndex = paramComboBox_->GetSelection(); + if(selIndex) + { + paramComboBox_->UseParameterList(selIndex-1); + } + else + { + float *myParameters = new float [6]; + myParameters[0] = sigmaS; + myParameters[1] = sigmaR; + myParameters[2] = aij; + myParameters[3] = epsilon; + myParameters[4] = minRegion; + myParameters[5] = kernelSize; + paramComboBox_->AddParameterList((void *) myParameters, 6); + } + + //set the selection to the current parameter slot + paramComboBox_->SetSelection(0); + isCurrentHistory_ = true; + } + return; + +} + +void BgMdiSegmentChild::Segment( void ) +{ + // parameters + // sigma_s + // sigma_r + // a + // epsilon + // minRegion + // kernel radius + // filter + // speedup level + + if (hasImage_ == 0) + { + bgLog("No image loaded!\n"); + return; + } + + //if image segmentaiton is not synergistic clear + //display and disable it, otherwise enable it + if(!useWeightMap_->GetValue()) + { + ClearDisplay(); + UpdateDisplay(false); + } + else + { + UpdateDisplay(true); + } + + //display parameters to the user + if(useWeightMap_->GetValue()) + { + bgLog("Input parameters:\n"); + bgLog("\tSpatial Bandwidth\t\t= %4d\n\tColor Bandwidth\t\t= %4.1f\n", sigmaS, sigmaR); + bgLog("\tMinimum Region\t\t= %4d\n", minRegion); + bgLog("\tGradient Window Radius\t= %4d\n", kernelSize); + bgLog("\tMixing Parameter\t\t= %4.1f\n", aij); + bgLog("\tThreshold\t\t\t= %4.1f\n", epsilon); + } + else + { + bgLog("Input parameters:\n"); + bgLog("\tSpatial Bandwidth\t= %4d\n\tColor Bandwidth\t= %4.1f\n", sigmaS, sigmaR); + bgLog("\tMinimum Region\t= %4d\n", minRegion); + } + + //obtain image dimensions + int width, height; + width = cbgImage_->x_; + height = cbgImage_->y_; + + //obtain image type (color or grayscale) + imageType gtype; + if(cbgImage_->colorIm_) + gtype = COLOR; + else + gtype = GRAYSCALE; + + //if gradient and confidence maps are not defined, + //and synergistic segmentation is requested, then compute them; + //also compute them if the parameters have changed + if(useWeightMap_->GetValue()) + { + + //if the weight map has already been defined + //then find out if it needs to be recomputed + if((weightMap_)&&(edgeParamsHaveChanged_)) + { + delete [] confMap_; + delete [] gradMap_; + delete [] weightMap_; + weightMap_ = (float *) NULL; + //indicate that the change has been recognized... + edgeParamsHaveChanged_ = false; + } + + //if the weight map has not been computed or discarded + //then recompute it... + if(!weightMap_) + { + + //allocate memory for gradient and confidence maps + confMap_ = new float[width*height]; + gradMap_ = new float[width*height]; + + //compute gradient and confidence maps + BgEdgeDetect edgeDetector(kernelSize); + edgeDetector.ComputeEdgeInfo(cbgImage_, confMap_, gradMap_); + + //compute weight map... + + /******************************************************************/ + + //allocate memory for weight map + weightMap_ = new float[width*height]; + + //compute weight map using gradient and confidence maps + int i; + for (i=0; i<width*height; i++) + { + if (gradMap_[i] > 0.02) + weightMap_[i] = aij*gradMap_[i] + (1 - aij)*confMap_[i]; + else + weightMap_[i] = 0; + } + + /******************************************************************/ + } + + } + + //determine operation (filtering or segmentation) + int operation = operationRadio_->GetSelection(); + + //create instance of image processor class + msImageProcessor *iProc = new msImageProcessor(); + + //define an input image using the image under consideration + //(if filtering or segmentation has taken place, then use this + // result upon performing fusing...) + if((operation == 2)&&(hasFilter_)) + iProc->DefineImage(filtImage_->im_, gtype, height, width); + else + iProc->DefineImage(cbgImage_->im_, gtype, height, width); + + //determine if a custom weight map is to be used + wxMenuBar *menubar = GetMenuBar(); + bool useCustomMap = menubar->IsChecked(BG_SEGM_USE_MAP); + + //set the weight map (if one was specified and a custom map is not being utilized) + if((useWeightMap_->GetValue())&&(weightMap_)&&(!useCustomMap)) iProc->SetWeightMap(weightMap_, epsilon); + + //set the custom map (if one was provided) + if((useWeightMap_->GetValue())&&(customMap_)&&(useCustomMap)) iProc->SetWeightMap(customMap_, epsilon); + + //check for errors in image definition or in the setting + //of the confidence map... + if (iProc->ErrorStatus) + { + bgLog("%s\n", iProc->ErrorMessage); + return; + } + + //perform image segmentation or filtering.... + timer_start(); //start the timer + iProc->SetSpeedThreshold(speedUpThreshold_); + switch(operation) + { + //filter + case 1: + + iProc->Filter(sigmaS, sigmaR, speedUpLevel_); + if (iProc->ErrorStatus == EL_ERROR) + { + bgLog("%s\n", iProc->ErrorMessage); + return; + } else if (iProc->ErrorStatus == EL_HALT) + { + break; + } + + //obtain the filtered image.... + filtImage_->Resize(width, height, cbgImage_->colorIm_); + iProc->GetResults(filtImage_->im_); + if (iProc->ErrorStatus == EL_ERROR) + { + bgLog("%s\n", iProc->ErrorMessage); + return; + } + + //indicate that only the filtered image has been computed... + hasFilter_ = 1; + hasSegment_ = 0; + + break; + + //fuse + case 2: + + iProc->FuseRegions(sigmaR, minRegion); + if (iProc->ErrorStatus == EL_ERROR) + { + bgLog("%s\n", iProc->ErrorMessage); + return; + } else if (iProc->ErrorStatus == EL_HALT) + { + break; + } + + //obtain the segmented image... + segmImage_->Resize(width, height, cbgImage_->colorIm_); + iProc->GetResults(segmImage_->im_); + if (iProc->ErrorStatus == EL_ERROR) + { + bgLog("%s\n", iProc->ErrorMessage); + return; + } + + //indicate that the segmented image has been computed... + hasSegment_ = 1; + + break; + + //segment + default: + + //filter the image... + iProc->Filter(sigmaS, sigmaR, speedUpLevel_); + if (iProc->ErrorStatus == EL_ERROR) + { + bgLog("%s\n", iProc->ErrorMessage); + return; + } else if (iProc->ErrorStatus == EL_HALT) + { + break; + } + + //filter the image.... + int dim; + if(cbgImage_->colorIm_) + dim = 3; + else + dim = 1; + unsigned char *tempImage = new unsigned char [dim*height*width]; + iProc->GetResults(tempImage); + if (iProc->ErrorStatus == EL_ERROR) + { + bgLog("%s\n", iProc->ErrorMessage); + delete [] tempImage; + return; + } + + //fuse regions... + iProc->FuseRegions(sigmaR, minRegion); + if (iProc->ErrorStatus == EL_ERROR) + { + bgLog("%s\n", iProc->ErrorMessage); + delete [] tempImage; + return; + } else if (iProc->ErrorStatus == EL_HALT) + { + delete [] tempImage; + break; + } + + //obtain the segmented and filtered image... + filtImage_->Resize(width, height, cbgImage_->colorIm_); + memcpy(filtImage_->im_, tempImage, dim*height*width*sizeof(unsigned char)); + delete [] tempImage; + segmImage_->Resize(width, height, cbgImage_->colorIm_); + iProc->GetResults(segmImage_->im_); + if (iProc->ErrorStatus) + { + bgLog("%s\n", iProc->ErrorMessage); + return; + } + + //indicate that both the filtered and segmented image have been computed... + hasFilter_ = 1; + hasSegment_ = 1; + + } + + //check and see if the algorithm has been halted, if so + //then de-allocate the image processing object and + //indicate to the working thread that it is safe + //to exit at this point and exit + if(iProc->ErrorStatus == EL_HALT) + { + delete iProc; + stop_flag = false; + bgLog("Operation Canceled.\n"); + return; + } + + //set has boundaries to true + hasBoundaries_ = true; + + //clean boundary data if any exists + boundaries_->CleanData(); + + //get boundary indeces from region list object + //of the image processor object... + RegionList *regionList = iProc->GetBoundaries(); + int *regionIndeces = regionList->GetRegionIndeces(0); + int numRegions = regionList->GetNumRegions(); + int boundaryPointCount = 0; + + //calculate the number of boundary points stored by region list + //class + int i; + for(i = 0; i < numRegions; i++) + boundaryPointCount += regionList->GetRegionCount(i); + + //create a point set using calculated boundary point count... + boundaries_->x_ = new int [boundaryPointCount]; + boundaries_->y_ = new int [boundaryPointCount]; + boundaries_->n_ = boundaryPointCount; + for(i = 0; i < boundaryPointCount; i++) + { + boundaries_->x_[i] = regionIndeces[i]%width; + boundaries_->y_[i] = regionIndeces[i]/width; + } + + //set pen width, and style + boundaries_->pen_.SetWidth(1); + boundaries_->pen_.SetStyle(wxSOLID); + + //set point type to point (= 1) + boundaries_->type_ = 1; + + //construct the phDiagram + if(useWeightMap_->GetValue()) SetphDiagram(width, confMap_, gradMap_); + + //display the confidence and gradient maps respectively + if(useWeightMap_->GetValue()) + { + wxCommandEvent myevent; + myevent.m_id = BG_CANVAS_VIEW1_CONFMAP; + OnUpdatePlotWindow1(myevent); + myevent.m_id = BG_CANVAS_VIEW2_GRADMAP; + OnUpdatePlotWindow2(myevent); + } + + //delete the image processing object + delete iProc; + + //done. + + //stop the timer + timer_stop(); + + //update the GUI... + + /**********************************************************************************/ + + //update the menu bar + menubar->Enable(BG_SEGM_SAVE_SEGMENTED, true); + + //update tool bar + SaveEnable(); + + //update segmentation window.... + switch(operation) + { + + //the image has been filtered only.... + case 1: + viewImSegRadio_->Enable(1, true); + viewImSegRadio_->Enable(2, false); + viewImSegRadio_->SetSelection(1); + break; + + //the image has been segmented only... + case 2: + viewImSegRadio_->Enable(2, true); + viewImSegRadio_->SetSelection(2); + break; + + //image has been filtered and segmented... + default: + viewImSegRadio_->Enable(1, true); + viewImSegRadio_->Enable(2, true); + viewImSegRadio_->SetSelection(2); + break; + + } + viewImSegRadio_->Enable(3, true); + viewBoundariesCheck_->Enable(true); + wxCommandEvent zcev; + OnViewImSeg(zcev); + + //update the menu bars... + winPanel1_->EnableMenu(useWeightMap_->GetValue()); + winPanel2_->EnableMenu(useWeightMap_->GetValue()); + + /**********************************************************************************/ + + //set progress to 100% (need this for case of filtering) + percentDone = 100; + + //indicate that it is safe for the thread to stop executing + stop_flag = false; + + //done. + return; + +} + +int BgMdiSegmentChild::GetParameters(int &sigmaS, float &sigmaR, float &aij, float &epsilon, int &minRegion, int &kernelSize, int dataEntryCheck) +{ + + double tempd; + char str[10]; + + //do not perform data entry check + if(!dataEntryCheck) + { + //sigmaS + txtSigmaS_->GetValue().ToDouble(&tempd); + sigmaS = bgRoundSign(tempd); + + //sigmaR + txtSigmaR_->GetValue().ToDouble(&tempd); + sigmaR = (float) tempd; + + //minRegion + txtMinRegion_->GetValue().ToDouble(&tempd); + minRegion = bgRoundSign(tempd); + + //kernel size + txtKernelSize_->GetValue().ToDouble(&tempd); + kernelSize = bgRoundSign(tempd); + + //aij + txtA_->GetValue().ToDouble(&tempd); + aij = (float) tempd; + + //epsilon + txtEpsilon_->GetValue().ToDouble(&tempd); + epsilon = (float) tempd; + + //done. + return 0; + } + + //perform data entry check + if ((txtSigmaS_->GetValue().ToDouble(&tempd) == TRUE) && (tempd > 0)) + { + sigmaS = (int)(tempd + 0.5); + sprintf(str, "%d", sigmaS); + txtSigmaS_->SetValue(str); + } + else + { + bgLog("The value of the spatial bandwidth cannot be zero or negative.\n"); + return 1; + } + if ((txtSigmaR_->GetValue().ToDouble(&tempd) == TRUE) && (tempd > 0)) + sigmaR = tempd; + else + { + bgLog("The value of the range bandwidth cannot be zero or negative.\n"); + return 1; + } + if ((txtMinRegion_->GetValue().ToDouble(&tempd) == TRUE) && (tempd >= 0)) + { + minRegion = (int)(tempd + 0.5); + sprintf(str, "%d", minRegion); + txtMinRegion_->SetValue(str); + } + else + { + bgLog("The value of minimum region cannot be negative.\n"); + return 1; + } + if ((txtKernelSize_->GetValue().ToDouble(&tempd) == TRUE) && (tempd > 0)) + { + kernelSize = (int)(tempd + 0.5); + sprintf(str, "%d", kernelSize); + txtKernelSize_->SetValue(str); + } + else + { + bgLog("The gradient window radius cannot be zero or negative.\n"); + return 1; + } + if ((txtA_->GetValue().ToDouble(&tempd) == TRUE) && (tempd >= 0) && (tempd <= 1)) + { + aij = tempd; + if(aij < 0.01) txtA_->SetValue("0.0"); + } + else + { + bgLog("The value of the mixture parameter cannot be negative or greater than one.\n"); + return 1; + } + if ((txtEpsilon_->GetValue().ToDouble(&tempd) == TRUE) && (tempd >= 0) && (tempd <= 1)) + { + epsilon = tempd; + if(epsilon < 0.01) txtEpsilon_->SetValue("0.0"); + } + else + { + bgLog("The threshold value cannot be negative or greater than one.\n"); + return 1; + } + return 0; } \ No newline at end of file diff --git a/Utilities/otbedison/GUI/bgimsystem.h b/Utilities/otbedison/GUI/bgimsystem.h old mode 100755 new mode 100644 index 0d64026bc3f484e5fc9dc7bacb0755472fa3b4f5..9f6d10b5a6b2651ee0ea08b43cdacf04cd78d406 --- a/Utilities/otbedison/GUI/bgimsystem.h +++ b/Utilities/otbedison/GUI/bgimsystem.h @@ -1,43 +1,43 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: bgimsystem.cpp -// Purpose: Image processing system -// Author: Bogdan Georgescu, Chris M. Christoudias -// Modified by: -// Created: 06/22/2000 -// Copyright: (c) Bogdan Georgescu, Chris M. Christoudias -// Version: v0.1 ///////////////////////////////////////////////////////////////////////////// - +// Name: bgimsystem.cpp +// Purpose: Image processing system +// Author: Bogdan Georgescu, Chris M. Christoudias +// Modified by: +// Created: 06/22/2000 +// Copyright: (c) Bogdan Georgescu, Chris M. Christoudias +// Version: v0.1 +///////////////////////////////////////////////////////////////////////////// + #include <wx/toolbar.h> #include <wx/image.h> #include <wx/bitmap.h> #include <wx/splitter.h> #include <wx/textfile.h> -#include <wx/textctrl.h> +#include <wx/textctrl.h> #include <wx/spinctrl.h> #include <wx/log.h> - -// segmentation defaults -#define BG_SEGM_OP_SIZEX 200 -#define BG_SEGM_OP_SIZEY 350 -#define BG_SP_WIDTH 170 -#define BG_SP_HEIGHT 110 -#define BG_SP_HEIGHT_2 93 -#define BG_SP_TOP_HEIGHT 70 -#define BG_RIGHT_CELL 112 -#define BG_LEFT_CELL 8 -#define HOVER_MENU_X 30 -#define HOVER_MENU_Y 30 -#define HOVER_MENU_BOUND 10 -#define PLOT_MENU_HEIGHT 25 - + +// segmentation defaults +#define BG_SEGM_OP_SIZEX 200 +#define BG_SEGM_OP_SIZEY 350 +#define BG_SP_WIDTH 170 +#define BG_SP_HEIGHT 110 +#define BG_SP_HEIGHT_2 93 +#define BG_SP_TOP_HEIGHT 70 +#define BG_RIGHT_CELL 112 +#define BG_LEFT_CELL 8 +#define HOVER_MENU_X 30 +#define HOVER_MENU_Y 30 +#define HOVER_MENU_BOUND 10 +#define PLOT_MENU_HEIGHT 25 + // end segmentation defaults #define C_PARAMX 10 #define C_PARAMDX 30 #define C_PARAMY 20 -#define C_PARAMDY 30 -#define C_PARAMSX 90 +#define C_PARAMDY 30 +#define C_PARAMSX 90 #define C_PARAMSY 20 #define SEQ_PANEL_SIZE_X 200 #define SEQ_PANEL_SIZE_Y 30 @@ -49,25 +49,25 @@ #define MAX_CUSTOM_NODES 100 #define RANK_CONF_IMSIZEX 256 -#define RANK_CONF_IMSIZEY 256 -#define RANK_CONF_MARGINX 70 +#define RANK_CONF_IMSIZEY 256 +#define RANK_CONF_MARGINX 70 #define RANK_CONF_MARGINY 40 - -//window type identifier constants -#define BG_EDGE_WINDOW 1 -#define BG_SEGM_WINDOW 2 - -//max image size -#define MAX_WIDTH 1600 -#define MAX_HEIGHT 1600 - -//min image size -#define MIN_WIDTH 16 -#define MIN_HEIGHT 16 - -//determines zooming action -#define ZOOM_OUT 0 -#define ZOOM_IN 1 + +//window type identifier constants +#define BG_EDGE_WINDOW 1 +#define BG_SEGM_WINDOW 2 + +//max image size +#define MAX_WIDTH 1600 +#define MAX_HEIGHT 1600 + +//min image size +#define MIN_WIDTH 16 +#define MIN_HEIGHT 16 + +//determines zooming action +#define ZOOM_OUT 0 +#define ZOOM_IN 1 // log everything to a text window (GUI only of course) class bgLogTextCtrl : public wxLog @@ -90,9 +90,9 @@ public: bool OnInit(); }; - - - + + + class BgPointSet { @@ -156,233 +156,233 @@ public: void StartDragging(int, int); void DragTo(int, int); void EndDragging(int, int); -}; - -class BgText -{ -public: - char *text_; - wxFont *font_; - int x_, y_; - int id_; - - BgText(void); - BgText(int,char*,wxFont,int,int); - ~BgText(void); - void SetText(char*); - void SetFont(wxFont); - void SetId(int); - void SetPlotLocation(int,int); -}; - -class BgTextObj -{ -public: - BgText *text_; - BgTextObj *next_; - - BgTextObj(void); - BgTextObj(BgText*); - ~BgTextObj(void); -}; - -class BgTextList -{ -public: - BgTextList(void); - ~BgTextList(void); - int AddText (BgText*); - int RemoveText(int); - BgText *GetText(void); - int GetTextCount(void); - void ResetList(void); - -private: - BgTextObj *head_, *cur_; - int itemcount_; - void DeleteText(void); -}; - -class BgBitmap -{ -public: - wxBitmap *bitmap_; - int location_x_, location_y_; - int id_; - - BgBitmap(void); - BgBitmap(wxBitmap*, int, int, int); - ~BgBitmap(void); - void SetMap(wxBitmap*); - void SetPlotLocation(int,int); - void SetId(int); -}; - -class BgBitmapObj -{ -public: - BgBitmap *bitmap_; - BgBitmapObj *next_; - - BgBitmapObj(void); - BgBitmapObj(BgBitmap*); - ~BgBitmapObj(void); -}; - -class BgBitmapList -{ -public: - BgBitmapList(void); - ~BgBitmapList(void); - int AddBitmap (BgBitmap*); - void RemoveBitmap(BgBitmap*); - BgBitmap *GetBitmap(void); - void ResetList(void); - int GetBitmapCount(void); - -private: - BgBitmapObj *head_, *cur_; - int itemcount_; - void DeleteBitmap(void); -}; - -class BgAxis -{ -public: - int start_x_, start_y_; //plotting origin of axis - int length_; //axis length - int direction_; //0 - horizontal, 1 - vertical - int ticknum_; //number of ticks - float start_val_, stop_val_; //starting and stopping location of axis - BgText *label_; //axis label - int label_x_, label_y_; //axis label plot location - int rotation_; //sets rotation - - BgAxis(void); - BgAxis(int, int, int, int, int, float, float); - ~BgAxis(void); - - void SetPlotOrigin(int, int); - void SetLength(int); - void SetDirection(int); - void SetTicknum(int); - void SetBounds(float,float); - void Label(BgText*); - void RemoveLabel(void); - void SetLabelRotation(int); - void PlotAxis(wxDC *dc); -}; - -class BgThread : public wxThread { -public: - BgThread(wxThreadKind, void foo(void*), void*); - ~BgThread( void ); - -private: - - //determines the entry point of the thread (foo) - void *Entry( void ); - - //pointer to the function foo and its corresponding object - void *Object_; - void (*function_)(void*); - -}; - -//Custom dialog box that allows for the addition of bitmaps -//and bold text (etc) -class BgDialog : public wxDialog { -public: - BgDialog(wxWindow*, wxWindowID, const wxString&, const wxPoint&, const wxSize&, long, const wxString&); - ~BgDialog(void); - - //add/remove objects.... - void AddText(BgText *); - void RemoveText(int); - void AddBitmap(BgBitmap *); - void RemoveBitmap(BgBitmap *); - - //paint/close dialog - virtual void OnPaint(wxPaintEvent& ); - void OnExit(wxCommandEvent& ); - wxButton* okButton_; - - //declare an event table for this class - DECLARE_EVENT_TABLE(); - -private: - - //text/bitmap lists... - BgTextList tlist_; - BgBitmapList blist_; - -}; - -class BgHoverBar : public wxWindow -{ -public: - BgHoverBar(wxWindow*, wxWindowID, int, int, int, int, int, int, int); - ~BgHoverBar( void ); - - wxBitmapButton* menuButton1_; - wxBitmapButton* menuButton2_; - wxStaticText* menuText1_; - wxStaticText* menuText2_; - wxMenu* view_menu; - wxMenu* save_menu; - - void ShowMenu(wxCommandEvent& ); - void CheckViewItem(long); - void Update( void ); - - int gradViewId_, confViewId_, weitViewId_, custViewId_; - int gradSaveId_, confSaveId_, weitSaveId_; - - //declare an event table for this class - DECLARE_EVENT_TABLE(); -}; - -class BgMenuPanel : public wxPanel -{ -public: - BgMenuPanel(wxWindow*, wxWindowID, int, int, int, int, int, int, int); - ~BgMenuPanel( void ); - - wxBitmapButton* menuButton1_; - wxBitmapButton* menuButton2_; - wxStaticText* menuText1_; - wxStaticText* menuText2_; - wxMenu* view_menu; - wxMenu* save_menu; - wxWindow* scrollWindow_; - - void ShowMenu(wxCommandEvent& ); - void CheckViewItem(long); - void Update( void ); - void EnableMenu(bool); - void OnSize(wxSizeEvent& ); - void SetScrollWindow(wxWindow*); - - int gradViewId_, confViewId_, weitViewId_, custViewId_; - int gradSaveId_, confSaveId_, weitSaveId_; - - //declare an event table for this class - DECLARE_EVENT_TABLE(); -}; +}; + +class BgText +{ +public: + char *text_; + wxFont *font_; + int x_, y_; + int id_; + + BgText(void); + BgText(int,char*,wxFont,int,int); + ~BgText(void); + void SetText(char*); + void SetFont(wxFont); + void SetId(int); + void SetPlotLocation(int,int); +}; + +class BgTextObj +{ +public: + BgText *text_; + BgTextObj *next_; + + BgTextObj(void); + BgTextObj(BgText*); + ~BgTextObj(void); +}; + +class BgTextList +{ +public: + BgTextList(void); + ~BgTextList(void); + int AddText (BgText*); + int RemoveText(int); + BgText *GetText(void); + int GetTextCount(void); + void ResetList(void); + +private: + BgTextObj *head_, *cur_; + int itemcount_; + void DeleteText(void); +}; + +class BgBitmap +{ +public: + wxBitmap *bitmap_; + int location_x_, location_y_; + int id_; + + BgBitmap(void); + BgBitmap(wxBitmap*, int, int, int); + ~BgBitmap(void); + void SetMap(wxBitmap*); + void SetPlotLocation(int,int); + void SetId(int); +}; + +class BgBitmapObj +{ +public: + BgBitmap *bitmap_; + BgBitmapObj *next_; + + BgBitmapObj(void); + BgBitmapObj(BgBitmap*); + ~BgBitmapObj(void); +}; + +class BgBitmapList +{ +public: + BgBitmapList(void); + ~BgBitmapList(void); + int AddBitmap (BgBitmap*); + void RemoveBitmap(BgBitmap*); + BgBitmap *GetBitmap(void); + void ResetList(void); + int GetBitmapCount(void); + +private: + BgBitmapObj *head_, *cur_; + int itemcount_; + void DeleteBitmap(void); +}; + +class BgAxis +{ +public: + int start_x_, start_y_; //plotting origin of axis + int length_; //axis length + int direction_; //0 - horizontal, 1 - vertical + int ticknum_; //number of ticks + float start_val_, stop_val_; //starting and stopping location of axis + BgText *label_; //axis label + int label_x_, label_y_; //axis label plot location + int rotation_; //sets rotation + + BgAxis(void); + BgAxis(int, int, int, int, int, float, float); + ~BgAxis(void); + + void SetPlotOrigin(int, int); + void SetLength(int); + void SetDirection(int); + void SetTicknum(int); + void SetBounds(float,float); + void Label(BgText*); + void RemoveLabel(void); + void SetLabelRotation(int); + void PlotAxis(wxDC *dc); +}; + +class BgThread : public wxThread { +public: + BgThread(wxThreadKind, void foo(void*), void*); + ~BgThread( void ); + +private: + + //determines the entry point of the thread (foo) + void *Entry( void ); + + //pointer to the function foo and its corresponding object + void *Object_; + void (*function_)(void*); + +}; + +//Custom dialog box that allows for the addition of bitmaps +//and bold text (etc) +class BgDialog : public wxDialog { +public: + BgDialog(wxWindow*, wxWindowID, const wxString&, const wxPoint&, const wxSize&, long, const wxString&); + ~BgDialog(void); + + //add/remove objects.... + void AddText(BgText *); + void RemoveText(int); + void AddBitmap(BgBitmap *); + void RemoveBitmap(BgBitmap *); + + //paint/close dialog + virtual void OnPaint(wxPaintEvent& ); + void OnExit(wxCommandEvent& ); + wxButton* okButton_; + + //declare an event table for this class + DECLARE_EVENT_TABLE(); + +private: + + //text/bitmap lists... + BgTextList tlist_; + BgBitmapList blist_; + +}; + +class BgHoverBar : public wxWindow +{ +public: + BgHoverBar(wxWindow*, wxWindowID, int, int, int, int, int, int, int); + ~BgHoverBar( void ); + + wxBitmapButton* menuButton1_; + wxBitmapButton* menuButton2_; + wxStaticText* menuText1_; + wxStaticText* menuText2_; + wxMenu* view_menu; + wxMenu* save_menu; + + void ShowMenu(wxCommandEvent& ); + void CheckViewItem(long); + void Update( void ); + + int gradViewId_, confViewId_, weitViewId_, custViewId_; + int gradSaveId_, confSaveId_, weitSaveId_; + + //declare an event table for this class + DECLARE_EVENT_TABLE(); +}; + +class BgMenuPanel : public wxPanel +{ +public: + BgMenuPanel(wxWindow*, wxWindowID, int, int, int, int, int, int, int); + ~BgMenuPanel( void ); + + wxBitmapButton* menuButton1_; + wxBitmapButton* menuButton2_; + wxStaticText* menuText1_; + wxStaticText* menuText2_; + wxMenu* view_menu; + wxMenu* save_menu; + wxWindow* scrollWindow_; + + void ShowMenu(wxCommandEvent& ); + void CheckViewItem(long); + void Update( void ); + void EnableMenu(bool); + void OnSize(wxSizeEvent& ); + void SetScrollWindow(wxWindow*); + + int gradViewId_, confViewId_, weitViewId_, custViewId_; + int gradSaveId_, confSaveId_, weitSaveId_; + + //declare an event table for this class + DECLARE_EVENT_TABLE(); +}; class BgImCanvas : public wxScrolledWindow { -public: +public: BgImCanvas(wxWindow* child_frame, wxWindow *parent, const wxPoint& pos, const wxSize& size); ~BgImCanvas(); virtual void OnDraw(wxDC& dc); // void OnEraseBackground(wxEraseEvent& ); bool IsDirty() const { return m_dirty; } - + void OnEvent(wxMouseEvent&); - void OnMouseRightDown(wxMouseEvent&); - //void OnScroll(wxScrollWinEvent&); + void OnMouseRightDown(wxMouseEvent&); + //void OnScroll(wxScrollWinEvent&); void AdjustScroll(int,int,int); wxBitmap *pbitmap; @@ -416,87 +416,87 @@ public: int ccy_; void FillCurveClick(); int mouseModif_; - int crossCursor_; + int crossCursor_; int m_x_, m_y_; - - //keep track of certain the window events - bool has_focus; - bool leaving; - - //text list object - BgTextList tlist_; - - //keep track of the number of un-plotted - //text objects + + //keep track of certain the window events + bool has_focus; + bool leaving; + + //text list object + BgTextList tlist_; + + //keep track of the number of un-plotted + //text objects int textObjectCount_; - - //x and y axis objects - BgAxis *xAxis, *yAxis; - - //list of bitmaps - BgBitmapList blist_; - - //clear display - bool clear_display_; - - //do not update display - bool noUpdate_; - - //determines if zooming is requested - bool zoom_in, zoom_out, zoom_window; - - //zooming window parameters - int zoom_level, max_zoom_level, min_zoom_level; - - //zoom buffers - unsigned char *buf; - - //zoom cursors - wxCursor *bgCURSOR_MAGNIFIER_PLUS; - wxCursor *bgCURSOR_MAGNIFIER_MINUS; - - //maintain copy of zoomed image - unsigned char *zImg; - - //define zoom box image - wxImage *zoombox; - - //defein refresh box image - wxImage *refresh_box; - - //maintain point map for reconstruction - //of image boundaries - bool *point_map; - wxColour *point_colour; - - //define upper corner of zoom and refresh box - int cx, cy; - - //popup menu window - int menuXl_, menuXu_, menuYl_, menuYu_; - int popup; - wxWindow* menuWindow; - + + //x and y axis objects + BgAxis *xAxis, *yAxis; + + //list of bitmaps + BgBitmapList blist_; + + //clear display + bool clear_display_; + + //do not update display + bool noUpdate_; + + //determines if zooming is requested + bool zoom_in, zoom_out, zoom_window; + + //zooming window parameters + int zoom_level, max_zoom_level, min_zoom_level; + + //zoom buffers + unsigned char *buf; + + //zoom cursors + wxCursor *bgCURSOR_MAGNIFIER_PLUS; + wxCursor *bgCURSOR_MAGNIFIER_MINUS; + + //maintain copy of zoomed image + unsigned char *zImg; + + //define zoom box image + wxImage *zoombox; + + //defein refresh box image + wxImage *refresh_box; + + //maintain point map for reconstruction + //of image boundaries + bool *point_map; + wxColour *point_colour; + + //define upper corner of zoom and refresh box + int cx, cy; + + //popup menu window + int menuXl_, menuXu_, menuYl_, menuYu_; + int popup; + wxWindow* menuWindow; + void AddPointSet(BgPointSet*); - void RemovePointSet(BgPointSet*); + void RemovePointSet(BgPointSet*); void AddLineSet(BgLineSet*); void RemoveLineSet(BgLineSet*); void AddCurveSet(BgCurveSet*); void RemoveCurveSet(BgCurveSet*); - void AddText(BgText*); - void RemoveText(int); - void AddHorizontalAxis(int,int,int,int,float,float); - void AddVerticalAxis (int,int,int,int,float,float); - void ClearAxis(); - void LabelHorizontalAxis(BgText*); - void LabelVerticalAxis(BgText*); - void RemoveHorizontalAxisLabel(void); - void RemoveVerticalAxisLabel(void); - void RotateHorizontalAxisLabel(int); - void RotateVerticalAxisLabel(int); - void AddBitmap(BgBitmap*); - void RemoveBitmap(BgBitmap*); - void ClearDisplay(void); + void AddText(BgText*); + void RemoveText(int); + void AddHorizontalAxis(int,int,int,int,float,float); + void AddVerticalAxis (int,int,int,int,float,float); + void ClearAxis(); + void LabelHorizontalAxis(BgText*); + void LabelVerticalAxis(BgText*); + void RemoveHorizontalAxisLabel(void); + void RemoveVerticalAxisLabel(void); + void RotateHorizontalAxisLabel(int); + void RotateVerticalAxisLabel(int); + void AddBitmap(BgBitmap*); + void RemoveBitmap(BgBitmap*); + void ClearDisplay(void); void AddTrackSet(int, int, int, int); void RemoveTrackSet(); @@ -504,20 +504,20 @@ public: int SetImage(wxString imname); void SetImage(wxImage& image); void SetSameImage(wxImage& image); - void SetImageFromGray(unsigned char* data, int w, int h); - void SetImage(unsigned char* data, int w, int h, bool color = false); + void SetImageFromGray(unsigned char* data, int w, int h); + void SetImage(unsigned char* data, int w, int h, bool color = false); void ShowBitmap(bool); void ClearData(int refresh=0); - void AddMargin(int, int); - - int Zoom(int); - int Zoom(int,int,int); - int ZoomIn(int, int); - int ZoomOut(int, int); - void SetMaxZoomLevel(int); - void SetMinZoomLevel(int); - void DisplayZoomWindow(int,int); - + void AddMargin(int, int); + + int Zoom(int); + int Zoom(int,int,int); + int ZoomIn(int, int); + int ZoomOut(int, int); + void SetMaxZoomLevel(int); + void SetMinZoomLevel(int); + void DisplayZoomWindow(int,int); + void OnCustomAddNode(wxCommandEvent&); void OnCustomDeleteNode(wxCommandEvent&); void OnCTypeEllipse(wxCommandEvent&); @@ -525,68 +525,68 @@ public: void OnCTypeHLine(wxCommandEvent&); void OnCTypeLine(wxCommandEvent&); void OnCTypeBox(wxCommandEvent&); - void OnCTypeCustom(wxCommandEvent&); - - void AddHoverWindow(wxWindow*, int); - void SetHoverWindowLocation(int, int); - - //************************* + void OnCTypeCustom(wxCommandEvent&); + + void AddHoverWindow(wxWindow*, int); + void SetHoverWindowLocation(int, int); + + //************************* private: bool m_dirty; - int x_offset_, y_offset_; + int x_offset_, y_offset_; void MyDrawEllipticArc(wxDC& dc, int x, int y, int w, int h, int sa, int ea); - wxWindow *child_frame_; - - //used for zoom window - void DefineZoomBox(int,int,int,int); - void DefineRefreshBox(void); - void CreatePointMap(int,int); - void AddPoints(unsigned char*, int); + wxWindow *child_frame_; + + //used for zoom window + void DefineZoomBox(int,int,int,int); + void DefineRefreshBox(void); + void CreatePointMap(int,int); + void AddPoints(unsigned char*, int); DECLARE_EVENT_TABLE() -}; - - -class BgParameterHistory { -public: - BgParameterHistory( void ); - BgParameterHistory(void*, int); - ~BgParameterHistory(); - - void *params_; - int listSize_; - BgParameterHistory *next_; -}; - - -//parameter history box tool -//IMPORTANT: WHEN ADDING A PARAMETER LIST, THIS OBJECT OBTAINS OWNERSHIP -// OF THAT LIST (I.E. IT WILL DELETE THE MEMORY FOR YOU!!!!). -class BgParameterHistoryBox : public wxComboBox { -public: - BgParameterHistoryBox(wxWindow*, wxWindowID, const wxString&, const wxPoint&, const wxSize&, int, long, const wxValidator&, const wxString&); - ~BgParameterHistoryBox( void ); - - //add/get parameter lists - void AddParameterList(void*, int); - void *GetParameterListData(int); - int GetParameterListCount(int); - - //keep track of parameter history - void SetCurrentList(void*, int); - void* GetCurrentListData( void ); - int GetCurrentListCount( void ); - void UseParameterList(int); - -private: - - //paramter list array... - BgParameterHistory *historyList_, currentList_; - int listCount_, maxCount_; - -}; - +}; + + +class BgParameterHistory { +public: + BgParameterHistory( void ); + BgParameterHistory(void*, int); + ~BgParameterHistory(); + + void *params_; + int listSize_; + BgParameterHistory *next_; +}; + + +//parameter history box tool +//IMPORTANT: WHEN ADDING A PARAMETER LIST, THIS OBJECT OBTAINS OWNERSHIP +// OF THAT LIST (I.E. IT WILL DELETE THE MEMORY FOR YOU!!!!). +class BgParameterHistoryBox : public wxComboBox { +public: + BgParameterHistoryBox(wxWindow*, wxWindowID, const wxString&, const wxPoint&, const wxSize&, int, long, const wxValidator&, const wxString&); + ~BgParameterHistoryBox( void ); + + //add/get parameter lists + void AddParameterList(void*, int); + void *GetParameterListData(int); + int GetParameterListCount(int); + + //keep track of parameter history + void SetCurrentList(void*, int); + void* GetCurrentListData( void ); + int GetCurrentListCount( void ); + void UseParameterList(int); + +private: + + //paramter list array... + BgParameterHistory *historyList_, currentList_; + int listCount_, maxCount_; + +}; + // Define the parameter dialog box @@ -634,29 +634,29 @@ public: DECLARE_EVENT_TABLE() }; -class BgSpeedSelect : public wxDialog -{ -public: - BgSpeedSelect(wxWindow* parent, wxWindowID id, const wxString& title, - const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = wxDEFAULT_DIALOG_STYLE, const wxString& name = "dialogBox"); - ~BgSpeedSelect(); - void OnOk(wxCommandEvent& ); - void OnCancel(wxCommandEvent& ); - void SetSliderValue(float); - void GetSliderValue(float&); - - // dialog parameters - wxButton* okButton_; - wxButton* cancelButton_; - - wxStaticText* txtQuality_; - wxStaticText* txtSpeed_; - - wxSlider *sldSpeed_; -DECLARE_EVENT_TABLE() -}; - +class BgSpeedSelect : public wxDialog +{ +public: + BgSpeedSelect(wxWindow* parent, wxWindowID id, const wxString& title, + const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, + long style = wxDEFAULT_DIALOG_STYLE, const wxString& name = "dialogBox"); + ~BgSpeedSelect(); + void OnOk(wxCommandEvent& ); + void OnCancel(wxCommandEvent& ); + void SetSliderValue(float); + void GetSliderValue(float&); + + // dialog parameters + wxButton* okButton_; + wxButton* cancelButton_; + + wxStaticText* txtQuality_; + wxStaticText* txtSpeed_; + + wxSlider *sldSpeed_; +DECLARE_EVENT_TABLE() +}; + // Define a new frame class BgMdiFrame : public wxMDIParentFrame @@ -667,30 +667,30 @@ public: wxTextCtrl *logtext_; wxLog *logTargetOld_; int logsize_; - bgLogTextCtrl* bglogctrl_; - char programDir_[1000]; + bgLogTextCtrl* bglogctrl_; + char programDir_[1000]; char helpDir_[1000]; - + BgMdiFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long style); - + void InitToolBar(wxToolBar* toolBar); - - void GetImageFileInfo(char**, char**); + + void GetImageFileInfo(char**, char**); void ZoomControl(wxCommandEvent& ); - void OnSize(wxSizeEvent&); + void OnSize(wxSizeEvent&); void OnAbout(wxCommandEvent&); - void OnHelp(wxCommandEvent&); - void OnNewEdgeWindow(wxCommandEvent&); - void OnNewSegmWindow(wxCommandEvent&); + void OnHelp(wxCommandEvent&); + void OnNewEdgeWindow(wxCommandEvent&); + void OnNewSegmWindow(wxCommandEvent&); void OnLoadImage(wxCommandEvent&); - void OnLoadImageEdge(wxCommandEvent&); + void OnLoadImageEdge(wxCommandEvent&); void OnLoadImageSegm(wxCommandEvent&); void OnSaveResult(wxCommandEvent& WXUNUSED(event)); void OnQuit(wxCommandEvent&); - void OnClose(wxCloseEvent&); - void SetChildTitle(wxMDIChildFrame*, int, int, int); - void UpdateZoomControl(wxMDIChildFrame*, int, int); + void OnClose(wxCloseEvent&); + void SetChildTitle(wxMDIChildFrame*, int, int, int); + void UpdateZoomControl(wxMDIChildFrame*, int, int); DECLARE_EVENT_TABLE() }; @@ -748,64 +748,64 @@ public: wxButton* edButton_; wxButton* cpButton_; wxCheckBox* viewOrigCheck_; - wxCheckBox* viewEdgeCheck_; - - // more right panel stuff - wxStaticText* txtNmxR_; - wxStaticText* txtNmxC_; - wxStaticText* txtHHR_; - wxStaticText* txtHHC_; - wxStaticText* txtHLR_; - wxStaticText* txtHLC_; - wxStaticText* txtMinPt_; - wxStaticText* txtNmxType_; - wxStaticText* txtHHType_; - wxStaticText* txtHLType_; - wxStaticText* txtKernelSize_; - - wxStaticText* valNmxR_; - wxStaticText* valNmxC_; - wxStaticText* valHHR_; - wxStaticText* valHHC_; - wxStaticText* valHLR_; - wxStaticText* valHLC_; - wxStaticText* valMinPt_; - wxStaticText* valNmxType_; - wxStaticText* valHHType_; - wxStaticText* valHLType_; - wxStaticText* valKernelSize_; - - int loopset_; - //parent toolbar - wxToolBar *toolbar; - - //keep track of current number of frames open - bool window_open; - - //keep track of max/min zoom - bool maxZoom_, minZoom_; - - //keep track of filename and window number - char *filename_; - int window_number_; - - //keep track of display image width, height, and zoom level - int width_, height_; + wxCheckBox* viewEdgeCheck_; + + // more right panel stuff + wxStaticText* txtNmxR_; + wxStaticText* txtNmxC_; + wxStaticText* txtHHR_; + wxStaticText* txtHHC_; + wxStaticText* txtHLR_; + wxStaticText* txtHLC_; + wxStaticText* txtMinPt_; + wxStaticText* txtNmxType_; + wxStaticText* txtHHType_; + wxStaticText* txtHLType_; + wxStaticText* txtKernelSize_; + + wxStaticText* valNmxR_; + wxStaticText* valNmxC_; + wxStaticText* valHHR_; + wxStaticText* valHHC_; + wxStaticText* valHLR_; + wxStaticText* valHLC_; + wxStaticText* valMinPt_; + wxStaticText* valNmxType_; + wxStaticText* valHHType_; + wxStaticText* valHLType_; + wxStaticText* valKernelSize_; + + int loopset_; + //parent toolbar + wxToolBar *toolbar; + + //keep track of current number of frames open + bool window_open; + + //keep track of max/min zoom + bool maxZoom_, minZoom_; + + //keep track of filename and window number + char *filename_; + int window_number_; + + //keep track of display image width, height, and zoom level + int width_, height_; BgMdiEdgeChild(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style); ~BgMdiEdgeChild(); void OnQuit(wxCommandEvent& ); - void OnClose(wxCloseEvent& ); - void OnFocus(wxFocusEvent& ); - void NoZoom(void); - void ZoomWindow(void); - void ZoomIn(void); - void ZoomOut(void); - void UpdateZoomControl(void); - void RunEnable(void); - void SaveEnable(void); - void UpdateToolBar(void); - void ResetToolBar(void); + void OnClose(wxCloseEvent& ); + void OnFocus(wxFocusEvent& ); + void NoZoom(void); + void ZoomWindow(void); + void ZoomIn(void); + void ZoomOut(void); + void UpdateZoomControl(void); + void RunEnable(void); + void SaveEnable(void); + void UpdateToolBar(void); + void ResetToolBar(void); void ReadImage(char*, char*); void OnLoadImage(wxCommandEvent& ); void OnSaveEdgeMap(wxCommandEvent& ); @@ -817,177 +817,177 @@ public: void OnCViewEdge(wxCommandEvent& ); void OnSize(wxSizeEvent& ); void SetTotalImage(void); - void SetNmxImage(void); - - // param events - void SetParametersNum(void); - void SetParametersStr(void); - void OnUpdateNum(wxCommandEvent& ); - + void SetNmxImage(void); + + // param events + void SetParametersNum(void); + void SetParametersStr(void); + void OnUpdateNum(wxCommandEvent& ); + DECLARE_EVENT_TABLE() }; -class BgMdiSegmentChild: public wxMDIChildFrame -{ -public: - BgImage* cbgImage_; - BgImage* filtImage_; - BgImage* segmImage_; - BgImage* whiteImage_; - - //segmemtation parameters - int sigmaS, minRegion, kernelSize; - float sigmaR, aij, epsilon, *gradMap_, *confMap_, *weightMap_, *customMap_; - bool edgeParamsHaveChanged_; - SpeedUpLevel speedUpLevel_; - float speedUpThreshold_; - - //point set used to draw boundaries - BgPointSet* boundaries_; - - //window stuff - BgImCanvas* displayImage_; - - //confidence map image - BgImCanvas* plotWindow1_; - - //rank map image - BgImCanvas* plotWindow2_; - - //ph diagram - BgImCanvas* phDiagram_; - - int hasBoundaries_; - int hasImage_; - int hasFilter_; - int hasSegment_; - - // left panel stuff - wxPanel* optionsPanel_; - wxPanel* subPanel1_; - wxPanel* subPanel2_; - wxPanel* subPanel3_; - BgMenuPanel* winPanel1_; - BgMenuPanel* winPanel2_; - wxStaticBox* subPanelBox1_; - wxStaticBox* subPanelBox2_; - wxStaticBox* subPanelBox3_; - wxStaticBox* subPanelBox4_; - - wxButton* runButton_; - wxButton* loadButton_; - - wxRadioBox* viewImSegRadio_; - wxRadioBox* operationRadio_; - wxCheckBox* viewBoundariesCheck_; - - wxStaticText* textKernelSize_; - wxTextCtrl* txtKernelSize_; - - wxStaticText* textSigmaR_; - wxTextCtrl* txtSigmaR_; - - wxStaticText* textSigmaS_; - wxTextCtrl* txtSigmaS_; - - wxStaticText* textA_; - wxTextCtrl* txtA_; - - wxStaticText* textEpsilon_; - wxTextCtrl* txtEpsilon_; - - wxStaticText* textMinRegion_; - wxTextCtrl* txtMinRegion_; - - bool isCurrentHistory_; - bool checkTextBoxes_; - wxStaticText* textParamBox_; - BgParameterHistoryBox* paramComboBox_; - - wxCheckBox* useWeightMap_; - - //used to split the window to display ph diagram - wxSplitterWindow* imagePlotSplitter_; - wxSplitterWindow* plotMapSplitter_; - wxSplitterWindow* mapSplitter_; - - //store pointer to parent frame toolbar - wxToolBar *toolbar; - - //keep track of current number of frames open - bool window_open; - - //keep track of filename and window number - char *filename_; - int window_number_; - - //keep track of display image width, height, and zoom level - int width_, height_; - - //keep track if max/min zoom occurred - int maxZoom_, minZoom_; - - BgMdiSegmentChild(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style); - ~BgMdiSegmentChild(); - - void OnQuit(wxCommandEvent& ); - void OnClose(wxCloseEvent& ); - void OnFocus(wxFocusEvent& ); - void ZoomWindow(void); - void ZoomIn(void); - void ZoomOut(void); - void NoZoom(void); - void UpdateZoomControl(void); - void RunEnable(void); - void SaveEnable(void); - void UpdateToolBar(void); - void ResetToolBar(void); - void ReadImage(char*, char*); - void OnLoadImage(wxCommandEvent& ); - void LoadCustomWeightMap(wxCommandEvent&); - void OnSaveSegmentedImage(wxCommandEvent& ); - void OnSaveBoundaries(char*, int); - void OnSegment(wxCommandEvent& ); - void Segment(void); - void SetphDiagram(int, float*, float*); - void OnViewImSeg(wxCommandEvent& ); - void OnChangeOperation(wxCommandEvent& ); - void OnChangeParameters(wxCommandEvent& ); - void OnUpdateTextBoxes(wxCommandEvent& ); - void OnUpdateSpeedUpLevel(wxCommandEvent& ); - void OnViewBoundaries(wxCommandEvent& ); - void OnUseWeightMap(wxCommandEvent& ); - void OnUpdatePlotWindow1(wxCommandEvent& ); - void OnUpdatePlotWindow2(wxCommandEvent& ); - void OnSaveEdgeInformation(wxCommandEvent& ); - //void OnChangeView - void OnSize(wxSizeEvent& ); - void ClearDisplay( void ); - void UpdateDisplay(bool); - int GetParameters(int&, float&, float&, float&, int&, int&, int); - DECLARE_EVENT_TABLE() -}; +class BgMdiSegmentChild: public wxMDIChildFrame +{ +public: + BgImage* cbgImage_; + BgImage* filtImage_; + BgImage* segmImage_; + BgImage* whiteImage_; + + //segmemtation parameters + int sigmaS, minRegion, kernelSize; + float sigmaR, aij, epsilon, *gradMap_, *confMap_, *weightMap_, *customMap_; + bool edgeParamsHaveChanged_; + SpeedUpLevel speedUpLevel_; + float speedUpThreshold_; + + //point set used to draw boundaries + BgPointSet* boundaries_; + + //window stuff + BgImCanvas* displayImage_; + + //confidence map image + BgImCanvas* plotWindow1_; + + //rank map image + BgImCanvas* plotWindow2_; + + //ph diagram + BgImCanvas* phDiagram_; + + int hasBoundaries_; + int hasImage_; + int hasFilter_; + int hasSegment_; + + // left panel stuff + wxPanel* optionsPanel_; + wxPanel* subPanel1_; + wxPanel* subPanel2_; + wxPanel* subPanel3_; + BgMenuPanel* winPanel1_; + BgMenuPanel* winPanel2_; + wxStaticBox* subPanelBox1_; + wxStaticBox* subPanelBox2_; + wxStaticBox* subPanelBox3_; + wxStaticBox* subPanelBox4_; + + wxButton* runButton_; + wxButton* loadButton_; + + wxRadioBox* viewImSegRadio_; + wxRadioBox* operationRadio_; + wxCheckBox* viewBoundariesCheck_; + + wxStaticText* textKernelSize_; + wxTextCtrl* txtKernelSize_; + + wxStaticText* textSigmaR_; + wxTextCtrl* txtSigmaR_; + + wxStaticText* textSigmaS_; + wxTextCtrl* txtSigmaS_; + + wxStaticText* textA_; + wxTextCtrl* txtA_; + + wxStaticText* textEpsilon_; + wxTextCtrl* txtEpsilon_; + + wxStaticText* textMinRegion_; + wxTextCtrl* txtMinRegion_; + + bool isCurrentHistory_; + bool checkTextBoxes_; + wxStaticText* textParamBox_; + BgParameterHistoryBox* paramComboBox_; + + wxCheckBox* useWeightMap_; + + //used to split the window to display ph diagram + wxSplitterWindow* imagePlotSplitter_; + wxSplitterWindow* plotMapSplitter_; + wxSplitterWindow* mapSplitter_; + + //store pointer to parent frame toolbar + wxToolBar *toolbar; + + //keep track of current number of frames open + bool window_open; + + //keep track of filename and window number + char *filename_; + int window_number_; + + //keep track of display image width, height, and zoom level + int width_, height_; + + //keep track if max/min zoom occurred + int maxZoom_, minZoom_; + + BgMdiSegmentChild(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style); + ~BgMdiSegmentChild(); + + void OnQuit(wxCommandEvent& ); + void OnClose(wxCloseEvent& ); + void OnFocus(wxFocusEvent& ); + void ZoomWindow(void); + void ZoomIn(void); + void ZoomOut(void); + void NoZoom(void); + void UpdateZoomControl(void); + void RunEnable(void); + void SaveEnable(void); + void UpdateToolBar(void); + void ResetToolBar(void); + void ReadImage(char*, char*); + void OnLoadImage(wxCommandEvent& ); + void LoadCustomWeightMap(wxCommandEvent&); + void OnSaveSegmentedImage(wxCommandEvent& ); + void OnSaveBoundaries(char*, int); + void OnSegment(wxCommandEvent& ); + void Segment(void); + void SetphDiagram(int, float*, float*); + void OnViewImSeg(wxCommandEvent& ); + void OnChangeOperation(wxCommandEvent& ); + void OnChangeParameters(wxCommandEvent& ); + void OnUpdateTextBoxes(wxCommandEvent& ); + void OnUpdateSpeedUpLevel(wxCommandEvent& ); + void OnViewBoundaries(wxCommandEvent& ); + void OnUseWeightMap(wxCommandEvent& ); + void OnUpdatePlotWindow1(wxCommandEvent& ); + void OnUpdatePlotWindow2(wxCommandEvent& ); + void OnSaveEdgeInformation(wxCommandEvent& ); + //void OnChangeView + void OnSize(wxSizeEvent& ); + void ClearDisplay( void ); + void UpdateDisplay(bool); + int GetParameters(int&, float&, float&, float&, int&, int&, int); + DECLARE_EVENT_TABLE() +}; // menu items ids enum { - BG_QUIT = 100, - BG_MENU_WINDOW, - BG_DIALOG_OK, - BG_CANVAS_VIEW1_GRADMAP, - BG_CANVAS_VIEW1_CONFMAP, - BG_CANVAS_VIEW1_WEITMAP, - BG_CANVAS_VIEW1_CUSTMAP, - BG_CANVAS_VIEW2_GRADMAP, - BG_CANVAS_VIEW2_CONFMAP, - BG_CANVAS_VIEW2_WEITMAP, - BG_CANVAS_VIEW2_CUSTMAP, - BG_CANVAS_VIEW_BUTTON, - BG_CANVAS_SAVE_GRADMAP, - BG_CANVAS_SAVE_CONFMAP, - BG_CANVAS_SAVE_WEITMAP, - BG_CANVAS_SAVE_BUTTON, - BG_NEW_EDGE_WINDOW, + BG_QUIT = 100, + BG_MENU_WINDOW, + BG_DIALOG_OK, + BG_CANVAS_VIEW1_GRADMAP, + BG_CANVAS_VIEW1_CONFMAP, + BG_CANVAS_VIEW1_WEITMAP, + BG_CANVAS_VIEW1_CUSTMAP, + BG_CANVAS_VIEW2_GRADMAP, + BG_CANVAS_VIEW2_CONFMAP, + BG_CANVAS_VIEW2_WEITMAP, + BG_CANVAS_VIEW2_CUSTMAP, + BG_CANVAS_VIEW_BUTTON, + BG_CANVAS_SAVE_GRADMAP, + BG_CANVAS_SAVE_CONFMAP, + BG_CANVAS_SAVE_WEITMAP, + BG_CANVAS_SAVE_BUTTON, + BG_NEW_EDGE_WINDOW, BG_NEW_SEGM_WINDOW, BG_LOAD_IMAGE_EDGE, BG_LOAD_IMAGE_IMAGE, @@ -996,19 +996,19 @@ enum BG_EDGE_VIEW_ORIG, BG_EDGE_VIEW_EDGE, BG_EDGE_CVIEW_ORIG, - BG_EDGE_CVIEW_EDGE, - BG_EDGE_PARAM_HHR, + BG_EDGE_CVIEW_EDGE, + BG_EDGE_PARAM_HHR, BG_CHANGE_PARAM_EDGE, BG_REFRESH, BG_CHANGE_TITLE, - BG_CHILD_EDGE_QUIT, + BG_CHILD_EDGE_QUIT, BG_CHILD_SEGM_QUIT, BG_ABOUT, BG_HELP, BG_PARAMD_OK, - BG_PARAMD_CANCEL, - BG_SPEEDSEL_OK, - BG_SPEEDSEL_CANCEL, + BG_PARAMD_CANCEL, + BG_SPEEDSEL_OK, + BG_SPEEDSEL_CANCEL, BG_SPEEDSEL_SLD, BG_IMC_ADDNODE, BG_IMC_DELETENODE, @@ -1017,34 +1017,34 @@ enum BG_IMC_SELTYPE_HLINE, BG_IMC_SELTYPE_LINE, BG_IMC_SELTYPE_BOX, - BG_IMC_SELTYPE_CUSTOM, - BG_SEGM_SPEEDUP, - BG_SEGM_SPEEDUP_NONE, - BG_SEGM_SPEEDUP_MEDM, - BG_SEGM_SPEEDUP_HIGH, - BG_SEGM_LOAD_IMAGE, - BG_SEGM_LOAD_MAP, - BG_SEGM_USE_MAP, - BG_SEGM_SAVE_SEGMENTED, - BG_SEGM_SAVE_EDGEMAP, - BG_SEGM_SEGMENT, - BG_SEGM_VIEW_IMSEG, - BG_SEGM_VIEW_EDGES, - BG_SEGM_OPERATION, - BG_SEGM_USE_EDGE_MAP, - BG_SEGM_CHANGE_PARAMS, - BG_SEGM_TEXT_SIGMAS, - BG_SEGM_TEXT_SIGMAR, - BG_SEGM_TEXT_MINREG, - BG_SEGM_TEXT_GRADWIN, - BG_SEGM_TEXT_AIJ, - BG_SEGM_TEXT_EPSILON, - BG_LOAD_IMAGE, - BG_SAVE_RESULT, - BG_CROSS, - BG_ZOOM_IN, - BG_ZOOM_OUT, - BG_POINTER, - BG_EVENT_UPDATE, - BG_EVENT_UPDATE_ID + BG_IMC_SELTYPE_CUSTOM, + BG_SEGM_SPEEDUP, + BG_SEGM_SPEEDUP_NONE, + BG_SEGM_SPEEDUP_MEDM, + BG_SEGM_SPEEDUP_HIGH, + BG_SEGM_LOAD_IMAGE, + BG_SEGM_LOAD_MAP, + BG_SEGM_USE_MAP, + BG_SEGM_SAVE_SEGMENTED, + BG_SEGM_SAVE_EDGEMAP, + BG_SEGM_SEGMENT, + BG_SEGM_VIEW_IMSEG, + BG_SEGM_VIEW_EDGES, + BG_SEGM_OPERATION, + BG_SEGM_USE_EDGE_MAP, + BG_SEGM_CHANGE_PARAMS, + BG_SEGM_TEXT_SIGMAS, + BG_SEGM_TEXT_SIGMAR, + BG_SEGM_TEXT_MINREG, + BG_SEGM_TEXT_GRADWIN, + BG_SEGM_TEXT_AIJ, + BG_SEGM_TEXT_EPSILON, + BG_LOAD_IMAGE, + BG_SAVE_RESULT, + BG_CROSS, + BG_ZOOM_IN, + BG_ZOOM_OUT, + BG_POINTER, + BG_EVENT_UPDATE, + BG_EVENT_UPDATE_ID }; diff --git a/Utilities/otbedison/edge/BgDefaults.h b/Utilities/otbedison/edge/BgDefaults.h old mode 100755 new mode 100644 index a0d11475b8f56ab8f7ce0841a4a69ee0c48dd2a2..c50bbe4fcf4ed3e4bef5b70e4cf80c29ba02b6d4 --- a/Utilities/otbedison/edge/BgDefaults.h +++ b/Utilities/otbedison/edge/BgDefaults.h @@ -1,70 +1,70 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: BGDefaults.h -// Purpose: Defines some program constants -// Author: Bogdan Georgescu -// Modified by: -// Created: 06/22/2000 -// Copyright: (c) Bogdan Georgescu -// Version: v0.1 -///////////////////////////////////////////////////////////////////////////// - -#define PI 3.1415926535 -#define GTRESH PI/6 -#define GTRESH_2 PI/4 -#define RTRESH 7.0 -#define RTRESH_2 20 -#define DF_SIGMA 1.0 -#define DF_HIGH 0.9 -#define DF_LOW 0.5 -#define DF_MINN 5 - -#define FC_ELLIPSE 0 -#define FC_VERT_LINE 1 -#define FC_HORIZ_LINE 2 -#define FC_LINE 3 -#define FC_SQUARE_BOX 4 -#define FC_CUSTOM 5 - -// Line detection -#define NE_TRESH 5 -#define MIN_DIST 30 -#define DMAX 9 -#define DMAX2 DMAX*DMAX -#define DMIN2 (DMAX-2)*(DMAX-2) -#define ALPHA_MAX 160.0*PI/180.0 - -#define MIN_LINE_REZID 1.2 -//#define MIN_LINE_INLIER 7 -#define MIN_LINE_INLIER 15 - -#define M_FRM_NO_POINT -10000000 - -#define AUGMENT_MIN_CORN 25 -#define AUGMENT_LINE_STEP 10 - -extern double bgSign(double); -extern int bgSolveCubic(double, double, double, double, double&, double&, double&); -extern inline int bgRound(double); -extern inline int bgRoundSign(double); -extern double bgMedian(double*, int, double); -extern inline double bgMedianToSigmaGaussian(double); -extern void bgSort(double*, int); - -//image sampling functions -extern void bgZoomIn(unsigned char**, unsigned char*, int, int, int, bool); -extern void bgZoomOut(unsigned char**, unsigned char*, int, int, int, bool); - -//file extension function -extern void BgAddExtension(char**, char*); - -extern void bgLog(const char*, ...); -extern void bgLogFile(const char*, ...); -extern int write_pgm_image(const char *outfilename, unsigned char *image, int rows, - int cols, char *comment, int maxval); -extern void write_MATLAB_ASCII(char *filename, float *data, int rows, int cols); -extern "C" int lmdif(int m, int n,double x[], double fvec[] , double ftol, double xtol, double gtol, int maxfev, - double epsfcn,double diag[],int mode, double factor, int nprint, int *info, int *nfev, - double fjac[],int ldfjac, int ipvt[], double qtf[], double wa1[], double wa2[] , - double wa3[], double wa4[]); -extern void timer_start(); -extern void timer_stop(); +///////////////////////////////////////////////////////////////////////////// +// Name: BGDefaults.h +// Purpose: Defines some program constants +// Author: Bogdan Georgescu +// Modified by: +// Created: 06/22/2000 +// Copyright: (c) Bogdan Georgescu +// Version: v0.1 +///////////////////////////////////////////////////////////////////////////// + +#define PI 3.1415926535 +#define GTRESH PI/6 +#define GTRESH_2 PI/4 +#define RTRESH 7.0 +#define RTRESH_2 20 +#define DF_SIGMA 1.0 +#define DF_HIGH 0.9 +#define DF_LOW 0.5 +#define DF_MINN 5 + +#define FC_ELLIPSE 0 +#define FC_VERT_LINE 1 +#define FC_HORIZ_LINE 2 +#define FC_LINE 3 +#define FC_SQUARE_BOX 4 +#define FC_CUSTOM 5 + +// Line detection +#define NE_TRESH 5 +#define MIN_DIST 30 +#define DMAX 9 +#define DMAX2 DMAX*DMAX +#define DMIN2 (DMAX-2)*(DMAX-2) +#define ALPHA_MAX 160.0*PI/180.0 + +#define MIN_LINE_REZID 1.2 +//#define MIN_LINE_INLIER 7 +#define MIN_LINE_INLIER 15 + +#define M_FRM_NO_POINT -10000000 + +#define AUGMENT_MIN_CORN 25 +#define AUGMENT_LINE_STEP 10 + +extern double bgSign(double); +extern int bgSolveCubic(double, double, double, double, double&, double&, double&); +extern inline int bgRound(double); +extern inline int bgRoundSign(double); +extern double bgMedian(double*, int, double); +extern inline double bgMedianToSigmaGaussian(double); +extern void bgSort(double*, int); + +//image sampling functions +extern void bgZoomIn(unsigned char**, unsigned char*, int, int, int, bool); +extern void bgZoomOut(unsigned char**, unsigned char*, int, int, int, bool); + +//file extension function +extern void BgAddExtension(char**, char*); + +extern void bgLog(const char*, ...); +extern void bgLogFile(const char*, ...); +extern int write_pgm_image(const char *outfilename, unsigned char *image, int rows, + int cols, char *comment, int maxval); +extern void write_MATLAB_ASCII(char *filename, float *data, int rows, int cols); +extern "C" int lmdif(int m, int n,double x[], double fvec[] , double ftol, double xtol, double gtol, int maxfev, + double epsfcn,double diag[],int mode, double factor, int nprint, int *info, int *nfev, + double fjac[],int ldfjac, int ipvt[], double qtf[], double wa1[], double wa2[] , + double wa3[], double wa4[]); +extern void timer_start(); +extern void timer_stop(); diff --git a/Utilities/otbedison/edge/BgEdge.cpp b/Utilities/otbedison/edge/BgEdge.cpp old mode 100755 new mode 100644 index 4b2742cc4740f2b91628a2b1fd3df441258d7fdf..c05c2276be48bbf16dd11e603f31c8d9109f5fbe --- a/Utilities/otbedison/edge/BgEdge.cpp +++ b/Utilities/otbedison/edge/BgEdge.cpp @@ -1,4 +1,4 @@ -///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// // Name: BgEdge.cpp // Purpose: BGEdge class functions // Author: Bogdan Georgescu diff --git a/Utilities/otbedison/edge/BgEdge.h b/Utilities/otbedison/edge/BgEdge.h old mode 100755 new mode 100644 index 81e655b5182eff8d363ebcf40edaed6f2b68caff..5504b370d110820bc44b7eab4155f915ec4832a0 --- a/Utilities/otbedison/edge/BgEdge.h +++ b/Utilities/otbedison/edge/BgEdge.h @@ -7,7 +7,7 @@ // Copyright: (c) Bogdan Georgescu // Version: v0.1 ///////////////////////////////////////////////////////////////////////////// - + // 8-connected neighbour static const int gNb8[8][2]= { @@ -20,7 +20,7 @@ static const int gNb8[8][2]= -1, 0, -1, 1 }; - + class BgEdge { public: @@ -31,7 +31,7 @@ public: unsigned char* mark_; int nPoints_; BgEdge* next_; - + BgEdge(); ~BgEdge(); void SetPoints(float*, int); diff --git a/Utilities/otbedison/edge/BgEdgeDetect.cpp b/Utilities/otbedison/edge/BgEdgeDetect.cpp old mode 100755 new mode 100644 index cb5264196d78b5f451319599f83827c16216da26..1b7b8e9f6d757ba4802de020010be6dc2391af65 --- a/Utilities/otbedison/edge/BgEdgeDetect.cpp +++ b/Utilities/otbedison/edge/BgEdgeDetect.cpp @@ -1,1601 +1,1601 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: BgEdgeDetect.cpp -// Purpose: BgEdgeDetect class functions -// Author: Bogdan Georgescu -// Modified by: -// Created: 06/22/2000 -// Copyright: (c) Bogdan Georgescu -// Version: v0.1 -///////////////////////////////////////////////////////////////////////////// - -#include <math.h> -#include "BgImage.h" -#include "BgEdge.h" -#include "BgEdgeList.h" -#include "BgEdgeDetect.h" -#include "BgDefaults.h" -#include <stdio.h> - -#define TOL_E 2.2e-8 -//#define TOL_E 0.05 -#define SIGN(x) (x<0)? -1:1; - -static int my_sign(double val) -{ - if(val>TOL_E) - return 1; - if(val<-TOL_E) - return -1; - return 0; -} - -extern double factorial(double); - -BgEdgeDetect::BgEdgeDetect(int filtDim) -{ - havePerm_ = false; - WL_ = filtDim; - WW_ = 2*WL_+1; - nhcust_ = 0; - nlcust_ = 0; - tcustx_ = new float[MAX_CUSTT]; - tcusty_ = new float[MAX_CUSTT]; - CreateFilters(); - CreateLookTable(); -} - -BgEdgeDetect::~BgEdgeDetect() -{ - if (havePerm_==true) - { - delete [] permGx_; - delete [] permGy_; - delete [] permConf_; - delete [] permRank_; - delete [] permNmxRank_; - delete [] permNmxConf_; - } - if (nhcust_>0) - { - delete [] hcustx_; - delete [] hcusty_; - } - if (nlcust_>0) - { - delete [] lcustx_; - delete [] lcusty_; - } - delete [] tcustx_; - delete [] tcusty_; - DeleteLookTable(); -} - -void BgEdgeDetect::IsGood(void) -{ - if (havePerm_==true) - bgLog("good\n"); - else - bgLog("bad\n"); -} - - -float BgEdgeDetect::EllipseEval(float x, float y) -{ - return ((x*x)/(rankTr_*rankTr_)+(y*y)/(confTr_*confTr_)-1); -} - -float BgEdgeDetect::EllipseComp(float x0, float y0, float x, float y) -{ -// return (EllipseEval(x,y)-EllipseEval(x0,y0)); - return ((x*x-x0*x0)/(rankTr_*rankTr_)+(y*y-y0*y0)/(confTr_*confTr_)); -} - -float BgEdgeDetect::LineEval(float x, float y) -{ - return (confTr_*x+rankTr_*y-confTr_*rankTr_); -} - -float BgEdgeDetect::LineComp(float x0, float y0, float x, float y) -{ -// return (LineEval(x,y)-LineEval(x0,y0)); - return (confTr_*(x-x0)+rankTr_*(y-y0)); -} - -float BgEdgeDetect::VerticalLineEval(float x, float y) -{ - return (x-rankTr_); -} - -float BgEdgeDetect::VerticalLineComp(float x0, float y0, float x, float y) -{ -// return (VerticalLineEval(x,y)-VerticalLineEval(x0,y0)); - return (x-x0); - -} - -float BgEdgeDetect::HorizontalLineEval(float x, float y) -{ - return(y-confTr_); -} - -float BgEdgeDetect::HorizontalLineComp(float x0, float y0, float x, float y) -{ -// return (HorizontalLineEval(x,y)-HorizontalLineEval(x0,y0)); - return (y-y0); -} - -float BgEdgeDetect::SquareEval(float x, float y) -{ - if ((x/rankTr_)>(y/confTr_)) - return(x-rankTr_); - else - return(y-confTr_); -} - -float BgEdgeDetect::SquareComp(float x0, float y0, float x, float y) -{ -// return(SquareEval(x,y)-SquareEval(x0,y0)); - static float tret; - tret = ((x/rankTr_)>(y/confTr_)) ? x-rankTr_ : y-confTr_; - tret -= ((x0/rankTr_)>(y0/confTr_)) ? x0-rankTr_ : y0-confTr_; - return tret; -} - -float BgEdgeDetect::CustomRegionEval(float r,float c) -{ - //evaluate user region function - //returns -1 if inside +1 if outside - - if ((r+c)<=ZERO_TRESH) - return -1; - int i; - int crossings=0; - float x; - - //shift to origin - for (i=0; i<ncust_; i++) - { - tcustx_[i]=custx_[i]-r; - tcusty_[i]=custy_[i]-c; - } - - for (i=0; i<(ncust_-1); i++) - { - if ( (tcusty_[i] >0 && tcusty_[i+1]<=0) || - (tcusty_[i+1]>0 && tcusty_[i] <=0) ) - { - x = (tcustx_[i]*tcusty_[i+1]-tcustx_[i+1]*tcusty_[i])/(tcusty_[i+1]-tcusty_[i]); - if (x>0) - crossings++; - } - } - - if ((crossings % 2) ==1) - return -1; - else - return 1; -} - -float BgEdgeDetect::CustomRegionComp(float r0, float c0, float r, float c) -{ - return 0; -} - -void BgEdgeDetect::GenerateMaskAngle(double* a,double theta) { - static int sflag; - static int i,j,k; - static double cval[4]; - static double corner[2][4]; - static double sinv,cosv; - static double intrs[2][4]; - static int scor[4],nscor[4]; - static int sind,rowind,colind; - static double cordi[2][4]; - static int lsigind,corin; - static int sigind[4]; - static double diffin[2]; - static double comcoor; - - theta = theta*PI/180.0; - sinv = sin(theta); - cosv = cos(theta); - - for (i=0; i<WW_*WW_; i++) - a[i]=0; - - for (i=WL_; i>=-WL_; i--) - { - for(j=-WL_; j<=WL_; j++) - { - corner[0][0] = j-0.5; - corner[0][1] = j+0.5; - corner[0][2] = j+0.5; - corner[0][3] = j-0.5; - - corner[1][0] = i+0.5; - corner[1][1] = i+0.5; - corner[1][2] = i-0.5; - corner[1][3] = i-0.5; - - cval[0] = -sinv*corner[0][0]+cosv*corner[1][0]; - cval[1] = -sinv*corner[0][1]+cosv*corner[1][1]; - cval[2] = -sinv*corner[0][2]+cosv*corner[1][2]; - cval[3] = -sinv*corner[0][3]+cosv*corner[1][3]; - - scor[0] = my_sign(cval[0]); - scor[1] = my_sign(cval[1]); - scor[2] = my_sign(cval[2]); - scor[3] = my_sign(cval[3]); - - sind = 0; - if (scor[0]!=0) - nscor[sind++] = scor[0]; - if (scor[1]!=0) - nscor[sind++] = scor[1]; - if (scor[2]!=0) - nscor[sind++] = scor[2]; - if (scor[3]!=0) - nscor[sind++] = scor[3]; - - sflag = 0; - for (k=1;k<sind;k++) - { - if (nscor[k]!=nscor[0]) - sflag++; - } - - rowind = i+WL_; - colind = j+WL_; - - if (sflag==0) - { - if (nscor[0]==1) - a[colind+rowind*WW_] = 1.0; - else - a[colind+rowind*WW_] = 0.0; - } - - if (sflag!=0) - { - for (k=0; k<4; k++) - intrs[0][k] = intrs[1][k] = 0.0; - - if(scor[0]==0) - { - intrs[0][0] = corner[0][0]; - intrs[1][0] = corner[1][0]; - } - if (scor[0]*scor[1]<0) - { - intrs[0][0] = corner[1][0]*cosv/sinv; - intrs[1][0] = corner[1][0]; - } - if (scor[1]==0) - { - intrs[0][1] = corner[0][1]; - intrs[1][1] = corner[1][1]; - } - if (scor[1]*scor[2]<0) - { - intrs[0][1] = corner[0][1]; - intrs[1][1] = corner[0][1]*sinv/cosv; - } - if (scor[2]==0) - { - intrs[0][2] = corner[0][2]; - intrs[1][2] = corner[1][2]; - } - if (scor[2]*scor[3]<0) - { - intrs[0][2] = corner[1][2]*cosv/sinv; - intrs[1][2] = corner[1][2]; - } - if (scor[3]==0) - { - intrs[0][3] = corner[0][3]; - intrs[1][3] = corner[1][3]; - } - if (scor[3]*scor[0]<0) - { - intrs[0][3] = corner[0][3]; - intrs[1][3] = corner[0][3]*sinv/cosv; - } - - corin = 0; - if (fabs(intrs[0][0])>TOL_E || fabs(intrs[1][0])>TOL_E) - { - cordi[0][corin] = intrs[0][0]; - cordi[1][corin++] = intrs[1][0]; - } - if (fabs(intrs[0][1])>TOL_E || fabs(intrs[1][1])>TOL_E) - { - cordi[0][corin] = intrs[0][1]; - cordi[1][corin++] = intrs[1][1]; - } - if (fabs(intrs[0][2])>TOL_E || fabs(intrs[1][2])>TOL_E) - { - cordi[0][corin] = intrs[0][2]; - cordi[1][corin++] = intrs[1][2]; - } - if (fabs(intrs[0][3])>TOL_E || fabs(intrs[1][3])>TOL_E) - { - cordi[0][corin] = intrs[0][3]; - cordi[1][corin++] = intrs[1][3]; - } - - lsigind=0; - if (scor[0]>0) - sigind[lsigind++] = 0; - if (scor[1]>0) - sigind[lsigind++] = 1; - if (scor[2]>0) - sigind[lsigind++] = 2; - if (scor[3]>0) - sigind[lsigind++] = 3; - - if (lsigind==1) - { - a[colind+rowind*WW_] = 0.5*fabs(cordi[0][0]-cordi[0][1])*fabs(cordi[1][0]-cordi[1][1]); - } - if (lsigind==2) - { - diffin[0] = (int) fabs(cordi[0][0]-cordi[0][1]); - diffin[1] = (int) fabs(cordi[1][0]-cordi[1][1]); - if (diffin[0]==1) - { - comcoor = corner[1][sigind[0]]; - a[colind+rowind*WW_] = 0.5*(fabs(comcoor-cordi[1][0])+fabs(comcoor-cordi[1][1])); - } - if (diffin[1]==1) - { - comcoor = corner[0][sigind[0]]; - a[colind+rowind*WW_] = 0.5*(fabs(comcoor-cordi[0][0])+fabs(comcoor-cordi[0][1])); - } - } - if(lsigind==3) - { - a[colind+rowind*WW_] = 1.0-0.5*fabs(cordi[0][0]-cordi[0][1])*fabs(cordi[1][0]-cordi[1][1]); - } - } - } - } - - //A=A-mean(mean(A)); - comcoor = 0; - for (i=0; i<WW_*WW_; i++) - comcoor += a[i]; - comcoor /= WW_*WW_; - for (i=0; i<WW_*WW_; i++) - a[i] -= comcoor; - - //A=A/norm(A,'fro') - comcoor = 0; - for (i=0; i<WW_*WW_; i++) - comcoor += a[i]*a[i]; - comcoor = sqrt(comcoor); - for (i=0; i<WW_*WW_; i++) - a[i] /= comcoor; -} - -void BgEdgeDetect::CreateFilters(void) -{ - int i,j; - double w; - for (i=-WL_; i<=WL_; i++) - { - w = pow(2,(-2*WL_))*factorial(2*WL_)/(factorial(WL_-i)*factorial(WL_+i)); - smofil_[i+WL_] = w; - diffil_[i+WL_] = (2*i*w)/WL_; - } - for (j=0; j<WW_; j++) - { - for (i=0; i<WW_; i++) - { - wdy_[j+i*WW_] = wdx_[i+j*WW_] = smofil_[j]*diffil_[i]; - } - } - - double norms = 0; - double normd = 0; - for (i=0; i<WW_; i++) - { - norms += smofil_[i]*smofil_[i]; - normd += diffil_[i]*diffil_[i]; - } - - for (j=0; j<WW_; j++) - { - for (i=0; i<WW_; i++) - { - mQ_[i][j] = (smofil_[j]*smofil_[i])/norms + (diffil_[j]*diffil_[i])/normd; - mN_[i][j] = (i==j) ? 1-mQ_[i][j] : -mQ_[i][j]; - } - } -} - -void BgEdgeDetect::CreateLookTable() -{ - bgLog("Creating angle lookup table\n"); - int i; - for (i=-180; i<=180; i++) - { - lookTable_[i+180] = new double[WW_*WW_]; - GenerateMaskAngle(lookTable_[i+180], (double) i); - } -} - -void BgEdgeDetect::DeleteLookTable() -{ - int i; - for (i=0; i<NO_ANGLES; i++) - { - delete [] lookTable_[i]; - } -} - -void BgEdgeDetect::GetPixels(int* nopix, int* pixx, int* pixy, double x1, double x2, double y1, double y2) -{ - double minx,maxx,miny,maxy; - - if (x1<x2) - { - minx = x1; - maxx = x2; - } - else - { - minx = x2; - maxx = x1; - } - - if (y1<y2) - { - miny = y1; - maxy = y2; - } - else - { - miny = y2; - maxy = y1; - } - - int i,j,npix; - npix = 0; - for (j=0; j<y_; j++) - { - for (i=0; i<x_; i++) - { - if (permRank_[i+j*x_]<maxx && permRank_[i+j*x_]>minx && - permConf_[i+j*x_]<maxy && permConf_[i+j*x_]>miny) - { - pixx[npix] = i; - pixy[npix++] = j; - } - } - } - *nopix = npix; -} - -void BgEdgeDetect::GetNmxPixels(int* nopix, int* pixx, int* pixy, double x1, double x2, double y1, double y2) -{ - double minx,maxx,miny,maxy; - if (x1<x2) - { - minx = x1; - maxx = x2; - } - else - { - minx = x2; - maxx = x1; - } - - if (y1<y2) - { - miny = y1; - maxy = y2; - } - else - { - miny = y2; - maxy = y1; - } - - int i,j,npix; - npix = 0; - for (j=0; j<y_; j++) - { - for (i=0; i<x_; i++) - { - if (permNmxRank_[i+j*x_]<maxx && permNmxRank_[i+j*x_]>minx && - permNmxConf_[i+j*x_]<maxy && permNmxConf_[i+j*x_]>miny) - { - pixx[npix] = i; - pixy[npix++] = j; - } - } - } - *nopix = npix; -} - -void BgEdgeDetect::DoRecompute(BgEdgeList* cel, double nmxr, double nmxc, - double rh, double ch, double rl, double cl, - int nMin, int nmxType, int hystTypeHigh, int hystTypeLow) -{ - float *tr, *tc, *tdh, *tdl; - bgLog("Start edge detection...\n"); - tr = new float[x_*y_]; - tc = new float[x_*y_]; - tdh = new float[x_*y_]; - tdl = new float[x_*y_]; - - //Nonmaximum supression - bgLog("...nonmaxima supression: "); - - float (BgEdgeDetect::*fcomp)(float,float,float,float); - float (BgEdgeDetect::*feval)(float,float); - - switch(nmxType) - { - case FC_ELLIPSE: - fcomp = &BgEdgeDetect::EllipseComp; - feval = &BgEdgeDetect::EllipseEval; - bgLog("arc\n"); - break; - case FC_VERT_LINE: - fcomp = &BgEdgeDetect::VerticalLineComp; - feval = &BgEdgeDetect::VerticalLineEval; - bgLog("vertical line\n"); - break; - case FC_HORIZ_LINE: - fcomp = &BgEdgeDetect::HorizontalLineComp; - feval = &BgEdgeDetect::HorizontalLineEval; - bgLog("horizontal line\n"); - break; - case FC_SQUARE_BOX: - fcomp = &BgEdgeDetect::SquareComp; - feval = &BgEdgeDetect::SquareEval; - bgLog("box\n"); - break; - case FC_LINE: - fcomp = &BgEdgeDetect::LineComp; - feval = &BgEdgeDetect::LineEval; - bgLog("line\n"); - break; - default: - bgLog("Type not known\n"); - return; - } - confTr_ = (float) nmxc; - rankTr_ = (float) nmxr; - - NewNonMaxSupress(permRank_,permConf_,permGx_,permGy_,permNmxRank_,permNmxConf_,fcomp); - bgLog("...hysteresis thresholding, high: "); - - switch(hystTypeHigh) - { - case FC_ELLIPSE: - fcomp = &BgEdgeDetect::EllipseComp; - feval = &BgEdgeDetect::EllipseEval; - bgLog("arc"); - break; - case FC_VERT_LINE: - fcomp = &BgEdgeDetect::VerticalLineComp; - feval = &BgEdgeDetect::VerticalLineEval; - bgLog("vertical line"); - break; - case FC_HORIZ_LINE: - fcomp = &BgEdgeDetect::HorizontalLineComp; - feval = &BgEdgeDetect::HorizontalLineEval; - bgLog("horizontal line"); - break; - case FC_SQUARE_BOX: - fcomp = &BgEdgeDetect::SquareComp; - feval = &BgEdgeDetect::SquareEval; - bgLog("box"); - break; - case FC_LINE: - fcomp = &BgEdgeDetect::LineComp; - feval = &BgEdgeDetect::LineEval; - bgLog("line"); - break; - case FC_CUSTOM: - custx_ = hcustx_; - custy_ = hcusty_; - ncust_ = nhcust_; - fcomp = &BgEdgeDetect::CustomRegionComp; - feval = &BgEdgeDetect::CustomRegionEval; - bgLog("custom"); - break; - } - confTr_ = (float) ch; - rankTr_ = (float) rh; - StrConfEstim(permNmxRank_, permNmxConf_, tdh, feval); - - bgLog(" low: "); - - switch(hystTypeLow) { - case FC_ELLIPSE: - fcomp = &BgEdgeDetect::EllipseComp; - feval = &BgEdgeDetect::EllipseEval; - bgLog("arc\n"); - break; - case FC_VERT_LINE: - fcomp = &BgEdgeDetect::VerticalLineComp; - feval = &BgEdgeDetect::VerticalLineEval; - bgLog("vertical line\n"); - break; - case FC_HORIZ_LINE: - fcomp = &BgEdgeDetect::HorizontalLineComp; - feval = &BgEdgeDetect::HorizontalLineEval; - bgLog("horizontal line\n"); - break; - case FC_SQUARE_BOX: - fcomp = &BgEdgeDetect::SquareComp; - feval = &BgEdgeDetect::SquareEval; - bgLog("box\n"); - break; - case FC_LINE: - fcomp = &BgEdgeDetect::LineComp; - feval = &BgEdgeDetect::LineEval; - bgLog("line\n"); - break; - case FC_CUSTOM: - custx_ = lcustx_; - custy_ = lcusty_; - ncust_ = nlcust_; - fcomp = &BgEdgeDetect::CustomRegionComp; - feval = &BgEdgeDetect::CustomRegionEval; - bgLog("custom\n"); - break; - } - confTr_ = (float) cl; - rankTr_ = (float) rl; - StrConfEstim(permNmxRank_, permNmxConf_, tdl, feval); - - //hysteresis thresholding - - grx_ = permGx_; - gry_ = permGy_; - int minpt = nMin; - NewHysteresisTr(tdh, tdl, cel, minpt, tr, tc); - bgLog("Done edge detection.\n"); - - delete [] tdl; - delete [] tdh; - delete [] tr; - delete [] tc; -} - -void BgEdgeDetect::SaveNmxValues() -{ - FILE* fd; - int i,j; - - fd = fopen("ranknmx.dat", "w"); - for (j=0; j<y_; j++) - { - for (i=0; i<x_; i++) - { - fprintf(fd, "%f ", *(permNmxRank_+j*x_+i)); - } - fprintf(fd, "\n"); - } - fclose(fd); - - fd=fopen("confnmx.dat", "w"); - for (j=0; j<y_; j++) - { - for (i=0; i<x_; i++) - { - fprintf(fd, "%f ", *(permNmxConf_+j*x_+i)); - } - fprintf(fd, "\n"); - } - fclose(fd); -} - -//Computes confedence map and rank -//Pre : cim is an image -//Post: confidence map and rank has been computed for cim -// and stored into confMap and rank respectively -void BgEdgeDetect::ComputeEdgeInfo(BgImage* cim, float* confMap, float *rank) -{ - x_ = cim->x_; - y_ = cim->y_; - bgLog("Computing confidence map...\n"); - float *pGx, *pGy, *pTemp; - BgImage tcim(x_, y_); - if (cim->colorIm_==1) - { - tcim.SetImageFromRGB(cim->im_, x_, y_, false); - } else - { - tcim = *cim; - } - - pGx = new float[x_*y_]; - pGy = new float[x_*y_]; - pTemp = new float[x_*y_]; - - // compute gradient images - bgLog("...smooth-differentiation filtering\n"); - GaussDiffFilter(&tcim, pGx, pGy, pTemp); - - // compute confidences (subspace estimate) - bgLog("...subspace estimate\n"); - SubspaceEstim(pTemp, pGx, pGy, confMap); - - // compute edge strength from gradient image - bgLog("...edge strengths\n"); - Strength(pGx, pGy, pTemp); - - // compute ranks of the strengths - bgLog("...computing ranks\n"); - CompRanks(pTemp, rank); - - //de-allocate memory - delete [] pTemp; - delete [] pGy; - delete [] pGx; -} -/* -void BgEdgeDetect::ComputeConfidenceMap1(BgImage* cim, float* confMap) -{ - ComputeConfidenceMap(cim, confMap); - BgEdgeList el; - DoEdgeDetect(cim, &el, RANK_NMX, CONF_NMX, RANK_H, CONF_H, RANK_L, CONF_L, - NMIN, FC_ELLIPSE, FC_SQUARE_BOX, FC_ELLIPSE); - BgImage tempImage(cim->x_, cim->y_); - el.SetBinImage(&tempImage); - int i; - for (i=0; i<(cim->x_*cim->y_); i++) - if (tempImage.im_[i] == 0) - confMap[i] = 0; -} -*/ -void BgEdgeDetect::DoEdgeDetect(BgImage* cim, BgEdgeList* cel, double nmxr, double nmxc, - double rh, double ch, double rl, double cl, - int nMin, int nmxType, int hystTypeHigh, int hystTypeLow) -{ - x_ = cim->x_; - y_ = cim->y_; - bgLog("Start edge detection...\n"); - permGx_ = new float[x_*y_]; - permGy_ = new float[x_*y_]; - permConf_ = new float[x_*y_]; - permRank_ = new float[x_*y_]; - permNmxRank_ = new float[x_*y_]; - permNmxConf_ = new float[x_*y_]; - havePerm_ = true; - float* tr; - float* tc; - float* tdh; - float* tdl; - - tr = new float[x_*y_]; - tc = new float[x_*y_]; - tdh = new float[x_*y_]; - tdl = new float[x_*y_]; - - // compute gradient images - bgLog("...smooth-differentiation filtering\n"); - GaussDiffFilter(cim, permGx_, permGy_, tr); - - // compute confidences (subspace estimate) - bgLog("...subspace estimate\n"); - SubspaceEstim(tr, permGx_, permGy_, permConf_); - - // compute edge strength from gradient image - bgLog("...edge strengths\n"); - Strength(permGx_, permGy_, tr); - - // compute ranks of the strengths - bgLog("...computing ranks\n"); - CompRanks(tr, permRank_); - - // new nonmaxima supression - bgLog("...nonmaxima supression: "); - - // select appropriate function - float (BgEdgeDetect::*fcomp)(float,float,float,float); - float (BgEdgeDetect::*feval)(float,float); - switch(nmxType) - { - case FC_ELLIPSE: - fcomp = &BgEdgeDetect::EllipseComp; - feval = &BgEdgeDetect::EllipseEval; - bgLog("arc\n"); - break; - case FC_VERT_LINE: - fcomp = &BgEdgeDetect::VerticalLineComp; - feval = &BgEdgeDetect::VerticalLineEval; - bgLog("vertical line\n"); - break; - case FC_HORIZ_LINE: - fcomp = &BgEdgeDetect::HorizontalLineComp; - feval = &BgEdgeDetect::HorizontalLineEval; - bgLog("horizontal line\n"); - break; - case FC_SQUARE_BOX: - fcomp = &BgEdgeDetect::SquareComp; - feval = &BgEdgeDetect::SquareEval; - bgLog("box\n"); - break; - case FC_LINE: - fcomp = &BgEdgeDetect::LineComp; - feval = &BgEdgeDetect::LineEval; - bgLog("line\n"); - break; - default: - bgLog("Type not known\n"); - return; - } - - confTr_ = (float) nmxc; - rankTr_ = (float) nmxr; - NewNonMaxSupress(permRank_, permConf_, permGx_, permGy_, permNmxRank_, permNmxConf_, fcomp); - - // new hysteresis thresholding - bgLog("...hysteresis thresholding, high: "); - - // select function, high curve - switch(hystTypeHigh) - { - case FC_ELLIPSE: - fcomp = &BgEdgeDetect::EllipseComp; - feval = &BgEdgeDetect::EllipseEval; - bgLog("arc"); - break; - case FC_VERT_LINE: - fcomp = &BgEdgeDetect::VerticalLineComp; - feval = &BgEdgeDetect::VerticalLineEval; - bgLog("vertical line"); - break; - case FC_HORIZ_LINE: - fcomp = &BgEdgeDetect::HorizontalLineComp; - feval = &BgEdgeDetect::HorizontalLineEval; - bgLog("horizontal line"); - break; - case FC_SQUARE_BOX: - fcomp = &BgEdgeDetect::SquareComp; - feval = &BgEdgeDetect::SquareEval; - bgLog("box"); - break; - case FC_LINE: - fcomp = &BgEdgeDetect::LineComp; - feval = &BgEdgeDetect::LineEval; - bgLog("line"); - break; - case FC_CUSTOM: - custx_ = hcustx_; - custy_ = hcusty_; - ncust_ = nhcust_; - fcomp = &BgEdgeDetect::CustomRegionComp; - feval = &BgEdgeDetect::CustomRegionEval; - bgLog("custom"); - break; - } - - confTr_ = (float) ch; - rankTr_ = (float) rh; - StrConfEstim(permNmxRank_, permNmxConf_, tdh, feval); - - bgLog(" low: "); - - // select function, low curve - switch(hystTypeLow) - { - case FC_ELLIPSE: - fcomp = &BgEdgeDetect::EllipseComp; - feval = &BgEdgeDetect::EllipseEval; - bgLog("arc\n"); - break; - case FC_VERT_LINE: - fcomp = &BgEdgeDetect::VerticalLineComp; - feval = &BgEdgeDetect::VerticalLineEval; - bgLog("vertical line\n"); - break; - case FC_HORIZ_LINE: - fcomp = &BgEdgeDetect::HorizontalLineComp; - feval = &BgEdgeDetect::HorizontalLineEval; - bgLog("horizontal line\n"); - break; - case FC_SQUARE_BOX: - fcomp = &BgEdgeDetect::SquareComp; - feval = &BgEdgeDetect::SquareEval; - bgLog("box\n"); - break; - case FC_LINE: - fcomp = &BgEdgeDetect::LineComp; - feval = &BgEdgeDetect::LineEval; - bgLog("line\n"); - break; - case FC_CUSTOM: - custx_ = lcustx_; - custy_ = lcusty_; - ncust_ = nlcust_; - fcomp = &BgEdgeDetect::CustomRegionComp; - feval = &BgEdgeDetect::CustomRegionEval; - bgLog("custom\n"); - break; - } - confTr_ = (float) cl; - rankTr_ = (float) rl; - - StrConfEstim(permNmxRank_, permNmxConf_, tdl, feval); - - grx_ = permGx_; - gry_ = permGy_; - - NewHysteresisTr(tdh, tdl, cel, nMin, tr, tc); - - bgLog("Done edge detection.\n"); - - delete [] tdl; - delete [] tdh; - delete [] tr; - delete [] tc; -} - -void BgEdgeDetect::SubspaceEstim(float* im, float* grx, float* gry, float* cee) -{ - // im original image - // grx, gry gradient of image - // cee confidence edge estimate - - float* itim; - float* itgx; - float* itgy; - float* itcee; - itim = im; - itgx = grx; - itgy = gry; - itcee = cee; - - double* tae; - double* ti; - - ti = new double[WW_*WW_]; - - int i,j,l,c; - double v1; - double angleEdge; - int WW2 = WW_*WW_; - - itim += WL_*x_; - itgx += WL_*x_; - itgy += WL_*x_; - itcee += WL_*x_; - - for (j=WL_; j<(y_-WL_); j++) - { - for (i=0; i<WL_; i++) - itcee[i] = 0; - itim += WL_; - itgx += WL_; - itgy += WL_; - itcee += WL_; - - - for (i=WL_; i<(x_-WL_); i++, itim++, itgx++, itgy++, itcee++) - { - if ((fabs(*itgx)+fabs(*itgy))>TOL_E) - { - angleEdge = (-atan2(*itgx, *itgy))*180.0/PI; - tae = lookTable_[(int) (angleEdge+180.49)]; - - //A=A-mean(A) - v1=0; - for (l=0; l<WW_; l++) - { - for (c=0; c<WW_; c++) - { - v1 += ti[l*WW_+c] = *(itim+(l-WL_)*x_+c-WL_); - } - } - v1 /= WW2; - for (l=0; l<WW2; l++) - ti[l] -= v1; - - //A/norm(A,'fro') - v1 = 0; - for (l=0; l<WW2; l++) - v1 += ti[l]*ti[l]; - v1 = sqrt(v1); - for (l=0; l<WW2; l++) - ti[l] /= v1; - - //global - v1 = 0; - for (l=0; l<WW2; l++) - v1 += tae[l]*ti[l]; - v1 = fabs(v1); - *itcee = (float) v1; - } - else - { - *itcee = 0; - } - } - for (i=0; i<WL_; i++) - itcee[i] = 0; - itim += WL_; - itgx += WL_; - itgy += WL_; - itcee += WL_; - } - WW2 = x_*y_; - for (j=0; j<(WL_*x_); j++) - { - cee[j] = 0; - cee[WW2-j-1] = 0; - } - - - delete [] ti; -} - -void BgEdgeDetect::GaussFilter(BgImage* cim, float* fim, double sigma, int width) -{ - double* filter; - unsigned char* im; - double* tim; - double sum = 0; - double sum1 = 0; - int i,ii,jj,j,k; - - im = cim->im_; - if (width==-2) - { - for (i=0; i<x_*y_;i++) - fim[i] = im[i]; - return; - } - - if (width<3) - width = (int) (1+2*ceil(2.5*sigma)); - int tail = width/2; - width = 2*tail+1; - - //create kernel - filter = new double[width]; - for (i=-tail; i<=tail; i++) - sum += filter[i+tail] = exp(-i*i/(2*sigma*sigma)); - for (i=0; i<width; i++) - filter[i] /= sum; - - //filter image - im = cim->im_; - tim = new double[x_*y_]; - for (j=0; j<y_; j++) - { - for (i=tail; i<(x_-tail); i++) - { - sum=0; - for (k=-tail; k<=tail; k++) - sum += im[j*x_+i+k]*filter[k+tail]; - tim[j*x_+i] = sum; - } - - for (i=0; i<tail; i++) - { - tim[j*x_+i] = 0; - tim[j*x_+x_-i-1] = 0; - for (k=-tail; k<=tail; k++) - { - ii = (k+i)>=0 ? k+i : 0; - tim[j*x_+i] += im[j*x_+ii]*filter[k+tail]; - ii = (x_-i-1+k)<x_ ? x_-i-1+k : x_-1; - tim[j*x_+x_-i-1] += im[j*x_+ii]*filter[k+tail]; - } - } - } - - for (i=0; i<x_; i++) - { - for (j=tail; j<(y_-tail); j++) - { - sum=0; - for (k=-tail; k<=tail; k++) - sum += tim[(j+k)*x_+i]*filter[k+tail]; - fim[j*x_+i] = (float) (sum); - } - for (j=0; j<tail; j++) - { - sum = 0; - sum1 = 0; - for (k=-tail; k<=tail; k++) - { - jj = (k+j)>=0 ? k+j : 0; - sum += tim[jj*x_+i]*filter[k+tail]; - jj = (y_-j-1+k)<y_ ? y_-j-1+k : y_-1; - sum1 += tim[jj*x_+i]*filter[k+tail]; - } - fim[j*x_+i] = (float) (sum); - fim[(y_-j-1)*x_+i] = (float) (sum1); - } - } - delete [] filter; - delete [] tim; -} - -void BgEdgeDetect::GaussDiffFilter(BgImage* cim, float* grx, float* gry, float* rezIm) -{ - - double* sf; //smooth filter - double* df; //diff filter - unsigned char* im; - - double* tim; - double sum = 0; - double sum1 = 0; - int i, j, k; - - //create kernels - sf = smofil_; - df = diffil_; - - im = cim->im_; - tim = new double[x_*y_]; - for (i=0; i<x_*y_; i++) - { - grx[i] = gry[i] = 0; - tim[i] = 0; - rezIm[i] = im[i]; - } - - //filter image x - //smooth on y - for (i=0; i<x_; i++) - { - for (j=WL_; j<(y_-WL_); j++) - { - sum = 0; - for (k=-WL_; k<=WL_; k++) - sum += im[(j+k)*x_+i]*sf[k+WL_]; - tim[j*x_+i] = sum; - } - } - //diff on x - for (j=0; j<y_; j++) - { - for (i=WL_; i<(x_-WL_); i++) - { - sum = 0; - for (k=-WL_; k<=WL_; k++) - sum += tim[j*x_+i+k]*df[k+WL_]; - grx[j*x_+i] = (float) (sum); - } - } - - //filter image y - for (i=0; i<x_*y_;i++) - tim[i] = 0; - im = cim->im_; - //smooth on x - for (j=0; j<y_; j++) - { - for (i=WL_; i<(x_-WL_); i++) - { - sum = 0; - for (k=-WL_; k<=WL_; k++) - sum += im[j*x_+i+k]*sf[k+WL_]; - tim[j*x_+i] = sum; - } - } - //diff on y - for (i=0; i<x_; i++) - { - for (j=WL_; j<(y_-WL_); j++) - { - sum = 0; - for (k=-WL_; k<=WL_; k++) - sum += tim[(j+k)*x_+i]*df[k+WL_]; - gry[j*x_+i] = (float) (sum); - } - } - delete [] tim; -} - -void BgEdgeDetect::CompRanks(float* strength, float* ranks) -{ - int* index; - float* ra; - ra = new float[x_*y_]; - index = new int[x_*y_]; - int ii; - - for (ii=0; ii<x_*y_; ii++) - { - index[ii] = ii; - ranks[ii] = 0; - ra[ii] = strength[ii]; - } - - //heap sort with ranks (from numerical recipies) - unsigned long i, ir, j, l; - unsigned long n; - n = x_*y_; - float rra; - int irra; - - if (n<2) - return; - l = (n>>1)+1; - ir = n; - for (;;) - { - if (l>1) - { - rra = ra[--l-1]; - irra = index[l-1]; - } - else - { - rra = ra[ir-1]; - irra = index[ir-1]; - ra[ir-1] = ra[1-1]; - index[ir-1] = index[1-1]; - if (--ir==1) - { - ra[1-1] = rra; - index[1-1] = irra; - break; - } - } - i = l; - j = l+l; - while (j<=ir) - { - if (j<ir && ra[j-1]<ra[j+1-1]) - j++; - if (rra<ra[j-1]) - { - ra[i-1] = ra[j-1]; - index[i-1] = index[j-1]; - i = j; - j <<= 1; - } - else - j = ir+1; - } - ra[i-1] = rra; - index[i-1] = irra; - } - - //setranks - irra = 1; - for (ii=1; ii<x_*y_; ii++) - { - if (ra[ii]>ZERO_TRESH) - { - ranks[index[ii]] = (float) irra; - if (ra[ii]>ra[ii-1]) - irra++; - } - } - irra--; - for (ii=0; ii<x_*y_; ii++) - ranks[ii] /= irra; - - delete [] index; - delete [] ra; -} - -void BgEdgeDetect::StrConfEstim(float* ranks, float* confidence, float* rezult, - float (BgEdgeDetect::*feval)(float,float)) -{ - int i; - for (i=0; i<x_*y_; i++) - { - rezult[i] = (this->*feval)(ranks[i], confidence[i]); - } -} - -void BgEdgeDetect::Strength(float* grx, float* gry, float* strength) -{ - int i,j; - float* itgx; - float* itgy; - float* its; - double val; - itgx = grx; - itgy = gry; - its = strength; - for (j=0; j<y_; j++) - for(i=0; i<x_; i++) - { - val = sqrt(((double) (*itgx*(*(itgx++))))+((double) (*itgy*(*(itgy++))))); - *(its++)=(float) (val); - } -} - -void BgEdgeDetect::NewNonMaxSupress(float* rank, float* conf, float* grx, float* gry, float* nmxRank, float* nmxConf, - float (BgEdgeDetect::*feval)(float, float, float, float)) -{ - int i,j; - float* itr; - float* itc; - float* itgx; - float* itgy; - float* itnmxr; - float* itnmxc; - float alpha,r1,c1,r2,c2,lambda; - itr = rank; - itc = conf; - itgx = grx; - itgy = gry; - itnmxr = nmxRank; - itnmxc = nmxConf; - - for (i=0; i<x_*y_; i++) - { - itnmxr[i] = itnmxc[i] = 0; - } - for(i=0; i<x_; i++) - { - itr[i] = itc[i] = 0; - itr[(y_-1)*x_+i] = itc[(y_-1)*x_+i] = 0; - } - for(j=0; j<y_; j++) - { - itr[j*x_] = itc[j*x_] = 0; - itr[j*x_+x_-1] = itc[j*x_+x_-1] = 0; - } - - for (j=0; j<y_; j++) - { - for (i=0; i<x_; i++, itr++, itc++, itgx++, itgy++, itnmxr++, itnmxc++) - { - if (*itr>0 && *itc>0) - { - alpha = (float) atan2(*itgy, *itgx); - alpha = (alpha<0) ? alpha+(float)PI : alpha; - if (alpha<=PI/4) - { - lambda = (float) tan(alpha); - r1 = (1-lambda)*(*(itr+1))+lambda*(*(itr+x_+1)); - c1 = (1-lambda)*(*(itc+1))+lambda*(*(itc+x_+1)); - r2 = (1-lambda)*(*(itr-1))+lambda*(*(itr-x_-1)); - c2 = (1-lambda)*(*(itc-1))+lambda*(*(itc-x_-1)); - if ((this->*feval)(*itr, *itc, r1, c1)<0 && (this->*feval)(*itr, *itc, r2, c2)<=0) - { - *itnmxr = *itr; - *itnmxc = *itc; - } - } - else if (alpha<=PI/2) - { - lambda = (float) tan(PI/2-alpha); - r1 = (1-lambda)*(*(itr+x_))+lambda*(*(itr+x_+1)); - c1 = (1-lambda)*(*(itc+x_))+lambda*(*(itc+x_+1)); - r2 = (1-lambda)*(*(itr-x_))+lambda*(*(itr-x_-1)); - c2 = (1-lambda)*(*(itc-x_))+lambda*(*(itc-x_-1)); - if ((this->*feval)(*itr, *itc, r1, c1)<0 && (this->*feval)(*itr, *itc, r2, c2)<=0) - { - *itnmxr = *itr; - *itnmxc = *itc; - } - - } - else if(alpha<=3*PI/4) - { - lambda = (float) tan(alpha-PI/2); - r1 = (1-lambda)*(*(itr+x_))+lambda*(*(itr+x_-1)); - c1 = (1-lambda)*(*(itc+x_))+lambda*(*(itc+x_-1)); - r2 = (1-lambda)*(*(itr-x_))+lambda*(*(itr-x_+1)); - c2 = (1-lambda)*(*(itc-x_))+lambda*(*(itc-x_+1)); - if ((this->*feval)(*itr, *itc, r1, c1)<0 && (this->*feval)(*itr, *itc, r2, c2)<=0) - { - *itnmxr = *itr; - *itnmxc = *itc; - } - } - else - { - lambda = (float) tan(PI-alpha); - r1 = (1-lambda)*(*(itr-1))+lambda*(*(itr+x_-1)); - c1 = (1-lambda)*(*(itc-1))+lambda*(*(itc+x_-1)); - r2 = (1-lambda)*(*(itr+1))+lambda*(*(itr-x_+1)); - c2 = (1-lambda)*(*(itc+1))+lambda*(*(itc-x_+1)); - if ((this->*feval)(*itr, *itc, r1, c1)<0 && (this->*feval)(*itr, *itc, r2, c2)<=0) - { - *itnmxr = *itr; - *itnmxc = *itc; - } - } - } - } - } -} - -void BgEdgeDetect::NewHysteresisTr(float* edge, float* low, BgEdgeList* cel, int nMin, float* mark, float* coord) -{ - float* tm; - float* te; - float* tl; - int i,j,n; - - n=0; - for (i=0, tm=mark; i<x_*y_; i++,tm++) - *tm=0; - - te_ = te = edge; - tm_ = tm = mark; - tl_ = tl = low; - - for (j=0; j<y_; j++) - { - for (i=0; i<x_; i++, tm++, te++) - { - if ((*tm==0) && ((*te)>HYST_LOW_CUT)) - { - //found an edge start - npt_ = 0; - *tm = 1; - tc_ = coord; - NewEdgeFollow(i, j); - //store the edge - if (npt_>=nMin) cel->AddEdge(coord, npt_); - } - } - } -} - -void BgEdgeDetect::NewEdgeFollow(int ii,int jj) -{ - int i; - int iin, jjn; - for (i=0; i<8; i++) - { - iin = ii+gNb[i][0]; - jjn = jj+gNb[i][1]; - if ((tm_[jjn*x_+iin]==0) && ((tl_[jjn*x_+iin])>0)) - { - tm_[jjn*x_+iin] = 1; - NewEdgeFollow(iin, jjn); - } - } - *(tc_++) = (float) ii; - *(tc_++) = (float) jj; - npt_++; -} - -void BgEdgeDetect::SetCustomHigh(int* x, int* y, int n, int sx, int sy) -{ - if (nhcust_>0) - { - delete [] hcustx_; - delete [] hcusty_; - } - nhcust_ = 0; - hcustx_ = hcusty_ = 0; - nhcust_ = n+2; - hcustx_ = new float[nhcust_]; - hcusty_ = new float[nhcust_]; - - int idx,i; - idx = 0; - hcustx_[idx] = 0; - hcusty_[idx++] = 0; - for (i=0; i<n; i++) - { - hcustx_[idx] = ((float) x[i])/sx; - hcusty_[idx++] = (float)(1.0-((float) y[i])/sy); - } - hcustx_[idx] = 0; - hcusty_[idx++] = 0; - - bgLog(" hyst high custom x: "); - for (i=0; i<=n; i++) - bgLog(" %f", hcustx_[i]); - bgLog("\n"); - bgLog(" hist high custom y: "); - for (i=0; i<=n; i++) - bgLog(" %f", hcusty_[i]); - bgLog("\n"); -} - -void BgEdgeDetect::SetCustomHigh(double* x, double* y, int n) -{ - if (nhcust_>0) - { - delete [] hcustx_; - delete [] hcusty_; - } - nhcust_ = 0; - hcustx_ = hcusty_ = 0; - nhcust_ = n+2; - hcustx_ = new float[nhcust_]; - hcusty_ = new float[nhcust_]; - - int idx,i; - idx = 0; - hcustx_[idx] = 0; - hcusty_[idx++] = 0; - for (i=0; i<n; i++) - { - hcustx_[idx] = (float) x[i]; - hcusty_[idx++] = (float) y[i]; - } - hcustx_[idx] = 0; - hcusty_[idx++] = 0; - - bgLog(" hyst high custom x: "); - for (i=0; i<=n; i++) - bgLog(" %f", hcustx_[i]); - bgLog("\n"); - bgLog(" hist high custom y: "); - for (i=0; i<=n; i++) - bgLog(" %f", hcusty_[i]); - bgLog("\n"); -} - -void BgEdgeDetect::SetCustomLow(int* x, int* y, int n, int sx, int sy) -{ - if(nlcust_>0) - { - delete [] lcustx_; - delete [] lcusty_; - } - nlcust_ = 0; - lcustx_ = lcusty_ = 0; - nlcust_ = n+2; - lcustx_ = new float[nlcust_]; - lcusty_ = new float[nlcust_]; - - int idx,i; - idx = 0; - lcustx_[idx] = 0; - lcusty_[idx++] = 0; - for (i=0; i<n; i++) - { - lcustx_[idx] = ((float) x[i])/sx; - lcusty_[idx++] = (float)(1.0-((float) y[i])/sy); - } - lcustx_[idx] = 0; - lcusty_[idx++] = 0; - bgLog(" hyst low custom x: "); - for (i=0; i<=n; i++) - bgLog(" %f", lcustx_[i]); - bgLog("\n"); - bgLog(" low custom y: "); - for (i=0; i<=n; i++) - bgLog(" %f", lcusty_[i]); - bgLog("\n"); -} - -void BgEdgeDetect::SetCustomLow(double* x, double* y, int n) -{ - if(nlcust_>0) - { - delete [] lcustx_; - delete [] lcusty_; - } - nlcust_ = 0; - lcustx_ = lcusty_ = 0; - nlcust_ = n+2; - lcustx_ = new float[nlcust_]; - lcusty_ = new float[nlcust_]; - - int idx,i; - idx = 0; - lcustx_[idx] = 0; - lcusty_[idx++] = 0; - for (i=0; i<n; i++) - { - lcustx_[idx] = (float) x[i]; - lcusty_[idx++] = (float) y[i]; - } - lcustx_[idx] = 0; - lcusty_[idx++] = 0; - bgLog(" hyst low custom x: "); - for (i=0; i<=n; i++) - bgLog(" %f", lcustx_[i]); - bgLog("\n"); - bgLog(" low custom y: "); - for (i=0; i<=n; i++) - bgLog(" %f", lcusty_[i]); - bgLog("\n"); -} +///////////////////////////////////////////////////////////////////////////// +// Name: BgEdgeDetect.cpp +// Purpose: BgEdgeDetect class functions +// Author: Bogdan Georgescu +// Modified by: +// Created: 06/22/2000 +// Copyright: (c) Bogdan Georgescu +// Version: v0.1 +///////////////////////////////////////////////////////////////////////////// + +#include <math.h> +#include "BgImage.h" +#include "BgEdge.h" +#include "BgEdgeList.h" +#include "BgEdgeDetect.h" +#include "BgDefaults.h" +#include <stdio.h> + +#define TOL_E 2.2e-8 +//#define TOL_E 0.05 +#define SIGN(x) (x<0)? -1:1; + +static int my_sign(double val) +{ + if(val>TOL_E) + return 1; + if(val<-TOL_E) + return -1; + return 0; +} + +extern double factorial(double); + +BgEdgeDetect::BgEdgeDetect(int filtDim) +{ + havePerm_ = false; + WL_ = filtDim; + WW_ = 2*WL_+1; + nhcust_ = 0; + nlcust_ = 0; + tcustx_ = new float[MAX_CUSTT]; + tcusty_ = new float[MAX_CUSTT]; + CreateFilters(); + CreateLookTable(); +} + +BgEdgeDetect::~BgEdgeDetect() +{ + if (havePerm_==true) + { + delete [] permGx_; + delete [] permGy_; + delete [] permConf_; + delete [] permRank_; + delete [] permNmxRank_; + delete [] permNmxConf_; + } + if (nhcust_>0) + { + delete [] hcustx_; + delete [] hcusty_; + } + if (nlcust_>0) + { + delete [] lcustx_; + delete [] lcusty_; + } + delete [] tcustx_; + delete [] tcusty_; + DeleteLookTable(); +} + +void BgEdgeDetect::IsGood(void) +{ + if (havePerm_==true) + bgLog("good\n"); + else + bgLog("bad\n"); +} + + +float BgEdgeDetect::EllipseEval(float x, float y) +{ + return ((x*x)/(rankTr_*rankTr_)+(y*y)/(confTr_*confTr_)-1); +} + +float BgEdgeDetect::EllipseComp(float x0, float y0, float x, float y) +{ +// return (EllipseEval(x,y)-EllipseEval(x0,y0)); + return ((x*x-x0*x0)/(rankTr_*rankTr_)+(y*y-y0*y0)/(confTr_*confTr_)); +} + +float BgEdgeDetect::LineEval(float x, float y) +{ + return (confTr_*x+rankTr_*y-confTr_*rankTr_); +} + +float BgEdgeDetect::LineComp(float x0, float y0, float x, float y) +{ +// return (LineEval(x,y)-LineEval(x0,y0)); + return (confTr_*(x-x0)+rankTr_*(y-y0)); +} + +float BgEdgeDetect::VerticalLineEval(float x, float y) +{ + return (x-rankTr_); +} + +float BgEdgeDetect::VerticalLineComp(float x0, float y0, float x, float y) +{ +// return (VerticalLineEval(x,y)-VerticalLineEval(x0,y0)); + return (x-x0); + +} + +float BgEdgeDetect::HorizontalLineEval(float x, float y) +{ + return(y-confTr_); +} + +float BgEdgeDetect::HorizontalLineComp(float x0, float y0, float x, float y) +{ +// return (HorizontalLineEval(x,y)-HorizontalLineEval(x0,y0)); + return (y-y0); +} + +float BgEdgeDetect::SquareEval(float x, float y) +{ + if ((x/rankTr_)>(y/confTr_)) + return(x-rankTr_); + else + return(y-confTr_); +} + +float BgEdgeDetect::SquareComp(float x0, float y0, float x, float y) +{ +// return(SquareEval(x,y)-SquareEval(x0,y0)); + static float tret; + tret = ((x/rankTr_)>(y/confTr_)) ? x-rankTr_ : y-confTr_; + tret -= ((x0/rankTr_)>(y0/confTr_)) ? x0-rankTr_ : y0-confTr_; + return tret; +} + +float BgEdgeDetect::CustomRegionEval(float r,float c) +{ + //evaluate user region function + //returns -1 if inside +1 if outside + + if ((r+c)<=ZERO_TRESH) + return -1; + int i; + int crossings=0; + float x; + + //shift to origin + for (i=0; i<ncust_; i++) + { + tcustx_[i]=custx_[i]-r; + tcusty_[i]=custy_[i]-c; + } + + for (i=0; i<(ncust_-1); i++) + { + if ( (tcusty_[i] >0 && tcusty_[i+1]<=0) || + (tcusty_[i+1]>0 && tcusty_[i] <=0) ) + { + x = (tcustx_[i]*tcusty_[i+1]-tcustx_[i+1]*tcusty_[i])/(tcusty_[i+1]-tcusty_[i]); + if (x>0) + crossings++; + } + } + + if ((crossings % 2) ==1) + return -1; + else + return 1; +} + +float BgEdgeDetect::CustomRegionComp(float r0, float c0, float r, float c) +{ + return 0; +} + +void BgEdgeDetect::GenerateMaskAngle(double* a,double theta) { + static int sflag; + static int i,j,k; + static double cval[4]; + static double corner[2][4]; + static double sinv,cosv; + static double intrs[2][4]; + static int scor[4],nscor[4]; + static int sind,rowind,colind; + static double cordi[2][4]; + static int lsigind,corin; + static int sigind[4]; + static double diffin[2]; + static double comcoor; + + theta = theta*PI/180.0; + sinv = sin(theta); + cosv = cos(theta); + + for (i=0; i<WW_*WW_; i++) + a[i]=0; + + for (i=WL_; i>=-WL_; i--) + { + for(j=-WL_; j<=WL_; j++) + { + corner[0][0] = j-0.5; + corner[0][1] = j+0.5; + corner[0][2] = j+0.5; + corner[0][3] = j-0.5; + + corner[1][0] = i+0.5; + corner[1][1] = i+0.5; + corner[1][2] = i-0.5; + corner[1][3] = i-0.5; + + cval[0] = -sinv*corner[0][0]+cosv*corner[1][0]; + cval[1] = -sinv*corner[0][1]+cosv*corner[1][1]; + cval[2] = -sinv*corner[0][2]+cosv*corner[1][2]; + cval[3] = -sinv*corner[0][3]+cosv*corner[1][3]; + + scor[0] = my_sign(cval[0]); + scor[1] = my_sign(cval[1]); + scor[2] = my_sign(cval[2]); + scor[3] = my_sign(cval[3]); + + sind = 0; + if (scor[0]!=0) + nscor[sind++] = scor[0]; + if (scor[1]!=0) + nscor[sind++] = scor[1]; + if (scor[2]!=0) + nscor[sind++] = scor[2]; + if (scor[3]!=0) + nscor[sind++] = scor[3]; + + sflag = 0; + for (k=1;k<sind;k++) + { + if (nscor[k]!=nscor[0]) + sflag++; + } + + rowind = i+WL_; + colind = j+WL_; + + if (sflag==0) + { + if (nscor[0]==1) + a[colind+rowind*WW_] = 1.0; + else + a[colind+rowind*WW_] = 0.0; + } + + if (sflag!=0) + { + for (k=0; k<4; k++) + intrs[0][k] = intrs[1][k] = 0.0; + + if(scor[0]==0) + { + intrs[0][0] = corner[0][0]; + intrs[1][0] = corner[1][0]; + } + if (scor[0]*scor[1]<0) + { + intrs[0][0] = corner[1][0]*cosv/sinv; + intrs[1][0] = corner[1][0]; + } + if (scor[1]==0) + { + intrs[0][1] = corner[0][1]; + intrs[1][1] = corner[1][1]; + } + if (scor[1]*scor[2]<0) + { + intrs[0][1] = corner[0][1]; + intrs[1][1] = corner[0][1]*sinv/cosv; + } + if (scor[2]==0) + { + intrs[0][2] = corner[0][2]; + intrs[1][2] = corner[1][2]; + } + if (scor[2]*scor[3]<0) + { + intrs[0][2] = corner[1][2]*cosv/sinv; + intrs[1][2] = corner[1][2]; + } + if (scor[3]==0) + { + intrs[0][3] = corner[0][3]; + intrs[1][3] = corner[1][3]; + } + if (scor[3]*scor[0]<0) + { + intrs[0][3] = corner[0][3]; + intrs[1][3] = corner[0][3]*sinv/cosv; + } + + corin = 0; + if (fabs(intrs[0][0])>TOL_E || fabs(intrs[1][0])>TOL_E) + { + cordi[0][corin] = intrs[0][0]; + cordi[1][corin++] = intrs[1][0]; + } + if (fabs(intrs[0][1])>TOL_E || fabs(intrs[1][1])>TOL_E) + { + cordi[0][corin] = intrs[0][1]; + cordi[1][corin++] = intrs[1][1]; + } + if (fabs(intrs[0][2])>TOL_E || fabs(intrs[1][2])>TOL_E) + { + cordi[0][corin] = intrs[0][2]; + cordi[1][corin++] = intrs[1][2]; + } + if (fabs(intrs[0][3])>TOL_E || fabs(intrs[1][3])>TOL_E) + { + cordi[0][corin] = intrs[0][3]; + cordi[1][corin++] = intrs[1][3]; + } + + lsigind=0; + if (scor[0]>0) + sigind[lsigind++] = 0; + if (scor[1]>0) + sigind[lsigind++] = 1; + if (scor[2]>0) + sigind[lsigind++] = 2; + if (scor[3]>0) + sigind[lsigind++] = 3; + + if (lsigind==1) + { + a[colind+rowind*WW_] = 0.5*fabs(cordi[0][0]-cordi[0][1])*fabs(cordi[1][0]-cordi[1][1]); + } + if (lsigind==2) + { + diffin[0] = (int) fabs(cordi[0][0]-cordi[0][1]); + diffin[1] = (int) fabs(cordi[1][0]-cordi[1][1]); + if (diffin[0]==1) + { + comcoor = corner[1][sigind[0]]; + a[colind+rowind*WW_] = 0.5*(fabs(comcoor-cordi[1][0])+fabs(comcoor-cordi[1][1])); + } + if (diffin[1]==1) + { + comcoor = corner[0][sigind[0]]; + a[colind+rowind*WW_] = 0.5*(fabs(comcoor-cordi[0][0])+fabs(comcoor-cordi[0][1])); + } + } + if(lsigind==3) + { + a[colind+rowind*WW_] = 1.0-0.5*fabs(cordi[0][0]-cordi[0][1])*fabs(cordi[1][0]-cordi[1][1]); + } + } + } + } + + //A=A-mean(mean(A)); + comcoor = 0; + for (i=0; i<WW_*WW_; i++) + comcoor += a[i]; + comcoor /= WW_*WW_; + for (i=0; i<WW_*WW_; i++) + a[i] -= comcoor; + + //A=A/norm(A,'fro') + comcoor = 0; + for (i=0; i<WW_*WW_; i++) + comcoor += a[i]*a[i]; + comcoor = sqrt(comcoor); + for (i=0; i<WW_*WW_; i++) + a[i] /= comcoor; +} + +void BgEdgeDetect::CreateFilters(void) +{ + int i,j; + double w; + for (i=-WL_; i<=WL_; i++) + { + w = pow(2,(-2*WL_))*factorial(2*WL_)/(factorial(WL_-i)*factorial(WL_+i)); + smofil_[i+WL_] = w; + diffil_[i+WL_] = (2*i*w)/WL_; + } + for (j=0; j<WW_; j++) + { + for (i=0; i<WW_; i++) + { + wdy_[j+i*WW_] = wdx_[i+j*WW_] = smofil_[j]*diffil_[i]; + } + } + + double norms = 0; + double normd = 0; + for (i=0; i<WW_; i++) + { + norms += smofil_[i]*smofil_[i]; + normd += diffil_[i]*diffil_[i]; + } + + for (j=0; j<WW_; j++) + { + for (i=0; i<WW_; i++) + { + mQ_[i][j] = (smofil_[j]*smofil_[i])/norms + (diffil_[j]*diffil_[i])/normd; + mN_[i][j] = (i==j) ? 1-mQ_[i][j] : -mQ_[i][j]; + } + } +} + +void BgEdgeDetect::CreateLookTable() +{ + bgLog("Creating angle lookup table\n"); + int i; + for (i=-180; i<=180; i++) + { + lookTable_[i+180] = new double[WW_*WW_]; + GenerateMaskAngle(lookTable_[i+180], (double) i); + } +} + +void BgEdgeDetect::DeleteLookTable() +{ + int i; + for (i=0; i<NO_ANGLES; i++) + { + delete [] lookTable_[i]; + } +} + +void BgEdgeDetect::GetPixels(int* nopix, int* pixx, int* pixy, double x1, double x2, double y1, double y2) +{ + double minx,maxx,miny,maxy; + + if (x1<x2) + { + minx = x1; + maxx = x2; + } + else + { + minx = x2; + maxx = x1; + } + + if (y1<y2) + { + miny = y1; + maxy = y2; + } + else + { + miny = y2; + maxy = y1; + } + + int i,j,npix; + npix = 0; + for (j=0; j<y_; j++) + { + for (i=0; i<x_; i++) + { + if (permRank_[i+j*x_]<maxx && permRank_[i+j*x_]>minx && + permConf_[i+j*x_]<maxy && permConf_[i+j*x_]>miny) + { + pixx[npix] = i; + pixy[npix++] = j; + } + } + } + *nopix = npix; +} + +void BgEdgeDetect::GetNmxPixels(int* nopix, int* pixx, int* pixy, double x1, double x2, double y1, double y2) +{ + double minx,maxx,miny,maxy; + if (x1<x2) + { + minx = x1; + maxx = x2; + } + else + { + minx = x2; + maxx = x1; + } + + if (y1<y2) + { + miny = y1; + maxy = y2; + } + else + { + miny = y2; + maxy = y1; + } + + int i,j,npix; + npix = 0; + for (j=0; j<y_; j++) + { + for (i=0; i<x_; i++) + { + if (permNmxRank_[i+j*x_]<maxx && permNmxRank_[i+j*x_]>minx && + permNmxConf_[i+j*x_]<maxy && permNmxConf_[i+j*x_]>miny) + { + pixx[npix] = i; + pixy[npix++] = j; + } + } + } + *nopix = npix; +} + +void BgEdgeDetect::DoRecompute(BgEdgeList* cel, double nmxr, double nmxc, + double rh, double ch, double rl, double cl, + int nMin, int nmxType, int hystTypeHigh, int hystTypeLow) +{ + float *tr, *tc, *tdh, *tdl; + bgLog("Start edge detection...\n"); + tr = new float[x_*y_]; + tc = new float[x_*y_]; + tdh = new float[x_*y_]; + tdl = new float[x_*y_]; + + //Nonmaximum supression + bgLog("...nonmaxima supression: "); + + float (BgEdgeDetect::*fcomp)(float,float,float,float); + float (BgEdgeDetect::*feval)(float,float); + + switch(nmxType) + { + case FC_ELLIPSE: + fcomp = &BgEdgeDetect::EllipseComp; + feval = &BgEdgeDetect::EllipseEval; + bgLog("arc\n"); + break; + case FC_VERT_LINE: + fcomp = &BgEdgeDetect::VerticalLineComp; + feval = &BgEdgeDetect::VerticalLineEval; + bgLog("vertical line\n"); + break; + case FC_HORIZ_LINE: + fcomp = &BgEdgeDetect::HorizontalLineComp; + feval = &BgEdgeDetect::HorizontalLineEval; + bgLog("horizontal line\n"); + break; + case FC_SQUARE_BOX: + fcomp = &BgEdgeDetect::SquareComp; + feval = &BgEdgeDetect::SquareEval; + bgLog("box\n"); + break; + case FC_LINE: + fcomp = &BgEdgeDetect::LineComp; + feval = &BgEdgeDetect::LineEval; + bgLog("line\n"); + break; + default: + bgLog("Type not known\n"); + return; + } + confTr_ = (float) nmxc; + rankTr_ = (float) nmxr; + + NewNonMaxSupress(permRank_,permConf_,permGx_,permGy_,permNmxRank_,permNmxConf_,fcomp); + bgLog("...hysteresis thresholding, high: "); + + switch(hystTypeHigh) + { + case FC_ELLIPSE: + fcomp = &BgEdgeDetect::EllipseComp; + feval = &BgEdgeDetect::EllipseEval; + bgLog("arc"); + break; + case FC_VERT_LINE: + fcomp = &BgEdgeDetect::VerticalLineComp; + feval = &BgEdgeDetect::VerticalLineEval; + bgLog("vertical line"); + break; + case FC_HORIZ_LINE: + fcomp = &BgEdgeDetect::HorizontalLineComp; + feval = &BgEdgeDetect::HorizontalLineEval; + bgLog("horizontal line"); + break; + case FC_SQUARE_BOX: + fcomp = &BgEdgeDetect::SquareComp; + feval = &BgEdgeDetect::SquareEval; + bgLog("box"); + break; + case FC_LINE: + fcomp = &BgEdgeDetect::LineComp; + feval = &BgEdgeDetect::LineEval; + bgLog("line"); + break; + case FC_CUSTOM: + custx_ = hcustx_; + custy_ = hcusty_; + ncust_ = nhcust_; + fcomp = &BgEdgeDetect::CustomRegionComp; + feval = &BgEdgeDetect::CustomRegionEval; + bgLog("custom"); + break; + } + confTr_ = (float) ch; + rankTr_ = (float) rh; + StrConfEstim(permNmxRank_, permNmxConf_, tdh, feval); + + bgLog(" low: "); + + switch(hystTypeLow) { + case FC_ELLIPSE: + fcomp = &BgEdgeDetect::EllipseComp; + feval = &BgEdgeDetect::EllipseEval; + bgLog("arc\n"); + break; + case FC_VERT_LINE: + fcomp = &BgEdgeDetect::VerticalLineComp; + feval = &BgEdgeDetect::VerticalLineEval; + bgLog("vertical line\n"); + break; + case FC_HORIZ_LINE: + fcomp = &BgEdgeDetect::HorizontalLineComp; + feval = &BgEdgeDetect::HorizontalLineEval; + bgLog("horizontal line\n"); + break; + case FC_SQUARE_BOX: + fcomp = &BgEdgeDetect::SquareComp; + feval = &BgEdgeDetect::SquareEval; + bgLog("box\n"); + break; + case FC_LINE: + fcomp = &BgEdgeDetect::LineComp; + feval = &BgEdgeDetect::LineEval; + bgLog("line\n"); + break; + case FC_CUSTOM: + custx_ = lcustx_; + custy_ = lcusty_; + ncust_ = nlcust_; + fcomp = &BgEdgeDetect::CustomRegionComp; + feval = &BgEdgeDetect::CustomRegionEval; + bgLog("custom\n"); + break; + } + confTr_ = (float) cl; + rankTr_ = (float) rl; + StrConfEstim(permNmxRank_, permNmxConf_, tdl, feval); + + //hysteresis thresholding + + grx_ = permGx_; + gry_ = permGy_; + int minpt = nMin; + NewHysteresisTr(tdh, tdl, cel, minpt, tr, tc); + bgLog("Done edge detection.\n"); + + delete [] tdl; + delete [] tdh; + delete [] tr; + delete [] tc; +} + +void BgEdgeDetect::SaveNmxValues() +{ + FILE* fd; + int i,j; + + fd = fopen("ranknmx.dat", "w"); + for (j=0; j<y_; j++) + { + for (i=0; i<x_; i++) + { + fprintf(fd, "%f ", *(permNmxRank_+j*x_+i)); + } + fprintf(fd, "\n"); + } + fclose(fd); + + fd=fopen("confnmx.dat", "w"); + for (j=0; j<y_; j++) + { + for (i=0; i<x_; i++) + { + fprintf(fd, "%f ", *(permNmxConf_+j*x_+i)); + } + fprintf(fd, "\n"); + } + fclose(fd); +} + +//Computes confedence map and rank +//Pre : cim is an image +//Post: confidence map and rank has been computed for cim +// and stored into confMap and rank respectively +void BgEdgeDetect::ComputeEdgeInfo(BgImage* cim, float* confMap, float *rank) +{ + x_ = cim->x_; + y_ = cim->y_; + bgLog("Computing confidence map...\n"); + float *pGx, *pGy, *pTemp; + BgImage tcim(x_, y_); + if (cim->colorIm_==1) + { + tcim.SetImageFromRGB(cim->im_, x_, y_, false); + } else + { + tcim = *cim; + } + + pGx = new float[x_*y_]; + pGy = new float[x_*y_]; + pTemp = new float[x_*y_]; + + // compute gradient images + bgLog("...smooth-differentiation filtering\n"); + GaussDiffFilter(&tcim, pGx, pGy, pTemp); + + // compute confidences (subspace estimate) + bgLog("...subspace estimate\n"); + SubspaceEstim(pTemp, pGx, pGy, confMap); + + // compute edge strength from gradient image + bgLog("...edge strengths\n"); + Strength(pGx, pGy, pTemp); + + // compute ranks of the strengths + bgLog("...computing ranks\n"); + CompRanks(pTemp, rank); + + //de-allocate memory + delete [] pTemp; + delete [] pGy; + delete [] pGx; +} +/* +void BgEdgeDetect::ComputeConfidenceMap1(BgImage* cim, float* confMap) +{ + ComputeConfidenceMap(cim, confMap); + BgEdgeList el; + DoEdgeDetect(cim, &el, RANK_NMX, CONF_NMX, RANK_H, CONF_H, RANK_L, CONF_L, + NMIN, FC_ELLIPSE, FC_SQUARE_BOX, FC_ELLIPSE); + BgImage tempImage(cim->x_, cim->y_); + el.SetBinImage(&tempImage); + int i; + for (i=0; i<(cim->x_*cim->y_); i++) + if (tempImage.im_[i] == 0) + confMap[i] = 0; +} +*/ +void BgEdgeDetect::DoEdgeDetect(BgImage* cim, BgEdgeList* cel, double nmxr, double nmxc, + double rh, double ch, double rl, double cl, + int nMin, int nmxType, int hystTypeHigh, int hystTypeLow) +{ + x_ = cim->x_; + y_ = cim->y_; + bgLog("Start edge detection...\n"); + permGx_ = new float[x_*y_]; + permGy_ = new float[x_*y_]; + permConf_ = new float[x_*y_]; + permRank_ = new float[x_*y_]; + permNmxRank_ = new float[x_*y_]; + permNmxConf_ = new float[x_*y_]; + havePerm_ = true; + float* tr; + float* tc; + float* tdh; + float* tdl; + + tr = new float[x_*y_]; + tc = new float[x_*y_]; + tdh = new float[x_*y_]; + tdl = new float[x_*y_]; + + // compute gradient images + bgLog("...smooth-differentiation filtering\n"); + GaussDiffFilter(cim, permGx_, permGy_, tr); + + // compute confidences (subspace estimate) + bgLog("...subspace estimate\n"); + SubspaceEstim(tr, permGx_, permGy_, permConf_); + + // compute edge strength from gradient image + bgLog("...edge strengths\n"); + Strength(permGx_, permGy_, tr); + + // compute ranks of the strengths + bgLog("...computing ranks\n"); + CompRanks(tr, permRank_); + + // new nonmaxima supression + bgLog("...nonmaxima supression: "); + + // select appropriate function + float (BgEdgeDetect::*fcomp)(float,float,float,float); + float (BgEdgeDetect::*feval)(float,float); + switch(nmxType) + { + case FC_ELLIPSE: + fcomp = &BgEdgeDetect::EllipseComp; + feval = &BgEdgeDetect::EllipseEval; + bgLog("arc\n"); + break; + case FC_VERT_LINE: + fcomp = &BgEdgeDetect::VerticalLineComp; + feval = &BgEdgeDetect::VerticalLineEval; + bgLog("vertical line\n"); + break; + case FC_HORIZ_LINE: + fcomp = &BgEdgeDetect::HorizontalLineComp; + feval = &BgEdgeDetect::HorizontalLineEval; + bgLog("horizontal line\n"); + break; + case FC_SQUARE_BOX: + fcomp = &BgEdgeDetect::SquareComp; + feval = &BgEdgeDetect::SquareEval; + bgLog("box\n"); + break; + case FC_LINE: + fcomp = &BgEdgeDetect::LineComp; + feval = &BgEdgeDetect::LineEval; + bgLog("line\n"); + break; + default: + bgLog("Type not known\n"); + return; + } + + confTr_ = (float) nmxc; + rankTr_ = (float) nmxr; + NewNonMaxSupress(permRank_, permConf_, permGx_, permGy_, permNmxRank_, permNmxConf_, fcomp); + + // new hysteresis thresholding + bgLog("...hysteresis thresholding, high: "); + + // select function, high curve + switch(hystTypeHigh) + { + case FC_ELLIPSE: + fcomp = &BgEdgeDetect::EllipseComp; + feval = &BgEdgeDetect::EllipseEval; + bgLog("arc"); + break; + case FC_VERT_LINE: + fcomp = &BgEdgeDetect::VerticalLineComp; + feval = &BgEdgeDetect::VerticalLineEval; + bgLog("vertical line"); + break; + case FC_HORIZ_LINE: + fcomp = &BgEdgeDetect::HorizontalLineComp; + feval = &BgEdgeDetect::HorizontalLineEval; + bgLog("horizontal line"); + break; + case FC_SQUARE_BOX: + fcomp = &BgEdgeDetect::SquareComp; + feval = &BgEdgeDetect::SquareEval; + bgLog("box"); + break; + case FC_LINE: + fcomp = &BgEdgeDetect::LineComp; + feval = &BgEdgeDetect::LineEval; + bgLog("line"); + break; + case FC_CUSTOM: + custx_ = hcustx_; + custy_ = hcusty_; + ncust_ = nhcust_; + fcomp = &BgEdgeDetect::CustomRegionComp; + feval = &BgEdgeDetect::CustomRegionEval; + bgLog("custom"); + break; + } + + confTr_ = (float) ch; + rankTr_ = (float) rh; + StrConfEstim(permNmxRank_, permNmxConf_, tdh, feval); + + bgLog(" low: "); + + // select function, low curve + switch(hystTypeLow) + { + case FC_ELLIPSE: + fcomp = &BgEdgeDetect::EllipseComp; + feval = &BgEdgeDetect::EllipseEval; + bgLog("arc\n"); + break; + case FC_VERT_LINE: + fcomp = &BgEdgeDetect::VerticalLineComp; + feval = &BgEdgeDetect::VerticalLineEval; + bgLog("vertical line\n"); + break; + case FC_HORIZ_LINE: + fcomp = &BgEdgeDetect::HorizontalLineComp; + feval = &BgEdgeDetect::HorizontalLineEval; + bgLog("horizontal line\n"); + break; + case FC_SQUARE_BOX: + fcomp = &BgEdgeDetect::SquareComp; + feval = &BgEdgeDetect::SquareEval; + bgLog("box\n"); + break; + case FC_LINE: + fcomp = &BgEdgeDetect::LineComp; + feval = &BgEdgeDetect::LineEval; + bgLog("line\n"); + break; + case FC_CUSTOM: + custx_ = lcustx_; + custy_ = lcusty_; + ncust_ = nlcust_; + fcomp = &BgEdgeDetect::CustomRegionComp; + feval = &BgEdgeDetect::CustomRegionEval; + bgLog("custom\n"); + break; + } + confTr_ = (float) cl; + rankTr_ = (float) rl; + + StrConfEstim(permNmxRank_, permNmxConf_, tdl, feval); + + grx_ = permGx_; + gry_ = permGy_; + + NewHysteresisTr(tdh, tdl, cel, nMin, tr, tc); + + bgLog("Done edge detection.\n"); + + delete [] tdl; + delete [] tdh; + delete [] tr; + delete [] tc; +} + +void BgEdgeDetect::SubspaceEstim(float* im, float* grx, float* gry, float* cee) +{ + // im original image + // grx, gry gradient of image + // cee confidence edge estimate + + float* itim; + float* itgx; + float* itgy; + float* itcee; + itim = im; + itgx = grx; + itgy = gry; + itcee = cee; + + double* tae; + double* ti; + + ti = new double[WW_*WW_]; + + int i,j,l,c; + double v1; + double angleEdge; + int WW2 = WW_*WW_; + + itim += WL_*x_; + itgx += WL_*x_; + itgy += WL_*x_; + itcee += WL_*x_; + + for (j=WL_; j<(y_-WL_); j++) + { + for (i=0; i<WL_; i++) + itcee[i] = 0; + itim += WL_; + itgx += WL_; + itgy += WL_; + itcee += WL_; + + + for (i=WL_; i<(x_-WL_); i++, itim++, itgx++, itgy++, itcee++) + { + if ((fabs(*itgx)+fabs(*itgy))>TOL_E) + { + angleEdge = (-atan2(*itgx, *itgy))*180.0/PI; + tae = lookTable_[(int) (angleEdge+180.49)]; + + //A=A-mean(A) + v1=0; + for (l=0; l<WW_; l++) + { + for (c=0; c<WW_; c++) + { + v1 += ti[l*WW_+c] = *(itim+(l-WL_)*x_+c-WL_); + } + } + v1 /= WW2; + for (l=0; l<WW2; l++) + ti[l] -= v1; + + //A/norm(A,'fro') + v1 = 0; + for (l=0; l<WW2; l++) + v1 += ti[l]*ti[l]; + v1 = sqrt(v1); + for (l=0; l<WW2; l++) + ti[l] /= v1; + + //global + v1 = 0; + for (l=0; l<WW2; l++) + v1 += tae[l]*ti[l]; + v1 = fabs(v1); + *itcee = (float) v1; + } + else + { + *itcee = 0; + } + } + for (i=0; i<WL_; i++) + itcee[i] = 0; + itim += WL_; + itgx += WL_; + itgy += WL_; + itcee += WL_; + } + WW2 = x_*y_; + for (j=0; j<(WL_*x_); j++) + { + cee[j] = 0; + cee[WW2-j-1] = 0; + } + + + delete [] ti; +} + +void BgEdgeDetect::GaussFilter(BgImage* cim, float* fim, double sigma, int width) +{ + double* filter; + unsigned char* im; + double* tim; + double sum = 0; + double sum1 = 0; + int i,ii,jj,j,k; + + im = cim->im_; + if (width==-2) + { + for (i=0; i<x_*y_;i++) + fim[i] = im[i]; + return; + } + + if (width<3) + width = (int) (1+2*ceil(2.5*sigma)); + int tail = width/2; + width = 2*tail+1; + + //create kernel + filter = new double[width]; + for (i=-tail; i<=tail; i++) + sum += filter[i+tail] = exp(-i*i/(2*sigma*sigma)); + for (i=0; i<width; i++) + filter[i] /= sum; + + //filter image + im = cim->im_; + tim = new double[x_*y_]; + for (j=0; j<y_; j++) + { + for (i=tail; i<(x_-tail); i++) + { + sum=0; + for (k=-tail; k<=tail; k++) + sum += im[j*x_+i+k]*filter[k+tail]; + tim[j*x_+i] = sum; + } + + for (i=0; i<tail; i++) + { + tim[j*x_+i] = 0; + tim[j*x_+x_-i-1] = 0; + for (k=-tail; k<=tail; k++) + { + ii = (k+i)>=0 ? k+i : 0; + tim[j*x_+i] += im[j*x_+ii]*filter[k+tail]; + ii = (x_-i-1+k)<x_ ? x_-i-1+k : x_-1; + tim[j*x_+x_-i-1] += im[j*x_+ii]*filter[k+tail]; + } + } + } + + for (i=0; i<x_; i++) + { + for (j=tail; j<(y_-tail); j++) + { + sum=0; + for (k=-tail; k<=tail; k++) + sum += tim[(j+k)*x_+i]*filter[k+tail]; + fim[j*x_+i] = (float) (sum); + } + for (j=0; j<tail; j++) + { + sum = 0; + sum1 = 0; + for (k=-tail; k<=tail; k++) + { + jj = (k+j)>=0 ? k+j : 0; + sum += tim[jj*x_+i]*filter[k+tail]; + jj = (y_-j-1+k)<y_ ? y_-j-1+k : y_-1; + sum1 += tim[jj*x_+i]*filter[k+tail]; + } + fim[j*x_+i] = (float) (sum); + fim[(y_-j-1)*x_+i] = (float) (sum1); + } + } + delete [] filter; + delete [] tim; +} + +void BgEdgeDetect::GaussDiffFilter(BgImage* cim, float* grx, float* gry, float* rezIm) +{ + + double* sf; //smooth filter + double* df; //diff filter + unsigned char* im; + + double* tim; + double sum = 0; + double sum1 = 0; + int i, j, k; + + //create kernels + sf = smofil_; + df = diffil_; + + im = cim->im_; + tim = new double[x_*y_]; + for (i=0; i<x_*y_; i++) + { + grx[i] = gry[i] = 0; + tim[i] = 0; + rezIm[i] = im[i]; + } + + //filter image x + //smooth on y + for (i=0; i<x_; i++) + { + for (j=WL_; j<(y_-WL_); j++) + { + sum = 0; + for (k=-WL_; k<=WL_; k++) + sum += im[(j+k)*x_+i]*sf[k+WL_]; + tim[j*x_+i] = sum; + } + } + //diff on x + for (j=0; j<y_; j++) + { + for (i=WL_; i<(x_-WL_); i++) + { + sum = 0; + for (k=-WL_; k<=WL_; k++) + sum += tim[j*x_+i+k]*df[k+WL_]; + grx[j*x_+i] = (float) (sum); + } + } + + //filter image y + for (i=0; i<x_*y_;i++) + tim[i] = 0; + im = cim->im_; + //smooth on x + for (j=0; j<y_; j++) + { + for (i=WL_; i<(x_-WL_); i++) + { + sum = 0; + for (k=-WL_; k<=WL_; k++) + sum += im[j*x_+i+k]*sf[k+WL_]; + tim[j*x_+i] = sum; + } + } + //diff on y + for (i=0; i<x_; i++) + { + for (j=WL_; j<(y_-WL_); j++) + { + sum = 0; + for (k=-WL_; k<=WL_; k++) + sum += tim[(j+k)*x_+i]*df[k+WL_]; + gry[j*x_+i] = (float) (sum); + } + } + delete [] tim; +} + +void BgEdgeDetect::CompRanks(float* strength, float* ranks) +{ + int* index; + float* ra; + ra = new float[x_*y_]; + index = new int[x_*y_]; + int ii; + + for (ii=0; ii<x_*y_; ii++) + { + index[ii] = ii; + ranks[ii] = 0; + ra[ii] = strength[ii]; + } + + //heap sort with ranks (from numerical recipies) + unsigned long i, ir, j, l; + unsigned long n; + n = x_*y_; + float rra; + int irra; + + if (n<2) + return; + l = (n>>1)+1; + ir = n; + for (;;) + { + if (l>1) + { + rra = ra[--l-1]; + irra = index[l-1]; + } + else + { + rra = ra[ir-1]; + irra = index[ir-1]; + ra[ir-1] = ra[1-1]; + index[ir-1] = index[1-1]; + if (--ir==1) + { + ra[1-1] = rra; + index[1-1] = irra; + break; + } + } + i = l; + j = l+l; + while (j<=ir) + { + if (j<ir && ra[j-1]<ra[j+1-1]) + j++; + if (rra<ra[j-1]) + { + ra[i-1] = ra[j-1]; + index[i-1] = index[j-1]; + i = j; + j <<= 1; + } + else + j = ir+1; + } + ra[i-1] = rra; + index[i-1] = irra; + } + + //setranks + irra = 1; + for (ii=1; ii<x_*y_; ii++) + { + if (ra[ii]>ZERO_TRESH) + { + ranks[index[ii]] = (float) irra; + if (ra[ii]>ra[ii-1]) + irra++; + } + } + irra--; + for (ii=0; ii<x_*y_; ii++) + ranks[ii] /= irra; + + delete [] index; + delete [] ra; +} + +void BgEdgeDetect::StrConfEstim(float* ranks, float* confidence, float* rezult, + float (BgEdgeDetect::*feval)(float,float)) +{ + int i; + for (i=0; i<x_*y_; i++) + { + rezult[i] = (this->*feval)(ranks[i], confidence[i]); + } +} + +void BgEdgeDetect::Strength(float* grx, float* gry, float* strength) +{ + int i,j; + float* itgx; + float* itgy; + float* its; + double val; + itgx = grx; + itgy = gry; + its = strength; + for (j=0; j<y_; j++) + for(i=0; i<x_; i++) + { + val = sqrt(((double) (*itgx*(*(itgx++))))+((double) (*itgy*(*(itgy++))))); + *(its++)=(float) (val); + } +} + +void BgEdgeDetect::NewNonMaxSupress(float* rank, float* conf, float* grx, float* gry, float* nmxRank, float* nmxConf, + float (BgEdgeDetect::*feval)(float, float, float, float)) +{ + int i,j; + float* itr; + float* itc; + float* itgx; + float* itgy; + float* itnmxr; + float* itnmxc; + float alpha,r1,c1,r2,c2,lambda; + itr = rank; + itc = conf; + itgx = grx; + itgy = gry; + itnmxr = nmxRank; + itnmxc = nmxConf; + + for (i=0; i<x_*y_; i++) + { + itnmxr[i] = itnmxc[i] = 0; + } + for(i=0; i<x_; i++) + { + itr[i] = itc[i] = 0; + itr[(y_-1)*x_+i] = itc[(y_-1)*x_+i] = 0; + } + for(j=0; j<y_; j++) + { + itr[j*x_] = itc[j*x_] = 0; + itr[j*x_+x_-1] = itc[j*x_+x_-1] = 0; + } + + for (j=0; j<y_; j++) + { + for (i=0; i<x_; i++, itr++, itc++, itgx++, itgy++, itnmxr++, itnmxc++) + { + if (*itr>0 && *itc>0) + { + alpha = (float) atan2(*itgy, *itgx); + alpha = (alpha<0) ? alpha+(float)PI : alpha; + if (alpha<=PI/4) + { + lambda = (float) tan(alpha); + r1 = (1-lambda)*(*(itr+1))+lambda*(*(itr+x_+1)); + c1 = (1-lambda)*(*(itc+1))+lambda*(*(itc+x_+1)); + r2 = (1-lambda)*(*(itr-1))+lambda*(*(itr-x_-1)); + c2 = (1-lambda)*(*(itc-1))+lambda*(*(itc-x_-1)); + if ((this->*feval)(*itr, *itc, r1, c1)<0 && (this->*feval)(*itr, *itc, r2, c2)<=0) + { + *itnmxr = *itr; + *itnmxc = *itc; + } + } + else if (alpha<=PI/2) + { + lambda = (float) tan(PI/2-alpha); + r1 = (1-lambda)*(*(itr+x_))+lambda*(*(itr+x_+1)); + c1 = (1-lambda)*(*(itc+x_))+lambda*(*(itc+x_+1)); + r2 = (1-lambda)*(*(itr-x_))+lambda*(*(itr-x_-1)); + c2 = (1-lambda)*(*(itc-x_))+lambda*(*(itc-x_-1)); + if ((this->*feval)(*itr, *itc, r1, c1)<0 && (this->*feval)(*itr, *itc, r2, c2)<=0) + { + *itnmxr = *itr; + *itnmxc = *itc; + } + + } + else if(alpha<=3*PI/4) + { + lambda = (float) tan(alpha-PI/2); + r1 = (1-lambda)*(*(itr+x_))+lambda*(*(itr+x_-1)); + c1 = (1-lambda)*(*(itc+x_))+lambda*(*(itc+x_-1)); + r2 = (1-lambda)*(*(itr-x_))+lambda*(*(itr-x_+1)); + c2 = (1-lambda)*(*(itc-x_))+lambda*(*(itc-x_+1)); + if ((this->*feval)(*itr, *itc, r1, c1)<0 && (this->*feval)(*itr, *itc, r2, c2)<=0) + { + *itnmxr = *itr; + *itnmxc = *itc; + } + } + else + { + lambda = (float) tan(PI-alpha); + r1 = (1-lambda)*(*(itr-1))+lambda*(*(itr+x_-1)); + c1 = (1-lambda)*(*(itc-1))+lambda*(*(itc+x_-1)); + r2 = (1-lambda)*(*(itr+1))+lambda*(*(itr-x_+1)); + c2 = (1-lambda)*(*(itc+1))+lambda*(*(itc-x_+1)); + if ((this->*feval)(*itr, *itc, r1, c1)<0 && (this->*feval)(*itr, *itc, r2, c2)<=0) + { + *itnmxr = *itr; + *itnmxc = *itc; + } + } + } + } + } +} + +void BgEdgeDetect::NewHysteresisTr(float* edge, float* low, BgEdgeList* cel, int nMin, float* mark, float* coord) +{ + float* tm; + float* te; + float* tl; + int i,j,n; + + n=0; + for (i=0, tm=mark; i<x_*y_; i++,tm++) + *tm=0; + + te_ = te = edge; + tm_ = tm = mark; + tl_ = tl = low; + + for (j=0; j<y_; j++) + { + for (i=0; i<x_; i++, tm++, te++) + { + if ((*tm==0) && ((*te)>HYST_LOW_CUT)) + { + //found an edge start + npt_ = 0; + *tm = 1; + tc_ = coord; + NewEdgeFollow(i, j); + //store the edge + if (npt_>=nMin) cel->AddEdge(coord, npt_); + } + } + } +} + +void BgEdgeDetect::NewEdgeFollow(int ii,int jj) +{ + int i; + int iin, jjn; + for (i=0; i<8; i++) + { + iin = ii+gNb[i][0]; + jjn = jj+gNb[i][1]; + if ((tm_[jjn*x_+iin]==0) && ((tl_[jjn*x_+iin])>0)) + { + tm_[jjn*x_+iin] = 1; + NewEdgeFollow(iin, jjn); + } + } + *(tc_++) = (float) ii; + *(tc_++) = (float) jj; + npt_++; +} + +void BgEdgeDetect::SetCustomHigh(int* x, int* y, int n, int sx, int sy) +{ + if (nhcust_>0) + { + delete [] hcustx_; + delete [] hcusty_; + } + nhcust_ = 0; + hcustx_ = hcusty_ = 0; + nhcust_ = n+2; + hcustx_ = new float[nhcust_]; + hcusty_ = new float[nhcust_]; + + int idx,i; + idx = 0; + hcustx_[idx] = 0; + hcusty_[idx++] = 0; + for (i=0; i<n; i++) + { + hcustx_[idx] = ((float) x[i])/sx; + hcusty_[idx++] = (float)(1.0-((float) y[i])/sy); + } + hcustx_[idx] = 0; + hcusty_[idx++] = 0; + + bgLog(" hyst high custom x: "); + for (i=0; i<=n; i++) + bgLog(" %f", hcustx_[i]); + bgLog("\n"); + bgLog(" hist high custom y: "); + for (i=0; i<=n; i++) + bgLog(" %f", hcusty_[i]); + bgLog("\n"); +} + +void BgEdgeDetect::SetCustomHigh(double* x, double* y, int n) +{ + if (nhcust_>0) + { + delete [] hcustx_; + delete [] hcusty_; + } + nhcust_ = 0; + hcustx_ = hcusty_ = 0; + nhcust_ = n+2; + hcustx_ = new float[nhcust_]; + hcusty_ = new float[nhcust_]; + + int idx,i; + idx = 0; + hcustx_[idx] = 0; + hcusty_[idx++] = 0; + for (i=0; i<n; i++) + { + hcustx_[idx] = (float) x[i]; + hcusty_[idx++] = (float) y[i]; + } + hcustx_[idx] = 0; + hcusty_[idx++] = 0; + + bgLog(" hyst high custom x: "); + for (i=0; i<=n; i++) + bgLog(" %f", hcustx_[i]); + bgLog("\n"); + bgLog(" hist high custom y: "); + for (i=0; i<=n; i++) + bgLog(" %f", hcusty_[i]); + bgLog("\n"); +} + +void BgEdgeDetect::SetCustomLow(int* x, int* y, int n, int sx, int sy) +{ + if(nlcust_>0) + { + delete [] lcustx_; + delete [] lcusty_; + } + nlcust_ = 0; + lcustx_ = lcusty_ = 0; + nlcust_ = n+2; + lcustx_ = new float[nlcust_]; + lcusty_ = new float[nlcust_]; + + int idx,i; + idx = 0; + lcustx_[idx] = 0; + lcusty_[idx++] = 0; + for (i=0; i<n; i++) + { + lcustx_[idx] = ((float) x[i])/sx; + lcusty_[idx++] = (float)(1.0-((float) y[i])/sy); + } + lcustx_[idx] = 0; + lcusty_[idx++] = 0; + bgLog(" hyst low custom x: "); + for (i=0; i<=n; i++) + bgLog(" %f", lcustx_[i]); + bgLog("\n"); + bgLog(" low custom y: "); + for (i=0; i<=n; i++) + bgLog(" %f", lcusty_[i]); + bgLog("\n"); +} + +void BgEdgeDetect::SetCustomLow(double* x, double* y, int n) +{ + if(nlcust_>0) + { + delete [] lcustx_; + delete [] lcusty_; + } + nlcust_ = 0; + lcustx_ = lcusty_ = 0; + nlcust_ = n+2; + lcustx_ = new float[nlcust_]; + lcusty_ = new float[nlcust_]; + + int idx,i; + idx = 0; + lcustx_[idx] = 0; + lcusty_[idx++] = 0; + for (i=0; i<n; i++) + { + lcustx_[idx] = (float) x[i]; + lcusty_[idx++] = (float) y[i]; + } + lcustx_[idx] = 0; + lcusty_[idx++] = 0; + bgLog(" hyst low custom x: "); + for (i=0; i<=n; i++) + bgLog(" %f", lcustx_[i]); + bgLog("\n"); + bgLog(" low custom y: "); + for (i=0; i<=n; i++) + bgLog(" %f", lcusty_[i]); + bgLog("\n"); +} diff --git a/Utilities/otbedison/edge/BgEdgeDetect.h b/Utilities/otbedison/edge/BgEdgeDetect.h old mode 100755 new mode 100644 index c07689d601a96d10f846e0a26e733d83aaa643cf..5824179f40875f96dd977065074ede16df37ea6a --- a/Utilities/otbedison/edge/BgEdgeDetect.h +++ b/Utilities/otbedison/edge/BgEdgeDetect.h @@ -7,10 +7,10 @@ // Copyright: (c) Bogdan Georgescu // Version: v0.1 ///////////////////////////////////////////////////////////////////////////// - + #define PI 3.1415926535 #define ZERO_TRESH 0.0000000001 - + // default values for edge detection #define CONF_NMX 0.5 #define RANK_NMX 0.5 @@ -20,14 +20,14 @@ #define RANK_L 0.99 #define NMIN 5 #define KERNEL_SIZE 2 - + #define HYST_LOW_CUT 0.0 #define MAX_CUSTT 30 #define MAX_FILTS 31 #define NO_ANGLES 361 - + #define ALF_TRESH PI/4 - + static const int gNb[8][2]= { 1, 0, @@ -39,7 +39,7 @@ static const int gNb[8][2]= -1, 1, -1,-1 }; - + static const double gAlpha[8][2]= { PI/2, PI/2, @@ -51,12 +51,12 @@ static const double gAlpha[8][2]= 3*PI/4, 3*PI/4, PI/4, PI/4 }; - + // main class, edge detection class BgEdgeDetect { public: - + // main function for edge detection // cim input image // cel edge list (will be filled with pixels on edges) @@ -66,22 +66,22 @@ public: // nMin, min number of pixels on an edge // nmxType, hystTypeHigh, hystTypeLow, type of nmx curve, hyst. high curve, hyst low curve // in (FC_ELLIPSE, FC_VERT_LINE, FC_HORIZ_LINE, FC_LINE, FC_SQUARE_BOX, FC_CUSTOM) - + void DoEdgeDetect(BgImage* cim, BgEdgeList* cel, double nmxr, double nmxc, double rh, double ch, double rl, double cl, - int nMin, int nmxType, int hystTypeHigh, int hystTypeLow); - - // computes confidence map and rank information of sepcified image + int nMin, int nmxType, int hystTypeHigh, int hystTypeLow); + + // computes confidence map and rank information of sepcified image void ComputeEdgeInfo(BgImage*, float*, float*); -// void ComputeConfidenceMap1(BgImage*, float*); +// void ComputeConfidenceMap1(BgImage*, float*); // if have permanent data, call this function (compute only last two steps is same kernel size) void DoRecompute(BgEdgeList*, double, double, double, double, double, double, int, int, int, int); - + BgEdgeDetect(int filtDim); ~BgEdgeDetect(); - + void SaveNmxValues(); - + float EllipseEval(float, float); float EllipseComp(float, float, float, float); float LineEval(float, float); @@ -94,12 +94,12 @@ public: float SquareComp(float, float, float, float); float CustomRegionEval(float, float); float CustomRegionComp(float, float, float, float); - + void SetCustomHigh(int*, int*, int, int, int); void SetCustomLow(int*, int*, int, int, int); void SetCustomHigh(double*, double*, int); void SetCustomLow(double*, double*, int); - + void IsGood(void); void GetPixels(int*, int*, int*, double, double, double, double); void GetNmxPixels(int*, int*, int*, double, double, double, double); @@ -111,25 +111,25 @@ public: double mN_[MAX_FILTS][MAX_FILTS]; double mQ_[MAX_FILTS][MAX_FILTS]; double* lookTable_[NO_ANGLES]; - + int WW_; int WL_; float confTr_; float rankTr_; - + float* custx_; float* custy_; float* tcustx_; float* tcusty_; int ncust_; - + float* hcustx_; float* hcusty_; int nhcust_; float* lcustx_; float* lcusty_; int nlcust_; - + int x_; int y_; float* permConf_; @@ -137,9 +137,9 @@ public: float* permNmxRank_; float* permNmxConf_; bool havePerm_; - + protected: - + void GenerateMaskAngle(double*, double); void CreateFilters(void); void CreateLookTable(void); @@ -154,14 +154,14 @@ protected: void NewHysteresisTr(float*, float*, BgEdgeList*, int, float*, float*); void NewEdgeFollow(int, int); void SubspaceEstim(float*, float*, float*, float*); - + float* te_; float* tm_; double low_; float* tc_; float* tl_; int npt_; - + float* grx_; float* gry_; float* permGx_; diff --git a/Utilities/otbedison/edge/BgEdgeList.cpp b/Utilities/otbedison/edge/BgEdgeList.cpp old mode 100755 new mode 100644 index 7dcdbfea2b02fb377cfb21ad799f0d1a055cc1a5..f79ca455e90f5410c73905659a3390e537d486c4 --- a/Utilities/otbedison/edge/BgEdgeList.cpp +++ b/Utilities/otbedison/edge/BgEdgeList.cpp @@ -1,225 +1,225 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: BgEdgeList.cpp -// Purpose: BgEdgeList class functions -// Author: Bogdan Georgescu -// Modified by: -// Created: 06/22/2000 -// Copyright: (c) Bogdan Georgescu -// Version: v0.1 -///////////////////////////////////////////////////////////////////////////// - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include "BgDefaults.h" -#include "BgImage.h" -#include "BgEdge.h" -#include "BgEdgeList.h" - -BgEdgeList::BgEdgeList() -{ - nEdges_ = 0; - edgelist_ = 0; - crtedge_ = 0; -} - -BgEdgeList::~BgEdgeList() -{ - if (nEdges_>0) - { - BgEdge* edge; - for (int i=0; i<nEdges_; i++) - { - edge = edgelist_->next_; - delete edgelist_; - edgelist_=edge; - } - } -} - -void BgEdgeList::AddEdge(float* edge, int nPoints) -{ - BgEdge* tedge; - tedge = new BgEdge(); - tedge->SetPoints(edge, nPoints); - if (nEdges_==0) - { - nEdges_ = 1; - edgelist_ = tedge; - crtedge_ = tedge; - } - else - { - nEdges_++; - crtedge_->next_ = tedge; - crtedge_ = tedge; - } -} - -void BgEdgeList::AddEdge(int* edge, int nPoints) -{ - BgEdge* tedge; - tedge = new BgEdge(); - tedge->SetPoints(edge, nPoints); - if (nEdges_==0) - { - nEdges_ = 1; - edgelist_ = tedge; - crtedge_ = tedge; - } - else - { - nEdges_++; - crtedge_->next_ = tedge; - crtedge_ = tedge; - } -} - -void BgEdgeList::SetGradient(float* grx, float* gry, float* mark, int ncol) -{ - BgEdge* it; - int i; - - it=edgelist_; - for (i=0; i<nEdges_; i++) - { - it->SetGradient(grx, gry, mark, ncol); - it = it->next_; - } -} - -void BgEdgeList::RemoveShortEdges(int minp) -{ - if (nEdges_==0) - return; - - int nEdges=nEdges_; - BgEdge* it1; - BgEdge* it2; - it1 = edgelist_; - it2 = it1->next_; - - for (int i=1; i<nEdges_; i++) - { - if (it2->nPoints_ < minp) - { - it1->next_ = it2->next_; - delete it2; - it2 = it1->next_; - nEdges--; - } - else - { - it1 = it2; - it2 = it1->next_; - } - } - - if (edgelist_->nPoints_ < minp) - { - it1 = edgelist_; - edgelist_ = edgelist_->next_; - delete it1; - nEdges--; - } - nEdges_=nEdges; -} - -void BgEdgeList::SetBinImage(BgImage* image) -{ - int i, j; - int ix, iy; - int x, y; - - x = image->x_; - y = image->y_; - unsigned char* im=image->im_; - - for (i=0; i<x; i++) - { - for (j=0;j<y;j++) - { - *(im++) = 0; - } - } - - im = image->im_; - int* ite; - crtedge_=edgelist_; - for (i=0; i<nEdges_; i++) - { - ite = crtedge_->edge_; - for (j=0; j<crtedge_->nPoints_; j++) - { - ix = *(ite++); - iy = *(ite++); - *(im+iy*x+ix) = 255; - } - crtedge_=crtedge_->next_; - } -} - -bool BgEdgeList::SaveEdgeList(char* edgeFile) -{ - int length; - int i,j; - BgEdge *crtedge; - - FILE* fp; - fp=fopen(edgeFile,"wb"); - crtedge = edgelist_; - for (i=0; i<nEdges_; i++) - { - length = crtedge->nPoints_; - for (j=0; j<length; j++) - { - fprintf(fp, "%d %d %d\n", *((crtedge->edge_)+2*j), *((crtedge->edge_)+2*j+1), i); - } - crtedge = crtedge->next_; - } - fclose(fp); - return true; -} - -void BgEdgeList::GetAllEdgePoints(int* x, int* y, int* n) -{ - int length; - int i,j; - BgEdge *crtedge; - int *edgep; - - crtedge = edgelist_; - *n = 0; - for (i=0; i<nEdges_; i++) - { - length = crtedge->nPoints_; - edgep = crtedge->edge_; - for (j=0; j<length; j++) - { - x[*n] = edgep[2*j]; - y[*n] = edgep[2*j+1]; - (*n)++; - } - crtedge = crtedge->next_; - } -} - -void BgEdgeList::SetNoMark(void) -{ - int length; - int i,j; - BgEdge* crtedge; - unsigned char* mark; - crtedge = edgelist_; - for (i=0; i<nEdges_; i++) - { - length = crtedge->nPoints_; - mark = crtedge->mark_ = new unsigned char[length]; - crtedge->isMarkSet_ = true; - for (j=0; j<length; j++) - { - *(mark+j) = 0; - } - crtedge = crtedge->next_; - } -} +///////////////////////////////////////////////////////////////////////////// +// Name: BgEdgeList.cpp +// Purpose: BgEdgeList class functions +// Author: Bogdan Georgescu +// Modified by: +// Created: 06/22/2000 +// Copyright: (c) Bogdan Georgescu +// Version: v0.1 +///////////////////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include "BgDefaults.h" +#include "BgImage.h" +#include "BgEdge.h" +#include "BgEdgeList.h" + +BgEdgeList::BgEdgeList() +{ + nEdges_ = 0; + edgelist_ = 0; + crtedge_ = 0; +} + +BgEdgeList::~BgEdgeList() +{ + if (nEdges_>0) + { + BgEdge* edge; + for (int i=0; i<nEdges_; i++) + { + edge = edgelist_->next_; + delete edgelist_; + edgelist_=edge; + } + } +} + +void BgEdgeList::AddEdge(float* edge, int nPoints) +{ + BgEdge* tedge; + tedge = new BgEdge(); + tedge->SetPoints(edge, nPoints); + if (nEdges_==0) + { + nEdges_ = 1; + edgelist_ = tedge; + crtedge_ = tedge; + } + else + { + nEdges_++; + crtedge_->next_ = tedge; + crtedge_ = tedge; + } +} + +void BgEdgeList::AddEdge(int* edge, int nPoints) +{ + BgEdge* tedge; + tedge = new BgEdge(); + tedge->SetPoints(edge, nPoints); + if (nEdges_==0) + { + nEdges_ = 1; + edgelist_ = tedge; + crtedge_ = tedge; + } + else + { + nEdges_++; + crtedge_->next_ = tedge; + crtedge_ = tedge; + } +} + +void BgEdgeList::SetGradient(float* grx, float* gry, float* mark, int ncol) +{ + BgEdge* it; + int i; + + it=edgelist_; + for (i=0; i<nEdges_; i++) + { + it->SetGradient(grx, gry, mark, ncol); + it = it->next_; + } +} + +void BgEdgeList::RemoveShortEdges(int minp) +{ + if (nEdges_==0) + return; + + int nEdges=nEdges_; + BgEdge* it1; + BgEdge* it2; + it1 = edgelist_; + it2 = it1->next_; + + for (int i=1; i<nEdges_; i++) + { + if (it2->nPoints_ < minp) + { + it1->next_ = it2->next_; + delete it2; + it2 = it1->next_; + nEdges--; + } + else + { + it1 = it2; + it2 = it1->next_; + } + } + + if (edgelist_->nPoints_ < minp) + { + it1 = edgelist_; + edgelist_ = edgelist_->next_; + delete it1; + nEdges--; + } + nEdges_=nEdges; +} + +void BgEdgeList::SetBinImage(BgImage* image) +{ + int i, j; + int ix, iy; + int x, y; + + x = image->x_; + y = image->y_; + unsigned char* im=image->im_; + + for (i=0; i<x; i++) + { + for (j=0;j<y;j++) + { + *(im++) = 0; + } + } + + im = image->im_; + int* ite; + crtedge_=edgelist_; + for (i=0; i<nEdges_; i++) + { + ite = crtedge_->edge_; + for (j=0; j<crtedge_->nPoints_; j++) + { + ix = *(ite++); + iy = *(ite++); + *(im+iy*x+ix) = 255; + } + crtedge_=crtedge_->next_; + } +} + +bool BgEdgeList::SaveEdgeList(char* edgeFile) +{ + int length; + int i,j; + BgEdge *crtedge; + + FILE* fp; + fp=fopen(edgeFile,"wb"); + crtedge = edgelist_; + for (i=0; i<nEdges_; i++) + { + length = crtedge->nPoints_; + for (j=0; j<length; j++) + { + fprintf(fp, "%d %d %d\n", *((crtedge->edge_)+2*j), *((crtedge->edge_)+2*j+1), i); + } + crtedge = crtedge->next_; + } + fclose(fp); + return true; +} + +void BgEdgeList::GetAllEdgePoints(int* x, int* y, int* n) +{ + int length; + int i,j; + BgEdge *crtedge; + int *edgep; + + crtedge = edgelist_; + *n = 0; + for (i=0; i<nEdges_; i++) + { + length = crtedge->nPoints_; + edgep = crtedge->edge_; + for (j=0; j<length; j++) + { + x[*n] = edgep[2*j]; + y[*n] = edgep[2*j+1]; + (*n)++; + } + crtedge = crtedge->next_; + } +} + +void BgEdgeList::SetNoMark(void) +{ + int length; + int i,j; + BgEdge* crtedge; + unsigned char* mark; + crtedge = edgelist_; + for (i=0; i<nEdges_; i++) + { + length = crtedge->nPoints_; + mark = crtedge->mark_ = new unsigned char[length]; + crtedge->isMarkSet_ = true; + for (j=0; j<length; j++) + { + *(mark+j) = 0; + } + crtedge = crtedge->next_; + } +} diff --git a/Utilities/otbedison/edge/BgEdgeList.h b/Utilities/otbedison/edge/BgEdgeList.h old mode 100755 new mode 100644 index d20c462b9c4b38aaf9abf97ba9c63e5a03724bc4..92f34f00f4876a57d5a266cfa4fec531462a48f9 --- a/Utilities/otbedison/edge/BgEdgeList.h +++ b/Utilities/otbedison/edge/BgEdgeList.h @@ -1,29 +1,29 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: BgEdgeList.h -// Purpose: BgEdgeList class -// Author: Bogdan Georgescu -// Modified by: -// Created: 06/22/2000 -// Copyright: (c) Bogdan Georgescu -// Version: v0.1 -///////////////////////////////////////////////////////////////////////////// - -class BgEdgeList -{ -public: - int nEdges_; - BgEdge* edgelist_; - BgEdge* crtedge_; - - BgEdgeList(); - ~BgEdgeList(); - void AddEdge(float*, int); - void AddEdge(int*, int nPoints); - void RemoveShortEdges(int); - void SetBinImage(BgImage*); - bool SaveEdgeList(char*); - void SetGradient(float*, float*, float*, int); - void SetNoMark(void); - void GetAllEdgePoints(int*, int*, int*); - -}; +///////////////////////////////////////////////////////////////////////////// +// Name: BgEdgeList.h +// Purpose: BgEdgeList class +// Author: Bogdan Georgescu +// Modified by: +// Created: 06/22/2000 +// Copyright: (c) Bogdan Georgescu +// Version: v0.1 +///////////////////////////////////////////////////////////////////////////// + +class BgEdgeList +{ +public: + int nEdges_; + BgEdge* edgelist_; + BgEdge* crtedge_; + + BgEdgeList(); + ~BgEdgeList(); + void AddEdge(float*, int); + void AddEdge(int*, int nPoints); + void RemoveShortEdges(int); + void SetBinImage(BgImage*); + bool SaveEdgeList(char*); + void SetGradient(float*, float*, float*, int); + void SetNoMark(void); + void GetAllEdgePoints(int*, int*, int*); + +}; diff --git a/Utilities/otbedison/edge/BgGlobalFc.cpp b/Utilities/otbedison/edge/BgGlobalFc.cpp old mode 100755 new mode 100644 index c94c6f143abe94e6eaef13801b04c42303f8b7b4..f2fcf3b284566f1aca56e709821ca8c1ac2eefdf --- a/Utilities/otbedison/edge/BgGlobalFc.cpp +++ b/Utilities/otbedison/edge/BgGlobalFc.cpp @@ -7,29 +7,29 @@ // Copyright: (c) Bogdan Georgescu // Version: v0.1 ///////////////////////////////////////////////////////////////////////////// - + #include <math.h> #include <stdio.h> #include <string.h> #include "BgDefaults.h" -// !!! only MSV -#include <sys/timeb.h> -#include <time.h> - +// !!! only MSV +#include <sys/timeb.h> +#include <time.h> + double bgSign(double x) { if (x>=0) return 1.0; return -1.0; } - + double factorial(double num) { if (num==0 || num==1) return 1; return (num * factorial(num - 1)); } - + // return 0 - error // return 1 - one real solution // return 3 - three real solutions @@ -37,18 +37,18 @@ int bgSolveCubic(double a, double b, double c, double d, double& s1, double& s2, { double p, q; double r, s, t, z; - + // convert to canonical form r = b/a; s = c/a; t = d/a; p = s-(r*r)/3.0; q = (2*r*r*r)/27.0-(r*s)/3.0+t; - + double D, phi, R; R = bgSign(q)*sqrt(fabs(p)/3.0); D = pow(p/3.0,3)+pow(q/2,2); - + if (p<0) { if (D<=0) @@ -73,18 +73,18 @@ int bgSolveCubic(double a, double b, double c, double d, double& s1, double& s2, phi = log(z+sqrt(z*z+1)); s1 = -2*R*sinh(phi/3)-r/3; return 1; - } + } return 0; } - - + + inline int bgRound(double in_x) { return int(floor(in_x + 0.5)); } - + inline int bgRoundSign(double in_x) { if (in_x>=0) @@ -96,7 +96,7 @@ inline int bgRoundSign(double in_x) return ((int) (in_x - 0.5)); } } - + void bgSort(double* ra, int nVec) { unsigned long n, l, ir, i, j; @@ -105,7 +105,7 @@ void bgSort(double* ra, int nVec) if (n<2) return; - + l = (n>>1)+1; ir = n; for (;;) @@ -142,7 +142,7 @@ void bgSort(double* ra, int nVec) ra[i-1] = rra; } } - + // rank in 0-1 range, 0 min, 1 max // inplace sort vec double bgMedian(double* vec, int nVec, double rank) @@ -153,22 +153,22 @@ double bgMedian(double* vec, int nVec, double rank) krank = nVec-1; return vec[krank]; } - + double bgMedianToSigmaGaussian(double med) { return med * 1.482602219; } - + int write_pgm_image(const char *outfilename, unsigned char *image, int rows, int cols, char *comment, int maxval) { FILE *fp; - + /*************************************************************************** * Open the output image file for writing if a filename was given. If no * filename was provided, set fp to write to standard output. ***************************************************************************/ - + if(outfilename == NULL) fp = stdout; else{ if((fp = fopen(outfilename, "wb")) == NULL){ @@ -177,291 +177,291 @@ int write_pgm_image(const char *outfilename, unsigned char *image, int rows, return(0); } } - + /*************************************************************************** * Write the header information to the PGM file. ***************************************************************************/ - + fprintf(fp, "P5\n%d %d\n", cols, rows); if(comment != NULL) if(strlen(comment) <= 70) fprintf(fp, "# %s\n", comment); fprintf(fp, "%d\n", maxval); - + /*************************************************************************** * Write the image data to the file. ***************************************************************************/ - + if(rows != fwrite(image, cols, rows, fp)){ fprintf(stderr, "Error writing the image data in write_pgm_image().\n"); if(fp != stdout) fclose(fp); return(0); } - + if(fp != stdout) fclose(fp); return(1); -} - - -void write_MATLAB_ASCII(char *filename, float *data, int rows, int cols) -{ - FILE *fp = fopen(filename, "wb"); - int i,j; - for(i = 0; i < rows; i++) - { - for(j = 0; j < cols-1; j++) - { - fprintf(fp, "%10.6f ", data[i*rows+j]); - } - fprintf(fp, "%10.6f\n", data[i*rows+cols-1]); - } - fclose(fp); -} - -/* -struct _timeb timestart; -struct _timeb timeend; -void timer_start() -{ - _ftime( ×tart ); - bgLog("timer start...\n"); -} -void timer_stop() -{ - _ftime( &timeend ); - - unsigned long seconds; - unsigned long milliseconds; - seconds = timeend.time - timestart.time; - long msdif; - msdif = timeend.millitm - timestart.millitm; - if (msdif > 0) - milliseconds = msdif; - else - { - seconds--; - milliseconds = (timeend.millitm + 1000) - timestart.millitm; - } - - bgLog("timer stop, elapsed %d.%d seconds.\n", seconds, milliseconds); -} -*/ -time_t timestart; -time_t timeend; -void timer_start() -{ - timestart = clock(); - bgLog("timer start...\n"); -} -void timer_stop() -{ - timeend = clock(); - unsigned long seconds, milliseconds; - seconds = (timeend-timestart)/CLOCKS_PER_SEC; - milliseconds = ((100*(timeend-timestart))/CLOCKS_PER_SEC) - 100*seconds; - bgLog("timer stop, elapsed %d.%d seconds.\n", seconds, milliseconds); -} - - -/********************************************/ -/* Image Sampling */ -/********************************************/ - -//zooms into an image -//pre : -// - dest is the pre-allocated destination color image -// - src is the (w x h) source color image -// - zconst is an integer zoom constant from that is >= 1 -// - interpolate is a flag that determines if interpolation -// should occur -//post: the src image has been zoomed by (zconst)x and stored into dest -void bgZoomIn(unsigned char **dest, unsigned char *src, int w, int h, int zconst, bool interpolate) -{ - - //if dest or src is NULL or zconst is < 1 exit - if((!(*dest))||(!src)||(zconst < 1)) - return; - - //if zconst = 1 then copy the image contents and return - if(zconst == 1) - { - memcpy(*dest, src, 3*w*h*sizeof(unsigned char)); - return; - } - - //calculate new image dimension - w *= zconst; - h *= zconst; - - //copy image data from source image to destination image - - //******************************************************// - - unsigned char *dptr = (*dest); - - int i, j, x, y, dp, offset, factor, index; - index = 0; - //zconst does not divide evenly into image width - if(factor = w%zconst) - { - for(j=0; j<(h-zconst); j+=zconst) - { - for(i=0; i<(w-zconst); i+=zconst) - { - dp = 3*(j*w+i); - for(y=0; y<zconst; y++) - { - for(x=0; x<zconst; x++) - { - offset = 3*(y*w+x); - dptr[dp+offset ] = src[index ]; - dptr[dp+offset+1] = src[index+1]; - dptr[dp+offset+2] = src[index+2]; - } - } - - //next data point - index += 3; - } - - dp = 3*(j*w+i); - for(y=0; y<(zconst-factor-1); y++) - { - for(x=0; x<(zconst-factor-1); x++) - { - offset = 3*(y*w+x); - dptr[dp+offset ] = src[index ]; - dptr[dp+offset+1] = src[index+1]; - dptr[dp+offset+2] = src[index+2]; - } - } - - //next data point - index += 3; - } - } - //zconst does divide evenly into image width - else - { - for(j=0; j<(h-zconst); j+=zconst) - { - for(i=0; i<(w); i+=zconst) - { - dp = 3*(j*w+i); - for(y=0; y<zconst; y++) - { - for(x=0; x<zconst; x++) - { - offset = 3*(y*w+x); - dptr[dp+offset ] = src[index ]; - dptr[dp+offset+1] = src[index+1]; - dptr[dp+offset+2] = src[index+2]; - } - } - - //next data point - index += 3; - } - } - } - - //consider last row of image - factor = h%zconst; - dp = 3*(h-zconst)*(w); - for(i=0; i<(w); i+=zconst) - { - for(y=0; y<(zconst-factor); y++) - { - for(x=0; x<(zconst-factor); x++) - { - offset = 3*(y*w+x); - dptr[dp+offset ] = src[index ]; - dptr[dp+offset+1] = src[index+1]; - dptr[dp+offset+2] = src[index+2]; - } - } - //next data point - dp += zconst*3; - index += 3; - } - - //******************************************************// - - //done. - return; - -} - -//zooms out of an image -//pre : -// - dest is the pre-allocated destination color image -// - src is the (w x h) source color image -// - zconst is an integer zoom constant from that is >= 1 -// - interpolate is a flag that determines if interpolation -// should occur -//post: the src image has been zoomed by (1/zconst)x and stored into dest -void bgZoomOut(unsigned char **dest, unsigned char *src, int w, int h, int zconst, bool interpolate) -{ - - //if dest or src is NULL or zconst is <= 1 exit - if((!(*dest))||(!src)||(zconst <= 1)) - return; - - //copy image data from source image to destination image - - //******************************************************// - - unsigned char *dptr = (*dest); - - int i, j, dp, index; - index = 0; - for(j=0; j<h; j+=zconst) - { - for(i=0; i<w; i+=zconst) - { - dp = 3*(j*w+i); - dptr[index ] = src[dp ]; - dptr[index+1] = src[dp+1]; - dptr[index+2] = src[dp+2]; - - //next data point - index += 3; - } - } - - //******************************************************// - - //done. - return; - -} - -/************************************/ -/* Filename Manipulation */ -/************************************/ - -//adds an extension (label) to a filename -void BgAddExtension(char **filename, char *label) -{ - //allocate memory for new filename - char *new_filename = new char [strlen(*filename) + strlen(label) + 1], ext[5]; - - //copy filename - strcpy(new_filename, *filename); - - //get extension of filename (e.g. '.txt') - char *pdest = strchr(new_filename, '.'); - strcpy(ext, pdest); - - //place filename label at the end of the filename - //followed by extension... - strcpy(pdest, label); - strcat(new_filename, ext); - - //delete old filename and replace it with new one... - delete *filename; - (*filename) = new_filename; - - //done. - return; -} - +} + + +void write_MATLAB_ASCII(char *filename, float *data, int rows, int cols) +{ + FILE *fp = fopen(filename, "wb"); + int i,j; + for(i = 0; i < rows; i++) + { + for(j = 0; j < cols-1; j++) + { + fprintf(fp, "%10.6f ", data[i*rows+j]); + } + fprintf(fp, "%10.6f\n", data[i*rows+cols-1]); + } + fclose(fp); +} + +/* +struct _timeb timestart; +struct _timeb timeend; +void timer_start() +{ + _ftime( ×tart ); + bgLog("timer start...\n"); +} +void timer_stop() +{ + _ftime( &timeend ); + + unsigned long seconds; + unsigned long milliseconds; + seconds = timeend.time - timestart.time; + long msdif; + msdif = timeend.millitm - timestart.millitm; + if (msdif > 0) + milliseconds = msdif; + else + { + seconds--; + milliseconds = (timeend.millitm + 1000) - timestart.millitm; + } + + bgLog("timer stop, elapsed %d.%d seconds.\n", seconds, milliseconds); +} +*/ +time_t timestart; +time_t timeend; +void timer_start() +{ + timestart = clock(); + bgLog("timer start...\n"); +} +void timer_stop() +{ + timeend = clock(); + unsigned long seconds, milliseconds; + seconds = (timeend-timestart)/CLOCKS_PER_SEC; + milliseconds = ((100*(timeend-timestart))/CLOCKS_PER_SEC) - 100*seconds; + bgLog("timer stop, elapsed %d.%d seconds.\n", seconds, milliseconds); +} + + +/********************************************/ +/* Image Sampling */ +/********************************************/ + +//zooms into an image +//pre : +// - dest is the pre-allocated destination color image +// - src is the (w x h) source color image +// - zconst is an integer zoom constant from that is >= 1 +// - interpolate is a flag that determines if interpolation +// should occur +//post: the src image has been zoomed by (zconst)x and stored into dest +void bgZoomIn(unsigned char **dest, unsigned char *src, int w, int h, int zconst, bool interpolate) +{ + + //if dest or src is NULL or zconst is < 1 exit + if((!(*dest))||(!src)||(zconst < 1)) + return; + + //if zconst = 1 then copy the image contents and return + if(zconst == 1) + { + memcpy(*dest, src, 3*w*h*sizeof(unsigned char)); + return; + } + + //calculate new image dimension + w *= zconst; + h *= zconst; + + //copy image data from source image to destination image + + //******************************************************// + + unsigned char *dptr = (*dest); + + int i, j, x, y, dp, offset, factor, index; + index = 0; + //zconst does not divide evenly into image width + if(factor = w%zconst) + { + for(j=0; j<(h-zconst); j+=zconst) + { + for(i=0; i<(w-zconst); i+=zconst) + { + dp = 3*(j*w+i); + for(y=0; y<zconst; y++) + { + for(x=0; x<zconst; x++) + { + offset = 3*(y*w+x); + dptr[dp+offset ] = src[index ]; + dptr[dp+offset+1] = src[index+1]; + dptr[dp+offset+2] = src[index+2]; + } + } + + //next data point + index += 3; + } + + dp = 3*(j*w+i); + for(y=0; y<(zconst-factor-1); y++) + { + for(x=0; x<(zconst-factor-1); x++) + { + offset = 3*(y*w+x); + dptr[dp+offset ] = src[index ]; + dptr[dp+offset+1] = src[index+1]; + dptr[dp+offset+2] = src[index+2]; + } + } + + //next data point + index += 3; + } + } + //zconst does divide evenly into image width + else + { + for(j=0; j<(h-zconst); j+=zconst) + { + for(i=0; i<(w); i+=zconst) + { + dp = 3*(j*w+i); + for(y=0; y<zconst; y++) + { + for(x=0; x<zconst; x++) + { + offset = 3*(y*w+x); + dptr[dp+offset ] = src[index ]; + dptr[dp+offset+1] = src[index+1]; + dptr[dp+offset+2] = src[index+2]; + } + } + + //next data point + index += 3; + } + } + } + + //consider last row of image + factor = h%zconst; + dp = 3*(h-zconst)*(w); + for(i=0; i<(w); i+=zconst) + { + for(y=0; y<(zconst-factor); y++) + { + for(x=0; x<(zconst-factor); x++) + { + offset = 3*(y*w+x); + dptr[dp+offset ] = src[index ]; + dptr[dp+offset+1] = src[index+1]; + dptr[dp+offset+2] = src[index+2]; + } + } + //next data point + dp += zconst*3; + index += 3; + } + + //******************************************************// + + //done. + return; + +} + +//zooms out of an image +//pre : +// - dest is the pre-allocated destination color image +// - src is the (w x h) source color image +// - zconst is an integer zoom constant from that is >= 1 +// - interpolate is a flag that determines if interpolation +// should occur +//post: the src image has been zoomed by (1/zconst)x and stored into dest +void bgZoomOut(unsigned char **dest, unsigned char *src, int w, int h, int zconst, bool interpolate) +{ + + //if dest or src is NULL or zconst is <= 1 exit + if((!(*dest))||(!src)||(zconst <= 1)) + return; + + //copy image data from source image to destination image + + //******************************************************// + + unsigned char *dptr = (*dest); + + int i, j, dp, index; + index = 0; + for(j=0; j<h; j+=zconst) + { + for(i=0; i<w; i+=zconst) + { + dp = 3*(j*w+i); + dptr[index ] = src[dp ]; + dptr[index+1] = src[dp+1]; + dptr[index+2] = src[dp+2]; + + //next data point + index += 3; + } + } + + //******************************************************// + + //done. + return; + +} + +/************************************/ +/* Filename Manipulation */ +/************************************/ + +//adds an extension (label) to a filename +void BgAddExtension(char **filename, char *label) +{ + //allocate memory for new filename + char *new_filename = new char [strlen(*filename) + strlen(label) + 1], ext[5]; + + //copy filename + strcpy(new_filename, *filename); + + //get extension of filename (e.g. '.txt') + char *pdest = strchr(new_filename, '.'); + strcpy(ext, pdest); + + //place filename label at the end of the filename + //followed by extension... + strcpy(pdest, label); + strcat(new_filename, ext); + + //delete old filename and replace it with new one... + delete *filename; + (*filename) = new_filename; + + //done. + return; +} + diff --git a/Utilities/otbedison/edge/BgImage.cpp b/Utilities/otbedison/edge/BgImage.cpp old mode 100755 new mode 100644 index b206d7dac9580867d3a4d307fc074602b018e5aa..009774ed39f950bfd71705d83e1d4aab89679882 --- a/Utilities/otbedison/edge/BgImage.cpp +++ b/Utilities/otbedison/edge/BgImage.cpp @@ -1,373 +1,373 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: BgImage.cpp -// Purpose: BgImage class functions -// Author: Bogdan Georgescu -// Modified by: -// Created: 06/22/2000 -// Copyright: (c) Bogdan Georgescu -// Version: v0.1 -///////////////////////////////////////////////////////////////////////////// - -#include "BgImage.h" - -BgImage::BgImage() -{ - hasIm_ = false; - colorIm_ = false; - im_ = 0; -} - -BgImage::BgImage(int x,int y, bool colorIm) -{ - colorIm_ = colorIm; - if (colorIm_ == false) - im_ = new unsigned char[x*y]; - else - im_ = new unsigned char[x*y*3]; - x_ = x; - y_ = y; - hasIm_ = true; -} - -BgImage::~BgImage() -{ - CleanData(); -} - -void BgImage::CleanData() -{ - if (hasIm_) - { - delete [] im_; - x_ = y_ = 0; - hasIm_ = false; - colorIm_ = false; - } -} - -void BgImage::SetImage(unsigned char* im, int x, int y, bool colorIm) -{ - CleanData(); - colorIm_ = colorIm; - if (colorIm_ == false) - im_ = new unsigned char[x*y]; - else - im_ = new unsigned char[x*y*3]; - x_ = x; - y_ = y; - hasIm_ = true; - - int i; - unsigned char *its, *itd; - if (colorIm_ == false) - { - for (i=0, its=im, itd=im_; i<x*y; i++) - { - *(itd++) = *(its++); - } - } - else - { - for (i=0, its=im, itd=im_; i<x*y*3; i++) - { - *(itd++) = *(its++); - } - } - -} - -void BgImage::SetImageFromRGB(unsigned char* im, int x, int y, bool colorIm) -{ - PrivateResize(x, y, colorIm); - - int i; - unsigned char *its, *itd; - if (colorIm_ == false) - { - for (i=0, its=im, itd=im_; i<x*y; i++, itd++, its+=3) - { - *itd = (int) (its[0]*RED_WEIGHT + its[1]*GREEN_WEIGHT + its[2]*BLUE_WEIGHT); - } - } - else - { - for (i=0, its=im, itd=im_; i<x*y*3; i++) - *(itd++) = *(its++); - } -} - -void BgImage::SetSameImageFromRGB(unsigned char* im) -{ - int i; - unsigned char *its, *itd; - if (colorIm_ == false) - { - for (i=0, its=im, itd=im_; i<x_*y_; i++, itd++, its+=3) - *itd = (int) (its[0]*RED_WEIGHT + its[1]*GREEN_WEIGHT + its[2]*BLUE_WEIGHT); - } - else - { - for (i=0, its=im, itd=im_; i<x_*y_*3; i++) - *(itd++) = *(its++); - } -} - -void BgImage::SetImage(short* im, int x, int y, bool colorIm) -{ - CleanData(); - colorIm_ = colorIm; - if (colorIm_ == false) - im_ = new unsigned char[x*y]; - else - im_ = new unsigned char[x*y*3]; - x_ = x; - y_ = y; - hasIm_ = true; - - int i; - unsigned char *itd; - short* its; - if (colorIm_ == false) - { - for (i=0, its=im, itd=im_; i<x*y; i++) - { - *(itd++) = (unsigned char) *(its++); - } - } - else - { - for (i=0, its=im, itd=im_; i<x*y*3; i++) - { - *(itd++) = (unsigned char) *(its++); - } - } -} - -void BgImage::GetImage(unsigned char* im) -{ - unsigned char *its, *itd; - int i; - if (colorIm_ == false) - { - for(i=0, its=im_, itd=im; i<x_*y_; i++) - *(itd++) = *(its++); - } - else - { - for(i=0, its=im_, itd=im; i<x_*y_*3; i++) - *(itd++) = *(its++); - } -} - -void BgImage::GetImageColor(unsigned char* im) -{ - unsigned char *its, *itd; - int i; - if (colorIm_ == false) - { - for(i=0, its=im_, itd=im; i<x_*y_; i++) - { - *(itd++) = *its; - *(itd++) = *its; - *(itd++) = *(its++); - } - } - else - { - for(i=0, its=im_, itd=im; i<(x_*y_*3); i++) - *(itd++) = *(its++); - } -} - -void BgImage::GetImageBW(unsigned char* im) -{ - unsigned char *its, *itd; - int i; - if (colorIm_ == false) - { - for(i=0, its=im_, itd=im; i<x_*y_; i++) - *(itd++) = *(its++); - } - else - { - for (i=0, its=im_, itd=im; i<x_*y_; i++, itd++, its+=3) - *itd = (int) (its[0]*RED_WEIGHT + its[1]*GREEN_WEIGHT + its[2]*BLUE_WEIGHT); - } -} - -void BgImage::GetImageR(unsigned char* im) -{ - unsigned char *its, *itd; - int i; - if (colorIm_ == false) - { - for(i=0, its=im_, itd=im; i<x_*y_; i++) - *(itd++) = *(its++); - } - else - { - for(i=0, its=im_, itd=im; i<x_*y_; i++) - { - *(itd++) = *its; - its += 3; - } - } -} - -void BgImage::GetImageG(unsigned char* im) -{ - unsigned char *its, *itd; - int i; - if (colorIm_ == false) - { - for(i=0, its=im_, itd=im; i<x_*y_; i++) - *(itd++) = *(its++); - } - else - { - for(i=0, its=im_+1, itd=im; i<x_*y_; i++) - { - *(itd++) = *its; - its += 3; - } - } -} - -void BgImage::GetImageB(unsigned char* im) -{ - unsigned char *its, *itd; - int i; - if (colorIm_ == false) - { - for(i=0, its=im_, itd=im; i<x_*y_; i++) - *(itd++) = *(its++); - } - else - { - for(i=0, its=im_+2, itd=im; i<x_*y_; i++) - { - *(itd++) = *its; - its += 3; - } - } -} - -inline unsigned char BgImage::operator()(int r, int c) const -{ - assert(hasIm_ && (r >= 0) && (r < y_) && (c >= 0) && (c < x_)); - return im_[c+r*x_]; -} - -inline unsigned char& BgImage::operator()(int r, int c) -{ - assert(hasIm_ && (r >= 0) && (r < y_) && (c >= 0) && (c < x_)); - return im_[c+r*x_]; -} - -unsigned char BgImage::PixelValue(int r, int c) -{ - assert(hasIm_ && (r >= 0) && (r < y_) && (c >= 0) && (c < x_)); - return im_[c+r*x_]; -} - -inline unsigned char gBgImPt(BgImage* in_im, int in_r, int in_c) -{ - assert(in_im->hasIm_ && (in_r >= 0) && (in_r < in_im->y_) && (in_c >= 0) && (in_c < in_im->x_)); - return in_im->im_[in_c+in_r*in_im->x_]; -} - -bool BgImage::ValidCoord(int in_x, int in_y) -{ - return ((in_x>=0) && (in_x<x_) && (in_y>=0) && (in_y<y_)); -} - -int BgImage::ValidReturnBW(int in_x, int in_y, int& cval) -{ - if ((in_x>=0) && (in_x<x_) && (in_y>=0) && (in_y<y_)) - { - cval = im_[in_x+in_y*x_]; - return 1; - } else - { - cval = -1; - return 0; - } -} -int BgImage::ValidReturnCol(int in_x, int in_y, int& rval, int& gval, int& bval) -{ - if ((in_x>=0) && (in_x<x_) && (in_y>=0) && (in_y<y_)) - { - rval = im_[in_x*3+0+in_y*(x_*3)]; - gval = im_[in_x*3+1+in_y*(x_*3)]; - bval = im_[in_x*3+2+in_y*(x_*3)]; - - return 1; - } else - { - rval = gval = bval = -1; - return 0; - } -} - -int BgImage::ReturnCol(int in_x, int in_y, int& rval, int& gval, int& bval) -{ - rval = im_[in_x*3+0+in_y*(x_*3)]; - gval = im_[in_x*3+1+in_y*(x_*3)]; - bval = im_[in_x*3+2+in_y*(x_*3)]; - return 1; -} - -bool BgImage::IsAllocated(void) const -{ - return hasIm_; -} - -const BgImage& BgImage::operator=(const BgImage& im) -{ - if (this == &im) - return *this; - - if (!im.IsAllocated()) - { - CleanData(); - return *this; - } - - PrivateCopyToThis(im); - return *this; -} - -void BgImage::PrivateCopyToThis(const BgImage& im) -{ - PrivateResize(im.x_, im.y_, im.colorIm_); - int ncopy, i; - ncopy = x_*y_; - if (colorIm_ == true) - ncopy *= 3; - - unsigned char *src; - src = im.im_; - for (i=0; i<ncopy; i++) - im_[i] = src[i]; -} - -void BgImage::PrivateResize(int width, int height, bool color) -{ - if ((hasIm_ == false) || (width != x_) || (height != y_) || (color != colorIm_)) - { - CleanData(); - x_ = width; - y_ = height; - colorIm_ = color; - if (color == false) - im_ = new unsigned char[x_*y_]; - else - im_ = new unsigned char[x_*y_*3]; - hasIm_ = true; - } -} - -void BgImage::Resize(int width, int height, bool color) -{ - PrivateResize(width, height, color); -} +///////////////////////////////////////////////////////////////////////////// +// Name: BgImage.cpp +// Purpose: BgImage class functions +// Author: Bogdan Georgescu +// Modified by: +// Created: 06/22/2000 +// Copyright: (c) Bogdan Georgescu +// Version: v0.1 +///////////////////////////////////////////////////////////////////////////// + +#include "BgImage.h" + +BgImage::BgImage() +{ + hasIm_ = false; + colorIm_ = false; + im_ = 0; +} + +BgImage::BgImage(int x,int y, bool colorIm) +{ + colorIm_ = colorIm; + if (colorIm_ == false) + im_ = new unsigned char[x*y]; + else + im_ = new unsigned char[x*y*3]; + x_ = x; + y_ = y; + hasIm_ = true; +} + +BgImage::~BgImage() +{ + CleanData(); +} + +void BgImage::CleanData() +{ + if (hasIm_) + { + delete [] im_; + x_ = y_ = 0; + hasIm_ = false; + colorIm_ = false; + } +} + +void BgImage::SetImage(unsigned char* im, int x, int y, bool colorIm) +{ + CleanData(); + colorIm_ = colorIm; + if (colorIm_ == false) + im_ = new unsigned char[x*y]; + else + im_ = new unsigned char[x*y*3]; + x_ = x; + y_ = y; + hasIm_ = true; + + int i; + unsigned char *its, *itd; + if (colorIm_ == false) + { + for (i=0, its=im, itd=im_; i<x*y; i++) + { + *(itd++) = *(its++); + } + } + else + { + for (i=0, its=im, itd=im_; i<x*y*3; i++) + { + *(itd++) = *(its++); + } + } + +} + +void BgImage::SetImageFromRGB(unsigned char* im, int x, int y, bool colorIm) +{ + PrivateResize(x, y, colorIm); + + int i; + unsigned char *its, *itd; + if (colorIm_ == false) + { + for (i=0, its=im, itd=im_; i<x*y; i++, itd++, its+=3) + { + *itd = (int) (its[0]*RED_WEIGHT + its[1]*GREEN_WEIGHT + its[2]*BLUE_WEIGHT); + } + } + else + { + for (i=0, its=im, itd=im_; i<x*y*3; i++) + *(itd++) = *(its++); + } +} + +void BgImage::SetSameImageFromRGB(unsigned char* im) +{ + int i; + unsigned char *its, *itd; + if (colorIm_ == false) + { + for (i=0, its=im, itd=im_; i<x_*y_; i++, itd++, its+=3) + *itd = (int) (its[0]*RED_WEIGHT + its[1]*GREEN_WEIGHT + its[2]*BLUE_WEIGHT); + } + else + { + for (i=0, its=im, itd=im_; i<x_*y_*3; i++) + *(itd++) = *(its++); + } +} + +void BgImage::SetImage(short* im, int x, int y, bool colorIm) +{ + CleanData(); + colorIm_ = colorIm; + if (colorIm_ == false) + im_ = new unsigned char[x*y]; + else + im_ = new unsigned char[x*y*3]; + x_ = x; + y_ = y; + hasIm_ = true; + + int i; + unsigned char *itd; + short* its; + if (colorIm_ == false) + { + for (i=0, its=im, itd=im_; i<x*y; i++) + { + *(itd++) = (unsigned char) *(its++); + } + } + else + { + for (i=0, its=im, itd=im_; i<x*y*3; i++) + { + *(itd++) = (unsigned char) *(its++); + } + } +} + +void BgImage::GetImage(unsigned char* im) +{ + unsigned char *its, *itd; + int i; + if (colorIm_ == false) + { + for(i=0, its=im_, itd=im; i<x_*y_; i++) + *(itd++) = *(its++); + } + else + { + for(i=0, its=im_, itd=im; i<x_*y_*3; i++) + *(itd++) = *(its++); + } +} + +void BgImage::GetImageColor(unsigned char* im) +{ + unsigned char *its, *itd; + int i; + if (colorIm_ == false) + { + for(i=0, its=im_, itd=im; i<x_*y_; i++) + { + *(itd++) = *its; + *(itd++) = *its; + *(itd++) = *(its++); + } + } + else + { + for(i=0, its=im_, itd=im; i<(x_*y_*3); i++) + *(itd++) = *(its++); + } +} + +void BgImage::GetImageBW(unsigned char* im) +{ + unsigned char *its, *itd; + int i; + if (colorIm_ == false) + { + for(i=0, its=im_, itd=im; i<x_*y_; i++) + *(itd++) = *(its++); + } + else + { + for (i=0, its=im_, itd=im; i<x_*y_; i++, itd++, its+=3) + *itd = (int) (its[0]*RED_WEIGHT + its[1]*GREEN_WEIGHT + its[2]*BLUE_WEIGHT); + } +} + +void BgImage::GetImageR(unsigned char* im) +{ + unsigned char *its, *itd; + int i; + if (colorIm_ == false) + { + for(i=0, its=im_, itd=im; i<x_*y_; i++) + *(itd++) = *(its++); + } + else + { + for(i=0, its=im_, itd=im; i<x_*y_; i++) + { + *(itd++) = *its; + its += 3; + } + } +} + +void BgImage::GetImageG(unsigned char* im) +{ + unsigned char *its, *itd; + int i; + if (colorIm_ == false) + { + for(i=0, its=im_, itd=im; i<x_*y_; i++) + *(itd++) = *(its++); + } + else + { + for(i=0, its=im_+1, itd=im; i<x_*y_; i++) + { + *(itd++) = *its; + its += 3; + } + } +} + +void BgImage::GetImageB(unsigned char* im) +{ + unsigned char *its, *itd; + int i; + if (colorIm_ == false) + { + for(i=0, its=im_, itd=im; i<x_*y_; i++) + *(itd++) = *(its++); + } + else + { + for(i=0, its=im_+2, itd=im; i<x_*y_; i++) + { + *(itd++) = *its; + its += 3; + } + } +} + +inline unsigned char BgImage::operator()(int r, int c) const +{ + assert(hasIm_ && (r >= 0) && (r < y_) && (c >= 0) && (c < x_)); + return im_[c+r*x_]; +} + +inline unsigned char& BgImage::operator()(int r, int c) +{ + assert(hasIm_ && (r >= 0) && (r < y_) && (c >= 0) && (c < x_)); + return im_[c+r*x_]; +} + +unsigned char BgImage::PixelValue(int r, int c) +{ + assert(hasIm_ && (r >= 0) && (r < y_) && (c >= 0) && (c < x_)); + return im_[c+r*x_]; +} + +inline unsigned char gBgImPt(BgImage* in_im, int in_r, int in_c) +{ + assert(in_im->hasIm_ && (in_r >= 0) && (in_r < in_im->y_) && (in_c >= 0) && (in_c < in_im->x_)); + return in_im->im_[in_c+in_r*in_im->x_]; +} + +bool BgImage::ValidCoord(int in_x, int in_y) +{ + return ((in_x>=0) && (in_x<x_) && (in_y>=0) && (in_y<y_)); +} + +int BgImage::ValidReturnBW(int in_x, int in_y, int& cval) +{ + if ((in_x>=0) && (in_x<x_) && (in_y>=0) && (in_y<y_)) + { + cval = im_[in_x+in_y*x_]; + return 1; + } else + { + cval = -1; + return 0; + } +} +int BgImage::ValidReturnCol(int in_x, int in_y, int& rval, int& gval, int& bval) +{ + if ((in_x>=0) && (in_x<x_) && (in_y>=0) && (in_y<y_)) + { + rval = im_[in_x*3+0+in_y*(x_*3)]; + gval = im_[in_x*3+1+in_y*(x_*3)]; + bval = im_[in_x*3+2+in_y*(x_*3)]; + + return 1; + } else + { + rval = gval = bval = -1; + return 0; + } +} + +int BgImage::ReturnCol(int in_x, int in_y, int& rval, int& gval, int& bval) +{ + rval = im_[in_x*3+0+in_y*(x_*3)]; + gval = im_[in_x*3+1+in_y*(x_*3)]; + bval = im_[in_x*3+2+in_y*(x_*3)]; + return 1; +} + +bool BgImage::IsAllocated(void) const +{ + return hasIm_; +} + +const BgImage& BgImage::operator=(const BgImage& im) +{ + if (this == &im) + return *this; + + if (!im.IsAllocated()) + { + CleanData(); + return *this; + } + + PrivateCopyToThis(im); + return *this; +} + +void BgImage::PrivateCopyToThis(const BgImage& im) +{ + PrivateResize(im.x_, im.y_, im.colorIm_); + int ncopy, i; + ncopy = x_*y_; + if (colorIm_ == true) + ncopy *= 3; + + unsigned char *src; + src = im.im_; + for (i=0; i<ncopy; i++) + im_[i] = src[i]; +} + +void BgImage::PrivateResize(int width, int height, bool color) +{ + if ((hasIm_ == false) || (width != x_) || (height != y_) || (color != colorIm_)) + { + CleanData(); + x_ = width; + y_ = height; + colorIm_ = color; + if (color == false) + im_ = new unsigned char[x_*y_]; + else + im_ = new unsigned char[x_*y_*3]; + hasIm_ = true; + } +} + +void BgImage::Resize(int width, int height, bool color) +{ + PrivateResize(width, height, color); +} diff --git a/Utilities/otbedison/edge/BgImage.h b/Utilities/otbedison/edge/BgImage.h old mode 100755 new mode 100644 index bf62e303886fcd1038d9fd23c20517372d5a90ae..127aea8759086c242ea37b170fbb2ea6666ba012 --- a/Utilities/otbedison/edge/BgImage.h +++ b/Utilities/otbedison/edge/BgImage.h @@ -1,74 +1,74 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: BgImage.h -// Purpose: BgImage class -// Author: Bogdan Georgescu -// Modified by: -// Created: 06/22/2000 -// Copyright: (c) Bogdan Georgescu -// Version: v0.1 -///////////////////////////////////////////////////////////////////////////// - -#ifndef _BG_IMAGE_H -#define _BG_IMAGE_H - -#include <assert.h> - -#define RED_WEIGHT 0.299 -#define GREEN_WEIGHT 0.587 -#define BLUE_WEIGHT 0.114 - -class BgImage -{ -public: - int x_; - int y_; - unsigned char* im_; - bool hasIm_; - bool colorIm_; // false - bw image - // true - color RGB image - - BgImage(); - BgImage(int, int, bool colorIm = false); - ~BgImage(); - - void SetImage(unsigned char*, int, int, bool colorIm = false); - void SetImageFromRGB(unsigned char*, int, int, bool colorIm = false); - void SetSameImageFromRGB(unsigned char*); - void SetImage(short*, int, int, bool colorIm = false); - void GetImage(unsigned char*); - void GetImageBW(unsigned char*); - void GetImageColor(unsigned char*); - void GetImageR(unsigned char*); - void GetImageG(unsigned char*); - void GetImageB(unsigned char*); - bool ValidCoord(int, int); - int ValidReturnBW(int in_x, int in_y, int& cval); - int ValidReturnCol(int in_x, int in_y, int& rval, int& gval, int& bval); - int ReturnCol(int in_x, int in_y, int& rval, int& gval, int& bval); - - inline int GetWidth() {return x_;}; - inline int GetHeight() {return y_;}; - - - const BgImage& operator=(const BgImage& im); - bool IsAllocated(void) const; - - void CleanData(); - inline unsigned char operator()(int, int) const; - inline unsigned char& operator()(int, int); - unsigned char PixelValue(int, int); - - void Resize(int width, int height, bool color); - -private: - void PrivateCopyToThis(const BgImage& im); - void PrivateResize(int width, int height, bool color); - - -}; -extern inline unsigned char gBgImPt(BgImage*, int, int); - -#endif - - - +///////////////////////////////////////////////////////////////////////////// +// Name: BgImage.h +// Purpose: BgImage class +// Author: Bogdan Georgescu +// Modified by: +// Created: 06/22/2000 +// Copyright: (c) Bogdan Georgescu +// Version: v0.1 +///////////////////////////////////////////////////////////////////////////// + +#ifndef _BG_IMAGE_H +#define _BG_IMAGE_H + +#include <assert.h> + +#define RED_WEIGHT 0.299 +#define GREEN_WEIGHT 0.587 +#define BLUE_WEIGHT 0.114 + +class BgImage +{ +public: + int x_; + int y_; + unsigned char* im_; + bool hasIm_; + bool colorIm_; // false - bw image + // true - color RGB image + + BgImage(); + BgImage(int, int, bool colorIm = false); + ~BgImage(); + + void SetImage(unsigned char*, int, int, bool colorIm = false); + void SetImageFromRGB(unsigned char*, int, int, bool colorIm = false); + void SetSameImageFromRGB(unsigned char*); + void SetImage(short*, int, int, bool colorIm = false); + void GetImage(unsigned char*); + void GetImageBW(unsigned char*); + void GetImageColor(unsigned char*); + void GetImageR(unsigned char*); + void GetImageG(unsigned char*); + void GetImageB(unsigned char*); + bool ValidCoord(int, int); + int ValidReturnBW(int in_x, int in_y, int& cval); + int ValidReturnCol(int in_x, int in_y, int& rval, int& gval, int& bval); + int ReturnCol(int in_x, int in_y, int& rval, int& gval, int& bval); + + inline int GetWidth() {return x_;}; + inline int GetHeight() {return y_;}; + + + const BgImage& operator=(const BgImage& im); + bool IsAllocated(void) const; + + void CleanData(); + inline unsigned char operator()(int, int) const; + inline unsigned char& operator()(int, int); + unsigned char PixelValue(int, int); + + void Resize(int width, int height, bool color); + +private: + void PrivateCopyToThis(const BgImage& im); + void PrivateResize(int width, int height, bool color); + + +}; +extern inline unsigned char gBgImPt(BgImage*, int, int); + +#endif + + + diff --git a/Utilities/otbedison/prompt/defs.h b/Utilities/otbedison/prompt/defs.h old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/edison.cpp b/Utilities/otbedison/prompt/edison.cpp old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/edison.h b/Utilities/otbedison/prompt/edison.h old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/error.h b/Utilities/otbedison/prompt/error.h old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/flags.h b/Utilities/otbedison/prompt/flags.h old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/globalFnc.cpp b/Utilities/otbedison/prompt/globalFnc.cpp old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/imfilt.h b/Utilities/otbedison/prompt/imfilt.h old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/libppm.cpp b/Utilities/otbedison/prompt/libppm.cpp old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/libppm.h b/Utilities/otbedison/prompt/libppm.h old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/main.cpp b/Utilities/otbedison/prompt/main.cpp old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/parser.cpp b/Utilities/otbedison/prompt/parser.cpp old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/prompt/parser.h b/Utilities/otbedison/prompt/parser.h old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/segm/RAList.cpp b/Utilities/otbedison/segm/RAList.cpp old mode 100755 new mode 100644 index eda5ddf02d0098bba36dd08de364c46a4f1b05b6..b5abe87552d64782fc7795e5a1829ad2380ce55c --- a/Utilities/otbedison/segm/RAList.cpp +++ b/Utilities/otbedison/segm/RAList.cpp @@ -1,172 +1,172 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Region Adjacency List: - ===================== - - The Region Adjacency List class is used by the Image - Processor class in the construction of a Region Adjacency - Matrix, used by this class to applying transitive closure - and to prune spurious regions during image segmentation. - - The definition of the RAList class is provided below. Its - prototype is provided in "RAList.h". - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ -//include Region Adjacency List class prototype -#include "RAList.h" - -//include needed libraries -#include <stdio.h> -#include <assert.h> -#include <stdlib.h> - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Class Constructor and Destructor */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Class Constructor */ -/*******************************************************/ -/*Constructs a RAList object. */ -/*******************************************************/ -/*Post: */ -/* - a RAlist object has been properly constru- */ -/* cted. */ -/*******************************************************/ - -RAList::RAList( void ) -{ - //initialize label and link - label = -1; - next = NULL; - - //initialize edge strenght weight and count - edgeStrength = 0; - edgePixelCount = 0; -} - -/*******************************************************/ -/*Class Destructor */ -/*******************************************************/ -/*Destructrs a RAList object. */ -/*******************************************************/ -/*Post: */ -/* - the RAList object has been properly dest- */ -/* ructed. */ -/*******************************************************/ - -RAList::~RAList( void ) -{ - //do nothing -} - -/*******************************************************/ -/*Insert */ -/*******************************************************/ -/*Insert a region node into the region adjacency list. */ -/*******************************************************/ -/*Pre: */ -/* - entry is a node representing a connected re- */ -/* gion */ -/*Post: */ -/* - entry has been inserted into the region adj- */ -/* acency list if it does not already exist */ -/* there. */ -/* - if the entry already exists in the region */ -/* adjacency list 1 is returned otherwise 0 is */ -/* returned. */ -/*******************************************************/ - -int RAList::Insert(RAList *entry) -{ - - //if the list contains only one element - //then insert this element into next - if(!next) - { - //insert entry - next = entry; - entry->next = NULL; - - //done - return 0; - } - - //traverse the list until either: - - //(a) entry's label already exists - do nothing - //(b) the list ends or the current label is - // greater than entry's label, thus insert the entry - // at this location - - //check first entry - if(next->label > entry->label) - { - //insert entry into the list at this location - entry->next = next; - next = entry; - - //done - return 0; - } - - //check the rest of the list... - exists = 0; - cur = next; - while(cur) - { - if(entry->label == cur->label) - { - //node already exists - exists = 1; - break; - } - else if((!(cur->next))||(cur->next->label > entry->label)) - { - //insert entry into the list at this location - entry->next = cur->next; - cur->next = entry; - break; - } - - //traverse the region adjacency list - cur = cur->next; - } - - //done. Return exists indicating whether or not a new node was - // actually inserted into the region adjacency list. - return (int)(exists); - -} - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Region Adjacency List: + ===================== + + The Region Adjacency List class is used by the Image + Processor class in the construction of a Region Adjacency + Matrix, used by this class to applying transitive closure + and to prune spurious regions during image segmentation. + + The definition of the RAList class is provided below. Its + prototype is provided in "RAList.h". + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ +//include Region Adjacency List class prototype +#include "RAList.h" + +//include needed libraries +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Class Constructor and Destructor */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Class Constructor */ +/*******************************************************/ +/*Constructs a RAList object. */ +/*******************************************************/ +/*Post: */ +/* - a RAlist object has been properly constru- */ +/* cted. */ +/*******************************************************/ + +RAList::RAList( void ) +{ + //initialize label and link + label = -1; + next = NULL; + + //initialize edge strenght weight and count + edgeStrength = 0; + edgePixelCount = 0; +} + +/*******************************************************/ +/*Class Destructor */ +/*******************************************************/ +/*Destructrs a RAList object. */ +/*******************************************************/ +/*Post: */ +/* - the RAList object has been properly dest- */ +/* ructed. */ +/*******************************************************/ + +RAList::~RAList( void ) +{ + //do nothing +} + +/*******************************************************/ +/*Insert */ +/*******************************************************/ +/*Insert a region node into the region adjacency list. */ +/*******************************************************/ +/*Pre: */ +/* - entry is a node representing a connected re- */ +/* gion */ +/*Post: */ +/* - entry has been inserted into the region adj- */ +/* acency list if it does not already exist */ +/* there. */ +/* - if the entry already exists in the region */ +/* adjacency list 1 is returned otherwise 0 is */ +/* returned. */ +/*******************************************************/ + +int RAList::Insert(RAList *entry) +{ + + //if the list contains only one element + //then insert this element into next + if(!next) + { + //insert entry + next = entry; + entry->next = NULL; + + //done + return 0; + } + + //traverse the list until either: + + //(a) entry's label already exists - do nothing + //(b) the list ends or the current label is + // greater than entry's label, thus insert the entry + // at this location + + //check first entry + if(next->label > entry->label) + { + //insert entry into the list at this location + entry->next = next; + next = entry; + + //done + return 0; + } + + //check the rest of the list... + exists = 0; + cur = next; + while(cur) + { + if(entry->label == cur->label) + { + //node already exists + exists = 1; + break; + } + else if((!(cur->next))||(cur->next->label > entry->label)) + { + //insert entry into the list at this location + entry->next = cur->next; + cur->next = entry; + break; + } + + //traverse the region adjacency list + cur = cur->next; + } + + //done. Return exists indicating whether or not a new node was + // actually inserted into the region adjacency list. + return (int)(exists); + +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + diff --git a/Utilities/otbedison/segm/RAList.h b/Utilities/otbedison/segm/RAList.h old mode 100755 new mode 100644 index 203d5cf81bf7aca114452a0308b2b47f12be5945..2c37fcff60cf9d26806bb5fed72ffc5cdebbd21b --- a/Utilities/otbedison/segm/RAList.h +++ b/Utilities/otbedison/segm/RAList.h @@ -1,92 +1,92 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Region Adjacency List: - ===================== - - The Region Adjacency List class is used by the Image - Processor class in the construction of a Region Adjacency - Matrix, used by this class to applying transitive closure - and to prune spurious regions during image segmentation. - - The prototype for the RAList class is provided below. Its - defition is provided in "RAList.cc". - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - -#ifndef RALIST_H -#define RALIST_H - -//define Region Adjacency List class prototype -class RAList { - -public: - - //============================ - // *** Public Data Members *** - //============================ - - ////////////RAM Label////////// - int label; - - ////////////RAM Weight///////// - float edgeStrength; - int edgePixelCount; - - ////////////RAM Link/////////// - RAList *next; - - //======================= - // *** Public Methods *** - //======================= - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Class Constructor and Destructor */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - //***Class Constrcutor*** - RAList( void ); - - //***Class Destructor*** - ~RAList( void ); - - /*/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* RAM List Manipulation */ - /*\/\/\/\/\/\/\/\/\/\/\/\/*/ - - //Usage: Insert(entry) - int Insert(RAList*); //Insert a region node into the region adjecency list - -private: - - //============================= - // *** Private Data Members *** - //============================= - - ///////current and previous pointer///// - RAList *cur, *prev; - - ////////flag/////////// - unsigned char exists; - -}; - -#endif +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Region Adjacency List: + ===================== + + The Region Adjacency List class is used by the Image + Processor class in the construction of a Region Adjacency + Matrix, used by this class to applying transitive closure + and to prune spurious regions during image segmentation. + + The prototype for the RAList class is provided below. Its + defition is provided in "RAList.cc". + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + +#ifndef RALIST_H +#define RALIST_H + +//define Region Adjacency List class prototype +class RAList { + +public: + + //============================ + // *** Public Data Members *** + //============================ + + ////////////RAM Label////////// + int label; + + ////////////RAM Weight///////// + float edgeStrength; + int edgePixelCount; + + ////////////RAM Link/////////// + RAList *next; + + //======================= + // *** Public Methods *** + //======================= + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Class Constructor and Destructor */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + //***Class Constrcutor*** + RAList( void ); + + //***Class Destructor*** + ~RAList( void ); + + /*/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* RAM List Manipulation */ + /*\/\/\/\/\/\/\/\/\/\/\/\/*/ + + //Usage: Insert(entry) + int Insert(RAList*); //Insert a region node into the region adjecency list + +private: + + //============================= + // *** Private Data Members *** + //============================= + + ///////current and previous pointer///// + RAList *cur, *prev; + + ////////flag/////////// + unsigned char exists; + +}; + +#endif diff --git a/Utilities/otbedison/segm/ms.cpp b/Utilities/otbedison/segm/ms.cpp old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/segm/ms.h b/Utilities/otbedison/segm/ms.h old mode 100755 new mode 100644 diff --git a/Utilities/otbedison/segm/msImageProcessor.cpp b/Utilities/otbedison/segm/msImageProcessor.cpp old mode 100755 new mode 100644 index ad7ac24016121a7b202105718323f07c9bf050d4..88d30e2c6c9bcfffb78f7db350ad597e7afce3ab --- a/Utilities/otbedison/segm/msImageProcessor.cpp +++ b/Utilities/otbedison/segm/msImageProcessor.cpp @@ -1,4669 +1,4669 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Mean Shift Image Processor Class: - ================================ - - The following class inherits from the mean shift library - in order to perform the specialized tasks of image - segmentation and filtering. - - The definition of the Mean Shift Image Processor Class - is provided below. Its prototype is provided in - 'msImageProcessor.h'. - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - -//include image processor class prototype -#include "msImageProcessor.h" - -//include needed libraries -#include <math.h> -#include <stdio.h> -#include <assert.h> -#include <string.h> -#include <stdlib.h> - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - /*/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Constructor/Destructor */ - /*\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Class Constructor */ -/*******************************************************/ -/*Post: */ -/* The msImageProcessor class has been properly */ -/* initialized. */ -/*******************************************************/ - -msImageProcessor::msImageProcessor( void ) -{ - - //intialize basin of attraction structure - //used by the filtering algorithm - modeTable = NULL; - pointList = NULL; - pointCount = 0; - - //initialize region list - regionList = NULL; - - //initialize output structures... - msRawData = NULL; - labels = NULL; - modes = NULL; - modePointCounts = NULL; - regionCount = 0; - - //intialize temporary buffers used for - //performing connected components - indexTable = NULL; - LUV_data = NULL; - - //initialize region adjacency matrix - raList = NULL; - freeRAList = NULL; - raPool = NULL; - - //intialize visit table to having NULL entries - visitTable = NULL; - - //initialize epsilon such that transitive closure - //does not take edge strength into consideration when - //fusing regions of similar color - epsilon = 1.0; - - //initialize class state to indicate that - //an output data structure has not yet been - //created... - class_state.OUTPUT_DEFINED = false; - - - LUV_treshold = 1.0; -} - -/*******************************************************/ -/*Class Destructor */ -/*******************************************************/ -/*Post: */ -/* The msImageProcessor class has been properly */ -/* destroyed. */ -/*******************************************************/ - -msImageProcessor::~msImageProcessor( void ) -{ - - //de-allocate memory - if(class_state.OUTPUT_DEFINED) DestroyOutput(); - if(regionList) delete regionList; - regionList = NULL; - - //done. - -} - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Input Image Declaration */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Define Image */ -/*******************************************************/ -/*Uploads an image into the image segmenter class to */ -/*be segmented. */ -/*******************************************************/ -/*Pre: */ -/* - data_ is a one dimensional array of unsigned */ -/* char RGB vectors */ -/* - type is the type of the image: COLOR or */ -/* GREYSCALE */ -/* - height_ and width_ define the dimension of */ -/* the image */ -/* - if the image is of type GREYSCALE then */ -/* data containes only one number per pixel */ -/* location, where a pixel location is defined */ -/* by the index into the data array */ -/*Post: */ -/* - the image specified has been uploaded into */ -/* the image segmenter class to be segmented. */ -/*******************************************************/ - -void msImageProcessor::DefineImage(byte *data_, imageType type, int height_, int width_) -{ - - //obtain image dimension from image type - int dim; - if(type == COLOR) - dim = 3; - else - dim = 1; - - //perfor rgb to luv conversion - int i; - float *luv = new float [height_*width_*dim]; - if(dim == 1) - { - for(i = 0; i < height_*width_; i++) - luv[i] = (float)(data_[i]); - } - else - { - for(i = 0; i < height_*width_; i++) - RGBtoLUV(&data_[dim*i], &luv[dim*i]); - } - - //define input defined on a lattice using mean shift base class - DefineLInput(luv, height_, width_, dim); - - //Define a default kernel if it has not been already - //defined by user - if(!h) - { - //define default kernel paramerters... - kernelType k[2] = {Uniform, Uniform}; - int P[2] = {2, N}; - float tempH[2] = {1.0 , 1.0}; - - //define default kernel in mean shift base class - DefineKernel(k, tempH, P, 2); - } - - //de-allocate memory - delete [] luv; - - //done. - return; - -} - -void msImageProcessor::DefineBgImage(byte* data_, imageType type, int height_, int width_) -{ - - //obtain image dimension from image type - int dim; - if(type == COLOR) - dim = 3; - else - dim = 1; - - //perform texton classification - int i; - float *luv = new float [height_*width_*dim]; - if(dim == 1) - { - for(i = 0; i < height_*width_; i++) - luv[i] = (float)(data_[i]); - } - else - { - for(i = 0; i < height_*width_; i++) - RGBtoLUV(&data_[dim*i], &luv[dim*i]); - } - - //define input defined on a lattice using mean shift base class - DefineLInput(luv, height_, width_, dim); - - //Define a default kernel if it has not been already - //defined by user - if(!h) - { - //define default kernel paramerters... - kernelType k[2] = {Uniform, Uniform}; - int P[2] = {2, N}; - float tempH[2] = {1.0 , 1.0}; - - //define default kernel in mean shift base class - DefineKernel(k, tempH, P, 2); - } - - //de-allocate memory - delete [] luv; - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\*/ - /* Weight Map */ - /*\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Set Weight Map */ -/*******************************************************/ -/*Populates the weight map with specified edge */ -/*strengths. */ -/*******************************************************/ -/*Pre: */ -/* - wm is a floating point array of size */ -/* (height x width) specifying for each pixel */ -/* edge strength. */ -/* - eps is a threshold used to fuse similar */ -/* regions during transitive closure. */ -/*Post: */ -/* - wm has been used to populate the weight */ -/* map. */ -/* - the threshold used during transitive closure */ -/* is taken as eps. */ -/*******************************************************/ - -void msImageProcessor::SetWeightMap(float *wm, float eps) -{ - - //initlaize confmap using wm - SetLatticeWeightMap(wm); - - //set threshold value - if((epsilon = eps) < 0) - ErrorHandler("msImageProcessor", "SetWeightMap", "Threshold is negative."); - - //done. - return; - -} - -/*******************************************************/ -/*Remove Weight Map */ -/*******************************************************/ -/*Removes the weight map. */ -/*******************************************************/ -/*Post: */ -/* - the weight map has been removed. */ -/* - if a weight map did not exist NO error */ -/* is flagged. */ -/*******************************************************/ - -void msImageProcessor::RemoveWeightMap( void ) -{ - - //remove confmap - RemoveLatticeWeightMap(); - - //set threshold value to zero - epsilon = 0; - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\/\*/ - /* Image Filtering */ - /*\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Filter */ -/*******************************************************/ -/*Performs mean shift filtering on the specified input */ -/*image using a user defined kernel. */ -/*******************************************************/ -/*Pre: */ -/* - the user defined kernel used to apply mean */ -/* shift filtering to the defined input image */ -/* has spatial bandwidth sigmaS and range band- */ -/* width sigmaR */ -/* - speedUpLevel determines whether or not the */ -/* filtering should be optimized for faster */ -/* execution: a value of NO_SPEEDUP turns this */ -/* optimization off and a value SPEEDUP turns */ -/* this optimization on */ -/* - a data set has been defined */ -/* - the height and width of the lattice has been */ -/* specified using method DefineLattice() */ -/*Post: */ -/* - mean shift filtering has been applied to the */ -/* input image using a user defined kernel */ -/* - the filtered image is stored in the private */ -/* data members of the msImageProcessor class. */ -/*******************************************************/ - -void msImageProcessor::Filter(int sigmaS, float sigmaR, SpeedUpLevel speedUpLevel) -{ - - //Check Class consistency... - - //check: - // (1) if this operation is consistent - // (2) if kernel was created - // (3) if data set is defined - // (4) if the dimension of the kernel agrees with that - // of the defined data set - // if not ... flag an error! - classConsistencyCheck(N+2, true); - if(ErrorStatus == EL_ERROR) - return; - - //If the algorithm has been halted, then exit - if((ErrorStatus = msSys.Progress((float)(0.0))) == EL_HALT) - { - return; - } - - //If the image has just been read then allocate memory - //for and initialize output data structure used to store - //image modes and their corresponding regions... - if(class_state.OUTPUT_DEFINED == false) - { - InitializeOutput(); - - //check for errors... - if(ErrorStatus == EL_ERROR) - return; - } - - //****************** Allocate Memory ****************** - - //Allocate memory for basin of attraction mode structure... - if((!(modeTable = new unsigned char [L]))||(!(pointList = new int [L]))) - { - ErrorHandler("msImageProcessor", "Allocate", "Not enough memory."); - return; - } - - //start timer -#ifdef PROMPT - double timer; - msSys.StartTimer(); -#endif - - //***************************************************** - - //filter image according to speedup level... - switch(speedUpLevel) - { - //no speedup... - case NO_SPEEDUP: - //NonOptimizedFilter((float)(sigmaS), sigmaR); break; - NewNonOptimizedFilter((float)(sigmaS), sigmaR); break; - //medium speedup - case MED_SPEEDUP: - //OptimizedFilter1((float)(sigmaS), sigmaR); break; - NewOptimizedFilter1((float)(sigmaS), sigmaR); break; - //high speedup - case HIGH_SPEEDUP: - //OptimizedFilter2((float)(sigmaS), sigmaR); break; - NewOptimizedFilter2((float)(sigmaS), sigmaR); break; - // new speedup - } - - //****************** Deallocate Memory ****************** - - //de-allocate memory used by basin of attraction mode structure - delete [] modeTable; - delete [] pointList; - - //re-initialize structure - modeTable = NULL; - pointList = NULL; - pointCount = 0; - - //******************************************************* - - //If the algorithm has been halted, then de-allocate the output - //and exit - if((ErrorStatus = msSys.Progress((float)(0.8))) == EL_HALT) - { - DestroyOutput(); - return; - } - - //Label image regions, also if segmentation is not to be - //performed use the resulting classification structure to - //calculate the image boundaries... - - /* - //copy msRawData into LUV_data, rounding each component of each - //LUV value stored by msRawData to the nearest integer - int i; - for(i = 0; i < L*N; i++) - { - if(msRawData[i] < 0) - LUV_data[i] = (int)(msRawData[i] - 0.5); - else - LUV_data[i] = (int)(msRawData[i] + 0.5); - } - */ - int i; - for (i=0; i<L*N; i++) - { - LUV_data[i] = msRawData[i]; - } - - -#ifdef PROMPT - timer = msSys.ElapsedTime(); - msSys.Prompt("(%6.2f sec)\nConnecting regions ...", timer); - msSys.StartTimer(); -#endif - - //Perform connecting (label image regions) using LUV_data - Connect(); - -#ifdef PROMPT - timer = msSys.ElapsedTime(); - msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount); - msSys.StartTimer(); -#endif - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\/\/\/\*/ - /* Image Region Fusing */ - /*\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Fuse Regions */ -/*******************************************************/ -/*Fuses the regions of a filtered image. */ -/*******************************************************/ -/*Pre: */ -/* - the range radius is specified by sigmaR */ -/* - minRegion is the minimum point density that */ -/* a region may have in the resulting segment- */ -/* ed image */ -/* - a data set has been defined */ -/* - the height and width of the lattice has been */ -/* specified using method DefineLattice() */ -/*Post: */ -/* - the image regions have been fused. */ -/* - if an result is stored by this class then */ -/* this result is used as input to this method. */ -/* - if no result is stored by this class, */ -/* the input image defined by calling the */ -/* method DefineImage is used. */ -/*******************************************************/ - -void msImageProcessor::FuseRegions(float sigmaS, int minRegion) -{ - - //Check Class consistency... - - //check: - // (1) if this operation is consistent - // (2) if kernel was created - // (3) if data set is defined - // (4) if the dimension of the kernel agrees with that - // of the defined data set - // if not ... flag an error! - classConsistencyCheck(N+2, true); - if(ErrorStatus == EL_ERROR) - return; - - //Check to see if the algorithm is to be halted, if so then - //destroy output and exit - if((ErrorStatus = msSys.Progress((float)(0.8))) == EL_HALT) - { - if(class_state.OUTPUT_DEFINED) DestroyOutput(); - return; - } - - //obtain sigmaS (make sure it is not zero or negative, if not - //flag an error) - if((h[1] = sigmaS) <= 0) - { - ErrorHandler("msImageProcessor", "FuseRegions", "The feature radius must be greater than or equal to zero."); - return; - } - - //if output has not yet been generated then classify the input - //image regions to be fused... - if(!(class_state.OUTPUT_DEFINED)) - { - - //Initialize output data structure used to store - //image modes and their corresponding regions... - InitializeOutput(); - - //check for errors... - if(ErrorStatus == EL_ERROR) - return; - - //copy data into LUV_data used to classify - //image regions - /* - int i; - for(i = 0; i < L*N; i++) - { - if(data[i] < 0) - LUV_data[i] = (int)(data[i] - 0.5); - else - LUV_data[i] = (int)(data[i] + 0.5); - } - */ - int i; - for (i=0; i<L*N; i++) - { - LUV_data[i] = data[i]; - } - -#ifdef PROMPT - msSys.Prompt("Connecting regions ..."); - msSys.StartTimer(); -#endif - - //Perform connecting (label image regions) using LUV_data - Connect(); - - //check for errors - if(ErrorStatus == EL_ERROR) - return; - -#ifdef PROMPT - double timer = msSys.ElapsedTime(); - msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount); -#endif - - } - - //Check to see if the algorithm is to be halted, if so then - //destroy output and exit - if((ErrorStatus = msSys.Progress((float)(0.85))) == EL_HALT) - { - DestroyOutput(); - return; - } - -#ifdef PROMPT - msSys.Prompt("Applying transitive closure..."); - msSys.StartTimer(); -#endif - - //allocate memory visit table - visitTable = new unsigned char [L]; - - //Apply transitive closure iteratively to the regions classified - //by the RAM updating labels and modes until the color of each neighboring - //region is within sqrt(rR2) of one another. - rR2 = (float)(h[1]*h[1]*0.25); - TransitiveClosure(); - int oldRC = regionCount; - int deltaRC, counter = 0; - do { - TransitiveClosure(); - deltaRC = oldRC-regionCount; - oldRC = regionCount; - counter++; - } while ((deltaRC <= 0)&&(counter < 10)); - - //de-allocate memory for visit table - delete [] visitTable; - visitTable = NULL; - - //Check to see if the algorithm is to be halted, if so then - //destroy output and region adjacency matrix and exit - if((ErrorStatus = msSys.Progress((float)(1.0))) == EL_HALT) - { - DestroyRAM(); - DestroyOutput(); - return; - } - -#ifdef PROMPT - double timer = msSys.ElapsedTime(); - msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\nPruning spurious regions ...", timer, regionCount); - msSys.StartTimer(); -#endif - - //Prune spurious regions (regions whose area is under - //minRegion) using RAM - Prune(minRegion); - -#ifdef PROMPT - timer = msSys.ElapsedTime(); - msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount); - msSys.StartTimer(); -#endif - - //Check to see if the algorithm is to be halted, if so then - //destroy output and region adjacency matrix and exit - if((ErrorStatus = msSys.Progress((float)(1.0))) == EL_HALT) - { - DestroyRAM(); - DestroyOutput(); - return; - } - - //de-allocate memory for region adjacency matrix - DestroyRAM(); - - //output to msRawData - int i, j, label; - for(i = 0; i < L; i++) - { - label = labels[i]; - for(j = 0; j < N; j++) - { - msRawData[N*i+j] = modes[N*label+j]; - } - } - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\/\/\*/ - /* Image Segmentation */ - /*\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Segment */ -/*******************************************************/ -/*Segments the defined image. */ -/*******************************************************/ -/*Pre: */ -/* - sigmaS and sigmaR are the spatial and range */ -/* radii of the search window respectively */ -/* - minRegion is the minimum point density that */ -/* a region may have in the resulting segment- */ -/* ed image */ -/* - speedUpLevel determines whether or not the */ -/* filtering should be optimized for faster */ -/* execution: a value of NO_SPEEDUP turns this */ -/* optimization off and a value SPEEDUP turns */ -/* this optimization on */ -/*Post: */ -/* - the defined image is segmented and the */ -/* resulting segmented image is stored in the */ -/* private data members of the image segmenter */ -/* class. */ -/* - any regions whose point densities are less */ -/* than or equal to minRegion have been pruned */ -/* from the segmented image. */ -/*******************************************************/ - -void msImageProcessor::Segment(int sigmaS, float sigmaR, int minRegion, SpeedUpLevel speedUpLevel) -{ - - //make sure kernel is properly defined... - if((!h)||(kp < 2)) - { - ErrorHandler("msImageProcessor", "Segment", "Kernel corrupt or undefined."); - return; - } - - //Apply mean shift to data set using sigmaS and sigmaR... - Filter(sigmaS, sigmaR, speedUpLevel); - - //check for errors - if(ErrorStatus == EL_ERROR) - return; - - //check to see if the system has been halted, if so exit - if(ErrorStatus == EL_HALT) - return; - - //Check to see if the algorithm is to be halted, if so then - //destroy output and exit - if((ErrorStatus = msSys.Progress((float)(0.85))) == EL_HALT) - { - DestroyOutput(); - return; - } - -#ifdef PROMPT - msSys.Prompt("Applying transitive closure..."); - msSys.StartTimer(); -#endif - - //allocate memory visit table - visitTable = new unsigned char [L]; - - //Apply transitive closure iteratively to the regions classified - //by the RAM updating labels and modes until the color of each neighboring - //region is within sqrt(rR2) of one another. - rR2 = (float)(h[1]*h[1]*0.25); - TransitiveClosure(); - int oldRC = regionCount; - int deltaRC, counter = 0; - do { - TransitiveClosure(); - deltaRC = oldRC-regionCount; - oldRC = regionCount; - counter++; - } while ((deltaRC <= 0)&&(counter < 10)); - - //de-allocate memory for visit table - delete [] visitTable; - visitTable = NULL; - - //Check to see if the algorithm is to be halted, if so then - //destroy output and regions adjacency matrix and exit - if((ErrorStatus = msSys.Progress((float)(0.95))) == EL_HALT) - { - DestroyRAM(); - DestroyOutput(); - return; - } - -#ifdef PROMPT - double timer = msSys.ElapsedTime(); - msSys.Prompt("done. (%6.2f seconds, numRegions = %6d).\nPruning spurious regions\t... ", timer, regionCount); - msSys.StartTimer(); -#endif - - //Prune spurious regions (regions whose area is under - //minRegion) using RAM - Prune(minRegion); - -#ifdef PROMPT - timer = msSys.ElapsedTime(); - msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\nPruning spurious regions ...", timer, regionCount); - msSys.StartTimer(); -#endif - - //Check to see if the algorithm is to be halted, if so then - //destroy output and regions adjacency matrix and exit - if((ErrorStatus = msSys.Progress(1.0)) == EL_HALT) - { - DestroyRAM(); - DestroyOutput(); - return; - } - - //de-allocate memory for region adjacency matrix - DestroyRAM(); - - //output to msRawData - int j, i, label; - for(i = 0; i < L; i++) - { - label = labels[i]; - for(j = 0; j < N; j++) - { - msRawData[N*i+j] = modes[N*label+j]; - } - } - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Data Space Conversion */ - /*\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*RGB To LUV */ -/*******************************************************/ -/*Converts an RGB vector to LUV. */ -/* */ -/*See: */ -/* G. Wyszecki and W.S. Stiles: Color Science: */ -/* Concepts and Methods, Quantitative Data and */ -/* Formulae, Wiley, New York, 1982. */ -/*******************************************************/ -/*Pre: */ -/* - rgbVal is an unsigned char array containing */ -/* the RGB vector */ -/* - luvVal is a floating point array containing */ -/* the resulting LUV vector */ -/*Post: */ -/* - rgbVal has been converted to LUV and the */ -/* result has been stored in luvVal. */ -/*******************************************************/ - -void msImageProcessor::RGBtoLUV(byte *rgbVal, float *luvVal) -{ - - //delcare variables - double x, y, z, L0, u_prime, v_prime, constant; - - //convert RGB to XYZ... - x = XYZ[0][0]*rgbVal[0] + XYZ[0][1]*rgbVal[1] + XYZ[0][2]*rgbVal[2]; - y = XYZ[1][0]*rgbVal[0] + XYZ[1][1]*rgbVal[1] + XYZ[1][2]*rgbVal[2]; - z = XYZ[2][0]*rgbVal[0] + XYZ[2][1]*rgbVal[1] + XYZ[2][2]*rgbVal[2]; - - //convert XYZ to LUV... - - //compute L* - L0 = y / (255.0 * Yn); - if(L0 > Lt) - luvVal[0] = (float)(116.0 * (pow(L0, 1.0/3.0)) - 16.0); - else - luvVal[0] = (float)(903.3 * L0); - - //compute u_prime and v_prime - constant = x + 15 * y + 3 * z; - if(constant != 0) - { - u_prime = (4 * x) / constant; - v_prime = (9 * y) / constant; - } - else - { - u_prime = 4.0; - v_prime = 9.0/15.0; - } - - //compute u* and v* - luvVal[1] = (float) (13 * luvVal[0] * (u_prime - Un_prime)); - luvVal[2] = (float) (13 * luvVal[0] * (v_prime - Vn_prime)); - - //done. - return; - -} - -/*******************************************************/ -/*LUV To RGB */ -/*******************************************************/ -/*Converts an LUV vector to RGB. */ -/*******************************************************/ -/*Pre: */ -/* - luvVal is a floating point array containing */ -/* the LUV vector */ -/* - rgbVal is an unsigned char array containing */ -/* the resulting RGB vector */ -/*Post: */ -/* - luvVal has been converted to RGB and the */ -/* result has been stored in rgbVal. */ -/*******************************************************/ - -//define inline rounding function... -inline int my_round(double in_x) -{ - if (in_x < 0) - return (int)(in_x - 0.5); - else - return (int)(in_x + 0.5); -} - -void msImageProcessor::LUVtoRGB(float *luvVal, byte *rgbVal) -{ - - //declare variables... - int r, g, b; - double x, y, z, u_prime, v_prime; - - //perform conversion - if(luvVal[0] < 0.1) - r = g = b = 0; - else - { - //convert luv to xyz... - if(luvVal[0] < 8.0) - y = Yn * luvVal[0] / 903.3; - else - { - y = (luvVal[0] + 16.0) / 116.0; - y *= Yn * y * y; - } - - u_prime = luvVal[1] / (13 * luvVal[0]) + Un_prime; - v_prime = luvVal[2] / (13 * luvVal[0]) + Vn_prime; - - x = 9 * u_prime * y / (4 * v_prime); - z = (12 - 3 * u_prime - 20 * v_prime) * y / (4 * v_prime); - - //convert xyz to rgb... - //[r, g, b] = RGB*[x, y, z]*255.0 - r = my_round((RGB[0][0]*x + RGB[0][1]*y + RGB[0][2]*z)*255.0); - g = my_round((RGB[1][0]*x + RGB[1][1]*y + RGB[1][2]*z)*255.0); - b = my_round((RGB[2][0]*x + RGB[2][1]*y + RGB[2][2]*z)*255.0); - - //check bounds... - if(r < 0) r = 0; if(r > 255) r = 255; - if(g < 0) g = 0; if(g > 255) g = 255; - if(b < 0) b = 0; if(b > 255) b = 255; - - } - - //assign rgb values to rgb vector rgbVal - rgbVal[0] = r; - rgbVal[1] = g; - rgbVal[2] = b; - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Filtered and Segmented Image Output */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Get Raw Data */ -/*******************************************************/ -/*The output image data is returned. */ -/*******************************************************/ -/*Pre: */ -/* - outputImageData is a pre-allocated floating */ -/* point array used to store the filtered or */ -/* segmented image pixels. */ -/*Post: */ -/* - the filtered or segmented image data is */ -/* stored by outputImageData. */ -/*******************************************************/ - -void msImageProcessor::GetRawData(float *outputImageData) -{ - //make sure that outputImageData is not NULL - if(!outputImageData) - { - ErrorHandler("msImageProcessor", "GetRawData", "Output image data buffer is NULL."); - return; - } - - //copy msRawData to outputImageData - int i; - for(i = 0; i < L*N; i++) - outputImageData[i] = msRawData[i]; - - //done. - return; -} - -/*******************************************************/ -/*Get Results */ -/*******************************************************/ -/*The output image is returned. */ -/*******************************************************/ -/*Pre: */ -/* - outputImage is a pre-allocated unsinged char */ -/* array used to store the filtered or segment- */ -/* ed image pixels */ -/*Post: */ -/* - the filtered or segmented image is stored by */ -/* outputImage. */ -/*******************************************************/ - -void msImageProcessor::GetResults(byte *outputImage) -{ - - //make sure that outpuImage is not NULL - if(!outputImage) - { - ErrorHandler("msImageProcessor", "GetResults", "Output image buffer is NULL."); - return; - } - - //if the image type is GREYSCALE simply - //copy it over to the segmentedImage - if(N == 1) - { - //copy over msRawData to segmentedImage checking - //bounds - int i, pxValue; - for(i = 0; i < L; i++) - { - - //get value - pxValue = (int)(msRawData[i]+0.5); - - //store into segmented image checking bounds... - if(pxValue < 0) - outputImage[i] = (byte)(0); - else if(pxValue > 255) - outputImage[i] = (byte)(255); - else - outputImage[i] = (byte)(pxValue); - - } - - } - else if (N == 3) - { - - //otherwise convert msRawData from LUV to RGB - //storing the result in segmentedImage - int i; - for(i = 0; i < L; i++) - LUVtoRGB(&msRawData[N*i], &outputImage[N*i]); - - } - else - //Unknown image type: should use MeanShift::GetRawData()... - ErrorHandler("msImageProcessor", "GetResults", "Unknown image type. Try using MeanShift::GetRawData()."); - - //done. - return; - -} - -/*******************************************************/ -/*Get Boundaries */ -/*******************************************************/ -/*A region list containing the boundary locations for */ -/*each region is returned. */ -/*******************************************************/ -/*Post: */ -/* - a region list object containing the boundary */ -/* locations for each region is constructed */ -/* - the region list is returned */ -/* - NULL is returned if the image has not been */ -/* filtered or segmented */ -/*******************************************************/ - -RegionList *msImageProcessor::GetBoundaries( void ) -{ - - //define bounds using label information - if(class_state.OUTPUT_DEFINED) - DefineBoundaries(); - - //return region list structure - return regionList; - -} - -/*******************************************************/ -/*Get Regions */ -/*******************************************************/ -/*Returns the regions of the processed image. */ -/*******************************************************/ -/*Pre: */ -/* - labels_out is an integer array of size */ -/* height*width that stores for each pixel a */ -/* label relating that pixel to a corresponding */ -/* region in the image */ -/* - modes_out is floating point array of size */ -/* regionCount*N storing the feature component */ -/* of each region, and indexed by region label */ -/* - modePointCounts is an integer array of size */ -/* regionCount, indexed by region label, that */ -/* stores the area of each region in pixels. */ -/*Post: */ -/* If an input image was defined and processed, */ -/* - memory has been allocated for labels_out, */ -/* modes_out and MPC_out. */ -/* - labels_out, modes_out, and MPC_out have been */ -/* populated. */ -/* - the number of regions contained by the segm- */ -/* ented image has been returned. */ -/* If the image has not been defined or processed */ -/* or if there is in-sufficient memory, */ -/* - no memory has been allocated for labels_out, */ -/* modes_out, and MPC_out. */ -/* - -1 is returned for regionCount. */ -/*******************************************************/ - -int msImageProcessor::GetRegions(int **labels_out, float **modes_out, int **MPC_out) -{ - //check to see if output has been defined for the given input image... - if(class_state.OUTPUT_DEFINED == false) - return -1; - - //allocate memory for labels_out, modes_out and MPC_out based - //on output storage structure - int *labels_ = *labels_out, *MPC_out_ = *MPC_out; - float *modes_ = *modes_out; - if(!(labels_ = new int [L])) - { - ErrorHandler("msImageProcessor", "GetRegions", "Not enough memory."); - return -1; - } - if(!(modes_ = new float [regionCount*N])) - { - ErrorHandler("msImageProcessor", "GetRegions", "Not enough memory."); - return -1; - } - if(!(MPC_out_ = new int [regionCount])) - { - ErrorHandler("msImageProcessor", "GetRegions", "Not enough memory."); - return -1; - } - - //populate labels_out with image labels - int i; - for(i = 0; i < L; i++) - labels_[i] = labels[i]; - - //populate modes_out and MPC_out with the color and point - //count of each region - for(i = 0; i < regionCount*N; i++) - modes_[i] = modes[i]; - for(i = 0; i < regionCount; i++) - MPC_out_[i] = modePointCounts[i]; - - //done. Return the number of regions resulting from filtering or segmentation. - return regionCount; -} - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PRIVATE METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - /*/\/\/\/\/\/\/\/\/\*/ - /* Image Filtering */ - /*\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Non Optimized Filter */ -/*******************************************************/ -/*Performs mean shift filtering on the specified input */ -/*image using a user defined kernel. */ -/*******************************************************/ -/*Pre: */ -/* - the user defined kernel used to apply mean */ -/* shift filtering to the defined input image */ -/* has spatial bandwidth sigmaS and range band- */ -/* width sigmaR */ -/* - a data set has been defined */ -/* - the height and width of the lattice has been */ -/* specified using method DefineLattice() */ -/*Post: */ -/* - mean shift filtering has been applied to the */ -/* input image using a user defined kernel */ -/* - the filtered image is stored in the private */ -/* data members of the msImageProcessor class. */ -/*******************************************************/ - -void msImageProcessor::NonOptimizedFilter(float sigmaS, float sigmaR) -{ - - // Declare Variables - int iterationCount, i, j; - double mvAbs; - - //make sure that a lattice height and width have - //been defined... - if(!height) - { - ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); - return; - } - - //re-assign bandwidths to sigmaS and sigmaR - if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) - { - ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); - return; - } - - //define input data dimension with lattice - int lN = N + 2; - - // Traverse each data point applying mean shift - // to each data point - - // Allcocate memory for yk - double *yk = new double [lN]; - - // Allocate memory for Mh - double *Mh = new double [lN]; - - // proceed ... -#ifdef PROMPT - msSys.Prompt("done.\nApplying mean shift (Using Lattice)... "); -#ifdef SHOW_PROGRESS - msSys.Prompt("\n 0%%"); -#endif -#endif - - for(i = 0; i < L; i++) - { - - // Assign window center (window centers are - // initialized by createLattice to be the point - // data[i]) - yk[0] = i%width; - yk[1] = i/width; - for(j = 0; j < N; j++) - yk[j+2] = data[N*i+j]; - - // Calculate the mean shift vector using the lattice - LatticeMSVector(Mh, yk); - - // Calculate its magnitude squared - mvAbs = 0; - for(j = 0; j < lN; j++) - mvAbs += Mh[j]*Mh[j]; - - // Keep shifting window center until the magnitude squared of the - // mean shift vector calculated at the window center location is - // under a specified threshold (Epsilon) - - // NOTE: iteration count is for speed up purposes only - it - // does not have any theoretical importance - iterationCount = 1; - while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) - { - - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // Calculate the mean shift vector at the new - // window location using lattice - LatticeMSVector(Mh, yk); - - // Calculate its magnitude squared - mvAbs = 0; - for(j = 0; j < lN; j++) - mvAbs += Mh[j]*Mh[j]; - - // Increment interation count - iterationCount++; - - } - - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - //store result into msRawData... - for(j = 0; j < N; j++) - msRawData[N*i+j] = (float)(yk[j+2]); - - // Prompt user on progress -#ifdef SHOW_PROGRESS - percent_complete = (float)(i/(float)(L))*100; - msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); -#endif - - // Check to see if the algorithm has been halted - if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) - break; - } - - // Prompt user that filtering is completed -#ifdef PROMPT -#ifdef SHOW_PROGRESS - msSys.Prompt("\r"); -#endif - msSys.Prompt("done."); -#endif - - // de-allocate memory - delete [] yk; - delete [] Mh; - - // done. - return; - -} - - - -/*******************************************************/ -/*Optimized Filter 1 */ -/*******************************************************/ -/*Performs mean shift filtering on the specified input */ -/*image using a user defined kernel. Previous mode */ -/*information is used to avoid re-applying mean shift */ -/*on certain data points to improve performance. */ -/*******************************************************/ -/*Pre: */ -/* - the user defined kernel used to apply mean */ -/* shift filtering to the defined input image */ -/* has spatial bandwidth sigmaS and range band- */ -/* width sigmaR */ -/* - a data set has been defined */ -/* - the height and width of the lattice has been */ -/* specified using method DefineLattice() */ -/*Post: */ -/* - mean shift filtering has been applied to the */ -/* input image using a user defined kernel */ -/* - the filtered image is stored in the private */ -/* data members of the msImageProcessor class. */ -/*******************************************************/ - -void msImageProcessor::OptimizedFilter1(float sigmaS, float sigmaR) -{ - - // Declare Variables - int iterationCount, i, j, k, s, p, modeCandidateX, modeCandidateY, modeCandidate_i; - float *modeCandidatePoint; - double mvAbs, diff, el; - - //make sure that a lattice height and width have - //been defined... - if(!height) - { - ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); - return; - } - - //re-assign bandwidths to sigmaS and sigmaR - if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) - { - ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); - return; - } - - //define input data dimension with lattice - int lN = N + 2; - - // Traverse each data point applying mean shift - // to each data point - - // Allcocate memory for yk - double *yk = new double [lN]; - - // Allocate memory for Mh - double *Mh = new double [lN]; - - // Initialize mode table used for basin of attraction - memset(modeTable, 0, width*height); - - // Allocate memory mode candidate data point... - //floating point version - modeCandidatePoint = new float [N]; - - // proceed ... -#ifdef PROMPT - msSys.Prompt("done.\nApplying mean shift (Using Lattice) ... "); -#ifdef SHOW_PROGRESS - msSys.Prompt("\n 0%%"); -#endif -#endif - - - for(i = 0; i < L; i++) - { - // if a mode was already assigned to this data point - // then skip this point, otherwise proceed to - // find its mode by applying mean shift... - if (modeTable[i] == 1) - continue; - - // initialize point list... - pointCount = 0; - - // Assign window center (window centers are - // initialized by createLattice to be the point - // data[i]) - yk[0] = i%width; - yk[1] = i/width; - for(j = 0; j < N; j++) - yk[j+2] = data[N*i+j]; - - // Calculate the mean shift vector using the lattice - LatticeMSVector(Mh, yk); - - // Calculate its magnitude squared - mvAbs = 0; - for(j = 0; j < lN; j++) - mvAbs += Mh[j]*Mh[j]; - - // Keep shifting window center until the magnitude squared of the - // mean shift vector calculated at the window center location is - // under a specified threshold (Epsilon) - - // NOTE: iteration count is for speed up purposes only - it - // does not have any theoretical importance - iterationCount = 1; - while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) - { - - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // check to see if the current mode location is in the - // basin of attraction... - - // calculate the location of yk on the lattice - modeCandidateX = (int) (yk[0]+0.5); - modeCandidateY = (int) (yk[1]+0.5); - modeCandidate_i = modeCandidateY*width + modeCandidateX; - - // if mvAbs != 0 (yk did indeed move) then check - // location basin_i in the mode table to see if - // this data point either: - - // (1) has not been associated with a mode yet - // (modeTable[basin_i] = 0), so associate - // it with this one - // - // (2) it has been associated with a mode other - // than the one that this data point is converging - // to (modeTable[basin_i] = 1), so assign to - // this data point the same mode as that of basin_i - - if ((modeTable[modeCandidate_i] != 2) && (modeCandidate_i != i)) - { - // obtain the data point at basin_i to - // see if it is within h*TC_DIST_FACTOR of - // of yk - for (j = 0; j < N; j++) - modeCandidatePoint[j] = data[N*modeCandidate_i + j]; - - // check basin on non-spatial data spaces only - k = 1; - s = 0; - diff = 0; - while ((diff < TC_DIST_FACTOR) && (k<kp)) - { - diff = 0; - for (p=0; p<P[k]; p++) - { - el = (modeCandidatePoint[p+s]-yk[p+s+2])/h[k]; - diff += el*el; - } - s+=P[k]; - k++; - } - - // if the data point at basin_i is within - // a distance of h*TC_DIST_FACTOR of yk - // then depending on modeTable[basin_i] perform - // either (1) or (2) - if (diff < TC_DIST_FACTOR) - { - // if the data point at basin_i has not - // been associated to a mode then associate - // it with the mode that this one will converge - // to - if (modeTable[modeCandidate_i] == 0) - { - // no mode associated yet so associate - // it with this one... - pointList[pointCount++] = modeCandidate_i; - modeTable[modeCandidate_i] = 2; - - } else - { - - // the mode has already been associated with - // another mode, thererfore associate this one - // mode and the modes in the point list with - // the mode associated with data[basin_i]... - - // store the mode info into yk using msRawData... - for (j = 0; j < N; j++) - yk[j+2] = msRawData[modeCandidate_i*N+j]; - - // update mode table for this data point - // indicating that a mode has been associated - // with it - modeTable[i] = 1; - - // indicate that a mode has been associated - // to this data point (data[i]) - mvAbs = -1; - - // stop mean shift calculation... - break; - } - } - } - - // Calculate the mean shift vector at the new - // window location using lattice - LatticeMSVector(Mh, yk); - - // Calculate its magnitude squared - mvAbs = 0; - for(j = 0; j < lN; j++) - mvAbs += Mh[j]*Mh[j]; - - // Increment iteration count - iterationCount++; - - } - - // if a mode was not associated with this data point - // yet associate it with yk... - if (mvAbs >= 0) - { - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // update mode table for this data point - // indicating that a mode has been associated - // with it - modeTable[i] = 1; - } - - // associate the data point indexed by - // the point list with the mode stored - // by yk - for (j = 0; j < pointCount; j++) - { - // obtain the point location from the - // point list - modeCandidate_i = pointList[j]; - - // update the mode table for this point - modeTable[modeCandidate_i] = 1; - - //store result into msRawData... - for(k = 0; k < N; k++) - msRawData[N*modeCandidate_i+k] = (float)(yk[k+2]); - } - - - //store result into msRawData... - for(j = 0; j < N; j++) - msRawData[N*i+j] = (float)(yk[j+2]); - - // Prompt user on progress -#ifdef SHOW_PROGRESS - percent_complete = (float)(i/(float)(L))*100; - msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); -#endif - - // Check to see if the algorithm has been halted - if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) - break; - } - - // Prompt user that filtering is completed -#ifdef PROMPT -#ifdef SHOW_PROGRESS - msSys.Prompt("\r"); -#endif - msSys.Prompt("done."); -#endif - - // de-allocate memory - delete [] modeCandidatePoint; - delete [] yk; - delete [] Mh; - - // done. - return; - -} - -/*******************************************************/ -/*Optimized Filter 2 */ -/*******************************************************/ -/*Performs mean shift filtering on the specified input */ -/*image using a user defined kernel. Previous mode */ -/*information is used to avoid re-applying mean shift */ -/*on certain data points to improve performance. To */ -/*further improve perfmance (during segmentation) poi- */ -/*nts within h of a window center during the window */ -/*center's traversal to a mode are associated with the */ -/*mode that the window converges to. */ -/*******************************************************/ -/*Pre: */ -/* - the user defined kernel used to apply mean */ -/* shift filtering to the defined input image */ -/* has spatial bandwidth sigmaS and range band- */ -/* width sigmaR */ -/* - a data set has been defined */ -/* - the height and width of the lattice has been */ -/* specified using method DefineLattice() */ -/*Post: */ -/* - mean shift filtering has been applied to the */ -/* input image using a user defined kernel */ -/* - the filtered image is stored in the private */ -/* data members of the msImageProcessor class. */ -/*******************************************************/ - -void msImageProcessor::OptimizedFilter2(float sigmaS, float sigmaR) -{ - - //if confidence map is null set it to zero - if(!weightMap) - { - weightMap = new float [L]; - int i; - for(i = 0; i < L; i++) - weightMap[i] = 0; - } - - // Declare Variables - int iterationCount, i, j, k, s, p, modeCandidateX, modeCandidateY, modeCandidate_i; - float *modeCandidatePoint; - double mvAbs, diff, el; - - //make sure that a lattice height and width have - //been defined... - if(!height) - { - ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); - return; - } - - //re-assign bandwidths to sigmaS and sigmaR - if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) - { - ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); - return; - } - - //define input data dimension with lattice - int lN = N + 2; - - // Traverse each data point applying mean shift - // to each data point - - // Allcocate memory for yk - double *yk = new double [lN]; - - // Allocate memory for Mh - double *Mh = new double [lN]; - - // Initialize mode table used for basin of attraction - memset(modeTable, 0, width*height); - - // Allocate memory mode candidate data point... - //floating point version - modeCandidatePoint = new float [N]; - - // proceed ... -#ifdef PROMPT - msSys.Prompt("done.\nApplying mean shift (Using Lattice)... "); -#ifdef SHOW_PROGRESS - msSys.Prompt("\n 0%%"); -#endif -#endif - - for(i = 0; i < L; i++) - { - // if a mode was already assigned to this data point - // then skip this point, otherwise proceed to - // find its mode by applying mean shift... - if (modeTable[i] == 1) - continue; - - // initialize point list... - pointCount = 0; - - // Assign window center (window centers are - // initialized by createLattice to be the point - // data[i]) - yk[0] = i%width; - yk[1] = i/width; - for(j = 0; j < N; j++) - yk[j+2] = data[N*i+j]; - - // Calculate the mean shift vector using the lattice - OptLatticeMSVector(Mh, yk); - - // Calculate its magnitude squared - mvAbs = 0; - for(j = 0; j < lN; j++) - mvAbs += Mh[j]*Mh[j]; - - // Keep shifting window center until the magnitude squared of the - // mean shift vector calculated at the window center location is - // under a specified threshold (Epsilon) - - // NOTE: iteration count is for speed up purposes only - it - // does not have any theoretical importance - iterationCount = 1; - while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) - { - - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // check to see if the current mode location is in the - // basin of attraction... - - // calculate the location of yk on the lattice - modeCandidateX = (int) (yk[0]+0.5); - modeCandidateY = (int) (yk[1]+0.5); - modeCandidate_i = modeCandidateY*width + modeCandidateX; - - // if mvAbs != 0 (yk did indeed move) then check - // location basin_i in the mode table to see if - // this data point either: - - // (1) has not been associated with a mode yet - // (modeTable[basin_i] = 0), so associate - // it with this one - // - // (2) it has been associated with a mode other - // than the one that this data point is converging - // to (modeTable[basin_i] = 1), so assign to - // this data point the same mode as that of basin_i - - if ((modeTable[modeCandidate_i] != 2) && (modeCandidate_i != i)) - { - // obtain the data point at basin_i to - // see if it is within h*TC_DIST_FACTOR of - // of yk - for (j = 0; j < N; j++) - modeCandidatePoint[j] = data[N*modeCandidate_i + j]; - - // check basin on non-spatial data spaces only - k = 1; - s = 0; - diff = 0; - while ((diff < TC_DIST_FACTOR) && (k<kp)) - { - diff = 0; - for (p=0; p<P[k]; p++) - { - el = (modeCandidatePoint[p+s]-yk[p+s+2])/h[k]; - diff += el*el; - } - s+=P[k]; - k++; - } - - // if the data point at basin_i is within - // a distance of h*TC_DIST_FACTOR of yk - // then depending on modeTable[basin_i] perform - // either (1) or (2) - if (diff < TC_DIST_FACTOR) - { - // if the data point at basin_i has not - // been associated to a mode then associate - // it with the mode that this one will converge - // to - if (modeTable[modeCandidate_i] == 0) - { - // no mode associated yet so associate - // it with this one... - pointList[pointCount++] = modeCandidate_i; - modeTable[modeCandidate_i] = 2; - - } else - { - - // the mode has already been associated with - // another mode, thererfore associate this one - // mode and the modes in the point list with - // the mode associated with data[basin_i]... - - // store the mode infor int yk using msRawData... - for (j = 0; j < N; j++) - yk[j+2] = msRawData[modeCandidate_i*N+j]; - - // update mode table for this data point - // indicating that a mode has been associated - // with it - modeTable[i] = 1; - - // indicate that a mode has been associated - // to this data point (data[i]) - mvAbs = -1; - - // stop mean shift calculation... - break; - } - } - } - - // Calculate the mean shift vector at the new - // window location using lattice - OptLatticeMSVector(Mh, yk); - - // Calculate its magnitude squared - mvAbs = 0; - for(j = 0; j < lN; j++) - mvAbs += Mh[j]*Mh[j]; - - // Increment interation count - iterationCount++; - - } - - // if a mode was not associated with this data point - // yet then perform a shift the window center yk one - // last time using the mean shift vector... - if (mvAbs >= 0) - { - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // update mode table for this data point - // indicating that a mode has been associated - // with it - modeTable[i] = 1; - } - - // associate the data point indexed by - // the point list with the mode stored - // by yk - for (j = 0; j < pointCount; j++) - { - // obtain the point location from the - // point list - modeCandidate_i = pointList[j]; - - // update the mode table for this point - modeTable[modeCandidate_i] = 1; - - //store result into msRawData... - for(k = 0; k < N; k++) - msRawData[N*modeCandidate_i+k] = (float)(yk[k+2]); - } - - - //store result into msRawData... - for(j = 0; j < N; j++) - msRawData[N*i+j] = (float)(yk[j+2]); - - // Prompt user on progress -#ifdef SHOW_PROGRESS - percent_complete = (float)(i/(float)(L))*100; - msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); -#endif - - // Check to see if the algorithm has been halted - if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) - break; - - } - - // Prompt user that filtering is completed -#ifdef PROMPT -#ifdef SHOW_PROGRESS - msSys.Prompt("\r"); -#endif - msSys.Prompt("done."); -#endif - - // de-allocate memory - delete [] modeCandidatePoint; - delete [] yk; - delete [] Mh; - - // done. - return; - -} - - /*/\/\/\/\/\/\/\/\/\/\/\*/ - /* Image Classification */ - /*\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Connect */ -/*******************************************************/ -/*Classifies the regions of the mean shift filtered */ -/*image. */ -/*******************************************************/ -/*Post: */ -/* - the regions of the mean shift image have been*/ -/* classified using the private classification */ -/* structure of the msImageProcessor Class. */ -/* Namely, each region uniquely identified by */ -/* its LUV color (stored by LUV_data) and loc- */ -/* ation has been labeled and its area computed */ -/* via an eight-connected fill. */ -/*******************************************************/ - -void msImageProcessor::Connect( void ) -{ - - //define eight connected neighbors - neigh[0] = 1; - neigh[1] = 1-width; - neigh[2] = -width; - neigh[3] = -(1+width); - neigh[4] = -1; - neigh[5] = width-1; - neigh[6] = width; - neigh[7] = width+1; - - //initialize labels and modePointCounts - int i; - for(i = 0; i < width*height; i++) - { - labels[i] = -1; - modePointCounts[i] = 0; - } - - //Traverse the image labeling each new region encountered - int k, label = -1; - for(i = 0; i < height*width; i++) - { - //if this region has not yet been labeled - label it - if(labels[i] < 0) - { - //assign new label to this region - labels[i] = ++label; - - //copy region color into modes - for(k = 0; k < N; k++) - modes[(N*label)+k] = LUV_data[(N*i)+k]; -// modes[(N*label)+k] = (float)(LUV_data[(N*i)+k]); - - //populate labels with label for this specified region - //calculating modePointCounts[label]... - Fill(i, label); - } - } - - //calculate region count using label - regionCount = label+1; - - //done. - return; -} - -/*******************************************************/ -/*Fill */ -/*******************************************************/ -/*Given a region seed and a region label, Fill uses */ -/*the region seed to perform an eight-connected fill */ -/*for the specified region, labeling all pixels con- */ -/*tained by the region with the specified label: */ -/*label. */ -/*******************************************************/ -/*Pre: */ -/* - regionLoc is a region seed - a pixel that is */ -/* identified as being part of the region */ -/* labled using the label, label. */ -/*Post: */ -/* - all pixels belonging to the region specified */ -/* by regionLoc (having the same integer LUV */ -/* value specified by LUV_data) are classified */ -/* as one region by labeling each pixel in the */ -/* image clasification structure using label */ -/* via an eight-connected fill. */ -/*******************************************************/ - -void msImageProcessor::Fill(int regionLoc, int label) -{ - - //declare variables - int i, k, neighLoc, neighborsFound, imageSize = width*height; - - //Fill region starting at region location - //using labels... - - //initialzie indexTable - int index = 0; - indexTable[0] = regionLoc; - - //increment mode point counts for this region to - //indicate that one pixel belongs to this region - modePointCounts[label]++; - - while(true) - { - - //assume no neighbors will be found - neighborsFound = 0; - - //check the eight connected neighbors at regionLoc - - //if a pixel has similar color to that located at - //regionLoc then declare it as part of this region - for(i = 0; i < 8; i++) - { - // no need - /* - //if at boundary do not check certain neighbors because - //they do not exist... - if((regionLoc%width == 0)&&((i == 3)||(i == 4)||(i == 5))) - continue; - if((regionLoc%(width-1) == 0)&&((i == 0)||(i == 1)||(i == 7))) - continue; - */ - - //check bounds and if neighbor has been already labeled - neighLoc = regionLoc + neigh[i]; - if((neighLoc >= 0)&&(neighLoc < imageSize)&&(labels[neighLoc] < 0)) - { - for(k = 0; k < N; k++) - { -// if(LUV_data[(regionLoc*N)+k] != LUV_data[(neighLoc*N)+k]) - if (fabs(LUV_data[(regionLoc*N)+k]-LUV_data[(neighLoc*N)+k])>=LUV_treshold) - break; - } - - //neighbor i belongs to this region so label it and - //place it onto the index table buffer for further - //processing - if(k == N) - { - //assign label to neighbor i - labels[neighLoc] = label; - - //increment region point count - modePointCounts[label]++; - - //place index of neighbor i onto the index tabel buffer - indexTable[++index] = neighLoc; - - //indicate that a neighboring region pixel was - //identified - neighborsFound = 1; - } - } - } - - //check the indexTable to see if there are any more - //entries to be explored - if so explore them, otherwise - //exit the loop - we are finished - if(neighborsFound) - regionLoc = indexTable[index]; - else if (index > 1) - regionLoc = indexTable[--index]; - else - break; //fill complete - } - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\*/ - /* Image Pruning */ - /*\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Build Region Adjacency Matrix */ -/*******************************************************/ -/*Constructs a region adjacency matrix. */ -/*******************************************************/ -/*Pre: */ -/* - the classification data structure has been */ -/* constructed. */ -/*Post: */ -/* - a region adjacency matrix has been built */ -/* using the classification data structure. */ -/*******************************************************/ - -void msImageProcessor::BuildRAM( void ) -{ - - //Allocate memory for region adjacency matrix if it hasn't already been allocated - if((!raList)&&((!(raList = new RAList [regionCount]))||(!(raPool = new RAList [NODE_MULTIPLE*regionCount])))) - { - ErrorHandler("msImageProcessor", "Allocate", "Not enough memory."); - return; - } - - //initialize the region adjacency list - int i; - for(i = 0; i < regionCount; i++) - { - raList[i].edgeStrength = 0; - raList[i].edgePixelCount = 0; - raList[i].label = i; - raList[i].next = NULL; - } - - //initialize RAM free list - freeRAList = raPool; - for(i = 0; i < NODE_MULTIPLE*regionCount-1; i++) - { - raPool[i].edgeStrength = 0; - raPool[i].edgePixelCount = 0; - raPool[i].next = &raPool[i+1]; - } - raPool[NODE_MULTIPLE*regionCount-1].next = NULL; - - //traverse the labeled image building - //the RAM by looking to the right of - //and below the current pixel location thus - //determining if a given region is adjacent - //to another - int j, curLabel, rightLabel, bottomLabel, exists; - RAList *raNode1, *raNode2, *oldRAFreeList; - for(i = 0; i < height - 1; i++) - { - //check the right and below neighbors - //for pixel locations whose x < width - 1 - for(j = 0; j < width - 1; j++) - { - //calculate pixel labels - curLabel = labels[i*width+j ]; //current pixel - rightLabel = labels[i*width+j+1 ]; //right pixel - bottomLabel = labels[(i+1)*width+j]; //bottom pixel - - //check to the right, if the label of - //the right pixel is not the same as that - //of the current one then region[j] and region[j+1] - //are adjacent to one another - update the RAM - if(curLabel != rightLabel) - { - //obtain RAList object from region adjacency free - //list - raNode1 = freeRAList; - raNode2 = freeRAList->next; - - //keep a pointer to the old region adj. free - //list just in case nodes already exist in respective - //region lists - oldRAFreeList = freeRAList; - - //update region adjacency free list - freeRAList = freeRAList->next->next; - - //populate RAList nodes - raNode1->label = curLabel; - raNode2->label = rightLabel; - - //insert nodes into the RAM - exists = 0; - raList[curLabel ].Insert(raNode2); - exists = raList[rightLabel].Insert(raNode1); - - //if the node already exists then place - //nodes back onto the region adjacency - //free list - if(exists) - freeRAList = oldRAFreeList; - - } - - //check below, if the label of - //the bottom pixel is not the same as that - //of the current one then region[j] and region[j+width] - //are adjacent to one another - update the RAM - if(curLabel != bottomLabel) - { - //obtain RAList object from region adjacency free - //list - raNode1 = freeRAList; - raNode2 = freeRAList->next; - - //keep a pointer to the old region adj. free - //list just in case nodes already exist in respective - //region lists - oldRAFreeList = freeRAList; - - //update region adjacency free list - freeRAList = freeRAList->next->next; - - //populate RAList nodes - raNode1->label = curLabel; - raNode2->label = bottomLabel; - - //insert nodes into the RAM - exists = 0; - raList[curLabel ].Insert(raNode2); - exists = raList[bottomLabel].Insert(raNode1); - - //if the node already exists then place - //nodes back onto the region adjacency - //free list - if(exists) - freeRAList = oldRAFreeList; - - } - - } - - //check only to the bottom neighbors of the right boundary - //pixels... - - //calculate pixel locations (j = width-1) - curLabel = labels[i*width+j ]; //current pixel - bottomLabel = labels[(i+1)*width+j]; //bottom pixel - - //check below, if the label of - //the bottom pixel is not the same as that - //of the current one then region[j] and region[j+width] - //are adjacent to one another - update the RAM - if(curLabel != bottomLabel) - { - //obtain RAList object from region adjacency free - //list - raNode1 = freeRAList; - raNode2 = freeRAList->next; - - //keep a pointer to the old region adj. free - //list just in case nodes already exist in respective - //region lists - oldRAFreeList = freeRAList; - - //update region adjacency free list - freeRAList = freeRAList->next->next; - - //populate RAList nodes - raNode1->label = curLabel; - raNode2->label = bottomLabel; - - //insert nodes into the RAM - exists = 0; - raList[curLabel ].Insert(raNode2); - exists = raList[bottomLabel].Insert(raNode1); - - //if the node already exists then place - //nodes back onto the region adjacency - //free list - if(exists) - freeRAList = oldRAFreeList; - - } - } - - //check only to the right neighbors of the bottom boundary - //pixels... - - //check the right for pixel locations whose x < width - 1 - for(j = 0; j < width - 1; j++) - { - //calculate pixel labels (i = height-1) - curLabel = labels[i*width+j ]; //current pixel - rightLabel = labels[i*width+j+1 ]; //right pixel - - //check to the right, if the label of - //the right pixel is not the same as that - //of the current one then region[j] and region[j+1] - //are adjacent to one another - update the RAM - if(curLabel != rightLabel) - { - //obtain RAList object from region adjacency free - //list - raNode1 = freeRAList; - raNode2 = freeRAList->next; - - //keep a pointer to the old region adj. free - //list just in case nodes already exist in respective - //region lists - oldRAFreeList = freeRAList; - - //update region adjacency free list - freeRAList = freeRAList->next->next; - - //populate RAList nodes - raNode1->label = curLabel; - raNode2->label = rightLabel; - - //insert nodes into the RAM - exists = 0; - raList[curLabel ].Insert(raNode2); - exists = raList[rightLabel].Insert(raNode1); - - //if the node already exists then place - //nodes back onto the region adjacency - //free list - if(exists) - freeRAList = oldRAFreeList; - - } - - } - - //done. - return; - -} - -/*******************************************************/ -/*Destroy Region Adjacency Matrix */ -/*******************************************************/ -/*Destroy a region adjacency matrix. */ -/*******************************************************/ -/*Post: */ -/* - the region adjacency matrix has been destr- */ -/* oyed: (1) its memory has been de-allocated, */ -/* (2) the RAM structure has been initialize */ -/* for re-use. */ -/*******************************************************/ - -void msImageProcessor::DestroyRAM( void ) -{ - - //de-allocate memory for region adjaceny list - if (raList) delete [] raList; - if (raPool) delete [] raPool; - - //initialize region adjacency matrix - raList = NULL; - freeRAList = NULL; - raPool = NULL; - - //done. - return; - -} - -/*******************************************************/ -/*Transitive Closure */ -/*******************************************************/ -/*Applies transitive closure to the RAM updating */ -/*labels, modes and modePointCounts to reflect the new */ -/*set of merged regions resulting from transitive clo- */ -/*sure. */ -/*******************************************************/ -/*Post: */ -/* - transitive closure has been applied to the */ -/* regions classified by the RAM and labels, */ -/* modes and modePointCounts have been updated */ -/* to reflect the new set of mergd regions res- */ -/* ulting from transitive closure. */ -/*******************************************************/ - -void msImageProcessor::TransitiveClosure( void ) -{ - - //Step (1): - - // Build RAM using classifiction structure originally - // generated by the method GridTable::Connect() - BuildRAM(); - - //Step (1a): - //Compute weights of weight graph using confidence map - //(if defined) - if(weightMapDefined) ComputeEdgeStrengths(); - - //Step (2): - - //Treat each region Ri as a disjoint set: - - // - attempt to join Ri and Rj for all i != j that are neighbors and - // whose associated modes are a normalized distance of < 0.5 from one - // another - - // - the label of each region in the raList is treated as a pointer to the - // canonical element of that region (e.g. raList[i], initially has raList[i].label = i, - // namely each region is initialized to have itself as its canonical element). - - //Traverse RAM attempting to join raList[i] with its neighbors... - int i, iCanEl, neighCanEl; - float threshold; - RAList *neighbor; - for(i = 0; i < regionCount; i++) - { - //aquire first neighbor in region adjacency list pointed to - //by raList[i] - neighbor = raList[i].next; - - //compute edge strenght threshold using global and local - //epsilon - if(epsilon > raList[i].edgeStrength) - threshold = epsilon; - else - threshold = raList[i].edgeStrength; - - //traverse region adjacency list of region i, attempting to join - //it with regions whose mode is a normalized distance < 0.5 from - //that of region i... - while(neighbor) - { - //attempt to join region and neighbor... - if((InWindow(i, neighbor->label))&&(neighbor->edgeStrength < epsilon)) - { - //region i and neighbor belong together so join them - //by: - - // (1) find the canonical element of region i - iCanEl = i; - while(raList[iCanEl].label != iCanEl) - iCanEl = raList[iCanEl].label; - - // (2) find the canonical element of neighboring region - neighCanEl = neighbor->label; - while(raList[neighCanEl].label != neighCanEl) - neighCanEl = raList[neighCanEl].label; - - // if the canonical elements of are not the same then assign - // the canonical element having the smaller label to be the parent - // of the other region... - if(iCanEl < neighCanEl) - raList[neighCanEl].label = iCanEl; - else - { - //must replace the canonical element of previous - //parent as well - raList[raList[iCanEl].label].label = neighCanEl; - - //re-assign canonical element - raList[iCanEl].label = neighCanEl; - } - } - - //check the next neighbor... - neighbor = neighbor->next; - - } - } - - // Step (3): - - // Level binary trees formed by canonical elements - for(i = 0; i < regionCount; i++) - { - iCanEl = i; - while(raList[iCanEl].label != iCanEl) - iCanEl = raList[iCanEl].label; - raList[i].label = iCanEl; - } - - // Step (4): - - //Traverse joint sets, relabeling image. - - // (a) - - // Accumulate modes and re-compute point counts using canonical - // elements generated by step 2. - - //allocate memory for mode and point count temporary buffers... - float *modes_buffer = new float [N*regionCount]; - int *MPC_buffer = new int [regionCount]; - - //initialize buffers to zero - for(i = 0; i < regionCount; i++) - MPC_buffer[i] = 0; - for(i = 0; i < N*regionCount; i++) - modes_buffer[i] = 0; - - //traverse raList accumulating modes and point counts - //using canoncial element information... - int k, iMPC; - for(i = 0; i < regionCount; i++) - { - - //obtain canonical element of region i - iCanEl = raList[i].label; - - //obtain mode point count of region i - iMPC = modePointCounts[i]; - - //accumulate modes_buffer[iCanEl] - for(k = 0; k < N; k++) - modes_buffer[(N*iCanEl)+k] += iMPC*modes[(N*i)+k]; - - //accumulate MPC_buffer[iCanEl] - MPC_buffer[iCanEl] += iMPC; - - } - - // (b) - - // Re-label new regions of the image using the canonical - // element information generated by step (2) - - // Also use this information to compute the modes of the newly - // defined regions, and to assign new region point counts in - // a consecute manner to the modePointCounts array - - //allocate memory for label buffer - int *label_buffer = new int [regionCount]; - - //initialize label buffer to -1 - for(i = 0; i < regionCount; i++) - label_buffer[i] = -1; - - //traverse raList re-labeling the regions - int label = -1; - for(i = 0; i < regionCount; i++) - { - //obtain canonical element of region i - iCanEl = raList[i].label; - if(label_buffer[iCanEl] < 0) - { - //assign a label to the new region indicated by canonical - //element of i - label_buffer[iCanEl] = ++label; - - //recompute mode storing the result in modes[label]... - iMPC = MPC_buffer[iCanEl]; - for(k = 0; k < N; k++) - modes[(N*label)+k] = (modes_buffer[(N*iCanEl)+k])/(iMPC); - - //assign a corresponding mode point count for this region into - //the mode point counts array using the MPC buffer... - modePointCounts[label] = MPC_buffer[iCanEl]; - } - } - - //re-assign region count using label counter - int oldRegionCount = regionCount; - regionCount = label+1; - - // (c) - - // Use the label buffer to reconstruct the label map, which specified - // the new image given its new regions calculated above - - for(i = 0; i < height*width; i++) - labels[i] = label_buffer[raList[labels[i]].label]; - - //de-allocate memory - delete [] modes_buffer; - delete [] MPC_buffer; - delete [] label_buffer; - - //done. - return; - -} - -/*******************************************************/ -/*Compute Edge Strengths */ -/*******************************************************/ -/*Computes the a weight for each link in the region */ -/*graph maintined by the RAM, resulting in a weighted */ -/*graph in which the weights consist of a confidence */ -/*between zero and one indicating if the regions are */ -/*separated by a strong or weak edge. */ -/*******************************************************/ -/*Post: */ -/* - an edge strength has been computed between */ -/* each region of the image and placed as a */ -/* weight in the RAM to be used during transi- */ -/* tive closure. */ -/*******************************************************/ - -void msImageProcessor::ComputeEdgeStrengths( void ) -{ - - //initialize visit table - used to keep track - //of which pixels have already been visited such - //as not to contribute their strength value to - //a boundary sum multiple times... - memset(visitTable, 0, L*sizeof(unsigned char)); - - //traverse labeled image computing edge strengths - //(excluding image boundary)... - int x, y, dp, curLabel, rightLabel, bottomLabel; - RAList *curRegion; - for(y = 1; y < height-1; y++) - { - for(x = 1; x < width-1; x++) - { - //compute data point location using x and y - dp = y*width + x; - - //obtain labels at different pixel locations - curLabel = labels[dp ]; //current pixel - rightLabel = labels[dp+1 ]; //right pixel - bottomLabel = labels[dp+width]; //bottom pixel - - //check right and bottom neighbor to see if there is a - //change in label then we are at an edge therefore record - //the edge strength at this edge accumulating its value - //in the RAM... - if(curLabel != rightLabel) - { - //traverse into RAM... - curRegion = &raList[curLabel]; - while((curRegion)&&(curRegion->label != rightLabel)) - curRegion = curRegion->next; - - //this should not occur... - assert(curRegion); - - //accumulate edge strength - curRegion->edgeStrength += weightMap[dp] + weightMap[dp+1]; - curRegion->edgePixelCount += 2; - } - - if(curLabel != bottomLabel) - { - //traverse into RAM... - curRegion = &raList[curLabel]; - while((curRegion)&&(curRegion->label != bottomLabel)) - curRegion = curRegion->next; - - //this should not occur... - assert(curRegion); - - //accumulate edge strength - if(curLabel == rightLabel) - { - curRegion->edgeStrength += weightMap[dp] + weightMap[dp+width]; - curRegion->edgePixelCount += 2; - } - else - { - curRegion->edgeStrength += weightMap[dp+width]; - curRegion->edgePixelCount += 1; - } - - } - } - } - - //compute strengths using accumulated strengths obtained above... - RAList *neighborRegion; - float edgeStrength; - int edgePixelCount; - for(x = 0; x < regionCount; x++) - { - //traverse the region list of the current region - curRegion = &raList[x]; - curRegion = curRegion->next; - while(curRegion) - { - //with the assumption that regions having a smaller - //label in the current region list have already - //had their edge strengths computed, only compute - //edge strengths for the regions whose label is greater - //than x, the current region (region list) under - //consideration... - curLabel = curRegion->label; - if(curLabel > x) - { - //obtain pointer to the element identifying the - //current region in the neighbors region list... - neighborRegion = &raList[curLabel]; - while((neighborRegion)&&(neighborRegion->label != x)) - neighborRegion = neighborRegion->next; - - //this should not occur... - assert(neighborRegion); - - //compute edge strengths using accumulated confidence - //value and pixel count - if((edgePixelCount = curRegion->edgePixelCount + neighborRegion->edgePixelCount) != 0) - { - //compute edge strength - edgeStrength = curRegion->edgeStrength + neighborRegion->edgeStrength; - edgeStrength /= edgePixelCount; - - //store edge strength and pixel count for corresponding regions - curRegion->edgeStrength = neighborRegion->edgeStrength = edgeStrength; - curRegion->edgePixelCount = neighborRegion->edgePixelCount = edgePixelCount; - } - } - - //traverse to the next region in the region adjacency list - //of the current region x - curRegion = curRegion->next; - - } - } - - //compute average edge strength amongst the edges connecting - //it to each of its neighbors - int numNeighbors; - for(x = 0; x < regionCount; x++) - { - //traverse the region list of the current region - //accumulating weights - curRegion = &raList[x]; - curRegion = curRegion->next; - edgeStrength = 0; - numNeighbors = 0; - while(curRegion) - { - numNeighbors++; - edgeStrength += curRegion->edgeStrength; - curRegion = curRegion->next; - } - - //divide by the number of regions connected - //to the current region - if(numNeighbors) edgeStrength /= numNeighbors; - - //store the result in the raList for region - //x - raList[x].edgeStrength = edgeStrength; - } - - //traverse raList and output the resulting list - //to a file - - //done. - return; - -} - -/*******************************************************/ -/*Prune */ -/*******************************************************/ -/*Prunes regions from the image whose pixel density */ -/*is less than a specified threshold. */ -/*******************************************************/ -/*Pre: */ -/* - minRegion is the minimum allowable pixel de- */ -/* nsity a region may have without being pruned */ -/* from the image */ -/*Post: */ -/* - regions whose pixel density is less than */ -/* or equal to minRegion have been pruned from */ -/* the image. */ -/*******************************************************/ - -void msImageProcessor::Prune(int minRegion) -{ - - //Allocate Memory for temporary buffers... - - //allocate memory for mode and point count temporary buffers... - float *modes_buffer = new float [N*regionCount]; - int *MPC_buffer = new int [regionCount]; - - //allocate memory for label buffer - int *label_buffer = new int [regionCount]; - - //Declare variables - int i, k, candidate, iCanEl, neighCanEl, iMPC, label, oldRegionCount, minRegionCount; - double minSqDistance, neighborDistance; - RAList *neighbor; - - //Apply pruning algorithm to classification structure, removing all regions whose area - //is under the threshold area minRegion (pixels) - do - { - //Assume that no region has area under threshold area of - minRegionCount = 0; - - //Step (1): - - // Build RAM using classifiction structure originally - // generated by the method GridTable::Connect() - BuildRAM(); - - // Step (2): - - // Traverse the RAM joining regions whose area is less than minRegion (pixels) - // with its respective candidate region. - - // A candidate region is a region that displays the following properties: - - // - it is adjacent to the region being pruned - - // - the distance of its mode is a minimum to that of the region being pruned - // such that or it is the only adjacent region having an area greater than - // minRegion - - for(i = 0; i < regionCount; i++) - { - //if the area of the ith region is less than minRegion - //join it with its candidate region... - - //******************************************************************************* - - //Note: Adjust this if statement if a more sophisticated pruning criterion - // is desired. Basically in this step a region whose area is less than - // minRegion is pruned by joining it with its "closest" neighbor (in color). - // Therefore, by placing a different criterion for fusing a region the - // pruning method may be altered to implement a more sophisticated algorithm. - - //******************************************************************************* - - if(modePointCounts[i] < minRegion) - { - //update minRegionCount to indicate that a region - //having area less than minRegion was found - minRegionCount++; - - //obtain a pointer to the first region in the - //region adjacency list of the ith region... - neighbor = raList[i].next; - - //calculate the distance between the mode of the ith - //region and that of the neighboring region... - candidate = neighbor->label; - minSqDistance = SqDistance(i, candidate); - - //traverse region adjacency list of region i and select - //a candidate region - neighbor = neighbor->next; - while(neighbor) - { - - //calculate the square distance between region i - //and current neighbor... - neighborDistance = SqDistance(i, neighbor->label); - - //if this neighbors square distance to region i is less - //than minSqDistance, then select this neighbor as the - //candidate region for region i - if(neighborDistance < minSqDistance) - { - minSqDistance = neighborDistance; - candidate = neighbor->label; - } - - //traverse region list of region i - neighbor = neighbor->next; - - } - - //join region i with its candidate region: - - // (1) find the canonical element of region i - iCanEl = i; - while(raList[iCanEl].label != iCanEl) - iCanEl = raList[iCanEl].label; - - // (2) find the canonical element of neighboring region - neighCanEl = candidate; - while(raList[neighCanEl].label != neighCanEl) - neighCanEl = raList[neighCanEl].label; - - // if the canonical elements of are not the same then assign - // the canonical element having the smaller label to be the parent - // of the other region... - if(iCanEl < neighCanEl) - raList[neighCanEl].label = iCanEl; - else - { - //must replace the canonical element of previous - //parent as well - raList[raList[iCanEl].label].label = neighCanEl; - - //re-assign canonical element - raList[iCanEl].label = neighCanEl; - } - } - } - - // Step (3): - - // Level binary trees formed by canonical elements - for(i = 0; i < regionCount; i++) - { - iCanEl = i; - while(raList[iCanEl].label != iCanEl) - iCanEl = raList[iCanEl].label; - raList[i].label = iCanEl; - } - - // Step (4): - - //Traverse joint sets, relabeling image. - - // Accumulate modes and re-compute point counts using canonical - // elements generated by step 2. - - //initialize buffers to zero - for(i = 0; i < regionCount; i++) - MPC_buffer[i] = 0; - for(i = 0; i < N*regionCount; i++) - modes_buffer[i] = 0; - - //traverse raList accumulating modes and point counts - //using canoncial element information... - for(i = 0; i < regionCount; i++) - { - - //obtain canonical element of region i - iCanEl = raList[i].label; - - //obtain mode point count of region i - iMPC = modePointCounts[i]; - - //accumulate modes_buffer[iCanEl] - for(k = 0; k < N; k++) - modes_buffer[(N*iCanEl)+k] += iMPC*modes[(N*i)+k]; - - //accumulate MPC_buffer[iCanEl] - MPC_buffer[iCanEl] += iMPC; - - } - - // (b) - - // Re-label new regions of the image using the canonical - // element information generated by step (2) - - // Also use this information to compute the modes of the newly - // defined regions, and to assign new region point counts in - // a consecute manner to the modePointCounts array - - //initialize label buffer to -1 - for(i = 0; i < regionCount; i++) - label_buffer[i] = -1; - - //traverse raList re-labeling the regions - label = -1; - for(i = 0; i < regionCount; i++) - { - //obtain canonical element of region i - iCanEl = raList[i].label; - if(label_buffer[iCanEl] < 0) - { - //assign a label to the new region indicated by canonical - //element of i - label_buffer[iCanEl] = ++label; - - //recompute mode storing the result in modes[label]... - iMPC = MPC_buffer[iCanEl]; - for(k = 0; k < N; k++) - modes[(N*label)+k] = (modes_buffer[(N*iCanEl)+k])/(iMPC); - - //assign a corresponding mode point count for this region into - //the mode point counts array using the MPC buffer... - modePointCounts[label] = MPC_buffer[iCanEl]; - } - } - - //re-assign region count using label counter - oldRegionCount = regionCount; - regionCount = label+1; - - // (c) - - // Use the label buffer to reconstruct the label map, which specified - // the new image given its new regions calculated above - - for(i = 0; i < height*width; i++) - labels[i] = label_buffer[raList[labels[i]].label]; - - - } while(minRegionCount > 0); - - //de-allocate memory - delete [] modes_buffer; - delete [] MPC_buffer; - delete [] label_buffer; - - //done. - return; - -} - -/*******************************************************/ -/*Define Boundaries */ -/*******************************************************/ -/*Defines the boundaries for each region of the segm- */ -/*ented image storing the result into a region list */ -/*object. */ -/*******************************************************/ -/*Pre: */ -/* - the image has been segmented and a classifi- */ -/* cation structure has been created for this */ -/* image */ -/*Post: */ -/* - the boundaries of the segmented image have */ -/* been defined and the boundaries of each reg- */ -/* ion has been stored into a region list obj- */ -/* ect. */ -/*******************************************************/ - -void msImageProcessor::DefineBoundaries( void ) -{ - - //declare and allocate memory for boundary map and count - int *boundaryMap, *boundaryCount; - if((!(boundaryMap = new int [L]))||(!(boundaryCount = new int [regionCount]))) - ErrorHandler("msImageProcessor", "DefineBoundaries", "Not enough memory."); - - //initialize boundary map and count - int i; - for(i = 0; i < L; i++) - boundaryMap[i] = -1; - for(i = 0; i < regionCount; i++) - boundaryCount[i] = 0; - - //initialize and declare total boundary count - - //the total number of boundary pixels present in - //the segmented image - int totalBoundaryCount = 0; - - //traverse the image checking the right and bottom - //four connected neighbors of each pixel marking - //boundary map with the boundaries of each region and - //incrementing boundaryCount using the label information - - //*********************************************************************** - //*********************************************************************** - - int j, label, dataPoint; - - //first row (every pixel is a boundary pixel) - for(i = 0; i < width; i++) - { - boundaryMap[i] = label = labels[i]; - boundaryCount[label]++; - totalBoundaryCount++; - } - - //define boundaries for all rows except for the first - //and last one... - for(i = 1; i < height - 1; i++) - { - //mark the first pixel in an image row as an image boundary... - dataPoint = i*width; - boundaryMap[dataPoint] = label = labels[dataPoint]; - boundaryCount[label]++; - totalBoundaryCount++; - - for(j = 1; j < width - 1; j++) - { - //define datapoint and its right and bottom - //four connected neighbors - dataPoint = i*width+j; - - //check four connected neighbors if they are - //different this pixel is a boundary pixel - label = labels[dataPoint]; - if((label != labels[dataPoint-1]) ||(label != labels[dataPoint+1])|| - (label != labels[dataPoint-width])||(label != labels[dataPoint+width])) - { - boundaryMap[dataPoint] = label = labels[dataPoint]; - boundaryCount[label]++; - totalBoundaryCount++; - } - } - - //mark the last pixel in an image row as an image boundary... - dataPoint = (i+1)*width-1; - boundaryMap[dataPoint] = label = labels[dataPoint]; - boundaryCount[label]++; - totalBoundaryCount++; - - } - - //last row (every pixel is a boundary pixel) (i = height-1) - register int start = (height-1)*width, stop = height*width; - for(i = start; i < stop; i++) - { - boundaryMap[i] = label = labels[i]; - boundaryCount[label]++; - totalBoundaryCount++; - } - - //*********************************************************************** - //*********************************************************************** - - //store boundary locations into a boundary buffer using - //boundary map and count - - //*********************************************************************** - //*********************************************************************** - - int *boundaryBuffer = new int [totalBoundaryCount], *boundaryIndex = new int [regionCount]; - - //use boundary count to initialize boundary index... - int counter = 0; - for(i = 0; i < regionCount; i++) - { - boundaryIndex[i] = counter; - counter += boundaryCount[i]; - } - - //traverse boundary map placing the boundary pixel - //locations into the boundaryBuffer - for(i = 0; i < L; i++) - { - //if its a boundary pixel store it into - //the boundary buffer - if((label = boundaryMap[i]) >= 0) - { - boundaryBuffer[boundaryIndex[label]] = i; - boundaryIndex[label]++; - } - } - - //*********************************************************************** - //*********************************************************************** - - //store the boundary locations stored by boundaryBuffer into - //the region list for each region - - //*********************************************************************** - //*********************************************************************** - - //destroy the old region list - if(regionList) delete regionList; - - //create a new region list - if(!(regionList = new RegionList(regionCount, totalBoundaryCount, N))) - ErrorHandler("msImageProcessor", "DefineBoundaries", "Not enough memory."); - - //add boundary locations for each region using the boundary - //buffer and boundary counts - counter = 0; - for(i = 0; i < regionCount; i++) - { - regionList->AddRegion(i, boundaryCount[i], &boundaryBuffer[counter]); - counter += boundaryCount[i]; - } - - //*********************************************************************** - //*********************************************************************** - - // dealocate local used memory - delete [] boundaryMap; - delete [] boundaryCount; - delete [] boundaryBuffer; - delete [] boundaryIndex; - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Image Data Searching/Distance Calculation */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*In Window */ -/*******************************************************/ -/*Returns true if the two specified data points are */ -/*within rR of each other. */ -/*******************************************************/ -/*Pre: */ -/* - mode1 and mode2 are indeces into msRawData */ -/* specifying the modes of the pixels having */ -/* these indeces. */ -/*Post: */ -/* - true is returned if mode1 and mode2 are wi- */ -/* thin rR of one another, false is returned */ -/* otherwise. */ -/*******************************************************/ - -bool msImageProcessor::InWindow(int mode1, int mode2) -{ - int k = 1, s = 0, p; - double diff = 0, el; - while((diff < 0.25)&&(k != kp)) // Partial Distortion Search - { - //Calculate distance squared of sub-space s - diff = 0; - for(p = 0; p < P[k]; p++) - { - el = (modes[mode1*N+p+s]-modes[mode2*N+p+s])/(h[k]*offset[k]); - if((!p)&&(k == 1)&&(modes[mode1*N] > 80)) - diff += 4*el*el; - else - diff += el*el; - } - - //next subspace - s += P[k]; - k++; - } - return (bool)(diff < 0.25); -} - -/*******************************************************/ -/*Square Distance */ -/*******************************************************/ -/*Computs the normalized square distance between two */ -/*modes. */ -/*******************************************************/ -/*Pre: */ -/* - mode1 and mode2 are indeces into the modes */ -/* array specifying two modes of the image */ -/*Post: */ -/* - the normalized square distance between modes */ -/* indexed by mode1 and mode2 has been calc- */ -/* ulated and the result has been returned. */ -/*******************************************************/ - -float msImageProcessor::SqDistance(int mode1, int mode2) -{ - - int k = 1, s = 0, p; - float dist = 0, el; - for(k = 1; k < kp; k++) - { - //Calculate distance squared of sub-space s - for(p = 0; p < P[k]; p++) - { - el = (modes[mode1*N+p+s]-modes[mode2*N+p+s])/(h[k]*offset[k]); - dist += el*el; - } - - //next subspace - s += P[k]; - k++; - } - - //return normalized square distance between modes - //1 and 2 - return dist; - -} - - /*/\/\/\/\/\/\/\/\/\/\*/ - /* Memory Management */ - /*\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Initialize Output */ -/*******************************************************/ -/*Allocates memory needed by the mean shift image pro- */ -/*cessor class output storage data structure. */ -/*******************************************************/ -/*Post: */ -/* - the memory needed by the output storage */ -/* structure of this class has been (re-)allo- */ -/* cated. */ -/*******************************************************/ - -void msImageProcessor::InitializeOutput( void ) -{ - - //De-allocate memory if output was defined for previous image - DestroyOutput(); - - //Allocate memory for msRawData (filtered image output) - if(!(msRawData = new float [L*N])) - { - ErrorHandler("msImageProcessor", "Allocate", "Not enough memory."); - return; - } - - //Allocate memory used to store image modes and their corresponding regions... - if((!(modes = new float [L*(N+2)]))||(!(labels = new int [L]))||(!(modePointCounts = new int [L]))||(!(indexTable = new int [L]))) - { - ErrorHandler("msImageProcessor", "Allocate", "Not enough memory"); - return; - } - - //Allocate memory for integer modes used to perform connected components - //(image labeling)... -// if(!(LUV_data = new int [N*L])) - if (!(LUV_data = new float[N*L])) - { - ErrorHandler("msImageProcessor", "Allocate", "Not enough memory"); - return; - } - - //indicate that the class output storage structure has been defined - class_state.OUTPUT_DEFINED = true; - -} - -/*******************************************************/ -/*Destroy Output */ -/*******************************************************/ -/*De-allocates memory needed by the mean shift image */ -/*processor class output storage data structure. */ -/*******************************************************/ -/*Post: */ -/* - the memory needed by the output storage */ -/* structure of this class has been de-alloc- */ -/* ated. */ -/* - the output storage structure has been init- */ -/* ialized for re-use. */ -/*******************************************************/ - -void msImageProcessor::DestroyOutput( void ) -{ - - //de-allocate memory for msRawData (filtered image output) - if (msRawData) delete [] msRawData; - - //de-allocate memory used by output storage and image - //classification structure - if (modes) delete [] modes; - if (labels) delete [] labels; - if (modePointCounts) delete [] modePointCounts; - if (indexTable) delete [] indexTable; - - //de-allocate memory for LUV_data - if (LUV_data) delete [] LUV_data; - - //initialize data members for re-use... - - //initialize output structures... - msRawData = NULL; - - //re-initialize classification structure - modes = NULL; - labels = NULL; - modePointCounts = NULL; - regionCount = 0; - - //indicate that the output has been destroyed - class_state.OUTPUT_DEFINED = false; - - //done. - return; - -} - -// NEW -void msImageProcessor::NewOptimizedFilter1(float sigmaS, float sigmaR) -{ - // Declare Variables - int iterationCount, i, j, k, modeCandidateX, modeCandidateY, modeCandidate_i; - double mvAbs, diff, el; - - //make sure that a lattice height and width have - //been defined... - if(!height) - { - ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); - return; - } - - //re-assign bandwidths to sigmaS and sigmaR - if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) - { - ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); - return; - } - - //define input data dimension with lattice - int lN = N + 2; - - // Traverse each data point applying mean shift - // to each data point - - // Allcocate memory for yk - double *yk = new double [lN]; - - // Allocate memory for Mh - double *Mh = new double [lN]; - - // let's use some temporary data - float* sdata; - sdata = new float[lN*L]; - - // copy the scaled data - int idxs, idxd; - idxs = idxd = 0; - if (N==3) - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i/width)/sigmaS; - sdata[idxs++] = data[idxd++]/sigmaR; - sdata[idxs++] = data[idxd++]/sigmaR; - sdata[idxs++] = data[idxd++]/sigmaR; - } - } else if (N==1) - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i/width)/sigmaS; - sdata[idxs++] = data[idxd++]/sigmaR; - } - } else - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i/width)/sigmaS; - for (j=0; j<N; j++) - sdata[idxs++] = data[idxd++]/sigmaR; - } - } - // index the data in the 3d buckets (x, y, L) - int* buckets; - int* slist; - slist = new int[L]; - int bucNeigh[27]; - - float sMins; // just for L - float sMaxs[3]; // for all - sMaxs[0] = width/sigmaS; - sMaxs[1] = height/sigmaS; - sMins = sMaxs[2] = sdata[2]; - idxs = 2; - float cval; - for(i=0; i<L; i++) - { - cval = sdata[idxs]; - if (cval < sMins) - sMins = cval; - else if (cval > sMaxs[2]) - sMaxs[2] = cval; - - idxs += lN; - } - - int nBuck1, nBuck2, nBuck3; - int cBuck1, cBuck2, cBuck3, cBuck; - nBuck1 = (int) (sMaxs[0] + 3); - nBuck2 = (int) (sMaxs[1] + 3); - nBuck3 = (int) (sMaxs[2] - sMins + 3); - buckets = new int[nBuck1*nBuck2*nBuck3]; - for(i=0; i<(nBuck1*nBuck2*nBuck3); i++) - buckets[i] = -1; - - idxs = 0; - for(i=0; i<L; i++) - { - // find bucket for current data and add it to the list - cBuck1 = (int) sdata[idxs] + 1; - cBuck2 = (int) sdata[idxs+1] + 1; - cBuck3 = (int) (sdata[idxs+2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - - slist[i] = buckets[cBuck]; - buckets[cBuck] = i; - - idxs += lN; - } - // init bucNeigh - idxd = 0; - for (cBuck1=-1; cBuck1<=1; cBuck1++) - { - for (cBuck2=-1; cBuck2<=1; cBuck2++) - { - for (cBuck3=-1; cBuck3<=1; cBuck3++) - { - bucNeigh[idxd++] = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - } - } - } - double wsuml, weight; - double hiLTr = 80.0/sigmaR; - // done indexing/hashing - - - // Initialize mode table used for basin of attraction - memset(modeTable, 0, width*height); - - // proceed ... -#ifdef PROMPT - msSys.Prompt("done.\nApplying mean shift (Using Lattice) ... "); -#ifdef SHOW_PROGRESS - msSys.Prompt("\n 0%%"); -#endif -#endif - - - for(i = 0; i < L; i++) - { - // if a mode was already assigned to this data point - // then skip this point, otherwise proceed to - // find its mode by applying mean shift... - if (modeTable[i] == 1) - continue; - - // initialize point list... - pointCount = 0; - - // Assign window center (window centers are - // initialized by createLattice to be the point - // data[i]) - idxs = i*lN; - for (j=0; j<lN; j++) - yk[j] = sdata[idxs+j]; - - // Calculate the mean shift vector using the lattice - // LatticeMSVector(Mh, yk); // modify to new - /*****************************************************/ - // Initialize mean shift vector - for(j = 0; j < lN; j++) - Mh[j] = 0; - wsuml = 0; - // uniformLSearch(Mh, yk_ptr); // modify to new - // find bucket of yk - cBuck1 = (int) yk[0] + 1; - cBuck2 = (int) yk[1] + 1; - cBuck3 = (int) (yk[2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - for (j=0; j<27; j++) - { - idxd = buckets[cBuck+bucNeigh[j]]; - // list parse, crt point is cHeadList - while (idxd>=0) - { - idxs = lN*idxd; - // determine if inside search window - el = sdata[idxs+0]-yk[0]; - diff = el*el; - el = sdata[idxs+1]-yk[1]; - diff += el*el; - - if (diff < 1.0) - { - el = sdata[idxs+2]-yk[2]; - if (yk[2] > hiLTr) - diff = 4*el*el; - else - diff = el*el; - - if (N>1) - { - el = sdata[idxs+3]-yk[3]; - diff += el*el; - el = sdata[idxs+4]-yk[4]; - diff += el*el; - } - - if (diff < 1.0) - { - weight = 1-weightMap[idxd]; - for (k=0; k<lN; k++) - Mh[k] += weight*sdata[idxs+k]; - wsuml += weight; - } - } - idxd = slist[idxd]; - } - } - if (wsuml > 0) - { - for(j = 0; j < lN; j++) - Mh[j] = Mh[j]/wsuml - yk[j]; - } - else - { - for(j = 0; j < lN; j++) - Mh[j] = 0; - } - /*****************************************************/ - // Calculate its magnitude squared - //mvAbs = 0; - //for(j = 0; j < lN; j++) - // mvAbs += Mh[j]*Mh[j]; - mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; - if (N==3) - mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; - else - mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; - - - // Keep shifting window center until the magnitude squared of the - // mean shift vector calculated at the window center location is - // under a specified threshold (Epsilon) - - // NOTE: iteration count is for speed up purposes only - it - // does not have any theoretical importance - iterationCount = 1; - while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) - { - - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // check to see if the current mode location is in the - // basin of attraction... - - // calculate the location of yk on the lattice - modeCandidateX = (int) (sigmaS*yk[0]+0.5); - modeCandidateY = (int) (sigmaS*yk[1]+0.5); - modeCandidate_i = modeCandidateY*width + modeCandidateX; - - // if mvAbs != 0 (yk did indeed move) then check - // location basin_i in the mode table to see if - // this data point either: - - // (1) has not been associated with a mode yet - // (modeTable[basin_i] = 0), so associate - // it with this one - // - // (2) it has been associated with a mode other - // than the one that this data point is converging - // to (modeTable[basin_i] = 1), so assign to - // this data point the same mode as that of basin_i - - if ((modeTable[modeCandidate_i] != 2) && (modeCandidate_i != i)) - { - // obtain the data point at basin_i to - // see if it is within h*TC_DIST_FACTOR of - // of yk - diff = 0; - idxs = lN*modeCandidate_i; - for (k=2; k<lN; k++) - { - el = sdata[idxs+k] - yk[k]; - diff += el*el; - } - - // if the data point at basin_i is within - // a distance of h*TC_DIST_FACTOR of yk - // then depending on modeTable[basin_i] perform - // either (1) or (2) - if (diff < TC_DIST_FACTOR) - { - // if the data point at basin_i has not - // been associated to a mode then associate - // it with the mode that this one will converge - // to - if (modeTable[modeCandidate_i] == 0) - { - // no mode associated yet so associate - // it with this one... - pointList[pointCount++] = modeCandidate_i; - modeTable[modeCandidate_i] = 2; - - } else - { - - // the mode has already been associated with - // another mode, thererfore associate this one - // mode and the modes in the point list with - // the mode associated with data[basin_i]... - - // store the mode info into yk using msRawData... - for (j = 0; j < N; j++) - yk[j+2] = msRawData[modeCandidate_i*N+j]/sigmaR; - - // update mode table for this data point - // indicating that a mode has been associated - // with it - modeTable[i] = 1; - - // indicate that a mode has been associated - // to this data point (data[i]) - mvAbs = -1; - - // stop mean shift calculation... - break; - } - } - } - - // Calculate the mean shift vector at the new - // window location using lattice - // Calculate the mean shift vector using the lattice - // LatticeMSVector(Mh, yk); // modify to new - /*****************************************************/ - // Initialize mean shift vector - for(j = 0; j < lN; j++) - Mh[j] = 0; - wsuml = 0; - // uniformLSearch(Mh, yk_ptr); // modify to new - // find bucket of yk - cBuck1 = (int) yk[0] + 1; - cBuck2 = (int) yk[1] + 1; - cBuck3 = (int) (yk[2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - for (j=0; j<27; j++) - { - idxd = buckets[cBuck+bucNeigh[j]]; - // list parse, crt point is cHeadList - while (idxd>=0) - { - idxs = lN*idxd; - // determine if inside search window - el = sdata[idxs+0]-yk[0]; - diff = el*el; - el = sdata[idxs+1]-yk[1]; - diff += el*el; - - if (diff < 1.0) - { - el = sdata[idxs+2]-yk[2]; - if (yk[2] > hiLTr) - diff = 4*el*el; - else - diff = el*el; - - if (N>1) - { - el = sdata[idxs+3]-yk[3]; - diff += el*el; - el = sdata[idxs+4]-yk[4]; - diff += el*el; - } - - if (diff < 1.0) - { - weight = 1-weightMap[idxd]; - for (k=0; k<lN; k++) - Mh[k] += weight*sdata[idxs+k]; - wsuml += weight; - } - } - idxd = slist[idxd]; - } - } - if (wsuml > 0) - { - for(j = 0; j < lN; j++) - Mh[j] = Mh[j]/wsuml - yk[j]; - } - else - { - for(j = 0; j < lN; j++) - Mh[j] = 0; - } - /*****************************************************/ - - // Calculate its magnitude squared - //mvAbs = 0; - //for(j = 0; j < lN; j++) - // mvAbs += Mh[j]*Mh[j]; - mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; - if (N==3) - mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; - else - mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; - - // Increment iteration count - iterationCount++; - - } - - // if a mode was not associated with this data point - // yet associate it with yk... - if (mvAbs >= 0) - { - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // update mode table for this data point - // indicating that a mode has been associated - // with it - modeTable[i] = 1; - - } - - for (k=0; k<N; k++) - yk[k+2] *= sigmaR; - - // associate the data point indexed by - // the point list with the mode stored - // by yk - for (j = 0; j < pointCount; j++) - { - // obtain the point location from the - // point list - modeCandidate_i = pointList[j]; - - // update the mode table for this point - modeTable[modeCandidate_i] = 1; - - //store result into msRawData... - for(k = 0; k < N; k++) - msRawData[N*modeCandidate_i+k] = (float)(yk[k+2]); - } - - //store result into msRawData... - for(j = 0; j < N; j++) - msRawData[N*i+j] = (float)(yk[j+2]); - - // Prompt user on progress -#ifdef SHOW_PROGRESS - percent_complete = (float)(i/(float)(L))*100; - msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); -#endif - - // Check to see if the algorithm has been halted - if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) - break; - } - - // Prompt user that filtering is completed -#ifdef PROMPT -#ifdef SHOW_PROGRESS - msSys.Prompt("\r"); -#endif - msSys.Prompt("done."); -#endif - // de-allocate memory - delete [] buckets; - delete [] slist; - delete [] sdata; - - delete [] yk; - delete [] Mh; - - // done. - return; - -} - -// NEW -void msImageProcessor::NewOptimizedFilter2(float sigmaS, float sigmaR) -{ - // Declare Variables - int iterationCount, i, j, k, modeCandidateX, modeCandidateY, modeCandidate_i; - double mvAbs, diff, el; - - //make sure that a lattice height and width have - //been defined... - if(!height) - { - ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); - return; - } - - //re-assign bandwidths to sigmaS and sigmaR - if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) - { - ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); - return; - } - - //define input data dimension with lattice - int lN = N + 2; - - // Traverse each data point applying mean shift - // to each data point - - // Allcocate memory for yk - double *yk = new double [lN]; - - // Allocate memory for Mh - double *Mh = new double [lN]; - - // let's use some temporary data - float* sdata; - sdata = new float[lN*L]; - - // copy the scaled data - int idxs, idxd; - idxs = idxd = 0; - if (N==3) - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i/width)/sigmaS; - sdata[idxs++] = data[idxd++]/sigmaR; - sdata[idxs++] = data[idxd++]/sigmaR; - sdata[idxs++] = data[idxd++]/sigmaR; - } - } else if (N==1) - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i/width)/sigmaS; - sdata[idxs++] = data[idxd++]/sigmaR; - } - } else - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i/width)/sigmaS; - for (j=0; j<N; j++) - sdata[idxs++] = data[idxd++]/sigmaR; - } - } - // index the data in the 3d buckets (x, y, L) - int* buckets; - int* slist; - slist = new int[L]; - int bucNeigh[27]; - - float sMins; // just for L - float sMaxs[3]; // for all - sMaxs[0] = width/sigmaS; - sMaxs[1] = height/sigmaS; - sMins = sMaxs[2] = sdata[2]; - idxs = 2; - float cval; - for(i=0; i<L; i++) - { - cval = sdata[idxs]; - if (cval < sMins) - sMins = cval; - else if (cval > sMaxs[2]) - sMaxs[2] = cval; - - idxs += lN; - } - - int nBuck1, nBuck2, nBuck3; - int cBuck1, cBuck2, cBuck3, cBuck; - nBuck1 = (int) (sMaxs[0] + 3); - nBuck2 = (int) (sMaxs[1] + 3); - nBuck3 = (int) (sMaxs[2] - sMins + 3); - buckets = new int[nBuck1*nBuck2*nBuck3]; - for(i=0; i<(nBuck1*nBuck2*nBuck3); i++) - buckets[i] = -1; - - idxs = 0; - for(i=0; i<L; i++) - { - // find bucket for current data and add it to the list - cBuck1 = (int) sdata[idxs] + 1; - cBuck2 = (int) sdata[idxs+1] + 1; - cBuck3 = (int) (sdata[idxs+2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - - slist[i] = buckets[cBuck]; - buckets[cBuck] = i; - - idxs += lN; - } - // init bucNeigh - idxd = 0; - for (cBuck1=-1; cBuck1<=1; cBuck1++) - { - for (cBuck2=-1; cBuck2<=1; cBuck2++) - { - for (cBuck3=-1; cBuck3<=1; cBuck3++) - { - bucNeigh[idxd++] = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - } - } - } - double wsuml, weight; - double hiLTr = 80.0/sigmaR; - // done indexing/hashing - - - // Initialize mode table used for basin of attraction - memset(modeTable, 0, width*height); - - // proceed ... -#ifdef PROMPT - msSys.Prompt("done.\nApplying mean shift (Using Lattice) ... "); -#ifdef SHOW_PROGRESS - msSys.Prompt("\n 0%%"); -#endif -#endif - - - for(i = 0; i < L; i++) - { - // if a mode was already assigned to this data point - // then skip this point, otherwise proceed to - // find its mode by applying mean shift... - if (modeTable[i] == 1) - continue; - - // initialize point list... - pointCount = 0; - - // Assign window center (window centers are - // initialized by createLattice to be the point - // data[i]) - idxs = i*lN; - for (j=0; j<lN; j++) - yk[j] = sdata[idxs+j]; - - // Calculate the mean shift vector using the lattice - // LatticeMSVector(Mh, yk); // modify to new - /*****************************************************/ - // Initialize mean shift vector - for(j = 0; j < lN; j++) - Mh[j] = 0; - wsuml = 0; - // uniformLSearch(Mh, yk_ptr); // modify to new - // find bucket of yk - cBuck1 = (int) yk[0] + 1; - cBuck2 = (int) yk[1] + 1; - cBuck3 = (int) (yk[2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - for (j=0; j<27; j++) - { - idxd = buckets[cBuck+bucNeigh[j]]; - // list parse, crt point is cHeadList - while (idxd>=0) - { - idxs = lN*idxd; - // determine if inside search window - el = sdata[idxs+0]-yk[0]; - diff = el*el; - el = sdata[idxs+1]-yk[1]; - diff += el*el; - - if (diff < 1.0) - { - el = sdata[idxs+2]-yk[2]; - if (yk[2] > hiLTr) - diff = 4*el*el; - else - diff = el*el; - - if (N>1) - { - el = sdata[idxs+3]-yk[3]; - diff += el*el; - el = sdata[idxs+4]-yk[4]; - diff += el*el; - } - - if (diff < 1.0) - { - weight = 1-weightMap[idxd]; - for (k=0; k<lN; k++) - Mh[k] += weight*sdata[idxs+k]; - wsuml += weight; - - //set basin of attraction mode table - if (diff < speedThreshold) - { - if(modeTable[idxd] == 0) - { - pointList[pointCount++] = idxd; - modeTable[idxd] = 2; - } - } - } - } - idxd = slist[idxd]; - } - } - if (wsuml > 0) - { - for(j = 0; j < lN; j++) - Mh[j] = Mh[j]/wsuml - yk[j]; - } - else - { - for(j = 0; j < lN; j++) - Mh[j] = 0; - } - /*****************************************************/ - // Calculate its magnitude squared - //mvAbs = 0; - //for(j = 0; j < lN; j++) - // mvAbs += Mh[j]*Mh[j]; - mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; - if (N==3) - mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; - else - mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; - - - // Keep shifting window center until the magnitude squared of the - // mean shift vector calculated at the window center location is - // under a specified threshold (Epsilon) - - // NOTE: iteration count is for speed up purposes only - it - // does not have any theoretical importance - iterationCount = 1; - while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) - { - - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // check to see if the current mode location is in the - // basin of attraction... - - // calculate the location of yk on the lattice - modeCandidateX = (int) (sigmaS*yk[0]+0.5); - modeCandidateY = (int) (sigmaS*yk[1]+0.5); - modeCandidate_i = modeCandidateY*width + modeCandidateX; - - // if mvAbs != 0 (yk did indeed move) then check - // location basin_i in the mode table to see if - // this data point either: - - // (1) has not been associated with a mode yet - // (modeTable[basin_i] = 0), so associate - // it with this one - // - // (2) it has been associated with a mode other - // than the one that this data point is converging - // to (modeTable[basin_i] = 1), so assign to - // this data point the same mode as that of basin_i - - if ((modeTable[modeCandidate_i] != 2) && (modeCandidate_i != i)) - { - // obtain the data point at basin_i to - // see if it is within h*TC_DIST_FACTOR of - // of yk - diff = 0; - idxs = lN*modeCandidate_i; - for (k=2; k<lN; k++) - { - el = sdata[idxs+k] - yk[k]; - diff += el*el; - } - - // if the data point at basin_i is within - // a distance of h*TC_DIST_FACTOR of yk - // then depending on modeTable[basin_i] perform - // either (1) or (2) - if (diff < speedThreshold) - { - // if the data point at basin_i has not - // been associated to a mode then associate - // it with the mode that this one will converge - // to - if (modeTable[modeCandidate_i] == 0) - { - // no mode associated yet so associate - // it with this one... - pointList[pointCount++] = modeCandidate_i; - modeTable[modeCandidate_i] = 2; - - } else - { - - // the mode has already been associated with - // another mode, thererfore associate this one - // mode and the modes in the point list with - // the mode associated with data[basin_i]... - - // store the mode info into yk using msRawData... - for (j = 0; j < N; j++) - yk[j+2] = msRawData[modeCandidate_i*N+j]/sigmaR; - - // update mode table for this data point - // indicating that a mode has been associated - // with it - modeTable[i] = 1; - - // indicate that a mode has been associated - // to this data point (data[i]) - mvAbs = -1; - - // stop mean shift calculation... - break; - } - } - } - - // Calculate the mean shift vector at the new - // window location using lattice - // Calculate the mean shift vector using the lattice - // LatticeMSVector(Mh, yk); // modify to new - /*****************************************************/ - // Initialize mean shift vector - for(j = 0; j < lN; j++) - Mh[j] = 0; - wsuml = 0; - // uniformLSearch(Mh, yk_ptr); // modify to new - // find bucket of yk - cBuck1 = (int) yk[0] + 1; - cBuck2 = (int) yk[1] + 1; - cBuck3 = (int) (yk[2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - for (j=0; j<27; j++) - { - idxd = buckets[cBuck+bucNeigh[j]]; - // list parse, crt point is cHeadList - while (idxd>=0) - { - idxs = lN*idxd; - // determine if inside search window - el = sdata[idxs+0]-yk[0]; - diff = el*el; - el = sdata[idxs+1]-yk[1]; - diff += el*el; - - if (diff < 1.0) - { - el = sdata[idxs+2]-yk[2]; - if (yk[2] > hiLTr) - diff = 4*el*el; - else - diff = el*el; - - if (N>1) - { - el = sdata[idxs+3]-yk[3]; - diff += el*el; - el = sdata[idxs+4]-yk[4]; - diff += el*el; - } - - if (diff < 1.0) - { - weight = 1-weightMap[idxd]; - for (k=0; k<lN; k++) - Mh[k] += weight*sdata[idxs+k]; - wsuml += weight; - - //set basin of attraction mode table - if (diff < speedThreshold) - { - if(modeTable[idxd] == 0) - { - pointList[pointCount++] = idxd; - modeTable[idxd] = 2; - } - } - - } - } - idxd = slist[idxd]; - } - } - if (wsuml > 0) - { - for(j = 0; j < lN; j++) - Mh[j] = Mh[j]/wsuml - yk[j]; - } - else - { - for(j = 0; j < lN; j++) - Mh[j] = 0; - } - /*****************************************************/ - - // Calculate its magnitude squared - //mvAbs = 0; - //for(j = 0; j < lN; j++) - // mvAbs += Mh[j]*Mh[j]; - mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; - if (N==3) - mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; - else - mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; - - // Increment iteration count - iterationCount++; - - } - - // if a mode was not associated with this data point - // yet associate it with yk... - if (mvAbs >= 0) - { - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // update mode table for this data point - // indicating that a mode has been associated - // with it - modeTable[i] = 1; - - } - - for (k=0; k<N; k++) - yk[k+2] *= sigmaR; - - // associate the data point indexed by - // the point list with the mode stored - // by yk - for (j = 0; j < pointCount; j++) - { - // obtain the point location from the - // point list - modeCandidate_i = pointList[j]; - - // update the mode table for this point - modeTable[modeCandidate_i] = 1; - - //store result into msRawData... - for(k = 0; k < N; k++) - msRawData[N*modeCandidate_i+k] = (float)(yk[k+2]); - } - - //store result into msRawData... - for(j = 0; j < N; j++) - msRawData[N*i+j] = (float)(yk[j+2]); - - // Prompt user on progress -#ifdef SHOW_PROGRESS - percent_complete = (float)(i/(float)(L))*100; - msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); -#endif - - // Check to see if the algorithm has been halted - if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) - break; - } - - // Prompt user that filtering is completed -#ifdef PROMPT -#ifdef SHOW_PROGRESS - msSys.Prompt("\r"); -#endif - msSys.Prompt("done."); -#endif - // de-allocate memory - delete [] buckets; - delete [] slist; - delete [] sdata; - - delete [] yk; - delete [] Mh; - - // done. - return; - -} - -void msImageProcessor::NewNonOptimizedFilter(float sigmaS, float sigmaR) -{ - - // Declare Variables - int iterationCount, i, j, k; - double mvAbs, diff, el; - - //make sure that a lattice height and width have - //been defined... - if(!height) - { - ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); - return; - } - - //re-assign bandwidths to sigmaS and sigmaR - if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) - { - ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); - return; - } - - //define input data dimension with lattice - int lN = N + 2; - - // Traverse each data point applying mean shift - // to each data point - - // Allcocate memory for yk - double *yk = new double [lN]; - - // Allocate memory for Mh - double *Mh = new double [lN]; - - // let's use some temporary data - double* sdata; - sdata = new double[lN*L]; - - // copy the scaled data - int idxs, idxd; - idxs = idxd = 0; - if (N==3) - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i/width)/sigmaS; - sdata[idxs++] = data[idxd++]/sigmaR; - sdata[idxs++] = data[idxd++]/sigmaR; - sdata[idxs++] = data[idxd++]/sigmaR; - } - } else if (N==1) - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i/width)/sigmaS; - sdata[idxs++] = data[idxd++]/sigmaR; - } - } else - { - for(i=0; i<L; i++) - { - sdata[idxs++] = (i%width)/sigmaS; - sdata[idxs++] = (i%width)/sigmaS; - for (j=0; j<N; j++) - sdata[idxs++] = data[idxd++]/sigmaR; - } - } - // index the data in the 3d buckets (x, y, L) - int* buckets; - int* slist; - slist = new int[L]; - int bucNeigh[27]; - - double sMins; // just for L - double sMaxs[3]; // for all - sMaxs[0] = width/sigmaS; - sMaxs[1] = height/sigmaS; - sMins = sMaxs[2] = sdata[2]; - idxs = 2; - double cval; - for(i=0; i<L; i++) - { - cval = sdata[idxs]; - if (cval < sMins) - sMins = cval; - else if (cval > sMaxs[2]) - sMaxs[2] = cval; - - idxs += lN; - } - - int nBuck1, nBuck2, nBuck3; - int cBuck1, cBuck2, cBuck3, cBuck; - nBuck1 = (int) (sMaxs[0] + 3); - nBuck2 = (int) (sMaxs[1] + 3); - nBuck3 = (int) (sMaxs[2] - sMins + 3); - buckets = new int[nBuck1*nBuck2*nBuck3]; - for(i=0; i<(nBuck1*nBuck2*nBuck3); i++) - buckets[i] = -1; - - idxs = 0; - for(i=0; i<L; i++) - { - // find bucket for current data and add it to the list - cBuck1 = (int) sdata[idxs] + 1; - cBuck2 = (int) sdata[idxs+1] + 1; - cBuck3 = (int) (sdata[idxs+2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - - slist[i] = buckets[cBuck]; - buckets[cBuck] = i; - - idxs += lN; - } - // init bucNeigh - idxd = 0; - for (cBuck1=-1; cBuck1<=1; cBuck1++) - { - for (cBuck2=-1; cBuck2<=1; cBuck2++) - { - for (cBuck3=-1; cBuck3<=1; cBuck3++) - { - bucNeigh[idxd++] = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - } - } - } - double wsuml, weight; - double hiLTr = 80.0/sigmaR; - // done indexing/hashing - - // proceed ... -#ifdef PROMPT - msSys.Prompt("done.\nApplying mean shift (Using Lattice)... "); -#ifdef SHOW_PROGRESS - msSys.Prompt("\n 0%%"); -#endif -#endif - - for(i = 0; i < L; i++) - { - - // Assign window center (window centers are - // initialized by createLattice to be the point - // data[i]) - idxs = i*lN; - for (j=0; j<lN; j++) - yk[j] = sdata[idxs+j]; - - // Calculate the mean shift vector using the lattice - // LatticeMSVector(Mh, yk); - /*****************************************************/ - // Initialize mean shift vector - for(j = 0; j < lN; j++) - Mh[j] = 0; - wsuml = 0; - // uniformLSearch(Mh, yk_ptr); // modify to new - // find bucket of yk - cBuck1 = (int) yk[0] + 1; - cBuck2 = (int) yk[1] + 1; - cBuck3 = (int) (yk[2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - for (j=0; j<27; j++) - { - idxd = buckets[cBuck+bucNeigh[j]]; - // list parse, crt point is cHeadList - while (idxd>=0) - { - idxs = lN*idxd; - // determine if inside search window - el = sdata[idxs+0]-yk[0]; - diff = el*el; - el = sdata[idxs+1]-yk[1]; - diff += el*el; - - if (diff < 1.0) - { - el = sdata[idxs+2]-yk[2]; - if (yk[2] > hiLTr) - diff = 4*el*el; - else - diff = el*el; - - if (N>1) - { - el = sdata[idxs+3]-yk[3]; - diff += el*el; - el = sdata[idxs+4]-yk[4]; - diff += el*el; - } - - if (diff < 1.0) - { - weight = 1-weightMap[idxd]; - for (k=0; k<lN; k++) - Mh[k] += weight*sdata[idxs+k]; - wsuml += weight; - } - } - idxd = slist[idxd]; - } - } - if (wsuml > 0) - { - for(j = 0; j < lN; j++) - Mh[j] = Mh[j]/wsuml - yk[j]; - } - else - { - for(j = 0; j < lN; j++) - Mh[j] = 0; - } - /*****************************************************/ - - // Calculate its magnitude squared - mvAbs = 0; - for(j = 0; j < lN; j++) - mvAbs += Mh[j]*Mh[j]; - - // Keep shifting window center until the magnitude squared of the - // mean shift vector calculated at the window center location is - // under a specified threshold (Epsilon) - - // NOTE: iteration count is for speed up purposes only - it - // does not have any theoretical importance - iterationCount = 1; - while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) - { - - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - // Calculate the mean shift vector at the new - // window location using lattice - // LatticeMSVector(Mh, yk); - /*****************************************************/ - // Initialize mean shift vector - for(j = 0; j < lN; j++) - Mh[j] = 0; - wsuml = 0; - // uniformLSearch(Mh, yk_ptr); // modify to new - // find bucket of yk - cBuck1 = (int) yk[0] + 1; - cBuck2 = (int) yk[1] + 1; - cBuck3 = (int) (yk[2] - sMins) + 1; - cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); - for (j=0; j<27; j++) - { - idxd = buckets[cBuck+bucNeigh[j]]; - // list parse, crt point is cHeadList - while (idxd>=0) - { - idxs = lN*idxd; - // determine if inside search window - el = sdata[idxs+0]-yk[0]; - diff = el*el; - el = sdata[idxs+1]-yk[1]; - diff += el*el; - - if (diff < 1.0) - { - el = sdata[idxs+2]-yk[2]; - if (yk[2] > hiLTr) - diff = 4*el*el; - else - diff = el*el; - - if (N>1) - { - el = sdata[idxs+3]-yk[3]; - diff += el*el; - el = sdata[idxs+4]-yk[4]; - diff += el*el; - } - - if (diff < 1.0) - { - weight = 1-weightMap[idxd]; - for (k=0; k<lN; k++) - Mh[k] += weight*sdata[idxs+k]; - wsuml += weight; - } - } - idxd = slist[idxd]; - } - } - if (wsuml > 0) - { - for(j = 0; j < lN; j++) - Mh[j] = Mh[j]/wsuml - yk[j]; - } - else - { - for(j = 0; j < lN; j++) - Mh[j] = 0; - } - /*****************************************************/ - - // Calculate its magnitude squared - //mvAbs = 0; - //for(j = 0; j < lN; j++) - // mvAbs += Mh[j]*Mh[j]; - mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; - if (N==3) - mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; - else - mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; - - // Increment interation count - iterationCount++; - } - - // Shift window location - for(j = 0; j < lN; j++) - yk[j] += Mh[j]; - - //store result into msRawData... - for(j = 0; j < N; j++) - msRawData[N*i+j] = (float)(yk[j+2]*sigmaR); - - // Prompt user on progress -#ifdef SHOW_PROGRESS - percent_complete = (float)(i/(float)(L))*100; - msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); -#endif - - // Check to see if the algorithm has been halted - if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) - break; - } - - // Prompt user that filtering is completed -#ifdef PROMPT -#ifdef SHOW_PROGRESS - msSys.Prompt("\r"); -#endif - msSys.Prompt("done."); -#endif - - // de-allocate memory - delete [] buckets; - delete [] slist; - delete [] sdata; - - delete [] yk; - delete [] Mh; - - // done. - return; - -} - -void msImageProcessor::SetSpeedThreshold(float speedUpThreshold) -{ - speedThreshold = speedUpThreshold; -} - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Mean Shift Image Processor Class: + ================================ + + The following class inherits from the mean shift library + in order to perform the specialized tasks of image + segmentation and filtering. + + The definition of the Mean Shift Image Processor Class + is provided below. Its prototype is provided in + 'msImageProcessor.h'. + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + +//include image processor class prototype +#include "msImageProcessor.h" + +//include needed libraries +#include <math.h> +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <stdlib.h> + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + /*/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Constructor/Destructor */ + /*\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Class Constructor */ +/*******************************************************/ +/*Post: */ +/* The msImageProcessor class has been properly */ +/* initialized. */ +/*******************************************************/ + +msImageProcessor::msImageProcessor( void ) +{ + + //intialize basin of attraction structure + //used by the filtering algorithm + modeTable = NULL; + pointList = NULL; + pointCount = 0; + + //initialize region list + regionList = NULL; + + //initialize output structures... + msRawData = NULL; + labels = NULL; + modes = NULL; + modePointCounts = NULL; + regionCount = 0; + + //intialize temporary buffers used for + //performing connected components + indexTable = NULL; + LUV_data = NULL; + + //initialize region adjacency matrix + raList = NULL; + freeRAList = NULL; + raPool = NULL; + + //intialize visit table to having NULL entries + visitTable = NULL; + + //initialize epsilon such that transitive closure + //does not take edge strength into consideration when + //fusing regions of similar color + epsilon = 1.0; + + //initialize class state to indicate that + //an output data structure has not yet been + //created... + class_state.OUTPUT_DEFINED = false; + + + LUV_treshold = 1.0; +} + +/*******************************************************/ +/*Class Destructor */ +/*******************************************************/ +/*Post: */ +/* The msImageProcessor class has been properly */ +/* destroyed. */ +/*******************************************************/ + +msImageProcessor::~msImageProcessor( void ) +{ + + //de-allocate memory + if(class_state.OUTPUT_DEFINED) DestroyOutput(); + if(regionList) delete regionList; + regionList = NULL; + + //done. + +} + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Input Image Declaration */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Define Image */ +/*******************************************************/ +/*Uploads an image into the image segmenter class to */ +/*be segmented. */ +/*******************************************************/ +/*Pre: */ +/* - data_ is a one dimensional array of unsigned */ +/* char RGB vectors */ +/* - type is the type of the image: COLOR or */ +/* GREYSCALE */ +/* - height_ and width_ define the dimension of */ +/* the image */ +/* - if the image is of type GREYSCALE then */ +/* data containes only one number per pixel */ +/* location, where a pixel location is defined */ +/* by the index into the data array */ +/*Post: */ +/* - the image specified has been uploaded into */ +/* the image segmenter class to be segmented. */ +/*******************************************************/ + +void msImageProcessor::DefineImage(byte *data_, imageType type, int height_, int width_) +{ + + //obtain image dimension from image type + int dim; + if(type == COLOR) + dim = 3; + else + dim = 1; + + //perfor rgb to luv conversion + int i; + float *luv = new float [height_*width_*dim]; + if(dim == 1) + { + for(i = 0; i < height_*width_; i++) + luv[i] = (float)(data_[i]); + } + else + { + for(i = 0; i < height_*width_; i++) + RGBtoLUV(&data_[dim*i], &luv[dim*i]); + } + + //define input defined on a lattice using mean shift base class + DefineLInput(luv, height_, width_, dim); + + //Define a default kernel if it has not been already + //defined by user + if(!h) + { + //define default kernel paramerters... + kernelType k[2] = {Uniform, Uniform}; + int P[2] = {2, N}; + float tempH[2] = {1.0 , 1.0}; + + //define default kernel in mean shift base class + DefineKernel(k, tempH, P, 2); + } + + //de-allocate memory + delete [] luv; + + //done. + return; + +} + +void msImageProcessor::DefineBgImage(byte* data_, imageType type, int height_, int width_) +{ + + //obtain image dimension from image type + int dim; + if(type == COLOR) + dim = 3; + else + dim = 1; + + //perform texton classification + int i; + float *luv = new float [height_*width_*dim]; + if(dim == 1) + { + for(i = 0; i < height_*width_; i++) + luv[i] = (float)(data_[i]); + } + else + { + for(i = 0; i < height_*width_; i++) + RGBtoLUV(&data_[dim*i], &luv[dim*i]); + } + + //define input defined on a lattice using mean shift base class + DefineLInput(luv, height_, width_, dim); + + //Define a default kernel if it has not been already + //defined by user + if(!h) + { + //define default kernel paramerters... + kernelType k[2] = {Uniform, Uniform}; + int P[2] = {2, N}; + float tempH[2] = {1.0 , 1.0}; + + //define default kernel in mean shift base class + DefineKernel(k, tempH, P, 2); + } + + //de-allocate memory + delete [] luv; + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\*/ + /* Weight Map */ + /*\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Set Weight Map */ +/*******************************************************/ +/*Populates the weight map with specified edge */ +/*strengths. */ +/*******************************************************/ +/*Pre: */ +/* - wm is a floating point array of size */ +/* (height x width) specifying for each pixel */ +/* edge strength. */ +/* - eps is a threshold used to fuse similar */ +/* regions during transitive closure. */ +/*Post: */ +/* - wm has been used to populate the weight */ +/* map. */ +/* - the threshold used during transitive closure */ +/* is taken as eps. */ +/*******************************************************/ + +void msImageProcessor::SetWeightMap(float *wm, float eps) +{ + + //initlaize confmap using wm + SetLatticeWeightMap(wm); + + //set threshold value + if((epsilon = eps) < 0) + ErrorHandler("msImageProcessor", "SetWeightMap", "Threshold is negative."); + + //done. + return; + +} + +/*******************************************************/ +/*Remove Weight Map */ +/*******************************************************/ +/*Removes the weight map. */ +/*******************************************************/ +/*Post: */ +/* - the weight map has been removed. */ +/* - if a weight map did not exist NO error */ +/* is flagged. */ +/*******************************************************/ + +void msImageProcessor::RemoveWeightMap( void ) +{ + + //remove confmap + RemoveLatticeWeightMap(); + + //set threshold value to zero + epsilon = 0; + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\/\*/ + /* Image Filtering */ + /*\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Filter */ +/*******************************************************/ +/*Performs mean shift filtering on the specified input */ +/*image using a user defined kernel. */ +/*******************************************************/ +/*Pre: */ +/* - the user defined kernel used to apply mean */ +/* shift filtering to the defined input image */ +/* has spatial bandwidth sigmaS and range band- */ +/* width sigmaR */ +/* - speedUpLevel determines whether or not the */ +/* filtering should be optimized for faster */ +/* execution: a value of NO_SPEEDUP turns this */ +/* optimization off and a value SPEEDUP turns */ +/* this optimization on */ +/* - a data set has been defined */ +/* - the height and width of the lattice has been */ +/* specified using method DefineLattice() */ +/*Post: */ +/* - mean shift filtering has been applied to the */ +/* input image using a user defined kernel */ +/* - the filtered image is stored in the private */ +/* data members of the msImageProcessor class. */ +/*******************************************************/ + +void msImageProcessor::Filter(int sigmaS, float sigmaR, SpeedUpLevel speedUpLevel) +{ + + //Check Class consistency... + + //check: + // (1) if this operation is consistent + // (2) if kernel was created + // (3) if data set is defined + // (4) if the dimension of the kernel agrees with that + // of the defined data set + // if not ... flag an error! + classConsistencyCheck(N+2, true); + if(ErrorStatus == EL_ERROR) + return; + + //If the algorithm has been halted, then exit + if((ErrorStatus = msSys.Progress((float)(0.0))) == EL_HALT) + { + return; + } + + //If the image has just been read then allocate memory + //for and initialize output data structure used to store + //image modes and their corresponding regions... + if(class_state.OUTPUT_DEFINED == false) + { + InitializeOutput(); + + //check for errors... + if(ErrorStatus == EL_ERROR) + return; + } + + //****************** Allocate Memory ****************** + + //Allocate memory for basin of attraction mode structure... + if((!(modeTable = new unsigned char [L]))||(!(pointList = new int [L]))) + { + ErrorHandler("msImageProcessor", "Allocate", "Not enough memory."); + return; + } + + //start timer +#ifdef PROMPT + double timer; + msSys.StartTimer(); +#endif + + //***************************************************** + + //filter image according to speedup level... + switch(speedUpLevel) + { + //no speedup... + case NO_SPEEDUP: + //NonOptimizedFilter((float)(sigmaS), sigmaR); break; + NewNonOptimizedFilter((float)(sigmaS), sigmaR); break; + //medium speedup + case MED_SPEEDUP: + //OptimizedFilter1((float)(sigmaS), sigmaR); break; + NewOptimizedFilter1((float)(sigmaS), sigmaR); break; + //high speedup + case HIGH_SPEEDUP: + //OptimizedFilter2((float)(sigmaS), sigmaR); break; + NewOptimizedFilter2((float)(sigmaS), sigmaR); break; + // new speedup + } + + //****************** Deallocate Memory ****************** + + //de-allocate memory used by basin of attraction mode structure + delete [] modeTable; + delete [] pointList; + + //re-initialize structure + modeTable = NULL; + pointList = NULL; + pointCount = 0; + + //******************************************************* + + //If the algorithm has been halted, then de-allocate the output + //and exit + if((ErrorStatus = msSys.Progress((float)(0.8))) == EL_HALT) + { + DestroyOutput(); + return; + } + + //Label image regions, also if segmentation is not to be + //performed use the resulting classification structure to + //calculate the image boundaries... + + /* + //copy msRawData into LUV_data, rounding each component of each + //LUV value stored by msRawData to the nearest integer + int i; + for(i = 0; i < L*N; i++) + { + if(msRawData[i] < 0) + LUV_data[i] = (int)(msRawData[i] - 0.5); + else + LUV_data[i] = (int)(msRawData[i] + 0.5); + } + */ + int i; + for (i=0; i<L*N; i++) + { + LUV_data[i] = msRawData[i]; + } + + +#ifdef PROMPT + timer = msSys.ElapsedTime(); + msSys.Prompt("(%6.2f sec)\nConnecting regions ...", timer); + msSys.StartTimer(); +#endif + + //Perform connecting (label image regions) using LUV_data + Connect(); + +#ifdef PROMPT + timer = msSys.ElapsedTime(); + msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount); + msSys.StartTimer(); +#endif + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\/\/\/\*/ + /* Image Region Fusing */ + /*\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Fuse Regions */ +/*******************************************************/ +/*Fuses the regions of a filtered image. */ +/*******************************************************/ +/*Pre: */ +/* - the range radius is specified by sigmaR */ +/* - minRegion is the minimum point density that */ +/* a region may have in the resulting segment- */ +/* ed image */ +/* - a data set has been defined */ +/* - the height and width of the lattice has been */ +/* specified using method DefineLattice() */ +/*Post: */ +/* - the image regions have been fused. */ +/* - if an result is stored by this class then */ +/* this result is used as input to this method. */ +/* - if no result is stored by this class, */ +/* the input image defined by calling the */ +/* method DefineImage is used. */ +/*******************************************************/ + +void msImageProcessor::FuseRegions(float sigmaS, int minRegion) +{ + + //Check Class consistency... + + //check: + // (1) if this operation is consistent + // (2) if kernel was created + // (3) if data set is defined + // (4) if the dimension of the kernel agrees with that + // of the defined data set + // if not ... flag an error! + classConsistencyCheck(N+2, true); + if(ErrorStatus == EL_ERROR) + return; + + //Check to see if the algorithm is to be halted, if so then + //destroy output and exit + if((ErrorStatus = msSys.Progress((float)(0.8))) == EL_HALT) + { + if(class_state.OUTPUT_DEFINED) DestroyOutput(); + return; + } + + //obtain sigmaS (make sure it is not zero or negative, if not + //flag an error) + if((h[1] = sigmaS) <= 0) + { + ErrorHandler("msImageProcessor", "FuseRegions", "The feature radius must be greater than or equal to zero."); + return; + } + + //if output has not yet been generated then classify the input + //image regions to be fused... + if(!(class_state.OUTPUT_DEFINED)) + { + + //Initialize output data structure used to store + //image modes and their corresponding regions... + InitializeOutput(); + + //check for errors... + if(ErrorStatus == EL_ERROR) + return; + + //copy data into LUV_data used to classify + //image regions + /* + int i; + for(i = 0; i < L*N; i++) + { + if(data[i] < 0) + LUV_data[i] = (int)(data[i] - 0.5); + else + LUV_data[i] = (int)(data[i] + 0.5); + } + */ + int i; + for (i=0; i<L*N; i++) + { + LUV_data[i] = data[i]; + } + +#ifdef PROMPT + msSys.Prompt("Connecting regions ..."); + msSys.StartTimer(); +#endif + + //Perform connecting (label image regions) using LUV_data + Connect(); + + //check for errors + if(ErrorStatus == EL_ERROR) + return; + +#ifdef PROMPT + double timer = msSys.ElapsedTime(); + msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount); +#endif + + } + + //Check to see if the algorithm is to be halted, if so then + //destroy output and exit + if((ErrorStatus = msSys.Progress((float)(0.85))) == EL_HALT) + { + DestroyOutput(); + return; + } + +#ifdef PROMPT + msSys.Prompt("Applying transitive closure..."); + msSys.StartTimer(); +#endif + + //allocate memory visit table + visitTable = new unsigned char [L]; + + //Apply transitive closure iteratively to the regions classified + //by the RAM updating labels and modes until the color of each neighboring + //region is within sqrt(rR2) of one another. + rR2 = (float)(h[1]*h[1]*0.25); + TransitiveClosure(); + int oldRC = regionCount; + int deltaRC, counter = 0; + do { + TransitiveClosure(); + deltaRC = oldRC-regionCount; + oldRC = regionCount; + counter++; + } while ((deltaRC <= 0)&&(counter < 10)); + + //de-allocate memory for visit table + delete [] visitTable; + visitTable = NULL; + + //Check to see if the algorithm is to be halted, if so then + //destroy output and region adjacency matrix and exit + if((ErrorStatus = msSys.Progress((float)(1.0))) == EL_HALT) + { + DestroyRAM(); + DestroyOutput(); + return; + } + +#ifdef PROMPT + double timer = msSys.ElapsedTime(); + msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\nPruning spurious regions ...", timer, regionCount); + msSys.StartTimer(); +#endif + + //Prune spurious regions (regions whose area is under + //minRegion) using RAM + Prune(minRegion); + +#ifdef PROMPT + timer = msSys.ElapsedTime(); + msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\n", timer, regionCount); + msSys.StartTimer(); +#endif + + //Check to see if the algorithm is to be halted, if so then + //destroy output and region adjacency matrix and exit + if((ErrorStatus = msSys.Progress((float)(1.0))) == EL_HALT) + { + DestroyRAM(); + DestroyOutput(); + return; + } + + //de-allocate memory for region adjacency matrix + DestroyRAM(); + + //output to msRawData + int i, j, label; + for(i = 0; i < L; i++) + { + label = labels[i]; + for(j = 0; j < N; j++) + { + msRawData[N*i+j] = modes[N*label+j]; + } + } + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\/\/\*/ + /* Image Segmentation */ + /*\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Segment */ +/*******************************************************/ +/*Segments the defined image. */ +/*******************************************************/ +/*Pre: */ +/* - sigmaS and sigmaR are the spatial and range */ +/* radii of the search window respectively */ +/* - minRegion is the minimum point density that */ +/* a region may have in the resulting segment- */ +/* ed image */ +/* - speedUpLevel determines whether or not the */ +/* filtering should be optimized for faster */ +/* execution: a value of NO_SPEEDUP turns this */ +/* optimization off and a value SPEEDUP turns */ +/* this optimization on */ +/*Post: */ +/* - the defined image is segmented and the */ +/* resulting segmented image is stored in the */ +/* private data members of the image segmenter */ +/* class. */ +/* - any regions whose point densities are less */ +/* than or equal to minRegion have been pruned */ +/* from the segmented image. */ +/*******************************************************/ + +void msImageProcessor::Segment(int sigmaS, float sigmaR, int minRegion, SpeedUpLevel speedUpLevel) +{ + + //make sure kernel is properly defined... + if((!h)||(kp < 2)) + { + ErrorHandler("msImageProcessor", "Segment", "Kernel corrupt or undefined."); + return; + } + + //Apply mean shift to data set using sigmaS and sigmaR... + Filter(sigmaS, sigmaR, speedUpLevel); + + //check for errors + if(ErrorStatus == EL_ERROR) + return; + + //check to see if the system has been halted, if so exit + if(ErrorStatus == EL_HALT) + return; + + //Check to see if the algorithm is to be halted, if so then + //destroy output and exit + if((ErrorStatus = msSys.Progress((float)(0.85))) == EL_HALT) + { + DestroyOutput(); + return; + } + +#ifdef PROMPT + msSys.Prompt("Applying transitive closure..."); + msSys.StartTimer(); +#endif + + //allocate memory visit table + visitTable = new unsigned char [L]; + + //Apply transitive closure iteratively to the regions classified + //by the RAM updating labels and modes until the color of each neighboring + //region is within sqrt(rR2) of one another. + rR2 = (float)(h[1]*h[1]*0.25); + TransitiveClosure(); + int oldRC = regionCount; + int deltaRC, counter = 0; + do { + TransitiveClosure(); + deltaRC = oldRC-regionCount; + oldRC = regionCount; + counter++; + } while ((deltaRC <= 0)&&(counter < 10)); + + //de-allocate memory for visit table + delete [] visitTable; + visitTable = NULL; + + //Check to see if the algorithm is to be halted, if so then + //destroy output and regions adjacency matrix and exit + if((ErrorStatus = msSys.Progress((float)(0.95))) == EL_HALT) + { + DestroyRAM(); + DestroyOutput(); + return; + } + +#ifdef PROMPT + double timer = msSys.ElapsedTime(); + msSys.Prompt("done. (%6.2f seconds, numRegions = %6d).\nPruning spurious regions\t... ", timer, regionCount); + msSys.StartTimer(); +#endif + + //Prune spurious regions (regions whose area is under + //minRegion) using RAM + Prune(minRegion); + +#ifdef PROMPT + timer = msSys.ElapsedTime(); + msSys.Prompt("done. (%6.2f seconds, numRegions = %6d)\nPruning spurious regions ...", timer, regionCount); + msSys.StartTimer(); +#endif + + //Check to see if the algorithm is to be halted, if so then + //destroy output and regions adjacency matrix and exit + if((ErrorStatus = msSys.Progress(1.0)) == EL_HALT) + { + DestroyRAM(); + DestroyOutput(); + return; + } + + //de-allocate memory for region adjacency matrix + DestroyRAM(); + + //output to msRawData + int j, i, label; + for(i = 0; i < L; i++) + { + label = labels[i]; + for(j = 0; j < N; j++) + { + msRawData[N*i+j] = modes[N*label+j]; + } + } + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Data Space Conversion */ + /*\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*RGB To LUV */ +/*******************************************************/ +/*Converts an RGB vector to LUV. */ +/* */ +/*See: */ +/* G. Wyszecki and W.S. Stiles: Color Science: */ +/* Concepts and Methods, Quantitative Data and */ +/* Formulae, Wiley, New York, 1982. */ +/*******************************************************/ +/*Pre: */ +/* - rgbVal is an unsigned char array containing */ +/* the RGB vector */ +/* - luvVal is a floating point array containing */ +/* the resulting LUV vector */ +/*Post: */ +/* - rgbVal has been converted to LUV and the */ +/* result has been stored in luvVal. */ +/*******************************************************/ + +void msImageProcessor::RGBtoLUV(byte *rgbVal, float *luvVal) +{ + + //delcare variables + double x, y, z, L0, u_prime, v_prime, constant; + + //convert RGB to XYZ... + x = XYZ[0][0]*rgbVal[0] + XYZ[0][1]*rgbVal[1] + XYZ[0][2]*rgbVal[2]; + y = XYZ[1][0]*rgbVal[0] + XYZ[1][1]*rgbVal[1] + XYZ[1][2]*rgbVal[2]; + z = XYZ[2][0]*rgbVal[0] + XYZ[2][1]*rgbVal[1] + XYZ[2][2]*rgbVal[2]; + + //convert XYZ to LUV... + + //compute L* + L0 = y / (255.0 * Yn); + if(L0 > Lt) + luvVal[0] = (float)(116.0 * (pow(L0, 1.0/3.0)) - 16.0); + else + luvVal[0] = (float)(903.3 * L0); + + //compute u_prime and v_prime + constant = x + 15 * y + 3 * z; + if(constant != 0) + { + u_prime = (4 * x) / constant; + v_prime = (9 * y) / constant; + } + else + { + u_prime = 4.0; + v_prime = 9.0/15.0; + } + + //compute u* and v* + luvVal[1] = (float) (13 * luvVal[0] * (u_prime - Un_prime)); + luvVal[2] = (float) (13 * luvVal[0] * (v_prime - Vn_prime)); + + //done. + return; + +} + +/*******************************************************/ +/*LUV To RGB */ +/*******************************************************/ +/*Converts an LUV vector to RGB. */ +/*******************************************************/ +/*Pre: */ +/* - luvVal is a floating point array containing */ +/* the LUV vector */ +/* - rgbVal is an unsigned char array containing */ +/* the resulting RGB vector */ +/*Post: */ +/* - luvVal has been converted to RGB and the */ +/* result has been stored in rgbVal. */ +/*******************************************************/ + +//define inline rounding function... +inline int my_round(double in_x) +{ + if (in_x < 0) + return (int)(in_x - 0.5); + else + return (int)(in_x + 0.5); +} + +void msImageProcessor::LUVtoRGB(float *luvVal, byte *rgbVal) +{ + + //declare variables... + int r, g, b; + double x, y, z, u_prime, v_prime; + + //perform conversion + if(luvVal[0] < 0.1) + r = g = b = 0; + else + { + //convert luv to xyz... + if(luvVal[0] < 8.0) + y = Yn * luvVal[0] / 903.3; + else + { + y = (luvVal[0] + 16.0) / 116.0; + y *= Yn * y * y; + } + + u_prime = luvVal[1] / (13 * luvVal[0]) + Un_prime; + v_prime = luvVal[2] / (13 * luvVal[0]) + Vn_prime; + + x = 9 * u_prime * y / (4 * v_prime); + z = (12 - 3 * u_prime - 20 * v_prime) * y / (4 * v_prime); + + //convert xyz to rgb... + //[r, g, b] = RGB*[x, y, z]*255.0 + r = my_round((RGB[0][0]*x + RGB[0][1]*y + RGB[0][2]*z)*255.0); + g = my_round((RGB[1][0]*x + RGB[1][1]*y + RGB[1][2]*z)*255.0); + b = my_round((RGB[2][0]*x + RGB[2][1]*y + RGB[2][2]*z)*255.0); + + //check bounds... + if(r < 0) r = 0; if(r > 255) r = 255; + if(g < 0) g = 0; if(g > 255) g = 255; + if(b < 0) b = 0; if(b > 255) b = 255; + + } + + //assign rgb values to rgb vector rgbVal + rgbVal[0] = r; + rgbVal[1] = g; + rgbVal[2] = b; + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Filtered and Segmented Image Output */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Get Raw Data */ +/*******************************************************/ +/*The output image data is returned. */ +/*******************************************************/ +/*Pre: */ +/* - outputImageData is a pre-allocated floating */ +/* point array used to store the filtered or */ +/* segmented image pixels. */ +/*Post: */ +/* - the filtered or segmented image data is */ +/* stored by outputImageData. */ +/*******************************************************/ + +void msImageProcessor::GetRawData(float *outputImageData) +{ + //make sure that outputImageData is not NULL + if(!outputImageData) + { + ErrorHandler("msImageProcessor", "GetRawData", "Output image data buffer is NULL."); + return; + } + + //copy msRawData to outputImageData + int i; + for(i = 0; i < L*N; i++) + outputImageData[i] = msRawData[i]; + + //done. + return; +} + +/*******************************************************/ +/*Get Results */ +/*******************************************************/ +/*The output image is returned. */ +/*******************************************************/ +/*Pre: */ +/* - outputImage is a pre-allocated unsinged char */ +/* array used to store the filtered or segment- */ +/* ed image pixels */ +/*Post: */ +/* - the filtered or segmented image is stored by */ +/* outputImage. */ +/*******************************************************/ + +void msImageProcessor::GetResults(byte *outputImage) +{ + + //make sure that outpuImage is not NULL + if(!outputImage) + { + ErrorHandler("msImageProcessor", "GetResults", "Output image buffer is NULL."); + return; + } + + //if the image type is GREYSCALE simply + //copy it over to the segmentedImage + if(N == 1) + { + //copy over msRawData to segmentedImage checking + //bounds + int i, pxValue; + for(i = 0; i < L; i++) + { + + //get value + pxValue = (int)(msRawData[i]+0.5); + + //store into segmented image checking bounds... + if(pxValue < 0) + outputImage[i] = (byte)(0); + else if(pxValue > 255) + outputImage[i] = (byte)(255); + else + outputImage[i] = (byte)(pxValue); + + } + + } + else if (N == 3) + { + + //otherwise convert msRawData from LUV to RGB + //storing the result in segmentedImage + int i; + for(i = 0; i < L; i++) + LUVtoRGB(&msRawData[N*i], &outputImage[N*i]); + + } + else + //Unknown image type: should use MeanShift::GetRawData()... + ErrorHandler("msImageProcessor", "GetResults", "Unknown image type. Try using MeanShift::GetRawData()."); + + //done. + return; + +} + +/*******************************************************/ +/*Get Boundaries */ +/*******************************************************/ +/*A region list containing the boundary locations for */ +/*each region is returned. */ +/*******************************************************/ +/*Post: */ +/* - a region list object containing the boundary */ +/* locations for each region is constructed */ +/* - the region list is returned */ +/* - NULL is returned if the image has not been */ +/* filtered or segmented */ +/*******************************************************/ + +RegionList *msImageProcessor::GetBoundaries( void ) +{ + + //define bounds using label information + if(class_state.OUTPUT_DEFINED) + DefineBoundaries(); + + //return region list structure + return regionList; + +} + +/*******************************************************/ +/*Get Regions */ +/*******************************************************/ +/*Returns the regions of the processed image. */ +/*******************************************************/ +/*Pre: */ +/* - labels_out is an integer array of size */ +/* height*width that stores for each pixel a */ +/* label relating that pixel to a corresponding */ +/* region in the image */ +/* - modes_out is floating point array of size */ +/* regionCount*N storing the feature component */ +/* of each region, and indexed by region label */ +/* - modePointCounts is an integer array of size */ +/* regionCount, indexed by region label, that */ +/* stores the area of each region in pixels. */ +/*Post: */ +/* If an input image was defined and processed, */ +/* - memory has been allocated for labels_out, */ +/* modes_out and MPC_out. */ +/* - labels_out, modes_out, and MPC_out have been */ +/* populated. */ +/* - the number of regions contained by the segm- */ +/* ented image has been returned. */ +/* If the image has not been defined or processed */ +/* or if there is in-sufficient memory, */ +/* - no memory has been allocated for labels_out, */ +/* modes_out, and MPC_out. */ +/* - -1 is returned for regionCount. */ +/*******************************************************/ + +int msImageProcessor::GetRegions(int **labels_out, float **modes_out, int **MPC_out) +{ + //check to see if output has been defined for the given input image... + if(class_state.OUTPUT_DEFINED == false) + return -1; + + //allocate memory for labels_out, modes_out and MPC_out based + //on output storage structure + int *labels_ = *labels_out, *MPC_out_ = *MPC_out; + float *modes_ = *modes_out; + if(!(labels_ = new int [L])) + { + ErrorHandler("msImageProcessor", "GetRegions", "Not enough memory."); + return -1; + } + if(!(modes_ = new float [regionCount*N])) + { + ErrorHandler("msImageProcessor", "GetRegions", "Not enough memory."); + return -1; + } + if(!(MPC_out_ = new int [regionCount])) + { + ErrorHandler("msImageProcessor", "GetRegions", "Not enough memory."); + return -1; + } + + //populate labels_out with image labels + int i; + for(i = 0; i < L; i++) + labels_[i] = labels[i]; + + //populate modes_out and MPC_out with the color and point + //count of each region + for(i = 0; i < regionCount*N; i++) + modes_[i] = modes[i]; + for(i = 0; i < regionCount; i++) + MPC_out_[i] = modePointCounts[i]; + + //done. Return the number of regions resulting from filtering or segmentation. + return regionCount; +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PRIVATE METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + /*/\/\/\/\/\/\/\/\/\*/ + /* Image Filtering */ + /*\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Non Optimized Filter */ +/*******************************************************/ +/*Performs mean shift filtering on the specified input */ +/*image using a user defined kernel. */ +/*******************************************************/ +/*Pre: */ +/* - the user defined kernel used to apply mean */ +/* shift filtering to the defined input image */ +/* has spatial bandwidth sigmaS and range band- */ +/* width sigmaR */ +/* - a data set has been defined */ +/* - the height and width of the lattice has been */ +/* specified using method DefineLattice() */ +/*Post: */ +/* - mean shift filtering has been applied to the */ +/* input image using a user defined kernel */ +/* - the filtered image is stored in the private */ +/* data members of the msImageProcessor class. */ +/*******************************************************/ + +void msImageProcessor::NonOptimizedFilter(float sigmaS, float sigmaR) +{ + + // Declare Variables + int iterationCount, i, j; + double mvAbs; + + //make sure that a lattice height and width have + //been defined... + if(!height) + { + ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); + return; + } + + //re-assign bandwidths to sigmaS and sigmaR + if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) + { + ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); + return; + } + + //define input data dimension with lattice + int lN = N + 2; + + // Traverse each data point applying mean shift + // to each data point + + // Allcocate memory for yk + double *yk = new double [lN]; + + // Allocate memory for Mh + double *Mh = new double [lN]; + + // proceed ... +#ifdef PROMPT + msSys.Prompt("done.\nApplying mean shift (Using Lattice)... "); +#ifdef SHOW_PROGRESS + msSys.Prompt("\n 0%%"); +#endif +#endif + + for(i = 0; i < L; i++) + { + + // Assign window center (window centers are + // initialized by createLattice to be the point + // data[i]) + yk[0] = i%width; + yk[1] = i/width; + for(j = 0; j < N; j++) + yk[j+2] = data[N*i+j]; + + // Calculate the mean shift vector using the lattice + LatticeMSVector(Mh, yk); + + // Calculate its magnitude squared + mvAbs = 0; + for(j = 0; j < lN; j++) + mvAbs += Mh[j]*Mh[j]; + + // Keep shifting window center until the magnitude squared of the + // mean shift vector calculated at the window center location is + // under a specified threshold (Epsilon) + + // NOTE: iteration count is for speed up purposes only - it + // does not have any theoretical importance + iterationCount = 1; + while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) + { + + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // Calculate the mean shift vector at the new + // window location using lattice + LatticeMSVector(Mh, yk); + + // Calculate its magnitude squared + mvAbs = 0; + for(j = 0; j < lN; j++) + mvAbs += Mh[j]*Mh[j]; + + // Increment interation count + iterationCount++; + + } + + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + //store result into msRawData... + for(j = 0; j < N; j++) + msRawData[N*i+j] = (float)(yk[j+2]); + + // Prompt user on progress +#ifdef SHOW_PROGRESS + percent_complete = (float)(i/(float)(L))*100; + msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); +#endif + + // Check to see if the algorithm has been halted + if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) + break; + } + + // Prompt user that filtering is completed +#ifdef PROMPT +#ifdef SHOW_PROGRESS + msSys.Prompt("\r"); +#endif + msSys.Prompt("done."); +#endif + + // de-allocate memory + delete [] yk; + delete [] Mh; + + // done. + return; + +} + + + +/*******************************************************/ +/*Optimized Filter 1 */ +/*******************************************************/ +/*Performs mean shift filtering on the specified input */ +/*image using a user defined kernel. Previous mode */ +/*information is used to avoid re-applying mean shift */ +/*on certain data points to improve performance. */ +/*******************************************************/ +/*Pre: */ +/* - the user defined kernel used to apply mean */ +/* shift filtering to the defined input image */ +/* has spatial bandwidth sigmaS and range band- */ +/* width sigmaR */ +/* - a data set has been defined */ +/* - the height and width of the lattice has been */ +/* specified using method DefineLattice() */ +/*Post: */ +/* - mean shift filtering has been applied to the */ +/* input image using a user defined kernel */ +/* - the filtered image is stored in the private */ +/* data members of the msImageProcessor class. */ +/*******************************************************/ + +void msImageProcessor::OptimizedFilter1(float sigmaS, float sigmaR) +{ + + // Declare Variables + int iterationCount, i, j, k, s, p, modeCandidateX, modeCandidateY, modeCandidate_i; + float *modeCandidatePoint; + double mvAbs, diff, el; + + //make sure that a lattice height and width have + //been defined... + if(!height) + { + ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); + return; + } + + //re-assign bandwidths to sigmaS and sigmaR + if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) + { + ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); + return; + } + + //define input data dimension with lattice + int lN = N + 2; + + // Traverse each data point applying mean shift + // to each data point + + // Allcocate memory for yk + double *yk = new double [lN]; + + // Allocate memory for Mh + double *Mh = new double [lN]; + + // Initialize mode table used for basin of attraction + memset(modeTable, 0, width*height); + + // Allocate memory mode candidate data point... + //floating point version + modeCandidatePoint = new float [N]; + + // proceed ... +#ifdef PROMPT + msSys.Prompt("done.\nApplying mean shift (Using Lattice) ... "); +#ifdef SHOW_PROGRESS + msSys.Prompt("\n 0%%"); +#endif +#endif + + + for(i = 0; i < L; i++) + { + // if a mode was already assigned to this data point + // then skip this point, otherwise proceed to + // find its mode by applying mean shift... + if (modeTable[i] == 1) + continue; + + // initialize point list... + pointCount = 0; + + // Assign window center (window centers are + // initialized by createLattice to be the point + // data[i]) + yk[0] = i%width; + yk[1] = i/width; + for(j = 0; j < N; j++) + yk[j+2] = data[N*i+j]; + + // Calculate the mean shift vector using the lattice + LatticeMSVector(Mh, yk); + + // Calculate its magnitude squared + mvAbs = 0; + for(j = 0; j < lN; j++) + mvAbs += Mh[j]*Mh[j]; + + // Keep shifting window center until the magnitude squared of the + // mean shift vector calculated at the window center location is + // under a specified threshold (Epsilon) + + // NOTE: iteration count is for speed up purposes only - it + // does not have any theoretical importance + iterationCount = 1; + while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) + { + + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // check to see if the current mode location is in the + // basin of attraction... + + // calculate the location of yk on the lattice + modeCandidateX = (int) (yk[0]+0.5); + modeCandidateY = (int) (yk[1]+0.5); + modeCandidate_i = modeCandidateY*width + modeCandidateX; + + // if mvAbs != 0 (yk did indeed move) then check + // location basin_i in the mode table to see if + // this data point either: + + // (1) has not been associated with a mode yet + // (modeTable[basin_i] = 0), so associate + // it with this one + // + // (2) it has been associated with a mode other + // than the one that this data point is converging + // to (modeTable[basin_i] = 1), so assign to + // this data point the same mode as that of basin_i + + if ((modeTable[modeCandidate_i] != 2) && (modeCandidate_i != i)) + { + // obtain the data point at basin_i to + // see if it is within h*TC_DIST_FACTOR of + // of yk + for (j = 0; j < N; j++) + modeCandidatePoint[j] = data[N*modeCandidate_i + j]; + + // check basin on non-spatial data spaces only + k = 1; + s = 0; + diff = 0; + while ((diff < TC_DIST_FACTOR) && (k<kp)) + { + diff = 0; + for (p=0; p<P[k]; p++) + { + el = (modeCandidatePoint[p+s]-yk[p+s+2])/h[k]; + diff += el*el; + } + s+=P[k]; + k++; + } + + // if the data point at basin_i is within + // a distance of h*TC_DIST_FACTOR of yk + // then depending on modeTable[basin_i] perform + // either (1) or (2) + if (diff < TC_DIST_FACTOR) + { + // if the data point at basin_i has not + // been associated to a mode then associate + // it with the mode that this one will converge + // to + if (modeTable[modeCandidate_i] == 0) + { + // no mode associated yet so associate + // it with this one... + pointList[pointCount++] = modeCandidate_i; + modeTable[modeCandidate_i] = 2; + + } else + { + + // the mode has already been associated with + // another mode, thererfore associate this one + // mode and the modes in the point list with + // the mode associated with data[basin_i]... + + // store the mode info into yk using msRawData... + for (j = 0; j < N; j++) + yk[j+2] = msRawData[modeCandidate_i*N+j]; + + // update mode table for this data point + // indicating that a mode has been associated + // with it + modeTable[i] = 1; + + // indicate that a mode has been associated + // to this data point (data[i]) + mvAbs = -1; + + // stop mean shift calculation... + break; + } + } + } + + // Calculate the mean shift vector at the new + // window location using lattice + LatticeMSVector(Mh, yk); + + // Calculate its magnitude squared + mvAbs = 0; + for(j = 0; j < lN; j++) + mvAbs += Mh[j]*Mh[j]; + + // Increment iteration count + iterationCount++; + + } + + // if a mode was not associated with this data point + // yet associate it with yk... + if (mvAbs >= 0) + { + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // update mode table for this data point + // indicating that a mode has been associated + // with it + modeTable[i] = 1; + } + + // associate the data point indexed by + // the point list with the mode stored + // by yk + for (j = 0; j < pointCount; j++) + { + // obtain the point location from the + // point list + modeCandidate_i = pointList[j]; + + // update the mode table for this point + modeTable[modeCandidate_i] = 1; + + //store result into msRawData... + for(k = 0; k < N; k++) + msRawData[N*modeCandidate_i+k] = (float)(yk[k+2]); + } + + + //store result into msRawData... + for(j = 0; j < N; j++) + msRawData[N*i+j] = (float)(yk[j+2]); + + // Prompt user on progress +#ifdef SHOW_PROGRESS + percent_complete = (float)(i/(float)(L))*100; + msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); +#endif + + // Check to see if the algorithm has been halted + if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) + break; + } + + // Prompt user that filtering is completed +#ifdef PROMPT +#ifdef SHOW_PROGRESS + msSys.Prompt("\r"); +#endif + msSys.Prompt("done."); +#endif + + // de-allocate memory + delete [] modeCandidatePoint; + delete [] yk; + delete [] Mh; + + // done. + return; + +} + +/*******************************************************/ +/*Optimized Filter 2 */ +/*******************************************************/ +/*Performs mean shift filtering on the specified input */ +/*image using a user defined kernel. Previous mode */ +/*information is used to avoid re-applying mean shift */ +/*on certain data points to improve performance. To */ +/*further improve perfmance (during segmentation) poi- */ +/*nts within h of a window center during the window */ +/*center's traversal to a mode are associated with the */ +/*mode that the window converges to. */ +/*******************************************************/ +/*Pre: */ +/* - the user defined kernel used to apply mean */ +/* shift filtering to the defined input image */ +/* has spatial bandwidth sigmaS and range band- */ +/* width sigmaR */ +/* - a data set has been defined */ +/* - the height and width of the lattice has been */ +/* specified using method DefineLattice() */ +/*Post: */ +/* - mean shift filtering has been applied to the */ +/* input image using a user defined kernel */ +/* - the filtered image is stored in the private */ +/* data members of the msImageProcessor class. */ +/*******************************************************/ + +void msImageProcessor::OptimizedFilter2(float sigmaS, float sigmaR) +{ + + //if confidence map is null set it to zero + if(!weightMap) + { + weightMap = new float [L]; + int i; + for(i = 0; i < L; i++) + weightMap[i] = 0; + } + + // Declare Variables + int iterationCount, i, j, k, s, p, modeCandidateX, modeCandidateY, modeCandidate_i; + float *modeCandidatePoint; + double mvAbs, diff, el; + + //make sure that a lattice height and width have + //been defined... + if(!height) + { + ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); + return; + } + + //re-assign bandwidths to sigmaS and sigmaR + if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) + { + ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); + return; + } + + //define input data dimension with lattice + int lN = N + 2; + + // Traverse each data point applying mean shift + // to each data point + + // Allcocate memory for yk + double *yk = new double [lN]; + + // Allocate memory for Mh + double *Mh = new double [lN]; + + // Initialize mode table used for basin of attraction + memset(modeTable, 0, width*height); + + // Allocate memory mode candidate data point... + //floating point version + modeCandidatePoint = new float [N]; + + // proceed ... +#ifdef PROMPT + msSys.Prompt("done.\nApplying mean shift (Using Lattice)... "); +#ifdef SHOW_PROGRESS + msSys.Prompt("\n 0%%"); +#endif +#endif + + for(i = 0; i < L; i++) + { + // if a mode was already assigned to this data point + // then skip this point, otherwise proceed to + // find its mode by applying mean shift... + if (modeTable[i] == 1) + continue; + + // initialize point list... + pointCount = 0; + + // Assign window center (window centers are + // initialized by createLattice to be the point + // data[i]) + yk[0] = i%width; + yk[1] = i/width; + for(j = 0; j < N; j++) + yk[j+2] = data[N*i+j]; + + // Calculate the mean shift vector using the lattice + OptLatticeMSVector(Mh, yk); + + // Calculate its magnitude squared + mvAbs = 0; + for(j = 0; j < lN; j++) + mvAbs += Mh[j]*Mh[j]; + + // Keep shifting window center until the magnitude squared of the + // mean shift vector calculated at the window center location is + // under a specified threshold (Epsilon) + + // NOTE: iteration count is for speed up purposes only - it + // does not have any theoretical importance + iterationCount = 1; + while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) + { + + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // check to see if the current mode location is in the + // basin of attraction... + + // calculate the location of yk on the lattice + modeCandidateX = (int) (yk[0]+0.5); + modeCandidateY = (int) (yk[1]+0.5); + modeCandidate_i = modeCandidateY*width + modeCandidateX; + + // if mvAbs != 0 (yk did indeed move) then check + // location basin_i in the mode table to see if + // this data point either: + + // (1) has not been associated with a mode yet + // (modeTable[basin_i] = 0), so associate + // it with this one + // + // (2) it has been associated with a mode other + // than the one that this data point is converging + // to (modeTable[basin_i] = 1), so assign to + // this data point the same mode as that of basin_i + + if ((modeTable[modeCandidate_i] != 2) && (modeCandidate_i != i)) + { + // obtain the data point at basin_i to + // see if it is within h*TC_DIST_FACTOR of + // of yk + for (j = 0; j < N; j++) + modeCandidatePoint[j] = data[N*modeCandidate_i + j]; + + // check basin on non-spatial data spaces only + k = 1; + s = 0; + diff = 0; + while ((diff < TC_DIST_FACTOR) && (k<kp)) + { + diff = 0; + for (p=0; p<P[k]; p++) + { + el = (modeCandidatePoint[p+s]-yk[p+s+2])/h[k]; + diff += el*el; + } + s+=P[k]; + k++; + } + + // if the data point at basin_i is within + // a distance of h*TC_DIST_FACTOR of yk + // then depending on modeTable[basin_i] perform + // either (1) or (2) + if (diff < TC_DIST_FACTOR) + { + // if the data point at basin_i has not + // been associated to a mode then associate + // it with the mode that this one will converge + // to + if (modeTable[modeCandidate_i] == 0) + { + // no mode associated yet so associate + // it with this one... + pointList[pointCount++] = modeCandidate_i; + modeTable[modeCandidate_i] = 2; + + } else + { + + // the mode has already been associated with + // another mode, thererfore associate this one + // mode and the modes in the point list with + // the mode associated with data[basin_i]... + + // store the mode infor int yk using msRawData... + for (j = 0; j < N; j++) + yk[j+2] = msRawData[modeCandidate_i*N+j]; + + // update mode table for this data point + // indicating that a mode has been associated + // with it + modeTable[i] = 1; + + // indicate that a mode has been associated + // to this data point (data[i]) + mvAbs = -1; + + // stop mean shift calculation... + break; + } + } + } + + // Calculate the mean shift vector at the new + // window location using lattice + OptLatticeMSVector(Mh, yk); + + // Calculate its magnitude squared + mvAbs = 0; + for(j = 0; j < lN; j++) + mvAbs += Mh[j]*Mh[j]; + + // Increment interation count + iterationCount++; + + } + + // if a mode was not associated with this data point + // yet then perform a shift the window center yk one + // last time using the mean shift vector... + if (mvAbs >= 0) + { + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // update mode table for this data point + // indicating that a mode has been associated + // with it + modeTable[i] = 1; + } + + // associate the data point indexed by + // the point list with the mode stored + // by yk + for (j = 0; j < pointCount; j++) + { + // obtain the point location from the + // point list + modeCandidate_i = pointList[j]; + + // update the mode table for this point + modeTable[modeCandidate_i] = 1; + + //store result into msRawData... + for(k = 0; k < N; k++) + msRawData[N*modeCandidate_i+k] = (float)(yk[k+2]); + } + + + //store result into msRawData... + for(j = 0; j < N; j++) + msRawData[N*i+j] = (float)(yk[j+2]); + + // Prompt user on progress +#ifdef SHOW_PROGRESS + percent_complete = (float)(i/(float)(L))*100; + msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); +#endif + + // Check to see if the algorithm has been halted + if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) + break; + + } + + // Prompt user that filtering is completed +#ifdef PROMPT +#ifdef SHOW_PROGRESS + msSys.Prompt("\r"); +#endif + msSys.Prompt("done."); +#endif + + // de-allocate memory + delete [] modeCandidatePoint; + delete [] yk; + delete [] Mh; + + // done. + return; + +} + + /*/\/\/\/\/\/\/\/\/\/\/\*/ + /* Image Classification */ + /*\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Connect */ +/*******************************************************/ +/*Classifies the regions of the mean shift filtered */ +/*image. */ +/*******************************************************/ +/*Post: */ +/* - the regions of the mean shift image have been*/ +/* classified using the private classification */ +/* structure of the msImageProcessor Class. */ +/* Namely, each region uniquely identified by */ +/* its LUV color (stored by LUV_data) and loc- */ +/* ation has been labeled and its area computed */ +/* via an eight-connected fill. */ +/*******************************************************/ + +void msImageProcessor::Connect( void ) +{ + + //define eight connected neighbors + neigh[0] = 1; + neigh[1] = 1-width; + neigh[2] = -width; + neigh[3] = -(1+width); + neigh[4] = -1; + neigh[5] = width-1; + neigh[6] = width; + neigh[7] = width+1; + + //initialize labels and modePointCounts + int i; + for(i = 0; i < width*height; i++) + { + labels[i] = -1; + modePointCounts[i] = 0; + } + + //Traverse the image labeling each new region encountered + int k, label = -1; + for(i = 0; i < height*width; i++) + { + //if this region has not yet been labeled - label it + if(labels[i] < 0) + { + //assign new label to this region + labels[i] = ++label; + + //copy region color into modes + for(k = 0; k < N; k++) + modes[(N*label)+k] = LUV_data[(N*i)+k]; +// modes[(N*label)+k] = (float)(LUV_data[(N*i)+k]); + + //populate labels with label for this specified region + //calculating modePointCounts[label]... + Fill(i, label); + } + } + + //calculate region count using label + regionCount = label+1; + + //done. + return; +} + +/*******************************************************/ +/*Fill */ +/*******************************************************/ +/*Given a region seed and a region label, Fill uses */ +/*the region seed to perform an eight-connected fill */ +/*for the specified region, labeling all pixels con- */ +/*tained by the region with the specified label: */ +/*label. */ +/*******************************************************/ +/*Pre: */ +/* - regionLoc is a region seed - a pixel that is */ +/* identified as being part of the region */ +/* labled using the label, label. */ +/*Post: */ +/* - all pixels belonging to the region specified */ +/* by regionLoc (having the same integer LUV */ +/* value specified by LUV_data) are classified */ +/* as one region by labeling each pixel in the */ +/* image clasification structure using label */ +/* via an eight-connected fill. */ +/*******************************************************/ + +void msImageProcessor::Fill(int regionLoc, int label) +{ + + //declare variables + int i, k, neighLoc, neighborsFound, imageSize = width*height; + + //Fill region starting at region location + //using labels... + + //initialzie indexTable + int index = 0; + indexTable[0] = regionLoc; + + //increment mode point counts for this region to + //indicate that one pixel belongs to this region + modePointCounts[label]++; + + while(true) + { + + //assume no neighbors will be found + neighborsFound = 0; + + //check the eight connected neighbors at regionLoc - + //if a pixel has similar color to that located at + //regionLoc then declare it as part of this region + for(i = 0; i < 8; i++) + { + // no need + /* + //if at boundary do not check certain neighbors because + //they do not exist... + if((regionLoc%width == 0)&&((i == 3)||(i == 4)||(i == 5))) + continue; + if((regionLoc%(width-1) == 0)&&((i == 0)||(i == 1)||(i == 7))) + continue; + */ + + //check bounds and if neighbor has been already labeled + neighLoc = regionLoc + neigh[i]; + if((neighLoc >= 0)&&(neighLoc < imageSize)&&(labels[neighLoc] < 0)) + { + for(k = 0; k < N; k++) + { +// if(LUV_data[(regionLoc*N)+k] != LUV_data[(neighLoc*N)+k]) + if (fabs(LUV_data[(regionLoc*N)+k]-LUV_data[(neighLoc*N)+k])>=LUV_treshold) + break; + } + + //neighbor i belongs to this region so label it and + //place it onto the index table buffer for further + //processing + if(k == N) + { + //assign label to neighbor i + labels[neighLoc] = label; + + //increment region point count + modePointCounts[label]++; + + //place index of neighbor i onto the index tabel buffer + indexTable[++index] = neighLoc; + + //indicate that a neighboring region pixel was + //identified + neighborsFound = 1; + } + } + } + + //check the indexTable to see if there are any more + //entries to be explored - if so explore them, otherwise + //exit the loop - we are finished + if(neighborsFound) + regionLoc = indexTable[index]; + else if (index > 1) + regionLoc = indexTable[--index]; + else + break; //fill complete + } + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\*/ + /* Image Pruning */ + /*\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Build Region Adjacency Matrix */ +/*******************************************************/ +/*Constructs a region adjacency matrix. */ +/*******************************************************/ +/*Pre: */ +/* - the classification data structure has been */ +/* constructed. */ +/*Post: */ +/* - a region adjacency matrix has been built */ +/* using the classification data structure. */ +/*******************************************************/ + +void msImageProcessor::BuildRAM( void ) +{ + + //Allocate memory for region adjacency matrix if it hasn't already been allocated + if((!raList)&&((!(raList = new RAList [regionCount]))||(!(raPool = new RAList [NODE_MULTIPLE*regionCount])))) + { + ErrorHandler("msImageProcessor", "Allocate", "Not enough memory."); + return; + } + + //initialize the region adjacency list + int i; + for(i = 0; i < regionCount; i++) + { + raList[i].edgeStrength = 0; + raList[i].edgePixelCount = 0; + raList[i].label = i; + raList[i].next = NULL; + } + + //initialize RAM free list + freeRAList = raPool; + for(i = 0; i < NODE_MULTIPLE*regionCount-1; i++) + { + raPool[i].edgeStrength = 0; + raPool[i].edgePixelCount = 0; + raPool[i].next = &raPool[i+1]; + } + raPool[NODE_MULTIPLE*regionCount-1].next = NULL; + + //traverse the labeled image building + //the RAM by looking to the right of + //and below the current pixel location thus + //determining if a given region is adjacent + //to another + int j, curLabel, rightLabel, bottomLabel, exists; + RAList *raNode1, *raNode2, *oldRAFreeList; + for(i = 0; i < height - 1; i++) + { + //check the right and below neighbors + //for pixel locations whose x < width - 1 + for(j = 0; j < width - 1; j++) + { + //calculate pixel labels + curLabel = labels[i*width+j ]; //current pixel + rightLabel = labels[i*width+j+1 ]; //right pixel + bottomLabel = labels[(i+1)*width+j]; //bottom pixel + + //check to the right, if the label of + //the right pixel is not the same as that + //of the current one then region[j] and region[j+1] + //are adjacent to one another - update the RAM + if(curLabel != rightLabel) + { + //obtain RAList object from region adjacency free + //list + raNode1 = freeRAList; + raNode2 = freeRAList->next; + + //keep a pointer to the old region adj. free + //list just in case nodes already exist in respective + //region lists + oldRAFreeList = freeRAList; + + //update region adjacency free list + freeRAList = freeRAList->next->next; + + //populate RAList nodes + raNode1->label = curLabel; + raNode2->label = rightLabel; + + //insert nodes into the RAM + exists = 0; + raList[curLabel ].Insert(raNode2); + exists = raList[rightLabel].Insert(raNode1); + + //if the node already exists then place + //nodes back onto the region adjacency + //free list + if(exists) + freeRAList = oldRAFreeList; + + } + + //check below, if the label of + //the bottom pixel is not the same as that + //of the current one then region[j] and region[j+width] + //are adjacent to one another - update the RAM + if(curLabel != bottomLabel) + { + //obtain RAList object from region adjacency free + //list + raNode1 = freeRAList; + raNode2 = freeRAList->next; + + //keep a pointer to the old region adj. free + //list just in case nodes already exist in respective + //region lists + oldRAFreeList = freeRAList; + + //update region adjacency free list + freeRAList = freeRAList->next->next; + + //populate RAList nodes + raNode1->label = curLabel; + raNode2->label = bottomLabel; + + //insert nodes into the RAM + exists = 0; + raList[curLabel ].Insert(raNode2); + exists = raList[bottomLabel].Insert(raNode1); + + //if the node already exists then place + //nodes back onto the region adjacency + //free list + if(exists) + freeRAList = oldRAFreeList; + + } + + } + + //check only to the bottom neighbors of the right boundary + //pixels... + + //calculate pixel locations (j = width-1) + curLabel = labels[i*width+j ]; //current pixel + bottomLabel = labels[(i+1)*width+j]; //bottom pixel + + //check below, if the label of + //the bottom pixel is not the same as that + //of the current one then region[j] and region[j+width] + //are adjacent to one another - update the RAM + if(curLabel != bottomLabel) + { + //obtain RAList object from region adjacency free + //list + raNode1 = freeRAList; + raNode2 = freeRAList->next; + + //keep a pointer to the old region adj. free + //list just in case nodes already exist in respective + //region lists + oldRAFreeList = freeRAList; + + //update region adjacency free list + freeRAList = freeRAList->next->next; + + //populate RAList nodes + raNode1->label = curLabel; + raNode2->label = bottomLabel; + + //insert nodes into the RAM + exists = 0; + raList[curLabel ].Insert(raNode2); + exists = raList[bottomLabel].Insert(raNode1); + + //if the node already exists then place + //nodes back onto the region adjacency + //free list + if(exists) + freeRAList = oldRAFreeList; + + } + } + + //check only to the right neighbors of the bottom boundary + //pixels... + + //check the right for pixel locations whose x < width - 1 + for(j = 0; j < width - 1; j++) + { + //calculate pixel labels (i = height-1) + curLabel = labels[i*width+j ]; //current pixel + rightLabel = labels[i*width+j+1 ]; //right pixel + + //check to the right, if the label of + //the right pixel is not the same as that + //of the current one then region[j] and region[j+1] + //are adjacent to one another - update the RAM + if(curLabel != rightLabel) + { + //obtain RAList object from region adjacency free + //list + raNode1 = freeRAList; + raNode2 = freeRAList->next; + + //keep a pointer to the old region adj. free + //list just in case nodes already exist in respective + //region lists + oldRAFreeList = freeRAList; + + //update region adjacency free list + freeRAList = freeRAList->next->next; + + //populate RAList nodes + raNode1->label = curLabel; + raNode2->label = rightLabel; + + //insert nodes into the RAM + exists = 0; + raList[curLabel ].Insert(raNode2); + exists = raList[rightLabel].Insert(raNode1); + + //if the node already exists then place + //nodes back onto the region adjacency + //free list + if(exists) + freeRAList = oldRAFreeList; + + } + + } + + //done. + return; + +} + +/*******************************************************/ +/*Destroy Region Adjacency Matrix */ +/*******************************************************/ +/*Destroy a region adjacency matrix. */ +/*******************************************************/ +/*Post: */ +/* - the region adjacency matrix has been destr- */ +/* oyed: (1) its memory has been de-allocated, */ +/* (2) the RAM structure has been initialize */ +/* for re-use. */ +/*******************************************************/ + +void msImageProcessor::DestroyRAM( void ) +{ + + //de-allocate memory for region adjaceny list + if (raList) delete [] raList; + if (raPool) delete [] raPool; + + //initialize region adjacency matrix + raList = NULL; + freeRAList = NULL; + raPool = NULL; + + //done. + return; + +} + +/*******************************************************/ +/*Transitive Closure */ +/*******************************************************/ +/*Applies transitive closure to the RAM updating */ +/*labels, modes and modePointCounts to reflect the new */ +/*set of merged regions resulting from transitive clo- */ +/*sure. */ +/*******************************************************/ +/*Post: */ +/* - transitive closure has been applied to the */ +/* regions classified by the RAM and labels, */ +/* modes and modePointCounts have been updated */ +/* to reflect the new set of mergd regions res- */ +/* ulting from transitive closure. */ +/*******************************************************/ + +void msImageProcessor::TransitiveClosure( void ) +{ + + //Step (1): + + // Build RAM using classifiction structure originally + // generated by the method GridTable::Connect() + BuildRAM(); + + //Step (1a): + //Compute weights of weight graph using confidence map + //(if defined) + if(weightMapDefined) ComputeEdgeStrengths(); + + //Step (2): + + //Treat each region Ri as a disjoint set: + + // - attempt to join Ri and Rj for all i != j that are neighbors and + // whose associated modes are a normalized distance of < 0.5 from one + // another + + // - the label of each region in the raList is treated as a pointer to the + // canonical element of that region (e.g. raList[i], initially has raList[i].label = i, + // namely each region is initialized to have itself as its canonical element). + + //Traverse RAM attempting to join raList[i] with its neighbors... + int i, iCanEl, neighCanEl; + float threshold; + RAList *neighbor; + for(i = 0; i < regionCount; i++) + { + //aquire first neighbor in region adjacency list pointed to + //by raList[i] + neighbor = raList[i].next; + + //compute edge strenght threshold using global and local + //epsilon + if(epsilon > raList[i].edgeStrength) + threshold = epsilon; + else + threshold = raList[i].edgeStrength; + + //traverse region adjacency list of region i, attempting to join + //it with regions whose mode is a normalized distance < 0.5 from + //that of region i... + while(neighbor) + { + //attempt to join region and neighbor... + if((InWindow(i, neighbor->label))&&(neighbor->edgeStrength < epsilon)) + { + //region i and neighbor belong together so join them + //by: + + // (1) find the canonical element of region i + iCanEl = i; + while(raList[iCanEl].label != iCanEl) + iCanEl = raList[iCanEl].label; + + // (2) find the canonical element of neighboring region + neighCanEl = neighbor->label; + while(raList[neighCanEl].label != neighCanEl) + neighCanEl = raList[neighCanEl].label; + + // if the canonical elements of are not the same then assign + // the canonical element having the smaller label to be the parent + // of the other region... + if(iCanEl < neighCanEl) + raList[neighCanEl].label = iCanEl; + else + { + //must replace the canonical element of previous + //parent as well + raList[raList[iCanEl].label].label = neighCanEl; + + //re-assign canonical element + raList[iCanEl].label = neighCanEl; + } + } + + //check the next neighbor... + neighbor = neighbor->next; + + } + } + + // Step (3): + + // Level binary trees formed by canonical elements + for(i = 0; i < regionCount; i++) + { + iCanEl = i; + while(raList[iCanEl].label != iCanEl) + iCanEl = raList[iCanEl].label; + raList[i].label = iCanEl; + } + + // Step (4): + + //Traverse joint sets, relabeling image. + + // (a) + + // Accumulate modes and re-compute point counts using canonical + // elements generated by step 2. + + //allocate memory for mode and point count temporary buffers... + float *modes_buffer = new float [N*regionCount]; + int *MPC_buffer = new int [regionCount]; + + //initialize buffers to zero + for(i = 0; i < regionCount; i++) + MPC_buffer[i] = 0; + for(i = 0; i < N*regionCount; i++) + modes_buffer[i] = 0; + + //traverse raList accumulating modes and point counts + //using canoncial element information... + int k, iMPC; + for(i = 0; i < regionCount; i++) + { + + //obtain canonical element of region i + iCanEl = raList[i].label; + + //obtain mode point count of region i + iMPC = modePointCounts[i]; + + //accumulate modes_buffer[iCanEl] + for(k = 0; k < N; k++) + modes_buffer[(N*iCanEl)+k] += iMPC*modes[(N*i)+k]; + + //accumulate MPC_buffer[iCanEl] + MPC_buffer[iCanEl] += iMPC; + + } + + // (b) + + // Re-label new regions of the image using the canonical + // element information generated by step (2) + + // Also use this information to compute the modes of the newly + // defined regions, and to assign new region point counts in + // a consecute manner to the modePointCounts array + + //allocate memory for label buffer + int *label_buffer = new int [regionCount]; + + //initialize label buffer to -1 + for(i = 0; i < regionCount; i++) + label_buffer[i] = -1; + + //traverse raList re-labeling the regions + int label = -1; + for(i = 0; i < regionCount; i++) + { + //obtain canonical element of region i + iCanEl = raList[i].label; + if(label_buffer[iCanEl] < 0) + { + //assign a label to the new region indicated by canonical + //element of i + label_buffer[iCanEl] = ++label; + + //recompute mode storing the result in modes[label]... + iMPC = MPC_buffer[iCanEl]; + for(k = 0; k < N; k++) + modes[(N*label)+k] = (modes_buffer[(N*iCanEl)+k])/(iMPC); + + //assign a corresponding mode point count for this region into + //the mode point counts array using the MPC buffer... + modePointCounts[label] = MPC_buffer[iCanEl]; + } + } + + //re-assign region count using label counter + int oldRegionCount = regionCount; + regionCount = label+1; + + // (c) + + // Use the label buffer to reconstruct the label map, which specified + // the new image given its new regions calculated above + + for(i = 0; i < height*width; i++) + labels[i] = label_buffer[raList[labels[i]].label]; + + //de-allocate memory + delete [] modes_buffer; + delete [] MPC_buffer; + delete [] label_buffer; + + //done. + return; + +} + +/*******************************************************/ +/*Compute Edge Strengths */ +/*******************************************************/ +/*Computes the a weight for each link in the region */ +/*graph maintined by the RAM, resulting in a weighted */ +/*graph in which the weights consist of a confidence */ +/*between zero and one indicating if the regions are */ +/*separated by a strong or weak edge. */ +/*******************************************************/ +/*Post: */ +/* - an edge strength has been computed between */ +/* each region of the image and placed as a */ +/* weight in the RAM to be used during transi- */ +/* tive closure. */ +/*******************************************************/ + +void msImageProcessor::ComputeEdgeStrengths( void ) +{ + + //initialize visit table - used to keep track + //of which pixels have already been visited such + //as not to contribute their strength value to + //a boundary sum multiple times... + memset(visitTable, 0, L*sizeof(unsigned char)); + + //traverse labeled image computing edge strengths + //(excluding image boundary)... + int x, y, dp, curLabel, rightLabel, bottomLabel; + RAList *curRegion; + for(y = 1; y < height-1; y++) + { + for(x = 1; x < width-1; x++) + { + //compute data point location using x and y + dp = y*width + x; + + //obtain labels at different pixel locations + curLabel = labels[dp ]; //current pixel + rightLabel = labels[dp+1 ]; //right pixel + bottomLabel = labels[dp+width]; //bottom pixel + + //check right and bottom neighbor to see if there is a + //change in label then we are at an edge therefore record + //the edge strength at this edge accumulating its value + //in the RAM... + if(curLabel != rightLabel) + { + //traverse into RAM... + curRegion = &raList[curLabel]; + while((curRegion)&&(curRegion->label != rightLabel)) + curRegion = curRegion->next; + + //this should not occur... + assert(curRegion); + + //accumulate edge strength + curRegion->edgeStrength += weightMap[dp] + weightMap[dp+1]; + curRegion->edgePixelCount += 2; + } + + if(curLabel != bottomLabel) + { + //traverse into RAM... + curRegion = &raList[curLabel]; + while((curRegion)&&(curRegion->label != bottomLabel)) + curRegion = curRegion->next; + + //this should not occur... + assert(curRegion); + + //accumulate edge strength + if(curLabel == rightLabel) + { + curRegion->edgeStrength += weightMap[dp] + weightMap[dp+width]; + curRegion->edgePixelCount += 2; + } + else + { + curRegion->edgeStrength += weightMap[dp+width]; + curRegion->edgePixelCount += 1; + } + + } + } + } + + //compute strengths using accumulated strengths obtained above... + RAList *neighborRegion; + float edgeStrength; + int edgePixelCount; + for(x = 0; x < regionCount; x++) + { + //traverse the region list of the current region + curRegion = &raList[x]; + curRegion = curRegion->next; + while(curRegion) + { + //with the assumption that regions having a smaller + //label in the current region list have already + //had their edge strengths computed, only compute + //edge strengths for the regions whose label is greater + //than x, the current region (region list) under + //consideration... + curLabel = curRegion->label; + if(curLabel > x) + { + //obtain pointer to the element identifying the + //current region in the neighbors region list... + neighborRegion = &raList[curLabel]; + while((neighborRegion)&&(neighborRegion->label != x)) + neighborRegion = neighborRegion->next; + + //this should not occur... + assert(neighborRegion); + + //compute edge strengths using accumulated confidence + //value and pixel count + if((edgePixelCount = curRegion->edgePixelCount + neighborRegion->edgePixelCount) != 0) + { + //compute edge strength + edgeStrength = curRegion->edgeStrength + neighborRegion->edgeStrength; + edgeStrength /= edgePixelCount; + + //store edge strength and pixel count for corresponding regions + curRegion->edgeStrength = neighborRegion->edgeStrength = edgeStrength; + curRegion->edgePixelCount = neighborRegion->edgePixelCount = edgePixelCount; + } + } + + //traverse to the next region in the region adjacency list + //of the current region x + curRegion = curRegion->next; + + } + } + + //compute average edge strength amongst the edges connecting + //it to each of its neighbors + int numNeighbors; + for(x = 0; x < regionCount; x++) + { + //traverse the region list of the current region + //accumulating weights + curRegion = &raList[x]; + curRegion = curRegion->next; + edgeStrength = 0; + numNeighbors = 0; + while(curRegion) + { + numNeighbors++; + edgeStrength += curRegion->edgeStrength; + curRegion = curRegion->next; + } + + //divide by the number of regions connected + //to the current region + if(numNeighbors) edgeStrength /= numNeighbors; + + //store the result in the raList for region + //x + raList[x].edgeStrength = edgeStrength; + } + + //traverse raList and output the resulting list + //to a file + + //done. + return; + +} + +/*******************************************************/ +/*Prune */ +/*******************************************************/ +/*Prunes regions from the image whose pixel density */ +/*is less than a specified threshold. */ +/*******************************************************/ +/*Pre: */ +/* - minRegion is the minimum allowable pixel de- */ +/* nsity a region may have without being pruned */ +/* from the image */ +/*Post: */ +/* - regions whose pixel density is less than */ +/* or equal to minRegion have been pruned from */ +/* the image. */ +/*******************************************************/ + +void msImageProcessor::Prune(int minRegion) +{ + + //Allocate Memory for temporary buffers... + + //allocate memory for mode and point count temporary buffers... + float *modes_buffer = new float [N*regionCount]; + int *MPC_buffer = new int [regionCount]; + + //allocate memory for label buffer + int *label_buffer = new int [regionCount]; + + //Declare variables + int i, k, candidate, iCanEl, neighCanEl, iMPC, label, oldRegionCount, minRegionCount; + double minSqDistance, neighborDistance; + RAList *neighbor; + + //Apply pruning algorithm to classification structure, removing all regions whose area + //is under the threshold area minRegion (pixels) + do + { + //Assume that no region has area under threshold area of + minRegionCount = 0; + + //Step (1): + + // Build RAM using classifiction structure originally + // generated by the method GridTable::Connect() + BuildRAM(); + + // Step (2): + + // Traverse the RAM joining regions whose area is less than minRegion (pixels) + // with its respective candidate region. + + // A candidate region is a region that displays the following properties: + + // - it is adjacent to the region being pruned + + // - the distance of its mode is a minimum to that of the region being pruned + // such that or it is the only adjacent region having an area greater than + // minRegion + + for(i = 0; i < regionCount; i++) + { + //if the area of the ith region is less than minRegion + //join it with its candidate region... + + //******************************************************************************* + + //Note: Adjust this if statement if a more sophisticated pruning criterion + // is desired. Basically in this step a region whose area is less than + // minRegion is pruned by joining it with its "closest" neighbor (in color). + // Therefore, by placing a different criterion for fusing a region the + // pruning method may be altered to implement a more sophisticated algorithm. + + //******************************************************************************* + + if(modePointCounts[i] < minRegion) + { + //update minRegionCount to indicate that a region + //having area less than minRegion was found + minRegionCount++; + + //obtain a pointer to the first region in the + //region adjacency list of the ith region... + neighbor = raList[i].next; + + //calculate the distance between the mode of the ith + //region and that of the neighboring region... + candidate = neighbor->label; + minSqDistance = SqDistance(i, candidate); + + //traverse region adjacency list of region i and select + //a candidate region + neighbor = neighbor->next; + while(neighbor) + { + + //calculate the square distance between region i + //and current neighbor... + neighborDistance = SqDistance(i, neighbor->label); + + //if this neighbors square distance to region i is less + //than minSqDistance, then select this neighbor as the + //candidate region for region i + if(neighborDistance < minSqDistance) + { + minSqDistance = neighborDistance; + candidate = neighbor->label; + } + + //traverse region list of region i + neighbor = neighbor->next; + + } + + //join region i with its candidate region: + + // (1) find the canonical element of region i + iCanEl = i; + while(raList[iCanEl].label != iCanEl) + iCanEl = raList[iCanEl].label; + + // (2) find the canonical element of neighboring region + neighCanEl = candidate; + while(raList[neighCanEl].label != neighCanEl) + neighCanEl = raList[neighCanEl].label; + + // if the canonical elements of are not the same then assign + // the canonical element having the smaller label to be the parent + // of the other region... + if(iCanEl < neighCanEl) + raList[neighCanEl].label = iCanEl; + else + { + //must replace the canonical element of previous + //parent as well + raList[raList[iCanEl].label].label = neighCanEl; + + //re-assign canonical element + raList[iCanEl].label = neighCanEl; + } + } + } + + // Step (3): + + // Level binary trees formed by canonical elements + for(i = 0; i < regionCount; i++) + { + iCanEl = i; + while(raList[iCanEl].label != iCanEl) + iCanEl = raList[iCanEl].label; + raList[i].label = iCanEl; + } + + // Step (4): + + //Traverse joint sets, relabeling image. + + // Accumulate modes and re-compute point counts using canonical + // elements generated by step 2. + + //initialize buffers to zero + for(i = 0; i < regionCount; i++) + MPC_buffer[i] = 0; + for(i = 0; i < N*regionCount; i++) + modes_buffer[i] = 0; + + //traverse raList accumulating modes and point counts + //using canoncial element information... + for(i = 0; i < regionCount; i++) + { + + //obtain canonical element of region i + iCanEl = raList[i].label; + + //obtain mode point count of region i + iMPC = modePointCounts[i]; + + //accumulate modes_buffer[iCanEl] + for(k = 0; k < N; k++) + modes_buffer[(N*iCanEl)+k] += iMPC*modes[(N*i)+k]; + + //accumulate MPC_buffer[iCanEl] + MPC_buffer[iCanEl] += iMPC; + + } + + // (b) + + // Re-label new regions of the image using the canonical + // element information generated by step (2) + + // Also use this information to compute the modes of the newly + // defined regions, and to assign new region point counts in + // a consecute manner to the modePointCounts array + + //initialize label buffer to -1 + for(i = 0; i < regionCount; i++) + label_buffer[i] = -1; + + //traverse raList re-labeling the regions + label = -1; + for(i = 0; i < regionCount; i++) + { + //obtain canonical element of region i + iCanEl = raList[i].label; + if(label_buffer[iCanEl] < 0) + { + //assign a label to the new region indicated by canonical + //element of i + label_buffer[iCanEl] = ++label; + + //recompute mode storing the result in modes[label]... + iMPC = MPC_buffer[iCanEl]; + for(k = 0; k < N; k++) + modes[(N*label)+k] = (modes_buffer[(N*iCanEl)+k])/(iMPC); + + //assign a corresponding mode point count for this region into + //the mode point counts array using the MPC buffer... + modePointCounts[label] = MPC_buffer[iCanEl]; + } + } + + //re-assign region count using label counter + oldRegionCount = regionCount; + regionCount = label+1; + + // (c) + + // Use the label buffer to reconstruct the label map, which specified + // the new image given its new regions calculated above + + for(i = 0; i < height*width; i++) + labels[i] = label_buffer[raList[labels[i]].label]; + + + } while(minRegionCount > 0); + + //de-allocate memory + delete [] modes_buffer; + delete [] MPC_buffer; + delete [] label_buffer; + + //done. + return; + +} + +/*******************************************************/ +/*Define Boundaries */ +/*******************************************************/ +/*Defines the boundaries for each region of the segm- */ +/*ented image storing the result into a region list */ +/*object. */ +/*******************************************************/ +/*Pre: */ +/* - the image has been segmented and a classifi- */ +/* cation structure has been created for this */ +/* image */ +/*Post: */ +/* - the boundaries of the segmented image have */ +/* been defined and the boundaries of each reg- */ +/* ion has been stored into a region list obj- */ +/* ect. */ +/*******************************************************/ + +void msImageProcessor::DefineBoundaries( void ) +{ + + //declare and allocate memory for boundary map and count + int *boundaryMap, *boundaryCount; + if((!(boundaryMap = new int [L]))||(!(boundaryCount = new int [regionCount]))) + ErrorHandler("msImageProcessor", "DefineBoundaries", "Not enough memory."); + + //initialize boundary map and count + int i; + for(i = 0; i < L; i++) + boundaryMap[i] = -1; + for(i = 0; i < regionCount; i++) + boundaryCount[i] = 0; + + //initialize and declare total boundary count - + //the total number of boundary pixels present in + //the segmented image + int totalBoundaryCount = 0; + + //traverse the image checking the right and bottom + //four connected neighbors of each pixel marking + //boundary map with the boundaries of each region and + //incrementing boundaryCount using the label information + + //*********************************************************************** + //*********************************************************************** + + int j, label, dataPoint; + + //first row (every pixel is a boundary pixel) + for(i = 0; i < width; i++) + { + boundaryMap[i] = label = labels[i]; + boundaryCount[label]++; + totalBoundaryCount++; + } + + //define boundaries for all rows except for the first + //and last one... + for(i = 1; i < height - 1; i++) + { + //mark the first pixel in an image row as an image boundary... + dataPoint = i*width; + boundaryMap[dataPoint] = label = labels[dataPoint]; + boundaryCount[label]++; + totalBoundaryCount++; + + for(j = 1; j < width - 1; j++) + { + //define datapoint and its right and bottom + //four connected neighbors + dataPoint = i*width+j; + + //check four connected neighbors if they are + //different this pixel is a boundary pixel + label = labels[dataPoint]; + if((label != labels[dataPoint-1]) ||(label != labels[dataPoint+1])|| + (label != labels[dataPoint-width])||(label != labels[dataPoint+width])) + { + boundaryMap[dataPoint] = label = labels[dataPoint]; + boundaryCount[label]++; + totalBoundaryCount++; + } + } + + //mark the last pixel in an image row as an image boundary... + dataPoint = (i+1)*width-1; + boundaryMap[dataPoint] = label = labels[dataPoint]; + boundaryCount[label]++; + totalBoundaryCount++; + + } + + //last row (every pixel is a boundary pixel) (i = height-1) + register int start = (height-1)*width, stop = height*width; + for(i = start; i < stop; i++) + { + boundaryMap[i] = label = labels[i]; + boundaryCount[label]++; + totalBoundaryCount++; + } + + //*********************************************************************** + //*********************************************************************** + + //store boundary locations into a boundary buffer using + //boundary map and count + + //*********************************************************************** + //*********************************************************************** + + int *boundaryBuffer = new int [totalBoundaryCount], *boundaryIndex = new int [regionCount]; + + //use boundary count to initialize boundary index... + int counter = 0; + for(i = 0; i < regionCount; i++) + { + boundaryIndex[i] = counter; + counter += boundaryCount[i]; + } + + //traverse boundary map placing the boundary pixel + //locations into the boundaryBuffer + for(i = 0; i < L; i++) + { + //if its a boundary pixel store it into + //the boundary buffer + if((label = boundaryMap[i]) >= 0) + { + boundaryBuffer[boundaryIndex[label]] = i; + boundaryIndex[label]++; + } + } + + //*********************************************************************** + //*********************************************************************** + + //store the boundary locations stored by boundaryBuffer into + //the region list for each region + + //*********************************************************************** + //*********************************************************************** + + //destroy the old region list + if(regionList) delete regionList; + + //create a new region list + if(!(regionList = new RegionList(regionCount, totalBoundaryCount, N))) + ErrorHandler("msImageProcessor", "DefineBoundaries", "Not enough memory."); + + //add boundary locations for each region using the boundary + //buffer and boundary counts + counter = 0; + for(i = 0; i < regionCount; i++) + { + regionList->AddRegion(i, boundaryCount[i], &boundaryBuffer[counter]); + counter += boundaryCount[i]; + } + + //*********************************************************************** + //*********************************************************************** + + // dealocate local used memory + delete [] boundaryMap; + delete [] boundaryCount; + delete [] boundaryBuffer; + delete [] boundaryIndex; + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Image Data Searching/Distance Calculation */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*In Window */ +/*******************************************************/ +/*Returns true if the two specified data points are */ +/*within rR of each other. */ +/*******************************************************/ +/*Pre: */ +/* - mode1 and mode2 are indeces into msRawData */ +/* specifying the modes of the pixels having */ +/* these indeces. */ +/*Post: */ +/* - true is returned if mode1 and mode2 are wi- */ +/* thin rR of one another, false is returned */ +/* otherwise. */ +/*******************************************************/ + +bool msImageProcessor::InWindow(int mode1, int mode2) +{ + int k = 1, s = 0, p; + double diff = 0, el; + while((diff < 0.25)&&(k != kp)) // Partial Distortion Search + { + //Calculate distance squared of sub-space s + diff = 0; + for(p = 0; p < P[k]; p++) + { + el = (modes[mode1*N+p+s]-modes[mode2*N+p+s])/(h[k]*offset[k]); + if((!p)&&(k == 1)&&(modes[mode1*N] > 80)) + diff += 4*el*el; + else + diff += el*el; + } + + //next subspace + s += P[k]; + k++; + } + return (bool)(diff < 0.25); +} + +/*******************************************************/ +/*Square Distance */ +/*******************************************************/ +/*Computs the normalized square distance between two */ +/*modes. */ +/*******************************************************/ +/*Pre: */ +/* - mode1 and mode2 are indeces into the modes */ +/* array specifying two modes of the image */ +/*Post: */ +/* - the normalized square distance between modes */ +/* indexed by mode1 and mode2 has been calc- */ +/* ulated and the result has been returned. */ +/*******************************************************/ + +float msImageProcessor::SqDistance(int mode1, int mode2) +{ + + int k = 1, s = 0, p; + float dist = 0, el; + for(k = 1; k < kp; k++) + { + //Calculate distance squared of sub-space s + for(p = 0; p < P[k]; p++) + { + el = (modes[mode1*N+p+s]-modes[mode2*N+p+s])/(h[k]*offset[k]); + dist += el*el; + } + + //next subspace + s += P[k]; + k++; + } + + //return normalized square distance between modes + //1 and 2 + return dist; + +} + + /*/\/\/\/\/\/\/\/\/\/\*/ + /* Memory Management */ + /*\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Initialize Output */ +/*******************************************************/ +/*Allocates memory needed by the mean shift image pro- */ +/*cessor class output storage data structure. */ +/*******************************************************/ +/*Post: */ +/* - the memory needed by the output storage */ +/* structure of this class has been (re-)allo- */ +/* cated. */ +/*******************************************************/ + +void msImageProcessor::InitializeOutput( void ) +{ + + //De-allocate memory if output was defined for previous image + DestroyOutput(); + + //Allocate memory for msRawData (filtered image output) + if(!(msRawData = new float [L*N])) + { + ErrorHandler("msImageProcessor", "Allocate", "Not enough memory."); + return; + } + + //Allocate memory used to store image modes and their corresponding regions... + if((!(modes = new float [L*(N+2)]))||(!(labels = new int [L]))||(!(modePointCounts = new int [L]))||(!(indexTable = new int [L]))) + { + ErrorHandler("msImageProcessor", "Allocate", "Not enough memory"); + return; + } + + //Allocate memory for integer modes used to perform connected components + //(image labeling)... +// if(!(LUV_data = new int [N*L])) + if (!(LUV_data = new float[N*L])) + { + ErrorHandler("msImageProcessor", "Allocate", "Not enough memory"); + return; + } + + //indicate that the class output storage structure has been defined + class_state.OUTPUT_DEFINED = true; + +} + +/*******************************************************/ +/*Destroy Output */ +/*******************************************************/ +/*De-allocates memory needed by the mean shift image */ +/*processor class output storage data structure. */ +/*******************************************************/ +/*Post: */ +/* - the memory needed by the output storage */ +/* structure of this class has been de-alloc- */ +/* ated. */ +/* - the output storage structure has been init- */ +/* ialized for re-use. */ +/*******************************************************/ + +void msImageProcessor::DestroyOutput( void ) +{ + + //de-allocate memory for msRawData (filtered image output) + if (msRawData) delete [] msRawData; + + //de-allocate memory used by output storage and image + //classification structure + if (modes) delete [] modes; + if (labels) delete [] labels; + if (modePointCounts) delete [] modePointCounts; + if (indexTable) delete [] indexTable; + + //de-allocate memory for LUV_data + if (LUV_data) delete [] LUV_data; + + //initialize data members for re-use... + + //initialize output structures... + msRawData = NULL; + + //re-initialize classification structure + modes = NULL; + labels = NULL; + modePointCounts = NULL; + regionCount = 0; + + //indicate that the output has been destroyed + class_state.OUTPUT_DEFINED = false; + + //done. + return; + +} + +// NEW +void msImageProcessor::NewOptimizedFilter1(float sigmaS, float sigmaR) +{ + // Declare Variables + int iterationCount, i, j, k, modeCandidateX, modeCandidateY, modeCandidate_i; + double mvAbs, diff, el; + + //make sure that a lattice height and width have + //been defined... + if(!height) + { + ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); + return; + } + + //re-assign bandwidths to sigmaS and sigmaR + if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) + { + ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); + return; + } + + //define input data dimension with lattice + int lN = N + 2; + + // Traverse each data point applying mean shift + // to each data point + + // Allcocate memory for yk + double *yk = new double [lN]; + + // Allocate memory for Mh + double *Mh = new double [lN]; + + // let's use some temporary data + float* sdata; + sdata = new float[lN*L]; + + // copy the scaled data + int idxs, idxd; + idxs = idxd = 0; + if (N==3) + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i/width)/sigmaS; + sdata[idxs++] = data[idxd++]/sigmaR; + sdata[idxs++] = data[idxd++]/sigmaR; + sdata[idxs++] = data[idxd++]/sigmaR; + } + } else if (N==1) + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i/width)/sigmaS; + sdata[idxs++] = data[idxd++]/sigmaR; + } + } else + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i/width)/sigmaS; + for (j=0; j<N; j++) + sdata[idxs++] = data[idxd++]/sigmaR; + } + } + // index the data in the 3d buckets (x, y, L) + int* buckets; + int* slist; + slist = new int[L]; + int bucNeigh[27]; + + float sMins; // just for L + float sMaxs[3]; // for all + sMaxs[0] = width/sigmaS; + sMaxs[1] = height/sigmaS; + sMins = sMaxs[2] = sdata[2]; + idxs = 2; + float cval; + for(i=0; i<L; i++) + { + cval = sdata[idxs]; + if (cval < sMins) + sMins = cval; + else if (cval > sMaxs[2]) + sMaxs[2] = cval; + + idxs += lN; + } + + int nBuck1, nBuck2, nBuck3; + int cBuck1, cBuck2, cBuck3, cBuck; + nBuck1 = (int) (sMaxs[0] + 3); + nBuck2 = (int) (sMaxs[1] + 3); + nBuck3 = (int) (sMaxs[2] - sMins + 3); + buckets = new int[nBuck1*nBuck2*nBuck3]; + for(i=0; i<(nBuck1*nBuck2*nBuck3); i++) + buckets[i] = -1; + + idxs = 0; + for(i=0; i<L; i++) + { + // find bucket for current data and add it to the list + cBuck1 = (int) sdata[idxs] + 1; + cBuck2 = (int) sdata[idxs+1] + 1; + cBuck3 = (int) (sdata[idxs+2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + + slist[i] = buckets[cBuck]; + buckets[cBuck] = i; + + idxs += lN; + } + // init bucNeigh + idxd = 0; + for (cBuck1=-1; cBuck1<=1; cBuck1++) + { + for (cBuck2=-1; cBuck2<=1; cBuck2++) + { + for (cBuck3=-1; cBuck3<=1; cBuck3++) + { + bucNeigh[idxd++] = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + } + } + } + double wsuml, weight; + double hiLTr = 80.0/sigmaR; + // done indexing/hashing + + + // Initialize mode table used for basin of attraction + memset(modeTable, 0, width*height); + + // proceed ... +#ifdef PROMPT + msSys.Prompt("done.\nApplying mean shift (Using Lattice) ... "); +#ifdef SHOW_PROGRESS + msSys.Prompt("\n 0%%"); +#endif +#endif + + + for(i = 0; i < L; i++) + { + // if a mode was already assigned to this data point + // then skip this point, otherwise proceed to + // find its mode by applying mean shift... + if (modeTable[i] == 1) + continue; + + // initialize point list... + pointCount = 0; + + // Assign window center (window centers are + // initialized by createLattice to be the point + // data[i]) + idxs = i*lN; + for (j=0; j<lN; j++) + yk[j] = sdata[idxs+j]; + + // Calculate the mean shift vector using the lattice + // LatticeMSVector(Mh, yk); // modify to new + /*****************************************************/ + // Initialize mean shift vector + for(j = 0; j < lN; j++) + Mh[j] = 0; + wsuml = 0; + // uniformLSearch(Mh, yk_ptr); // modify to new + // find bucket of yk + cBuck1 = (int) yk[0] + 1; + cBuck2 = (int) yk[1] + 1; + cBuck3 = (int) (yk[2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + for (j=0; j<27; j++) + { + idxd = buckets[cBuck+bucNeigh[j]]; + // list parse, crt point is cHeadList + while (idxd>=0) + { + idxs = lN*idxd; + // determine if inside search window + el = sdata[idxs+0]-yk[0]; + diff = el*el; + el = sdata[idxs+1]-yk[1]; + diff += el*el; + + if (diff < 1.0) + { + el = sdata[idxs+2]-yk[2]; + if (yk[2] > hiLTr) + diff = 4*el*el; + else + diff = el*el; + + if (N>1) + { + el = sdata[idxs+3]-yk[3]; + diff += el*el; + el = sdata[idxs+4]-yk[4]; + diff += el*el; + } + + if (diff < 1.0) + { + weight = 1-weightMap[idxd]; + for (k=0; k<lN; k++) + Mh[k] += weight*sdata[idxs+k]; + wsuml += weight; + } + } + idxd = slist[idxd]; + } + } + if (wsuml > 0) + { + for(j = 0; j < lN; j++) + Mh[j] = Mh[j]/wsuml - yk[j]; + } + else + { + for(j = 0; j < lN; j++) + Mh[j] = 0; + } + /*****************************************************/ + // Calculate its magnitude squared + //mvAbs = 0; + //for(j = 0; j < lN; j++) + // mvAbs += Mh[j]*Mh[j]; + mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; + if (N==3) + mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; + else + mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; + + + // Keep shifting window center until the magnitude squared of the + // mean shift vector calculated at the window center location is + // under a specified threshold (Epsilon) + + // NOTE: iteration count is for speed up purposes only - it + // does not have any theoretical importance + iterationCount = 1; + while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) + { + + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // check to see if the current mode location is in the + // basin of attraction... + + // calculate the location of yk on the lattice + modeCandidateX = (int) (sigmaS*yk[0]+0.5); + modeCandidateY = (int) (sigmaS*yk[1]+0.5); + modeCandidate_i = modeCandidateY*width + modeCandidateX; + + // if mvAbs != 0 (yk did indeed move) then check + // location basin_i in the mode table to see if + // this data point either: + + // (1) has not been associated with a mode yet + // (modeTable[basin_i] = 0), so associate + // it with this one + // + // (2) it has been associated with a mode other + // than the one that this data point is converging + // to (modeTable[basin_i] = 1), so assign to + // this data point the same mode as that of basin_i + + if ((modeTable[modeCandidate_i] != 2) && (modeCandidate_i != i)) + { + // obtain the data point at basin_i to + // see if it is within h*TC_DIST_FACTOR of + // of yk + diff = 0; + idxs = lN*modeCandidate_i; + for (k=2; k<lN; k++) + { + el = sdata[idxs+k] - yk[k]; + diff += el*el; + } + + // if the data point at basin_i is within + // a distance of h*TC_DIST_FACTOR of yk + // then depending on modeTable[basin_i] perform + // either (1) or (2) + if (diff < TC_DIST_FACTOR) + { + // if the data point at basin_i has not + // been associated to a mode then associate + // it with the mode that this one will converge + // to + if (modeTable[modeCandidate_i] == 0) + { + // no mode associated yet so associate + // it with this one... + pointList[pointCount++] = modeCandidate_i; + modeTable[modeCandidate_i] = 2; + + } else + { + + // the mode has already been associated with + // another mode, thererfore associate this one + // mode and the modes in the point list with + // the mode associated with data[basin_i]... + + // store the mode info into yk using msRawData... + for (j = 0; j < N; j++) + yk[j+2] = msRawData[modeCandidate_i*N+j]/sigmaR; + + // update mode table for this data point + // indicating that a mode has been associated + // with it + modeTable[i] = 1; + + // indicate that a mode has been associated + // to this data point (data[i]) + mvAbs = -1; + + // stop mean shift calculation... + break; + } + } + } + + // Calculate the mean shift vector at the new + // window location using lattice + // Calculate the mean shift vector using the lattice + // LatticeMSVector(Mh, yk); // modify to new + /*****************************************************/ + // Initialize mean shift vector + for(j = 0; j < lN; j++) + Mh[j] = 0; + wsuml = 0; + // uniformLSearch(Mh, yk_ptr); // modify to new + // find bucket of yk + cBuck1 = (int) yk[0] + 1; + cBuck2 = (int) yk[1] + 1; + cBuck3 = (int) (yk[2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + for (j=0; j<27; j++) + { + idxd = buckets[cBuck+bucNeigh[j]]; + // list parse, crt point is cHeadList + while (idxd>=0) + { + idxs = lN*idxd; + // determine if inside search window + el = sdata[idxs+0]-yk[0]; + diff = el*el; + el = sdata[idxs+1]-yk[1]; + diff += el*el; + + if (diff < 1.0) + { + el = sdata[idxs+2]-yk[2]; + if (yk[2] > hiLTr) + diff = 4*el*el; + else + diff = el*el; + + if (N>1) + { + el = sdata[idxs+3]-yk[3]; + diff += el*el; + el = sdata[idxs+4]-yk[4]; + diff += el*el; + } + + if (diff < 1.0) + { + weight = 1-weightMap[idxd]; + for (k=0; k<lN; k++) + Mh[k] += weight*sdata[idxs+k]; + wsuml += weight; + } + } + idxd = slist[idxd]; + } + } + if (wsuml > 0) + { + for(j = 0; j < lN; j++) + Mh[j] = Mh[j]/wsuml - yk[j]; + } + else + { + for(j = 0; j < lN; j++) + Mh[j] = 0; + } + /*****************************************************/ + + // Calculate its magnitude squared + //mvAbs = 0; + //for(j = 0; j < lN; j++) + // mvAbs += Mh[j]*Mh[j]; + mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; + if (N==3) + mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; + else + mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; + + // Increment iteration count + iterationCount++; + + } + + // if a mode was not associated with this data point + // yet associate it with yk... + if (mvAbs >= 0) + { + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // update mode table for this data point + // indicating that a mode has been associated + // with it + modeTable[i] = 1; + + } + + for (k=0; k<N; k++) + yk[k+2] *= sigmaR; + + // associate the data point indexed by + // the point list with the mode stored + // by yk + for (j = 0; j < pointCount; j++) + { + // obtain the point location from the + // point list + modeCandidate_i = pointList[j]; + + // update the mode table for this point + modeTable[modeCandidate_i] = 1; + + //store result into msRawData... + for(k = 0; k < N; k++) + msRawData[N*modeCandidate_i+k] = (float)(yk[k+2]); + } + + //store result into msRawData... + for(j = 0; j < N; j++) + msRawData[N*i+j] = (float)(yk[j+2]); + + // Prompt user on progress +#ifdef SHOW_PROGRESS + percent_complete = (float)(i/(float)(L))*100; + msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); +#endif + + // Check to see if the algorithm has been halted + if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) + break; + } + + // Prompt user that filtering is completed +#ifdef PROMPT +#ifdef SHOW_PROGRESS + msSys.Prompt("\r"); +#endif + msSys.Prompt("done."); +#endif + // de-allocate memory + delete [] buckets; + delete [] slist; + delete [] sdata; + + delete [] yk; + delete [] Mh; + + // done. + return; + +} + +// NEW +void msImageProcessor::NewOptimizedFilter2(float sigmaS, float sigmaR) +{ + // Declare Variables + int iterationCount, i, j, k, modeCandidateX, modeCandidateY, modeCandidate_i; + double mvAbs, diff, el; + + //make sure that a lattice height and width have + //been defined... + if(!height) + { + ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); + return; + } + + //re-assign bandwidths to sigmaS and sigmaR + if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) + { + ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); + return; + } + + //define input data dimension with lattice + int lN = N + 2; + + // Traverse each data point applying mean shift + // to each data point + + // Allcocate memory for yk + double *yk = new double [lN]; + + // Allocate memory for Mh + double *Mh = new double [lN]; + + // let's use some temporary data + float* sdata; + sdata = new float[lN*L]; + + // copy the scaled data + int idxs, idxd; + idxs = idxd = 0; + if (N==3) + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i/width)/sigmaS; + sdata[idxs++] = data[idxd++]/sigmaR; + sdata[idxs++] = data[idxd++]/sigmaR; + sdata[idxs++] = data[idxd++]/sigmaR; + } + } else if (N==1) + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i/width)/sigmaS; + sdata[idxs++] = data[idxd++]/sigmaR; + } + } else + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i/width)/sigmaS; + for (j=0; j<N; j++) + sdata[idxs++] = data[idxd++]/sigmaR; + } + } + // index the data in the 3d buckets (x, y, L) + int* buckets; + int* slist; + slist = new int[L]; + int bucNeigh[27]; + + float sMins; // just for L + float sMaxs[3]; // for all + sMaxs[0] = width/sigmaS; + sMaxs[1] = height/sigmaS; + sMins = sMaxs[2] = sdata[2]; + idxs = 2; + float cval; + for(i=0; i<L; i++) + { + cval = sdata[idxs]; + if (cval < sMins) + sMins = cval; + else if (cval > sMaxs[2]) + sMaxs[2] = cval; + + idxs += lN; + } + + int nBuck1, nBuck2, nBuck3; + int cBuck1, cBuck2, cBuck3, cBuck; + nBuck1 = (int) (sMaxs[0] + 3); + nBuck2 = (int) (sMaxs[1] + 3); + nBuck3 = (int) (sMaxs[2] - sMins + 3); + buckets = new int[nBuck1*nBuck2*nBuck3]; + for(i=0; i<(nBuck1*nBuck2*nBuck3); i++) + buckets[i] = -1; + + idxs = 0; + for(i=0; i<L; i++) + { + // find bucket for current data and add it to the list + cBuck1 = (int) sdata[idxs] + 1; + cBuck2 = (int) sdata[idxs+1] + 1; + cBuck3 = (int) (sdata[idxs+2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + + slist[i] = buckets[cBuck]; + buckets[cBuck] = i; + + idxs += lN; + } + // init bucNeigh + idxd = 0; + for (cBuck1=-1; cBuck1<=1; cBuck1++) + { + for (cBuck2=-1; cBuck2<=1; cBuck2++) + { + for (cBuck3=-1; cBuck3<=1; cBuck3++) + { + bucNeigh[idxd++] = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + } + } + } + double wsuml, weight; + double hiLTr = 80.0/sigmaR; + // done indexing/hashing + + + // Initialize mode table used for basin of attraction + memset(modeTable, 0, width*height); + + // proceed ... +#ifdef PROMPT + msSys.Prompt("done.\nApplying mean shift (Using Lattice) ... "); +#ifdef SHOW_PROGRESS + msSys.Prompt("\n 0%%"); +#endif +#endif + + + for(i = 0; i < L; i++) + { + // if a mode was already assigned to this data point + // then skip this point, otherwise proceed to + // find its mode by applying mean shift... + if (modeTable[i] == 1) + continue; + + // initialize point list... + pointCount = 0; + + // Assign window center (window centers are + // initialized by createLattice to be the point + // data[i]) + idxs = i*lN; + for (j=0; j<lN; j++) + yk[j] = sdata[idxs+j]; + + // Calculate the mean shift vector using the lattice + // LatticeMSVector(Mh, yk); // modify to new + /*****************************************************/ + // Initialize mean shift vector + for(j = 0; j < lN; j++) + Mh[j] = 0; + wsuml = 0; + // uniformLSearch(Mh, yk_ptr); // modify to new + // find bucket of yk + cBuck1 = (int) yk[0] + 1; + cBuck2 = (int) yk[1] + 1; + cBuck3 = (int) (yk[2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + for (j=0; j<27; j++) + { + idxd = buckets[cBuck+bucNeigh[j]]; + // list parse, crt point is cHeadList + while (idxd>=0) + { + idxs = lN*idxd; + // determine if inside search window + el = sdata[idxs+0]-yk[0]; + diff = el*el; + el = sdata[idxs+1]-yk[1]; + diff += el*el; + + if (diff < 1.0) + { + el = sdata[idxs+2]-yk[2]; + if (yk[2] > hiLTr) + diff = 4*el*el; + else + diff = el*el; + + if (N>1) + { + el = sdata[idxs+3]-yk[3]; + diff += el*el; + el = sdata[idxs+4]-yk[4]; + diff += el*el; + } + + if (diff < 1.0) + { + weight = 1-weightMap[idxd]; + for (k=0; k<lN; k++) + Mh[k] += weight*sdata[idxs+k]; + wsuml += weight; + + //set basin of attraction mode table + if (diff < speedThreshold) + { + if(modeTable[idxd] == 0) + { + pointList[pointCount++] = idxd; + modeTable[idxd] = 2; + } + } + } + } + idxd = slist[idxd]; + } + } + if (wsuml > 0) + { + for(j = 0; j < lN; j++) + Mh[j] = Mh[j]/wsuml - yk[j]; + } + else + { + for(j = 0; j < lN; j++) + Mh[j] = 0; + } + /*****************************************************/ + // Calculate its magnitude squared + //mvAbs = 0; + //for(j = 0; j < lN; j++) + // mvAbs += Mh[j]*Mh[j]; + mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; + if (N==3) + mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; + else + mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; + + + // Keep shifting window center until the magnitude squared of the + // mean shift vector calculated at the window center location is + // under a specified threshold (Epsilon) + + // NOTE: iteration count is for speed up purposes only - it + // does not have any theoretical importance + iterationCount = 1; + while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) + { + + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // check to see if the current mode location is in the + // basin of attraction... + + // calculate the location of yk on the lattice + modeCandidateX = (int) (sigmaS*yk[0]+0.5); + modeCandidateY = (int) (sigmaS*yk[1]+0.5); + modeCandidate_i = modeCandidateY*width + modeCandidateX; + + // if mvAbs != 0 (yk did indeed move) then check + // location basin_i in the mode table to see if + // this data point either: + + // (1) has not been associated with a mode yet + // (modeTable[basin_i] = 0), so associate + // it with this one + // + // (2) it has been associated with a mode other + // than the one that this data point is converging + // to (modeTable[basin_i] = 1), so assign to + // this data point the same mode as that of basin_i + + if ((modeTable[modeCandidate_i] != 2) && (modeCandidate_i != i)) + { + // obtain the data point at basin_i to + // see if it is within h*TC_DIST_FACTOR of + // of yk + diff = 0; + idxs = lN*modeCandidate_i; + for (k=2; k<lN; k++) + { + el = sdata[idxs+k] - yk[k]; + diff += el*el; + } + + // if the data point at basin_i is within + // a distance of h*TC_DIST_FACTOR of yk + // then depending on modeTable[basin_i] perform + // either (1) or (2) + if (diff < speedThreshold) + { + // if the data point at basin_i has not + // been associated to a mode then associate + // it with the mode that this one will converge + // to + if (modeTable[modeCandidate_i] == 0) + { + // no mode associated yet so associate + // it with this one... + pointList[pointCount++] = modeCandidate_i; + modeTable[modeCandidate_i] = 2; + + } else + { + + // the mode has already been associated with + // another mode, thererfore associate this one + // mode and the modes in the point list with + // the mode associated with data[basin_i]... + + // store the mode info into yk using msRawData... + for (j = 0; j < N; j++) + yk[j+2] = msRawData[modeCandidate_i*N+j]/sigmaR; + + // update mode table for this data point + // indicating that a mode has been associated + // with it + modeTable[i] = 1; + + // indicate that a mode has been associated + // to this data point (data[i]) + mvAbs = -1; + + // stop mean shift calculation... + break; + } + } + } + + // Calculate the mean shift vector at the new + // window location using lattice + // Calculate the mean shift vector using the lattice + // LatticeMSVector(Mh, yk); // modify to new + /*****************************************************/ + // Initialize mean shift vector + for(j = 0; j < lN; j++) + Mh[j] = 0; + wsuml = 0; + // uniformLSearch(Mh, yk_ptr); // modify to new + // find bucket of yk + cBuck1 = (int) yk[0] + 1; + cBuck2 = (int) yk[1] + 1; + cBuck3 = (int) (yk[2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + for (j=0; j<27; j++) + { + idxd = buckets[cBuck+bucNeigh[j]]; + // list parse, crt point is cHeadList + while (idxd>=0) + { + idxs = lN*idxd; + // determine if inside search window + el = sdata[idxs+0]-yk[0]; + diff = el*el; + el = sdata[idxs+1]-yk[1]; + diff += el*el; + + if (diff < 1.0) + { + el = sdata[idxs+2]-yk[2]; + if (yk[2] > hiLTr) + diff = 4*el*el; + else + diff = el*el; + + if (N>1) + { + el = sdata[idxs+3]-yk[3]; + diff += el*el; + el = sdata[idxs+4]-yk[4]; + diff += el*el; + } + + if (diff < 1.0) + { + weight = 1-weightMap[idxd]; + for (k=0; k<lN; k++) + Mh[k] += weight*sdata[idxs+k]; + wsuml += weight; + + //set basin of attraction mode table + if (diff < speedThreshold) + { + if(modeTable[idxd] == 0) + { + pointList[pointCount++] = idxd; + modeTable[idxd] = 2; + } + } + + } + } + idxd = slist[idxd]; + } + } + if (wsuml > 0) + { + for(j = 0; j < lN; j++) + Mh[j] = Mh[j]/wsuml - yk[j]; + } + else + { + for(j = 0; j < lN; j++) + Mh[j] = 0; + } + /*****************************************************/ + + // Calculate its magnitude squared + //mvAbs = 0; + //for(j = 0; j < lN; j++) + // mvAbs += Mh[j]*Mh[j]; + mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; + if (N==3) + mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; + else + mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; + + // Increment iteration count + iterationCount++; + + } + + // if a mode was not associated with this data point + // yet associate it with yk... + if (mvAbs >= 0) + { + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // update mode table for this data point + // indicating that a mode has been associated + // with it + modeTable[i] = 1; + + } + + for (k=0; k<N; k++) + yk[k+2] *= sigmaR; + + // associate the data point indexed by + // the point list with the mode stored + // by yk + for (j = 0; j < pointCount; j++) + { + // obtain the point location from the + // point list + modeCandidate_i = pointList[j]; + + // update the mode table for this point + modeTable[modeCandidate_i] = 1; + + //store result into msRawData... + for(k = 0; k < N; k++) + msRawData[N*modeCandidate_i+k] = (float)(yk[k+2]); + } + + //store result into msRawData... + for(j = 0; j < N; j++) + msRawData[N*i+j] = (float)(yk[j+2]); + + // Prompt user on progress +#ifdef SHOW_PROGRESS + percent_complete = (float)(i/(float)(L))*100; + msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); +#endif + + // Check to see if the algorithm has been halted + if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) + break; + } + + // Prompt user that filtering is completed +#ifdef PROMPT +#ifdef SHOW_PROGRESS + msSys.Prompt("\r"); +#endif + msSys.Prompt("done."); +#endif + // de-allocate memory + delete [] buckets; + delete [] slist; + delete [] sdata; + + delete [] yk; + delete [] Mh; + + // done. + return; + +} + +void msImageProcessor::NewNonOptimizedFilter(float sigmaS, float sigmaR) +{ + + // Declare Variables + int iterationCount, i, j, k; + double mvAbs, diff, el; + + //make sure that a lattice height and width have + //been defined... + if(!height) + { + ErrorHandler("msImageProcessor", "LFilter", "Lattice height and width are undefined."); + return; + } + + //re-assign bandwidths to sigmaS and sigmaR + if(((h[0] = sigmaS) <= 0)||((h[1] = sigmaR) <= 0)) + { + ErrorHandler("msImageProcessor", "Segment", "sigmaS and/or sigmaR is zero or negative."); + return; + } + + //define input data dimension with lattice + int lN = N + 2; + + // Traverse each data point applying mean shift + // to each data point + + // Allcocate memory for yk + double *yk = new double [lN]; + + // Allocate memory for Mh + double *Mh = new double [lN]; + + // let's use some temporary data + double* sdata; + sdata = new double[lN*L]; + + // copy the scaled data + int idxs, idxd; + idxs = idxd = 0; + if (N==3) + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i/width)/sigmaS; + sdata[idxs++] = data[idxd++]/sigmaR; + sdata[idxs++] = data[idxd++]/sigmaR; + sdata[idxs++] = data[idxd++]/sigmaR; + } + } else if (N==1) + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i/width)/sigmaS; + sdata[idxs++] = data[idxd++]/sigmaR; + } + } else + { + for(i=0; i<L; i++) + { + sdata[idxs++] = (i%width)/sigmaS; + sdata[idxs++] = (i%width)/sigmaS; + for (j=0; j<N; j++) + sdata[idxs++] = data[idxd++]/sigmaR; + } + } + // index the data in the 3d buckets (x, y, L) + int* buckets; + int* slist; + slist = new int[L]; + int bucNeigh[27]; + + double sMins; // just for L + double sMaxs[3]; // for all + sMaxs[0] = width/sigmaS; + sMaxs[1] = height/sigmaS; + sMins = sMaxs[2] = sdata[2]; + idxs = 2; + double cval; + for(i=0; i<L; i++) + { + cval = sdata[idxs]; + if (cval < sMins) + sMins = cval; + else if (cval > sMaxs[2]) + sMaxs[2] = cval; + + idxs += lN; + } + + int nBuck1, nBuck2, nBuck3; + int cBuck1, cBuck2, cBuck3, cBuck; + nBuck1 = (int) (sMaxs[0] + 3); + nBuck2 = (int) (sMaxs[1] + 3); + nBuck3 = (int) (sMaxs[2] - sMins + 3); + buckets = new int[nBuck1*nBuck2*nBuck3]; + for(i=0; i<(nBuck1*nBuck2*nBuck3); i++) + buckets[i] = -1; + + idxs = 0; + for(i=0; i<L; i++) + { + // find bucket for current data and add it to the list + cBuck1 = (int) sdata[idxs] + 1; + cBuck2 = (int) sdata[idxs+1] + 1; + cBuck3 = (int) (sdata[idxs+2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + + slist[i] = buckets[cBuck]; + buckets[cBuck] = i; + + idxs += lN; + } + // init bucNeigh + idxd = 0; + for (cBuck1=-1; cBuck1<=1; cBuck1++) + { + for (cBuck2=-1; cBuck2<=1; cBuck2++) + { + for (cBuck3=-1; cBuck3<=1; cBuck3++) + { + bucNeigh[idxd++] = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + } + } + } + double wsuml, weight; + double hiLTr = 80.0/sigmaR; + // done indexing/hashing + + // proceed ... +#ifdef PROMPT + msSys.Prompt("done.\nApplying mean shift (Using Lattice)... "); +#ifdef SHOW_PROGRESS + msSys.Prompt("\n 0%%"); +#endif +#endif + + for(i = 0; i < L; i++) + { + + // Assign window center (window centers are + // initialized by createLattice to be the point + // data[i]) + idxs = i*lN; + for (j=0; j<lN; j++) + yk[j] = sdata[idxs+j]; + + // Calculate the mean shift vector using the lattice + // LatticeMSVector(Mh, yk); + /*****************************************************/ + // Initialize mean shift vector + for(j = 0; j < lN; j++) + Mh[j] = 0; + wsuml = 0; + // uniformLSearch(Mh, yk_ptr); // modify to new + // find bucket of yk + cBuck1 = (int) yk[0] + 1; + cBuck2 = (int) yk[1] + 1; + cBuck3 = (int) (yk[2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + for (j=0; j<27; j++) + { + idxd = buckets[cBuck+bucNeigh[j]]; + // list parse, crt point is cHeadList + while (idxd>=0) + { + idxs = lN*idxd; + // determine if inside search window + el = sdata[idxs+0]-yk[0]; + diff = el*el; + el = sdata[idxs+1]-yk[1]; + diff += el*el; + + if (diff < 1.0) + { + el = sdata[idxs+2]-yk[2]; + if (yk[2] > hiLTr) + diff = 4*el*el; + else + diff = el*el; + + if (N>1) + { + el = sdata[idxs+3]-yk[3]; + diff += el*el; + el = sdata[idxs+4]-yk[4]; + diff += el*el; + } + + if (diff < 1.0) + { + weight = 1-weightMap[idxd]; + for (k=0; k<lN; k++) + Mh[k] += weight*sdata[idxs+k]; + wsuml += weight; + } + } + idxd = slist[idxd]; + } + } + if (wsuml > 0) + { + for(j = 0; j < lN; j++) + Mh[j] = Mh[j]/wsuml - yk[j]; + } + else + { + for(j = 0; j < lN; j++) + Mh[j] = 0; + } + /*****************************************************/ + + // Calculate its magnitude squared + mvAbs = 0; + for(j = 0; j < lN; j++) + mvAbs += Mh[j]*Mh[j]; + + // Keep shifting window center until the magnitude squared of the + // mean shift vector calculated at the window center location is + // under a specified threshold (Epsilon) + + // NOTE: iteration count is for speed up purposes only - it + // does not have any theoretical importance + iterationCount = 1; + while((mvAbs >= EPSILON)&&(iterationCount < LIMIT)) + { + + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + // Calculate the mean shift vector at the new + // window location using lattice + // LatticeMSVector(Mh, yk); + /*****************************************************/ + // Initialize mean shift vector + for(j = 0; j < lN; j++) + Mh[j] = 0; + wsuml = 0; + // uniformLSearch(Mh, yk_ptr); // modify to new + // find bucket of yk + cBuck1 = (int) yk[0] + 1; + cBuck2 = (int) yk[1] + 1; + cBuck3 = (int) (yk[2] - sMins) + 1; + cBuck = cBuck1 + nBuck1*(cBuck2 + nBuck2*cBuck3); + for (j=0; j<27; j++) + { + idxd = buckets[cBuck+bucNeigh[j]]; + // list parse, crt point is cHeadList + while (idxd>=0) + { + idxs = lN*idxd; + // determine if inside search window + el = sdata[idxs+0]-yk[0]; + diff = el*el; + el = sdata[idxs+1]-yk[1]; + diff += el*el; + + if (diff < 1.0) + { + el = sdata[idxs+2]-yk[2]; + if (yk[2] > hiLTr) + diff = 4*el*el; + else + diff = el*el; + + if (N>1) + { + el = sdata[idxs+3]-yk[3]; + diff += el*el; + el = sdata[idxs+4]-yk[4]; + diff += el*el; + } + + if (diff < 1.0) + { + weight = 1-weightMap[idxd]; + for (k=0; k<lN; k++) + Mh[k] += weight*sdata[idxs+k]; + wsuml += weight; + } + } + idxd = slist[idxd]; + } + } + if (wsuml > 0) + { + for(j = 0; j < lN; j++) + Mh[j] = Mh[j]/wsuml - yk[j]; + } + else + { + for(j = 0; j < lN; j++) + Mh[j] = 0; + } + /*****************************************************/ + + // Calculate its magnitude squared + //mvAbs = 0; + //for(j = 0; j < lN; j++) + // mvAbs += Mh[j]*Mh[j]; + mvAbs = (Mh[0]*Mh[0]+Mh[1]*Mh[1])*sigmaS*sigmaS; + if (N==3) + mvAbs += (Mh[2]*Mh[2]+Mh[3]*Mh[3]+Mh[4]*Mh[4])*sigmaR*sigmaR; + else + mvAbs += Mh[2]*Mh[2]*sigmaR*sigmaR; + + // Increment interation count + iterationCount++; + } + + // Shift window location + for(j = 0; j < lN; j++) + yk[j] += Mh[j]; + + //store result into msRawData... + for(j = 0; j < N; j++) + msRawData[N*i+j] = (float)(yk[j+2]*sigmaR); + + // Prompt user on progress +#ifdef SHOW_PROGRESS + percent_complete = (float)(i/(float)(L))*100; + msSys.Prompt("\r%2d%%", (int)(percent_complete + 0.5)); +#endif + + // Check to see if the algorithm has been halted + if((i%PROGRESS_RATE == 0)&&((ErrorStatus = msSys.Progress((float)(i/(float)(L))*(float)(0.8)))) == EL_HALT) + break; + } + + // Prompt user that filtering is completed +#ifdef PROMPT +#ifdef SHOW_PROGRESS + msSys.Prompt("\r"); +#endif + msSys.Prompt("done."); +#endif + + // de-allocate memory + delete [] buckets; + delete [] slist; + delete [] sdata; + + delete [] yk; + delete [] Mh; + + // done. + return; + +} + +void msImageProcessor::SetSpeedThreshold(float speedUpThreshold) +{ + speedThreshold = speedUpThreshold; +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + diff --git a/Utilities/otbedison/segm/msImageProcessor.h b/Utilities/otbedison/segm/msImageProcessor.h old mode 100755 new mode 100644 index fe4ae4f91c0aa287bc6e48127d99a766ee061d7d..62095c90fb10059cee35235faddfcf5e255e0e29 --- a/Utilities/otbedison/segm/msImageProcessor.h +++ b/Utilities/otbedison/segm/msImageProcessor.h @@ -1,798 +1,798 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Mean Shift Image Processor Class: - ================================ - - The following class inherits from the mean shift library - in order to perform the specialized tasks of image - segmentation and filtering. - - The prototype of the Mean Shift Image Processor Class - is provided below. Its definition is provided in - 'msImageProcessor.cc'. - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - -#ifndef msImageProcessor_H -#define msImageProcessor_H - -//include mean shift library -#include "ms.h" - -//include prototypes of additional strucuters -//used for image segmentation... - -//include region list used to store boundary pixel -//indeces for each region -#include "rlist.h" - -//include region adjacency list class used for -//region pruning and transitive closure -#include "RAList.h" - -//define constants - - //image pruning -#define TOTAL_ITERATIONS 14 -#define BIG_NUM 0xffffffff //BIG_NUM = 2^32-1 -#define NODE_MULTIPLE 10 - - //data space conversion... -const double Xn = 0.95050; -const double Yn = 1.00000; -const double Zn = 1.08870; -//const double Un_prime = 0.19780; -//const double Vn_prime = 0.46830; -const double Un_prime = 0.19784977571475; -const double Vn_prime = 0.46834507665248; -const double Lt = 0.008856; - - //RGB to LUV conversion -const double XYZ[3][3] = { { 0.4125, 0.3576, 0.1804 }, - { 0.2125, 0.7154, 0.0721 }, - { 0.0193, 0.1192, 0.9502 } }; - - //LUV to RGB conversion -const double RGB[3][3] = { { 3.2405, -1.5371, -0.4985 }, - { -0.9693, 1.8760, 0.0416 }, - { 0.0556, -0.2040, 1.0573 } }; - -//define data types -typedef unsigned char byte; - -//define enumerations -enum imageType {GRAYSCALE, COLOR}; - -//define prototype -class msImageProcessor: public MeanShift { - -public: - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Class Constructor and Destructor */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - msImageProcessor( void ); //Default Constructor - ~msImageProcessor( void ); //Class Destructor - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Input Image Declaration */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Define Image * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Uploads an image to be segmented by the image |// - //| segmenter class. |// - //| |// - //| An image is defined by specifying the folloing: |// - //| |// - //| <* data *> |// - //| A one dimensional unsigned char array of RGB |// - //| vectors. |// - //| |// - //| <* type *> |// - //| Specifies the image type: COLOR or GREYSCALE. |// - //| |// - //| <* height *> |// - //| The image height. |// - //| |// - //| <* width *> |// - //| The image width. |// - //| |// - //| This method uploads the image and converts its |// - //| data into the LUV space. If another conversion |// - //| is desired data may be uploaded into this class |// - //| via the procedure MeanShift::UploadInput(). |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| DefineImage(data, type, height, width) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void DefineImage(byte*,imageType, int, int); - void DefineBgImage(byte*, imageType , int , int ); - - - /*/\/\/\/\/\/\*/ - /* Weight Map */ - /*\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Set Weight Map * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Uploads weight map specifying for each pixel |// - //| in the image a value between 0 and 1 - 1 indica- |// - //| ting the presence of an edge and 0 the absense |// - //| of an edge. |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* weightMap *> |// - //| A floating point array of size (height x width) |// - //| specifying at location (i,j) the edge strength |// - //| of pixel (i,j). (e.g. pixel (i,j) has an edge |// - //| strength of weightMap[j*width+i]). |// - //| |// - //| <* epsilon *> |// - //| A floating point number specifying the threshold |// - //| used to fuse regions during transitive closure. |// - //| |// - //| Note: DefineImage must be called prior to call- |// - //| ing this method. DefineImage is used to |// - //| define the dimensions of the image. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| SetWeightMap(weightMap, epsilon) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void SetWeightMap(float*, float); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Remove Weight Map * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Removes weight map. An error is NOT flagged |// - //| if a weight map was not defined prior to calling |// - //| this method. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| RemoveWeightMap(void) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void RemoveWeightMap(void); - - /*/\/\/\/\/\/\/\/\/\*/ - /* Image Filtering */ - /*\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Filter * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Apply mean shift filter to the defined image, |// - //| defined either via MeanShift::DefineLInput or |// - //| msImageProcessor::DefineImage. The resulting |// - //| segmented image is stored in the private data |// - //| members of the image segmenter class which can |// - //| be obtained by calling image msImageProcessor:: |// - //| GetResults(). |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* sigmaS *> |// - //| The spatial radius of the mean shift window. |// - //| |// - //| <* sigmaR *> |// - //| The range radius of the mean shift window. |// - //| |// - //| <* speedUpLevel *> |// - //| Determines if a speed up optimization should be |// - //| used to perform image filtering. A value of |// - //| NO_SPEEDUP turns this optimization off and a |// - //| value of SPEEDUP turns this optimization on. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| Filter(sigmaS, sigmaR, speedUpLevel) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void Filter(int, float, SpeedUpLevel); - - /*/\/\/\/\/\/\/\/\/\/\/\*/ - /* Image Region Fusing */ - /*\/\/\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Fuse Regions * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Fuses the regions of a filtered image, |// - //| defined either via MeanShift::DefineLInput or |// - //| msImageProcessor::DefineImage. The resulting |// - //| segmented image is stored in the private data |// - //| members of the image segmenter class which can |// - //| be obtained by calling image msImageProcessor:: |// - //| GetResults(). |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* sigmaR *> |// - //| The range radius that defines similar color |// - //| amongst image regions. |// - //| |// - //| <* minRegion *> |// - //| The minimum density a region may have in the |// - //| resulting segmented image. All regions have |// - //| point density < minRegion are pruned from the |// - //| image. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| FuseRegions(sigmaR, minRegion) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void FuseRegions(float, int); - - /*/\/\/\/\/\/\/\/\/\/\*/ - /* Image Segmentation */ - /*\/\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Segment * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Segments the defined image, defined either via |// - //| MeanShift::DefineLInput or msImageProcessor::De- |// - //| fineImage. The resulting segmented image is |// - //| stored in the private data members of the image |// - //| processor class which can be obtained by calling |// - //| ImageSegmenter::GetResults(). |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* sigmaS *> |// - //| The spatial radius of the mean shift window. |// - //| |// - //| <* sigmaR *> |// - //| The range radius of the mean shift window. |// - //| |// - //| <* minRegion *> |// - //| The minimum density a region may have in the |// - //| resulting segmented image. All regions have |// - //| point density < minRegion are pruned from the |// - //| image. |// - //| |// - //| <* speedUpLevel *> |// - //| Determines if a speed up optimization should be |// - //| used to perform image filtering. A value of |// - //| NO_SPEEDUP turns this optimization off and a |// - //| value of SPEEDUP turns this optimization on. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| Segment(sigmaS, sigmaR, minRegion, |// - //| speedUpLevel) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void Segment(int, float, int, SpeedUpLevel); - - /*/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Data Space Conversion */ - /*\/\/\/\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * RGB To LUV * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Converts an RGB vector to LUV. |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* rgbVal *> |// - //| An unsigned char array containing the RGB |// - //| vector. |// - //| |// - //| <* luvVal *> |// - //| A floating point array containing the LUV |// - //| vector. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| RGBtoLUV(rgbVal, luvVal) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void RGBtoLUV(byte*, float*); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * LUV To RGB * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Converts an LUV vector to RGB. |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* luvVal *> |// - //| A floating point array containing the LUV |// - //| vector. |// - //| |// - //| <* rgbVal *> |// - //| An unsigned char array containing the RGB |// - //| vector. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| LUVtoRGB(luvVal, rgbVal) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void LUVtoRGB(float*, byte*); - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Filtered and Segmented Image Output */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Get Raw Data * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns the resulting filtered or segmented im- |// - //| age data after calling Filter() or Segment(). |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* outputImageData *> |// - //| A floating point array containing the vector |// - //| data of the filtered or segmented image. |// - //| |// - //| NOTE: If DefineImage was used to specify the |// - //| the input to this class, outputImageData |// - //| is in the LUV data space. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| GetResults(outputImageData) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void GetRawData(float*); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Get Results * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns the resulting filtered or segmented im- |// - //| age after calling Filter() or Segment(). |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* outputImage *> |// - //| An unsigned char array containing the RGB |// - //| vector data of the output image. |// - //| |// - //| To obtain the un-converted (LUV) data space |// - //| output one may use |// - //| msImageProcessor::GetRawData(). |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| GetResults(outputImage) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void GetResults(byte*); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Get Boundaries * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns the boundaries of each region of the |// - //| segmented image using a region list object, |// - //| available after filtering or segmenting the |// - //| defined image. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| regionList = GetBoundaries() |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - RegionList *GetBoundaries( void ); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Get Regions * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns the regions of the processed image. |// - //| Each region in the image is uniquely character- |// - //| ized by its location and color (e.g. RGB). |// - //| GetRegions() therefore returns the following |// - //| information about the regions of the processed |// - //| image: |// - //| |// - //| <* regionCount *> |// - //| An integer that specifies the number of regions |// - //| contained in the processed image. |// - //| |// - //| <* modes *> |// - //| A floating point array of length regionCount*N |// - //| containing the feature space component of each |// - //| region (e.g. LUV), and indexed by region label. |// - //| |// - //| <* labels *> |// - //| An integer array of length (height*width) which |// - //| contains at every pixel location (x,y) a label |// - //| relating that pixel to a region whose mode is |// - //| specified by modes and whose area is specified |// - //| by modePointCounts. |// - //| |// - //| <* modePointCounts *> |// - //| An integer array of length regionCount and ind- |// - //| exed by region label, that specifies the region |// - //| area (in pixels) for each segmented image reg- |// - //| ion. (e.g. Area of region having label specif- |// - //| ified by l, has area modePointCounts[l] (pix- |// - //| els).) |// - //| |// - //| NOTE: Memory for the above integer and floating |// - //| point arrays is allocated inside this |// - //| method. |// - //| |// - //| Also modes stored by the modes array are |// - //| not in the RGB space. Instead if the |// - //| method DefineImage was used, these data |// - //| points are in the LUV space, and if the |// - //| method DefineLInput was used these data |// - //| points are in whatever space you specified |// - //| them to be in when calling DefineLInput. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| regionCount = GetRegions(labels, modes |// - //| modePointCounts) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - int GetRegions(int**, float**, int**); - - - void SetSpeedThreshold(float); -private: - - //======================== - // *** Private Methods *** - //======================== - - /*/\/\/\/\/\/\/\/\/\*/ - /* Image Filtering */ - /*\/\/\/\/\/\/\/\/\/*/ - - void NonOptimizedFilter(float, float); // filters the image applying mean shift to each point - // Advantage : most accurate - // Disadvantage : time expensive - void NewNonOptimizedFilter(float, float); - - void OptimizedFilter1(float, float); // filters the image using previous mode information - // to avoid re-applying mean shift to some data points - // Advantage : maintains high level of accuracy, - // large speed up compared to non-optimized - // version - // Disadvantage : POSSIBLY not as accurate as non-optimized - // version - void NewOptimizedFilter1(float, float); - - - void OptimizedFilter2(float, float); //filter the image using previous mode information - //and window traversals to avoid re-applying mean shift to - //some data points - // Advantage : huge speed up - maintains accuracy good enough - // for segmentation - // Disadvantage : not as accurate as previous filters - void NewOptimizedFilter2(float, float); - - - /*/\/\/\/\/\/\/\/\/\/\/\*/ - /* Image Classification */ - /*\/\/\/\/\/\/\/\/\/\/\/*/ - - void Connect( void ); // classifies mean shift filtered image regions using - // private classification structure of this class - - void Fill(int, int); // used by Connect to perform label each region in the - // mean shift filtered image using an eight-connected - // fill - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Transitive Closure and Image Pruning */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - void BuildRAM( void ); // build a region adjacency matrix using the region list - // object - - void DestroyRAM( void ); // destroy the region adjacency matrix: de-allocate its memory - // initialize it for re-use - - void TransitiveClosure( void ); // use the RAM to apply transitive closure to the image modes - - void ComputeEdgeStrengths( void ); // computes the weights of the weighted graph using the weight - // map - - //Usage: Prune(minRegion) - void Prune(int); // use the RAM to prune the image of spurious regions (regions - // whose area is less than minRegion pixels, where minRegion is - // an argument of this method) - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Region Boundary Detection */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - void DefineBoundaries( void ); // defines the boundaries of each region using the classified segmented - // image storing the resulting boundary locations for each region using - // a region list object - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Image Data Searching/Distance Calculation */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - //Usage: InWindow(modeIndex1, modeIndex2) - bool InWindow(int, int); //returns true if the range data of the specified data points - //are within the defined search window (defined by kernel - //bandwidth h[1]) - - float SqDistance(int, int); // computes the normalized square distance between two modes - - /*/\/\/\/\/\/\/\/\/\/\*/ - /* Memory Management */ - /*\/\/\/\/\/\/\/\/\/\/*/ - - void InitializeOutput( void ); //Allocates memory needed by this class to perform image - //filtering and segmentation - - void DestroyOutput( void ); //De-allocates memory needed by this class to perform image - //filtering and segmentation - - //============================= - // *** Private Data Members *** - //============================= - - //########################################## - //####### IMAGE CLASSIFICATION ######## - //########################################## - - /////////Image Boundaries///////// - RegionList *regionList; // stores the boundary locations for each region - - /////////Image Regions//////// - int regionCount; // stores the number of connected regions contained by the - // image - - /////////8 Connected Neighbors///////// - int neigh[8]; - - /////////Index Table///////////////// - int *indexTable; //used during fill algorithm - - /////////LUV_data///////////////// - //int *LUV_data; //stores modes in integer format on lattice - float *LUV_data; //stores modes in float format on lattice - float LUV_treshold; //in float mode this determines what "close" means between modes - - - //########################################## - //####### OUTPUT DATA STORAGE ######## - //########################################## - - ////////Raw Data (1 to 1 correlation with input)//////// - float *msRawData; // Raw data output of mean shift algorithm - // to the location of the data point on the lattice - - ////////Data Modes//////// - int *labels; // assigns a label to each data point associating it to - // a mode in modes (e.g. a data point having label l has - // mode modes[l]) - - float *modes; // stores the mode data of the input data set, indexed by labels - - int *modePointCounts; // stores for each mode the number of point mapped to that mode, - // indexed by labels - - //########################################## - //####### REGION ADJACENCY MATRIX ######## - //########################################## - - //////////Region Adjacency List///////// - RAList *raList; // an array of RAList objects containing an entry for each - // region of the image - - //////////RAMatrix Free List/////////// - RAList *freeRAList; // a pointer to the head of a region adjacency list object - // free list - - RAList *raPool; // a pool of RAList objects used in the construction of the - // RAM - - //############################################## - //####### COMPUTATION OF EDGE STRENGTHS ####### - //############################################## - - //////////Epsilon/////////// - float epsilon; //Epsilon used for transitive closure - - //////Visit Table////// - unsigned char *visitTable; //Table used to keep track of which pixels have been - //already visited upon computing the boundary edge strengths - - //########################################## - //####### IMAGE PRUNING ######## - //########################################## - - ////////Transitive Closure///////// - float rR2; //defines square range radius used when clustering pixels - //together, thus defining image regions - - float speedThreshold; // the % of window radius used in new optimized filter 2. -}; - -#endif +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Mean Shift Image Processor Class: + ================================ + + The following class inherits from the mean shift library + in order to perform the specialized tasks of image + segmentation and filtering. + + The prototype of the Mean Shift Image Processor Class + is provided below. Its definition is provided in + 'msImageProcessor.cc'. + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + +#ifndef msImageProcessor_H +#define msImageProcessor_H + +//include mean shift library +#include "ms.h" + +//include prototypes of additional strucuters +//used for image segmentation... + +//include region list used to store boundary pixel +//indeces for each region +#include "rlist.h" + +//include region adjacency list class used for +//region pruning and transitive closure +#include "RAList.h" + +//define constants + + //image pruning +#define TOTAL_ITERATIONS 14 +#define BIG_NUM 0xffffffff //BIG_NUM = 2^32-1 +#define NODE_MULTIPLE 10 + + //data space conversion... +const double Xn = 0.95050; +const double Yn = 1.00000; +const double Zn = 1.08870; +//const double Un_prime = 0.19780; +//const double Vn_prime = 0.46830; +const double Un_prime = 0.19784977571475; +const double Vn_prime = 0.46834507665248; +const double Lt = 0.008856; + + //RGB to LUV conversion +const double XYZ[3][3] = { { 0.4125, 0.3576, 0.1804 }, + { 0.2125, 0.7154, 0.0721 }, + { 0.0193, 0.1192, 0.9502 } }; + + //LUV to RGB conversion +const double RGB[3][3] = { { 3.2405, -1.5371, -0.4985 }, + { -0.9693, 1.8760, 0.0416 }, + { 0.0556, -0.2040, 1.0573 } }; + +//define data types +typedef unsigned char byte; + +//define enumerations +enum imageType {GRAYSCALE, COLOR}; + +//define prototype +class msImageProcessor: public MeanShift { + +public: + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Class Constructor and Destructor */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + msImageProcessor( void ); //Default Constructor + ~msImageProcessor( void ); //Class Destructor + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Input Image Declaration */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Define Image * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Uploads an image to be segmented by the image |// + //| segmenter class. |// + //| |// + //| An image is defined by specifying the folloing: |// + //| |// + //| <* data *> |// + //| A one dimensional unsigned char array of RGB |// + //| vectors. |// + //| |// + //| <* type *> |// + //| Specifies the image type: COLOR or GREYSCALE. |// + //| |// + //| <* height *> |// + //| The image height. |// + //| |// + //| <* width *> |// + //| The image width. |// + //| |// + //| This method uploads the image and converts its |// + //| data into the LUV space. If another conversion |// + //| is desired data may be uploaded into this class |// + //| via the procedure MeanShift::UploadInput(). |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| DefineImage(data, type, height, width) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void DefineImage(byte*,imageType, int, int); + void DefineBgImage(byte*, imageType , int , int ); + + + /*/\/\/\/\/\/\*/ + /* Weight Map */ + /*\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Set Weight Map * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Uploads weight map specifying for each pixel |// + //| in the image a value between 0 and 1 - 1 indica- |// + //| ting the presence of an edge and 0 the absense |// + //| of an edge. |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* weightMap *> |// + //| A floating point array of size (height x width) |// + //| specifying at location (i,j) the edge strength |// + //| of pixel (i,j). (e.g. pixel (i,j) has an edge |// + //| strength of weightMap[j*width+i]). |// + //| |// + //| <* epsilon *> |// + //| A floating point number specifying the threshold |// + //| used to fuse regions during transitive closure. |// + //| |// + //| Note: DefineImage must be called prior to call- |// + //| ing this method. DefineImage is used to |// + //| define the dimensions of the image. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| SetWeightMap(weightMap, epsilon) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void SetWeightMap(float*, float); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Remove Weight Map * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Removes weight map. An error is NOT flagged |// + //| if a weight map was not defined prior to calling |// + //| this method. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| RemoveWeightMap(void) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void RemoveWeightMap(void); + + /*/\/\/\/\/\/\/\/\/\*/ + /* Image Filtering */ + /*\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Filter * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Apply mean shift filter to the defined image, |// + //| defined either via MeanShift::DefineLInput or |// + //| msImageProcessor::DefineImage. The resulting |// + //| segmented image is stored in the private data |// + //| members of the image segmenter class which can |// + //| be obtained by calling image msImageProcessor:: |// + //| GetResults(). |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* sigmaS *> |// + //| The spatial radius of the mean shift window. |// + //| |// + //| <* sigmaR *> |// + //| The range radius of the mean shift window. |// + //| |// + //| <* speedUpLevel *> |// + //| Determines if a speed up optimization should be |// + //| used to perform image filtering. A value of |// + //| NO_SPEEDUP turns this optimization off and a |// + //| value of SPEEDUP turns this optimization on. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| Filter(sigmaS, sigmaR, speedUpLevel) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void Filter(int, float, SpeedUpLevel); + + /*/\/\/\/\/\/\/\/\/\/\/\*/ + /* Image Region Fusing */ + /*\/\/\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Fuse Regions * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Fuses the regions of a filtered image, |// + //| defined either via MeanShift::DefineLInput or |// + //| msImageProcessor::DefineImage. The resulting |// + //| segmented image is stored in the private data |// + //| members of the image segmenter class which can |// + //| be obtained by calling image msImageProcessor:: |// + //| GetResults(). |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* sigmaR *> |// + //| The range radius that defines similar color |// + //| amongst image regions. |// + //| |// + //| <* minRegion *> |// + //| The minimum density a region may have in the |// + //| resulting segmented image. All regions have |// + //| point density < minRegion are pruned from the |// + //| image. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| FuseRegions(sigmaR, minRegion) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void FuseRegions(float, int); + + /*/\/\/\/\/\/\/\/\/\/\*/ + /* Image Segmentation */ + /*\/\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Segment * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Segments the defined image, defined either via |// + //| MeanShift::DefineLInput or msImageProcessor::De- |// + //| fineImage. The resulting segmented image is |// + //| stored in the private data members of the image |// + //| processor class which can be obtained by calling |// + //| ImageSegmenter::GetResults(). |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* sigmaS *> |// + //| The spatial radius of the mean shift window. |// + //| |// + //| <* sigmaR *> |// + //| The range radius of the mean shift window. |// + //| |// + //| <* minRegion *> |// + //| The minimum density a region may have in the |// + //| resulting segmented image. All regions have |// + //| point density < minRegion are pruned from the |// + //| image. |// + //| |// + //| <* speedUpLevel *> |// + //| Determines if a speed up optimization should be |// + //| used to perform image filtering. A value of |// + //| NO_SPEEDUP turns this optimization off and a |// + //| value of SPEEDUP turns this optimization on. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| Segment(sigmaS, sigmaR, minRegion, |// + //| speedUpLevel) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void Segment(int, float, int, SpeedUpLevel); + + /*/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Data Space Conversion */ + /*\/\/\/\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * RGB To LUV * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Converts an RGB vector to LUV. |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* rgbVal *> |// + //| An unsigned char array containing the RGB |// + //| vector. |// + //| |// + //| <* luvVal *> |// + //| A floating point array containing the LUV |// + //| vector. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| RGBtoLUV(rgbVal, luvVal) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void RGBtoLUV(byte*, float*); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * LUV To RGB * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Converts an LUV vector to RGB. |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* luvVal *> |// + //| A floating point array containing the LUV |// + //| vector. |// + //| |// + //| <* rgbVal *> |// + //| An unsigned char array containing the RGB |// + //| vector. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| LUVtoRGB(luvVal, rgbVal) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void LUVtoRGB(float*, byte*); + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Filtered and Segmented Image Output */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Get Raw Data * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns the resulting filtered or segmented im- |// + //| age data after calling Filter() or Segment(). |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* outputImageData *> |// + //| A floating point array containing the vector |// + //| data of the filtered or segmented image. |// + //| |// + //| NOTE: If DefineImage was used to specify the |// + //| the input to this class, outputImageData |// + //| is in the LUV data space. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| GetResults(outputImageData) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void GetRawData(float*); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Get Results * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns the resulting filtered or segmented im- |// + //| age after calling Filter() or Segment(). |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* outputImage *> |// + //| An unsigned char array containing the RGB |// + //| vector data of the output image. |// + //| |// + //| To obtain the un-converted (LUV) data space |// + //| output one may use |// + //| msImageProcessor::GetRawData(). |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| GetResults(outputImage) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void GetResults(byte*); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Get Boundaries * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns the boundaries of each region of the |// + //| segmented image using a region list object, |// + //| available after filtering or segmenting the |// + //| defined image. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| regionList = GetBoundaries() |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + RegionList *GetBoundaries( void ); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Get Regions * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns the regions of the processed image. |// + //| Each region in the image is uniquely character- |// + //| ized by its location and color (e.g. RGB). |// + //| GetRegions() therefore returns the following |// + //| information about the regions of the processed |// + //| image: |// + //| |// + //| <* regionCount *> |// + //| An integer that specifies the number of regions |// + //| contained in the processed image. |// + //| |// + //| <* modes *> |// + //| A floating point array of length regionCount*N |// + //| containing the feature space component of each |// + //| region (e.g. LUV), and indexed by region label. |// + //| |// + //| <* labels *> |// + //| An integer array of length (height*width) which |// + //| contains at every pixel location (x,y) a label |// + //| relating that pixel to a region whose mode is |// + //| specified by modes and whose area is specified |// + //| by modePointCounts. |// + //| |// + //| <* modePointCounts *> |// + //| An integer array of length regionCount and ind- |// + //| exed by region label, that specifies the region |// + //| area (in pixels) for each segmented image reg- |// + //| ion. (e.g. Area of region having label specif- |// + //| ified by l, has area modePointCounts[l] (pix- |// + //| els).) |// + //| |// + //| NOTE: Memory for the above integer and floating |// + //| point arrays is allocated inside this |// + //| method. |// + //| |// + //| Also modes stored by the modes array are |// + //| not in the RGB space. Instead if the |// + //| method DefineImage was used, these data |// + //| points are in the LUV space, and if the |// + //| method DefineLInput was used these data |// + //| points are in whatever space you specified |// + //| them to be in when calling DefineLInput. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| regionCount = GetRegions(labels, modes |// + //| modePointCounts) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + int GetRegions(int**, float**, int**); + + + void SetSpeedThreshold(float); +private: + + //======================== + // *** Private Methods *** + //======================== + + /*/\/\/\/\/\/\/\/\/\*/ + /* Image Filtering */ + /*\/\/\/\/\/\/\/\/\/*/ + + void NonOptimizedFilter(float, float); // filters the image applying mean shift to each point + // Advantage : most accurate + // Disadvantage : time expensive + void NewNonOptimizedFilter(float, float); + + void OptimizedFilter1(float, float); // filters the image using previous mode information + // to avoid re-applying mean shift to some data points + // Advantage : maintains high level of accuracy, + // large speed up compared to non-optimized + // version + // Disadvantage : POSSIBLY not as accurate as non-optimized + // version + void NewOptimizedFilter1(float, float); + + + void OptimizedFilter2(float, float); //filter the image using previous mode information + //and window traversals to avoid re-applying mean shift to + //some data points + // Advantage : huge speed up - maintains accuracy good enough + // for segmentation + // Disadvantage : not as accurate as previous filters + void NewOptimizedFilter2(float, float); + + + /*/\/\/\/\/\/\/\/\/\/\/\*/ + /* Image Classification */ + /*\/\/\/\/\/\/\/\/\/\/\/*/ + + void Connect( void ); // classifies mean shift filtered image regions using + // private classification structure of this class + + void Fill(int, int); // used by Connect to perform label each region in the + // mean shift filtered image using an eight-connected + // fill + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Transitive Closure and Image Pruning */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + void BuildRAM( void ); // build a region adjacency matrix using the region list + // object + + void DestroyRAM( void ); // destroy the region adjacency matrix: de-allocate its memory + // initialize it for re-use + + void TransitiveClosure( void ); // use the RAM to apply transitive closure to the image modes + + void ComputeEdgeStrengths( void ); // computes the weights of the weighted graph using the weight + // map + + //Usage: Prune(minRegion) + void Prune(int); // use the RAM to prune the image of spurious regions (regions + // whose area is less than minRegion pixels, where minRegion is + // an argument of this method) + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Region Boundary Detection */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + void DefineBoundaries( void ); // defines the boundaries of each region using the classified segmented + // image storing the resulting boundary locations for each region using + // a region list object + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Image Data Searching/Distance Calculation */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + //Usage: InWindow(modeIndex1, modeIndex2) + bool InWindow(int, int); //returns true if the range data of the specified data points + //are within the defined search window (defined by kernel + //bandwidth h[1]) + + float SqDistance(int, int); // computes the normalized square distance between two modes + + /*/\/\/\/\/\/\/\/\/\/\*/ + /* Memory Management */ + /*\/\/\/\/\/\/\/\/\/\/*/ + + void InitializeOutput( void ); //Allocates memory needed by this class to perform image + //filtering and segmentation + + void DestroyOutput( void ); //De-allocates memory needed by this class to perform image + //filtering and segmentation + + //============================= + // *** Private Data Members *** + //============================= + + //########################################## + //####### IMAGE CLASSIFICATION ######## + //########################################## + + /////////Image Boundaries///////// + RegionList *regionList; // stores the boundary locations for each region + + /////////Image Regions//////// + int regionCount; // stores the number of connected regions contained by the + // image + + /////////8 Connected Neighbors///////// + int neigh[8]; + + /////////Index Table///////////////// + int *indexTable; //used during fill algorithm + + /////////LUV_data///////////////// + //int *LUV_data; //stores modes in integer format on lattice + float *LUV_data; //stores modes in float format on lattice + float LUV_treshold; //in float mode this determines what "close" means between modes + + + //########################################## + //####### OUTPUT DATA STORAGE ######## + //########################################## + + ////////Raw Data (1 to 1 correlation with input)//////// + float *msRawData; // Raw data output of mean shift algorithm + // to the location of the data point on the lattice + + ////////Data Modes//////// + int *labels; // assigns a label to each data point associating it to + // a mode in modes (e.g. a data point having label l has + // mode modes[l]) + + float *modes; // stores the mode data of the input data set, indexed by labels + + int *modePointCounts; // stores for each mode the number of point mapped to that mode, + // indexed by labels + + //########################################## + //####### REGION ADJACENCY MATRIX ######## + //########################################## + + //////////Region Adjacency List///////// + RAList *raList; // an array of RAList objects containing an entry for each + // region of the image + + //////////RAMatrix Free List/////////// + RAList *freeRAList; // a pointer to the head of a region adjacency list object + // free list + + RAList *raPool; // a pool of RAList objects used in the construction of the + // RAM + + //############################################## + //####### COMPUTATION OF EDGE STRENGTHS ####### + //############################################## + + //////////Epsilon/////////// + float epsilon; //Epsilon used for transitive closure + + //////Visit Table////// + unsigned char *visitTable; //Table used to keep track of which pixels have been + //already visited upon computing the boundary edge strengths + + //########################################## + //####### IMAGE PRUNING ######## + //########################################## + + ////////Transitive Closure///////// + float rR2; //defines square range radius used when clustering pixels + //together, thus defining image regions + + float speedThreshold; // the % of window radius used in new optimized filter 2. +}; + +#endif diff --git a/Utilities/otbedison/segm/msSys.cpp b/Utilities/otbedison/segm/msSys.cpp old mode 100755 new mode 100644 index ea2b3fc5afa267f390a0d35dddb75a30a42a6799..4523170e75fb38b8fa21470e3c2ce8d3e0823403 --- a/Utilities/otbedison/segm/msSys.cpp +++ b/Utilities/otbedison/segm/msSys.cpp @@ -1,234 +1,234 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Mean Shift System: - ================== - - The Mean Shift System class provides a mechanism for the - mean shift library classes to prompt progress and to - time its computations. When porting the mean shift library - to an application the methods of this class may be changed - such that the output of the mean shift class prompts - will be given to whatever hardware or software device that - is desired. - - The definition for the mean shift system class is provided - below. Its prototype is provided in "msSys.cc". - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - -//include the msSystem class prototype -#include "msSys.h" - -//include needed system libraries -#include <time.h> -#include <stdio.h> -#include <stdarg.h> -#include <stdlib.h> - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /*** Class Constructor and Destructor ***/ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Class Constructor */ -/*******************************************************/ -/*Constructs a mean shift system object. */ -/*******************************************************/ -/*Post: */ -/* - an msSystem object has been properly init- */ -/* ialized. */ -/*******************************************************/ - -msSystem::msSystem( void ) -{ - - //initialize currentTime - currentTime = clock(); - - //done. - -} - -/*******************************************************/ -/*Class Destructor */ -/*******************************************************/ -/*Destroys a mean shift system object. */ -/*******************************************************/ -/*Post: */ -/* - an msSystem object has been properly dest- */ -/* royed. */ -/*******************************************************/ - -msSystem::~msSystem( void ) -{ - /* do nothing */ -} - - /*/\/\/\/\/\/\/\/\/\*/ - /*** System Timer ***/ - /*\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Start Timer */ -/*******************************************************/ -/*Sets the mean shift system time to the current */ -/*system time. */ -/*******************************************************/ -/*Post: */ -/* - the mean shift system time has been set to */ -/* the current system time. */ -/*******************************************************/ - -void msSystem::StartTimer( void ) -{ - - //set msSystem time to system time - currentTime = clock(); - - //done. - return; - -} - -/*******************************************************/ -/*Elapsed Time */ -/*******************************************************/ -/*Returns the amount of time in seconds since the */ -/*mean shift system time was last set. */ -/*******************************************************/ -/*Post: */ -/* - the amount of time in seconds since the mean */ -/* shift system time was last set is returned. */ -/*******************************************************/ - -double msSystem::ElapsedTime( void ) -{ - - //return the amount of time elapsed in seconds - //since the msSystem time was last set... - return ((double) (clock() - currentTime))/(CLOCKS_PER_SEC); - -} - - /*/\/\/\/\/\/\/\/\/\/\*/ - /*** System Output ***/ - /*\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Prompt */ -/*******************************************************/ -/*Output a text message to the user. */ -/*******************************************************/ -/*Pre: */ -/* - PromptStr is a string containing delimeters */ -/* that is to be output to the user. */ -/* - a variable set of arguments is also passed */ -/* to this method that are used to replace */ -/* the delimeters contained by PromptStr */ -/*Post: */ -/* - the delimeters of PromptStr have been */ -/* replaced accordingly using the variable */ -/* set of arguments and the resulting string */ -/* has been output to the user. */ -/*******************************************************/ - -extern void bgLogVar(const char *, va_list); - -void msSystem::Prompt(const char *PromptStr, ...) -{ - - //obtain argument list using ANSI standard... - va_list argList; - va_start(argList, PromptStr); - - //print the output string to stderr using - //vfprintf - bgLogVar(PromptStr, argList); - va_end(argList); - - //done. - return; - -} - -/*******************************************************/ -/*Progress */ -/*******************************************************/ -/*The progress of a specific algorithm of the mean */ -/*shift library is output to the user. */ -/*******************************************************/ -/*Pre: */ -/* - percentComplete indicates the percentage */ -/* of the algorithm that has executed and is */ -/* a floating point number from zero to one */ -/*Post: */ -/* - the percentComplete has been noted by the */ -/* interface (possibly to update a progress */ -/* bar). */ -/* - if the thread executing the mean shift code */ -/* must halt execution msSYS_HALT is returned, */ -/* msSYS_OK is returned otherwise */ -/*******************************************************/ - -/////////////////////////////////////////////////////////////////// -//NOTE: This implementation is specific to EDISON. In order -// for one to port the mean shift class to another project -// or program one must re-implement this method. -/////////////////////////////////////////////////////////////////// - -//is set by the GUI when the user presses the Cancel button -//on the wxWindows progress modal window; this flag indicates -//to the mean shift library that it is to halt execution. -//This parameter is used and checked in the method -//BgMdiSegmentChild::OnSegment. -extern bool stop_flag; - -//is updated in the msSystem::Progress method and indicates to -//the wxWindows progress modal window the percent complete, such -//that it may update its progress bar accordingly; This parameter -//is used and checked in the method BgMdiSegmentChild::OnSegment. -extern int percentDone; - -ErrorLevel msSystem::Progress(float percentComplete) -{ - percentDone = (int)(percentComplete*100); - - //check stop flag and return appropriate system state - ErrorLevel myState = EL_OKAY; - if(stop_flag) myState = EL_HALT; - - //done. - return myState; - -} - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Mean Shift System: + ================== + + The Mean Shift System class provides a mechanism for the + mean shift library classes to prompt progress and to + time its computations. When porting the mean shift library + to an application the methods of this class may be changed + such that the output of the mean shift class prompts + will be given to whatever hardware or software device that + is desired. + + The definition for the mean shift system class is provided + below. Its prototype is provided in "msSys.cc". + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + +//include the msSystem class prototype +#include "msSys.h" + +//include needed system libraries +#include <time.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /*** Class Constructor and Destructor ***/ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Class Constructor */ +/*******************************************************/ +/*Constructs a mean shift system object. */ +/*******************************************************/ +/*Post: */ +/* - an msSystem object has been properly init- */ +/* ialized. */ +/*******************************************************/ + +msSystem::msSystem( void ) +{ + + //initialize currentTime + currentTime = clock(); + + //done. + +} + +/*******************************************************/ +/*Class Destructor */ +/*******************************************************/ +/*Destroys a mean shift system object. */ +/*******************************************************/ +/*Post: */ +/* - an msSystem object has been properly dest- */ +/* royed. */ +/*******************************************************/ + +msSystem::~msSystem( void ) +{ + /* do nothing */ +} + + /*/\/\/\/\/\/\/\/\/\*/ + /*** System Timer ***/ + /*\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Start Timer */ +/*******************************************************/ +/*Sets the mean shift system time to the current */ +/*system time. */ +/*******************************************************/ +/*Post: */ +/* - the mean shift system time has been set to */ +/* the current system time. */ +/*******************************************************/ + +void msSystem::StartTimer( void ) +{ + + //set msSystem time to system time + currentTime = clock(); + + //done. + return; + +} + +/*******************************************************/ +/*Elapsed Time */ +/*******************************************************/ +/*Returns the amount of time in seconds since the */ +/*mean shift system time was last set. */ +/*******************************************************/ +/*Post: */ +/* - the amount of time in seconds since the mean */ +/* shift system time was last set is returned. */ +/*******************************************************/ + +double msSystem::ElapsedTime( void ) +{ + + //return the amount of time elapsed in seconds + //since the msSystem time was last set... + return ((double) (clock() - currentTime))/(CLOCKS_PER_SEC); + +} + + /*/\/\/\/\/\/\/\/\/\/\*/ + /*** System Output ***/ + /*\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Prompt */ +/*******************************************************/ +/*Output a text message to the user. */ +/*******************************************************/ +/*Pre: */ +/* - PromptStr is a string containing delimeters */ +/* that is to be output to the user. */ +/* - a variable set of arguments is also passed */ +/* to this method that are used to replace */ +/* the delimeters contained by PromptStr */ +/*Post: */ +/* - the delimeters of PromptStr have been */ +/* replaced accordingly using the variable */ +/* set of arguments and the resulting string */ +/* has been output to the user. */ +/*******************************************************/ + +extern void bgLogVar(const char *, va_list); + +void msSystem::Prompt(const char *PromptStr, ...) +{ + + //obtain argument list using ANSI standard... + va_list argList; + va_start(argList, PromptStr); + + //print the output string to stderr using + //vfprintf + bgLogVar(PromptStr, argList); + va_end(argList); + + //done. + return; + +} + +/*******************************************************/ +/*Progress */ +/*******************************************************/ +/*The progress of a specific algorithm of the mean */ +/*shift library is output to the user. */ +/*******************************************************/ +/*Pre: */ +/* - percentComplete indicates the percentage */ +/* of the algorithm that has executed and is */ +/* a floating point number from zero to one */ +/*Post: */ +/* - the percentComplete has been noted by the */ +/* interface (possibly to update a progress */ +/* bar). */ +/* - if the thread executing the mean shift code */ +/* must halt execution msSYS_HALT is returned, */ +/* msSYS_OK is returned otherwise */ +/*******************************************************/ + +/////////////////////////////////////////////////////////////////// +//NOTE: This implementation is specific to EDISON. In order +// for one to port the mean shift class to another project +// or program one must re-implement this method. +/////////////////////////////////////////////////////////////////// + +//is set by the GUI when the user presses the Cancel button +//on the wxWindows progress modal window; this flag indicates +//to the mean shift library that it is to halt execution. +//This parameter is used and checked in the method +//BgMdiSegmentChild::OnSegment. +extern bool stop_flag; + +//is updated in the msSystem::Progress method and indicates to +//the wxWindows progress modal window the percent complete, such +//that it may update its progress bar accordingly; This parameter +//is used and checked in the method BgMdiSegmentChild::OnSegment. +extern int percentDone; + +ErrorLevel msSystem::Progress(float percentComplete) +{ + percentDone = (int)(percentComplete*100); + + //check stop flag and return appropriate system state + ErrorLevel myState = EL_OKAY; + if(stop_flag) myState = EL_HALT; + + //done. + return myState; + +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ diff --git a/Utilities/otbedison/segm/msSys.h b/Utilities/otbedison/segm/msSys.h old mode 100755 new mode 100644 index 9bd968d6c16229f3d5942860f69ed3d400c11b31..d7411b0941661bcc318a9bc5516facf7483e5a0b --- a/Utilities/otbedison/segm/msSys.h +++ b/Utilities/otbedison/segm/msSys.h @@ -1,229 +1,229 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Mean Shift System: - ================== - - The Mean Shift System class provides a mechanism for the - mean shift library classes to prompt progress and to - time its computations. When porting the mean shift library - to an application the methods of this class may be changed - such that the output of the mean shift class prompts - will be given to whatever hardware or software device that - is desired. - - The prototype for the mean shift system class is provided - below. Its defition is provided in "msSys.cc". - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - - -#ifndef MSSYS_H -#define MSSYS_H - -//Include standard mean shift library type definitions -#include "tdef.h" - -//Include standard libraries needed for msSystem prototype -#include <time.h> - -extern void bgLogFile(const char*, ...); - -//Mean Shify System class prototype -class msSystem { - - public: - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Class Constructor and Destructor */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - msSystem( void ); //Default Constructor - ~msSystem( void ); //Class Destructor - - /*/\/\/\/\/\/\/\*/ - /* System Timer */ - /*\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Start Timer * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Initializes the system timer. The timer object |// - //| synthesized by this class is initialized during |// - //| construction of the msSystem class to be the |// - //| current time during construction. |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void StartTimer( void ); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Elapsed Time * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns the amount of time elapsed in seconds |// - //| from when StartTimer() was called. If |// - //| StartTimer() was not called, the time returned |// - //| is the time elapsed from the construction of the |// - //| msSystem object. |// - //| |// - //| In order to create a valid kernel the following |// - //| argumens must be provided this method: |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| TimeInSeconds = ElapsedTime() |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - double ElapsedTime( void ); - - /*/\/\/\/\/\/\/\/\*/ - /* System Output */ - /*\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Prompt * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Outputs to a device a character message contain- |// - //| ing delimeters. These delimeters are replaced by |// - //| the variable input parameters passed to prompt. |// - //| (Like printf.) |// - //| |// - //| This method should be altered if a special |// - //| device either than stderr is desired to be used |// - //| as an output prompt. |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* PromptStr *> |// - //| A string possibly containing delimeters that |// - //| is to be output to the user. |// - //| |// - //| <* varArgs *> |// - //| A variable set of arguments to be placed into |// - //| the prompt string. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| Prompt(PromptStr, varArgs) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void Prompt(const char*, ...); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Progress * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| This method is called by the mean shift library |// - //| methods during the application of a specific |// - //| algorithm in which the progress of the algorithm |// - //| is indicated. Its main use is for a multi-thre- |// - //| aded programming envioronment. Namely, it is |// - //| called fairly frequently by the mean shift |// - //| library methods. It then can be used to grace- |// - //| fully halt the algorithm, or to simply update |// - //| a progress bar. |// - //| |// - //| This method depends strongly on the interface |// - //| and therefore must be re-implemented to accom- |// - //| odate ones needs. |// - //| |// - //| To facilitate a multi-threaded enviornment |// - //| the prompt function returns a value that |// - //| indicates to the mean shift method whether |// - //| to continue execution. EL_HALT is returned |// - //| when the mean shift procedure is to stop |// - //| execution and EL_OKAY is returned otherwise. |// - //| |// - //| The arguments to this method are: |// - //| |// - //| <* PercentComplete *> |// - //| A floating point number that indicates the perc- |// - //| ent complete of the algorithm. PercentComplete |// - //| takes a value between zero and one. |// - //| |// - //| <* SystemState *> |// - //| Indicates the system state. It is EL_HALT |// - //| when the mean shift method is to halt execution |// - //| and it is EL_OKAY otherwise. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| SystemState = Progress(PercentComplete) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - ErrorLevel Progress(float); - - private: - - //Timer object... - time_t currentTime; - -}; - -#endif +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Mean Shift System: + ================== + + The Mean Shift System class provides a mechanism for the + mean shift library classes to prompt progress and to + time its computations. When porting the mean shift library + to an application the methods of this class may be changed + such that the output of the mean shift class prompts + will be given to whatever hardware or software device that + is desired. + + The prototype for the mean shift system class is provided + below. Its defition is provided in "msSys.cc". + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + + +#ifndef MSSYS_H +#define MSSYS_H + +//Include standard mean shift library type definitions +#include "tdef.h" + +//Include standard libraries needed for msSystem prototype +#include <time.h> + +extern void bgLogFile(const char*, ...); + +//Mean Shify System class prototype +class msSystem { + + public: + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Class Constructor and Destructor */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + msSystem( void ); //Default Constructor + ~msSystem( void ); //Class Destructor + + /*/\/\/\/\/\/\/\*/ + /* System Timer */ + /*\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Start Timer * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Initializes the system timer. The timer object |// + //| synthesized by this class is initialized during |// + //| construction of the msSystem class to be the |// + //| current time during construction. |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void StartTimer( void ); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Elapsed Time * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns the amount of time elapsed in seconds |// + //| from when StartTimer() was called. If |// + //| StartTimer() was not called, the time returned |// + //| is the time elapsed from the construction of the |// + //| msSystem object. |// + //| |// + //| In order to create a valid kernel the following |// + //| argumens must be provided this method: |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| TimeInSeconds = ElapsedTime() |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + double ElapsedTime( void ); + + /*/\/\/\/\/\/\/\/\*/ + /* System Output */ + /*\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Prompt * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Outputs to a device a character message contain- |// + //| ing delimeters. These delimeters are replaced by |// + //| the variable input parameters passed to prompt. |// + //| (Like printf.) |// + //| |// + //| This method should be altered if a special |// + //| device either than stderr is desired to be used |// + //| as an output prompt. |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* PromptStr *> |// + //| A string possibly containing delimeters that |// + //| is to be output to the user. |// + //| |// + //| <* varArgs *> |// + //| A variable set of arguments to be placed into |// + //| the prompt string. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| Prompt(PromptStr, varArgs) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void Prompt(const char*, ...); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Progress * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| This method is called by the mean shift library |// + //| methods during the application of a specific |// + //| algorithm in which the progress of the algorithm |// + //| is indicated. Its main use is for a multi-thre- |// + //| aded programming envioronment. Namely, it is |// + //| called fairly frequently by the mean shift |// + //| library methods. It then can be used to grace- |// + //| fully halt the algorithm, or to simply update |// + //| a progress bar. |// + //| |// + //| This method depends strongly on the interface |// + //| and therefore must be re-implemented to accom- |// + //| odate ones needs. |// + //| |// + //| To facilitate a multi-threaded enviornment |// + //| the prompt function returns a value that |// + //| indicates to the mean shift method whether |// + //| to continue execution. EL_HALT is returned |// + //| when the mean shift procedure is to stop |// + //| execution and EL_OKAY is returned otherwise. |// + //| |// + //| The arguments to this method are: |// + //| |// + //| <* PercentComplete *> |// + //| A floating point number that indicates the perc- |// + //| ent complete of the algorithm. PercentComplete |// + //| takes a value between zero and one. |// + //| |// + //| <* SystemState *> |// + //| Indicates the system state. It is EL_HALT |// + //| when the mean shift method is to halt execution |// + //| and it is EL_OKAY otherwise. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| SystemState = Progress(PercentComplete) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + ErrorLevel Progress(float); + + private: + + //Timer object... + time_t currentTime; + +}; + +#endif diff --git a/Utilities/otbedison/segm/msSysPrompt.cpp b/Utilities/otbedison/segm/msSysPrompt.cpp old mode 100755 new mode 100644 index 8ca2f4b9f8b937a3d37083ec0fc3e281c63ec9fe..a4f2f43e980e867a729f31844303c31d864f123b --- a/Utilities/otbedison/segm/msSysPrompt.cpp +++ b/Utilities/otbedison/segm/msSysPrompt.cpp @@ -1,232 +1,232 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Mean Shift System: - ================== - - The Mean Shift System class provides a mechanism for the - mean shift library classes to prompt progress and to - time its computations. When porting the mean shift library - to an application the methods of this class may be changed - such that the output of the mean shift class prompts - will be given to whatever hardware or software device that - is desired. - - The definition for the mean shift system class is provided - below. Its prototype is provided in "msSys.cc". - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - -//////////////////////////////////////////////////////////////////////// -// Command Line Version: -// This version of mean shift system is written for the command -// line version of EDISON. -//////////////////////////////////////////////////////////////////////// - -//include the msSystem class prototype -#include "msSys.h" - -//include needed system libraries -#include <time.h> -#include <stdio.h> -#include <stdarg.h> -#include <stdlib.h> - -//define bgLog -extern bool CmCDisplayProgress; -void bgLog(const char *PromptStr, ...) -{ - //obtain argument list using ANSI standard... - va_list argList; - va_start(argList, PromptStr); - - //print the output string to stderr using - if(CmCDisplayProgress) vfprintf(stdout, PromptStr, argList); - va_end(argList); - - //done. - return; -} - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /*** Class Constructor and Destructor ***/ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Class Constructor */ -/*******************************************************/ -/*Constructs a mean shift system object. */ -/*******************************************************/ -/*Post: */ -/* - an msSystem object has been properly init- */ -/* ialized. */ -/*******************************************************/ - -msSystem::msSystem( void ) -{ - - //initialize currentTime - currentTime = clock(); - - //done. - -} - -/*******************************************************/ -/*Class Destructor */ -/*******************************************************/ -/*Destroys a mean shift system object. */ -/*******************************************************/ -/*Post: */ -/* - an msSystem object has been properly dest- */ -/* royed. */ -/*******************************************************/ - -msSystem::~msSystem( void ) -{ - /* do nothing */ -} - - /*/\/\/\/\/\/\/\/\/\*/ - /*** System Timer ***/ - /*\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Start Timer */ -/*******************************************************/ -/*Sets the mean shift system time to the current */ -/*system time. */ -/*******************************************************/ -/*Post: */ -/* - the mean shift system time has been set to */ -/* the current system time. */ -/*******************************************************/ - -void msSystem::StartTimer( void ) -{ - - //set msSystem time to system time - currentTime = clock(); - - //done. - return; - -} - -/*******************************************************/ -/*Elapsed Time */ -/*******************************************************/ -/*Returns the amount of time in seconds since the */ -/*mean shift system time was last set. */ -/*******************************************************/ -/*Post: */ -/* - the amount of time in seconds since the mean */ -/* shift system time was last set is returned. */ -/*******************************************************/ - -double msSystem::ElapsedTime( void ) -{ - - //return the amount of time elapsed in seconds - //since the msSystem time was last set... - return ((double) (clock() - currentTime))/(CLOCKS_PER_SEC); - -} - - /*/\/\/\/\/\/\/\/\/\/\*/ - /*** System Output ***/ - /*\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Prompt */ -/*******************************************************/ -/*Output a text message to the user. */ -/*******************************************************/ -/*Pre: */ -/* - PromptStr is a string containing delimeters */ -/* that is to be output to the user. */ -/* - a variable set of arguments is also passed */ -/* to this method that are used to replace */ -/* the delimeters contained by PromptStr */ -/*Post: */ -/* - the delimeters of PromptStr have been */ -/* replaced accordingly using the variable */ -/* set of arguments and the resulting string */ -/* has been output to the user. */ -/*******************************************************/ - -void msSystem::Prompt(const char *PromptStr, ...) -{ - - //obtain argument list using ANSI standard... - va_list argList; - va_start(argList, PromptStr); - - //print the output string to stderr using - if(CmCDisplayProgress) vfprintf(stdout, PromptStr, argList); - va_end(argList); - - //done. - return; - -} - -/*******************************************************/ -/*Progress */ -/*******************************************************/ -/*The progress of a specific algorithm of the mean */ -/*shift library is output to the user. */ -/*******************************************************/ -/*Pre: */ -/* - percentComplete indicates the percentage */ -/* of the algorithm that has executed and is */ -/* a floating point number from zero to one */ -/*Post: */ -/* - the percentComplete has been noted by the */ -/* interface (possibly to update a progress */ -/* bar). */ -/* - if the thread executing the mean shift code */ -/* must halt execution msSYS_HALT is returned, */ -/* msSYS_OK is returned otherwise */ -/*******************************************************/ - -/////////////////////////////////////////////////////////////////// -//NOTE: This implementation is specific to EDISON. In order -// for one to port the mean shift class to another project -// or program one must re-implement this method. -/////////////////////////////////////////////////////////////////// - -ErrorLevel msSystem::Progress(float percentComplete) -{ - return EL_OKAY; -} - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Mean Shift System: + ================== + + The Mean Shift System class provides a mechanism for the + mean shift library classes to prompt progress and to + time its computations. When porting the mean shift library + to an application the methods of this class may be changed + such that the output of the mean shift class prompts + will be given to whatever hardware or software device that + is desired. + + The definition for the mean shift system class is provided + below. Its prototype is provided in "msSys.cc". + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + +//////////////////////////////////////////////////////////////////////// +// Command Line Version: +// This version of mean shift system is written for the command +// line version of EDISON. +//////////////////////////////////////////////////////////////////////// + +//include the msSystem class prototype +#include "msSys.h" + +//include needed system libraries +#include <time.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> + +//define bgLog +extern bool CmCDisplayProgress; +void bgLog(const char *PromptStr, ...) +{ + //obtain argument list using ANSI standard... + va_list argList; + va_start(argList, PromptStr); + + //print the output string to stderr using + if(CmCDisplayProgress) vfprintf(stdout, PromptStr, argList); + va_end(argList); + + //done. + return; +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /*** Class Constructor and Destructor ***/ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Class Constructor */ +/*******************************************************/ +/*Constructs a mean shift system object. */ +/*******************************************************/ +/*Post: */ +/* - an msSystem object has been properly init- */ +/* ialized. */ +/*******************************************************/ + +msSystem::msSystem( void ) +{ + + //initialize currentTime + currentTime = clock(); + + //done. + +} + +/*******************************************************/ +/*Class Destructor */ +/*******************************************************/ +/*Destroys a mean shift system object. */ +/*******************************************************/ +/*Post: */ +/* - an msSystem object has been properly dest- */ +/* royed. */ +/*******************************************************/ + +msSystem::~msSystem( void ) +{ + /* do nothing */ +} + + /*/\/\/\/\/\/\/\/\/\*/ + /*** System Timer ***/ + /*\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Start Timer */ +/*******************************************************/ +/*Sets the mean shift system time to the current */ +/*system time. */ +/*******************************************************/ +/*Post: */ +/* - the mean shift system time has been set to */ +/* the current system time. */ +/*******************************************************/ + +void msSystem::StartTimer( void ) +{ + + //set msSystem time to system time + currentTime = clock(); + + //done. + return; + +} + +/*******************************************************/ +/*Elapsed Time */ +/*******************************************************/ +/*Returns the amount of time in seconds since the */ +/*mean shift system time was last set. */ +/*******************************************************/ +/*Post: */ +/* - the amount of time in seconds since the mean */ +/* shift system time was last set is returned. */ +/*******************************************************/ + +double msSystem::ElapsedTime( void ) +{ + + //return the amount of time elapsed in seconds + //since the msSystem time was last set... + return ((double) (clock() - currentTime))/(CLOCKS_PER_SEC); + +} + + /*/\/\/\/\/\/\/\/\/\/\*/ + /*** System Output ***/ + /*\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Prompt */ +/*******************************************************/ +/*Output a text message to the user. */ +/*******************************************************/ +/*Pre: */ +/* - PromptStr is a string containing delimeters */ +/* that is to be output to the user. */ +/* - a variable set of arguments is also passed */ +/* to this method that are used to replace */ +/* the delimeters contained by PromptStr */ +/*Post: */ +/* - the delimeters of PromptStr have been */ +/* replaced accordingly using the variable */ +/* set of arguments and the resulting string */ +/* has been output to the user. */ +/*******************************************************/ + +void msSystem::Prompt(const char *PromptStr, ...) +{ + + //obtain argument list using ANSI standard... + va_list argList; + va_start(argList, PromptStr); + + //print the output string to stderr using + if(CmCDisplayProgress) vfprintf(stdout, PromptStr, argList); + va_end(argList); + + //done. + return; + +} + +/*******************************************************/ +/*Progress */ +/*******************************************************/ +/*The progress of a specific algorithm of the mean */ +/*shift library is output to the user. */ +/*******************************************************/ +/*Pre: */ +/* - percentComplete indicates the percentage */ +/* of the algorithm that has executed and is */ +/* a floating point number from zero to one */ +/*Post: */ +/* - the percentComplete has been noted by the */ +/* interface (possibly to update a progress */ +/* bar). */ +/* - if the thread executing the mean shift code */ +/* must halt execution msSYS_HALT is returned, */ +/* msSYS_OK is returned otherwise */ +/*******************************************************/ + +/////////////////////////////////////////////////////////////////// +//NOTE: This implementation is specific to EDISON. In order +// for one to port the mean shift class to another project +// or program one must re-implement this method. +/////////////////////////////////////////////////////////////////// + +ErrorLevel msSystem::Progress(float percentComplete) +{ + return EL_OKAY; +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ diff --git a/Utilities/otbedison/segm/rlist.cpp b/Utilities/otbedison/segm/rlist.cpp old mode 100755 new mode 100644 index d613c9cfb5f9725726de0f16ef85cebe832fd90a..3b0da9dae1d8781efd757c37e0764198717a9276 --- a/Utilities/otbedison/segm/rlist.cpp +++ b/Utilities/otbedison/segm/rlist.cpp @@ -1,339 +1,339 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Region List Class: - ================= - - During segmentation, data regions are defined. The - RegionList class provides a mechanism for doing so, as - well as defines some basic operations, such as region - growing or small region pruning, on the defined regions. - It is defined below. Its prototype is given in "region.h". - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - - -#include "rlist.h" -#include <stdio.h> -#include <stdlib.h> - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /*** Class Constructor and Destructor ***/ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Constructor */ -/*******************************************************/ -/*Constructor */ -/*******************************************************/ -/*Pre: */ -/* - modesPtr is a pointer to an array of modes */ -/* - maxRegions_ is the maximum number of regions */ -/* that can be defined */ -/* - L_ is the number of data points being class- */ -/* ified by the region list class */ -/* - N is the dimension of the data set being cl- */ -/* assified by the region list class */ -/*Post: */ -/* - a region list object has been properly init- */ -/* ialized. */ -/*******************************************************/ - -RegionList::RegionList(int maxRegions_, int L_, int N_) -{ - - //Obtain maximum number of regions that can be - //defined by user - if((maxRegions = maxRegions_) <= 0) - ErrorHandler("RegionList", "Maximum number of regions is zero or negative.", FATAL); - - //Obtain dimension of data set being classified by - //region list class - if((N = N_) <= 0) - ErrorHandler("RegionList", "Dimension is zero or negative.", FATAL); - - //Obtain length of input data set... - if((L = L_) <= 0) - ErrorHandler("RegionList", "Length of data set is zero or negative.", FATAL); - - //Allocate memory for index table - if(!(indexTable = new int [L])) - ErrorHandler("RegionList", "Not enough memory.", FATAL); - - //Allocate memory for region list array - if(!(regionList = new REGION [maxRegions])) - ErrorHandler("RegionList", "Not enough memory.", FATAL); - - //Initialize region list... - numRegions = freeRegion = 0; - - //Initialize indexTable - freeBlockLoc = 0; - - //done. - return; - -} - -/*******************************************************/ -/*Destructor */ -/*******************************************************/ -/*Destroys region list object. */ -/*******************************************************/ -/*Post: */ -/* - region list object has been properly dest- */ -/* oyed. */ -/*******************************************************/ - -RegionList::~RegionList( void ) -{ - //de-allocate memory... - delete [] regionList; - delete [] indexTable; - - //done. - return; -} - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /*** Region List Manipulation ***/ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Add Region */ -/*******************************************************/ -/*Adds a region to the region list. */ -/*******************************************************/ -/*Pre: */ -/* - label is a positive integer used to uniquely */ -/* identify a region */ -/* - pointCount is the number of N-dimensional */ -/* data points that exist in the region being */ -/* classified. */ -/* - indeces is a set of indeces specifying the */ -/* data points contained within this region */ -/* - pointCount must be > 0 */ -/*Post: */ -/* - a new region labeled using label and contai- */ -/* ning pointCount number of points has been */ -/* added to the region list. */ -/*******************************************************/ - -void RegionList::AddRegion(int label, int pointCount, int *indeces) -{ - - //make sure that there is enough room for this new region - //in the region list array... - if(numRegions >= maxRegions) - ErrorHandler("AddRegion", "Not enough memory allocated.", FATAL); - - //make sure that label is positive and point Count > 0... - if((label < 0)||(pointCount <= 0)) - ErrorHandler("AddRegion", "Label is negative or number of points in region is invalid.", FATAL); - - //make sure that there is enough memory in the indexTable - //for this region... - if((freeBlockLoc + pointCount) > L) - ErrorHandler("AddRegion", "Adding more points than what is contained in data set.", FATAL); - - //place new region into region list array using - //freeRegion index - regionList[freeRegion].label = label; - regionList[freeRegion].pointCount = pointCount; - regionList[freeRegion].region = freeBlockLoc; - - //copy indeces into indexTable using freeBlock... - int i; - for(i = 0; i < pointCount; i++) - indexTable[freeBlockLoc+i] = indeces[i]; - - //increment freeBlock to point to the next free - //block - freeBlockLoc += pointCount; - - //increment freeRegion to point to the next free region - //also, increment numRegions to indicate that another - //region has been added to the region list - freeRegion++; - numRegions++; - - //done. - return; - -} - -/*******************************************************/ -/*Reset */ -/*******************************************************/ -/*Resets the region list. */ -/*******************************************************/ -/*Post: */ -/* - the region list has been reset. */ -/*******************************************************/ - -void RegionList::Reset( void ) -{ - - //reset region list - freeRegion = numRegions = freeBlockLoc = 0; - - //done. - return; - -} - - /*/\/\/\/\/\/\/\/\/\/\*/ - /* Query Region List */ - /*\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Get Number Regions */ -/*******************************************************/ -/*Returns the number of regions stored by region list. */ -/*******************************************************/ -/*Post: */ -/* - the number of regions stored by the region */ -/* list is returned. */ -/*******************************************************/ - -int RegionList::GetNumRegions( void ) -{ - // return region count - return numRegions; -} - -/*******************************************************/ -/*Get Label */ -/*******************************************************/ -/*Returns the label of a specified region. */ -/*******************************************************/ -/*Pre: */ -/* - regionNum is an index into the region list */ -/* array. */ -/*Post: */ -/* - the label of the region having region index */ -/* specified by regionNum has been returned. */ -/*******************************************************/ - -int RegionList::GetLabel(int regionNum) -{ - //return the label of a specified region - return regionList[regionNum].label; -} - -/*******************************************************/ -/*Get Region Count */ -/*******************************************************/ -/*Returns the point count of a specified region. */ -/*******************************************************/ -/*Pre: */ -/* - regionNum is an index into the region list */ -/* array. */ -/*Post: */ -/* - the number of points that classify the */ -/* region whose index is specified by regionNum */ -/* is returned. */ -/*******************************************************/ - -int RegionList::GetRegionCount(int regionNum) -{ - //return the region count of a specified region - return regionList[regionNum].pointCount; -} - -/*******************************************************/ -/*Get Region Indeces */ -/*******************************************************/ -/*Returns the point indeces specifying a region. */ -/*******************************************************/ -/*Pre: */ -/* - regionNum is an index into the region list */ -/* array. */ -/*Post: */ -/* - the region indeces specifying the points */ -/* contained by the region specified by region- */ -/* Num are returned. */ -/*******************************************************/ - -int *RegionList::GetRegionIndeces(int regionNum) -{ - //return point indeces using regionNum - return &indexTable[regionList[regionNum].region]; -} - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PRIVATE METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ - - /*/\/\/\/\/\/\/\/\/\/\/\*/ - /* Class Error Handler */ - /*\/\/\/\/\/\/\/\/\/\/\/*/ - -/*******************************************************/ -/*Error Handler */ -/*******************************************************/ -/*Class error handler. */ -/*******************************************************/ -/*Pre: */ -/* - functName is the name of the function that */ -/* caused an error */ -/* - errmsg is the error message given by the */ -/* calling function */ -/* - status is the error status: FATAL or NON- */ -/* FATAL */ -/*Post: */ -/* - the error message errmsg is flagged on beh- */ -/* ave of function functName. */ -/* - if the error status is FATAL then the program*/ -/* is halted, otherwise execution is continued, */ -/* error recovery is assumed to be handled by */ -/* the calling function. */ -/*******************************************************/ - -void RegionList::ErrorHandler(char *functName, char* errmsg, ErrorType status) -{ - - //flag error message on behalf of calling function, error format - //specified by the error status... - if(status == NONFATAL) - fprintf(stderr, "\n%s Error: %s\n", functName, errmsg); - else - { - fprintf(stderr, "\n%s Fatal Error: %s\n\nAborting Program.\n\n", functName, errmsg); - exit(1); - } - -} - -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ -/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Region List Class: + ================= + + During segmentation, data regions are defined. The + RegionList class provides a mechanism for doing so, as + well as defines some basic operations, such as region + growing or small region pruning, on the defined regions. + It is defined below. Its prototype is given in "region.h". + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + + +#include "rlist.h" +#include <stdio.h> +#include <stdlib.h> + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PUBLIC METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /*** Class Constructor and Destructor ***/ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Constructor */ +/*******************************************************/ +/*Constructor */ +/*******************************************************/ +/*Pre: */ +/* - modesPtr is a pointer to an array of modes */ +/* - maxRegions_ is the maximum number of regions */ +/* that can be defined */ +/* - L_ is the number of data points being class- */ +/* ified by the region list class */ +/* - N is the dimension of the data set being cl- */ +/* assified by the region list class */ +/*Post: */ +/* - a region list object has been properly init- */ +/* ialized. */ +/*******************************************************/ + +RegionList::RegionList(int maxRegions_, int L_, int N_) +{ + + //Obtain maximum number of regions that can be + //defined by user + if((maxRegions = maxRegions_) <= 0) + ErrorHandler("RegionList", "Maximum number of regions is zero or negative.", FATAL); + + //Obtain dimension of data set being classified by + //region list class + if((N = N_) <= 0) + ErrorHandler("RegionList", "Dimension is zero or negative.", FATAL); + + //Obtain length of input data set... + if((L = L_) <= 0) + ErrorHandler("RegionList", "Length of data set is zero or negative.", FATAL); + + //Allocate memory for index table + if(!(indexTable = new int [L])) + ErrorHandler("RegionList", "Not enough memory.", FATAL); + + //Allocate memory for region list array + if(!(regionList = new REGION [maxRegions])) + ErrorHandler("RegionList", "Not enough memory.", FATAL); + + //Initialize region list... + numRegions = freeRegion = 0; + + //Initialize indexTable + freeBlockLoc = 0; + + //done. + return; + +} + +/*******************************************************/ +/*Destructor */ +/*******************************************************/ +/*Destroys region list object. */ +/*******************************************************/ +/*Post: */ +/* - region list object has been properly dest- */ +/* oyed. */ +/*******************************************************/ + +RegionList::~RegionList( void ) +{ + //de-allocate memory... + delete [] regionList; + delete [] indexTable; + + //done. + return; +} + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /*** Region List Manipulation ***/ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Add Region */ +/*******************************************************/ +/*Adds a region to the region list. */ +/*******************************************************/ +/*Pre: */ +/* - label is a positive integer used to uniquely */ +/* identify a region */ +/* - pointCount is the number of N-dimensional */ +/* data points that exist in the region being */ +/* classified. */ +/* - indeces is a set of indeces specifying the */ +/* data points contained within this region */ +/* - pointCount must be > 0 */ +/*Post: */ +/* - a new region labeled using label and contai- */ +/* ning pointCount number of points has been */ +/* added to the region list. */ +/*******************************************************/ + +void RegionList::AddRegion(int label, int pointCount, int *indeces) +{ + + //make sure that there is enough room for this new region + //in the region list array... + if(numRegions >= maxRegions) + ErrorHandler("AddRegion", "Not enough memory allocated.", FATAL); + + //make sure that label is positive and point Count > 0... + if((label < 0)||(pointCount <= 0)) + ErrorHandler("AddRegion", "Label is negative or number of points in region is invalid.", FATAL); + + //make sure that there is enough memory in the indexTable + //for this region... + if((freeBlockLoc + pointCount) > L) + ErrorHandler("AddRegion", "Adding more points than what is contained in data set.", FATAL); + + //place new region into region list array using + //freeRegion index + regionList[freeRegion].label = label; + regionList[freeRegion].pointCount = pointCount; + regionList[freeRegion].region = freeBlockLoc; + + //copy indeces into indexTable using freeBlock... + int i; + for(i = 0; i < pointCount; i++) + indexTable[freeBlockLoc+i] = indeces[i]; + + //increment freeBlock to point to the next free + //block + freeBlockLoc += pointCount; + + //increment freeRegion to point to the next free region + //also, increment numRegions to indicate that another + //region has been added to the region list + freeRegion++; + numRegions++; + + //done. + return; + +} + +/*******************************************************/ +/*Reset */ +/*******************************************************/ +/*Resets the region list. */ +/*******************************************************/ +/*Post: */ +/* - the region list has been reset. */ +/*******************************************************/ + +void RegionList::Reset( void ) +{ + + //reset region list + freeRegion = numRegions = freeBlockLoc = 0; + + //done. + return; + +} + + /*/\/\/\/\/\/\/\/\/\/\*/ + /* Query Region List */ + /*\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Get Number Regions */ +/*******************************************************/ +/*Returns the number of regions stored by region list. */ +/*******************************************************/ +/*Post: */ +/* - the number of regions stored by the region */ +/* list is returned. */ +/*******************************************************/ + +int RegionList::GetNumRegions( void ) +{ + // return region count + return numRegions; +} + +/*******************************************************/ +/*Get Label */ +/*******************************************************/ +/*Returns the label of a specified region. */ +/*******************************************************/ +/*Pre: */ +/* - regionNum is an index into the region list */ +/* array. */ +/*Post: */ +/* - the label of the region having region index */ +/* specified by regionNum has been returned. */ +/*******************************************************/ + +int RegionList::GetLabel(int regionNum) +{ + //return the label of a specified region + return regionList[regionNum].label; +} + +/*******************************************************/ +/*Get Region Count */ +/*******************************************************/ +/*Returns the point count of a specified region. */ +/*******************************************************/ +/*Pre: */ +/* - regionNum is an index into the region list */ +/* array. */ +/*Post: */ +/* - the number of points that classify the */ +/* region whose index is specified by regionNum */ +/* is returned. */ +/*******************************************************/ + +int RegionList::GetRegionCount(int regionNum) +{ + //return the region count of a specified region + return regionList[regionNum].pointCount; +} + +/*******************************************************/ +/*Get Region Indeces */ +/*******************************************************/ +/*Returns the point indeces specifying a region. */ +/*******************************************************/ +/*Pre: */ +/* - regionNum is an index into the region list */ +/* array. */ +/*Post: */ +/* - the region indeces specifying the points */ +/* contained by the region specified by region- */ +/* Num are returned. */ +/*******************************************************/ + +int *RegionList::GetRegionIndeces(int regionNum) +{ + //return point indeces using regionNum + return &indexTable[regionList[regionNum].region]; +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ PRIVATE METHODS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + /*/\/\/\/\/\/\/\/\/\/\/\*/ + /* Class Error Handler */ + /*\/\/\/\/\/\/\/\/\/\/\/*/ + +/*******************************************************/ +/*Error Handler */ +/*******************************************************/ +/*Class error handler. */ +/*******************************************************/ +/*Pre: */ +/* - functName is the name of the function that */ +/* caused an error */ +/* - errmsg is the error message given by the */ +/* calling function */ +/* - status is the error status: FATAL or NON- */ +/* FATAL */ +/*Post: */ +/* - the error message errmsg is flagged on beh- */ +/* ave of function functName. */ +/* - if the error status is FATAL then the program*/ +/* is halted, otherwise execution is continued, */ +/* error recovery is assumed to be handled by */ +/* the calling function. */ +/*******************************************************/ + +void RegionList::ErrorHandler(char *functName, char* errmsg, ErrorType status) +{ + + //flag error message on behalf of calling function, error format + //specified by the error status... + if(status == NONFATAL) + fprintf(stderr, "\n%s Error: %s\n", functName, errmsg); + else + { + fprintf(stderr, "\n%s Fatal Error: %s\n\nAborting Program.\n\n", functName, errmsg); + exit(1); + } + +} + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ END OF CLASS DEFINITION @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ diff --git a/Utilities/otbedison/segm/rlist.h b/Utilities/otbedison/segm/rlist.h old mode 100755 new mode 100644 index 453fdc74c1760c069c43d69dc83b823e5541b0ee..55bb67ce2353b9f42fc29656491ccea18b6fc7ff --- a/Utilities/otbedison/segm/rlist.h +++ b/Utilities/otbedison/segm/rlist.h @@ -1,337 +1,337 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Region List Class: - ================= - - During segmentation, data regions are defined. The - RegionList class provides a mechanism for doing so, as - well as defines some basic operations, such as region - growing or small region pruning, on the defined regions. - The prototype for the RegionList class is provided below. It - is defined in "region.cc". - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - -#ifndef RLIST_H -#define RLIST_H - -//include global type definitions -#include "tdef.h" - -//define region structure -struct REGION { - int label; - int pointCount; - int region; - -}; - -//region class prototype... -class RegionList { - -public: - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Class Constructor and Destructor */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Class Constructor * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Constructs a region list object. |// - //| |// - //| Its arguments are: |// - //| |// - //| <* maxRegions *> |// - //| The maximum amount of regions that can be class- |// - //| ified by the region list. |// - //| |// - //| <* L *> |// - //| The length of the input data set being class- |// - //| ified by the region list object. |// - //| |// - //| <* N *> |// - //| The dimension of the input data set being class- |// - //| ified by the region list object. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| RegionList(maxRegions, L, N) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - RegionList(int, int, int); - - // Class Destructor - ~RegionList( void ); - - /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ - /* Region List Manipulation */ - /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Add Region * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Adds a region to the region list. |// - //| |// - //| Its arguments are: |// - //| |// - //| <* label *> |// - //| |// - //| A positive integer used to uniquely identify |// - //| a region. |// - //| |// - //| <* pointCount *> |// - //| A positive integer that specifies the number of |// - //| N-dimensional data points that exist in the re- |// - //| gion being classified. |// - //| |// - //| <* indeces *> |// - //| An integer array that specifies the set of ind- |// - //| eces of the data points that are contianed with- |// - //| in this region. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| AddRegion(label, pointCount, indeces) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void AddRegion(int, int, int*); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Reset * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Resets the region list for re-use (for new |// - //| classification). |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - void Reset( void ); - - /*/\/\/\/\/\/\/\/\/\/\*/ - /* Query Region List */ - /*\/\/\/\/\/\/\/\/\/\/*/ - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Get Number of Regions * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns the number of regions stored by the |// - //| region list. |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - int GetNumRegions ( void ); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Get Label * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns the label of a specified region. |// - //| |// - //| Its arguments are: |// - //| |// - //| <* regionNumber *> |// - //| The index of the region in the region list |// - //| array. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| label = GetLabel(regionNumber) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - int GetLabel(int); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Get Region Count * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns number of data points contained by a sp- |// - //| ecified region. |// - //| |// - //| Its arguments are: |// - //| |// - //| <* regionNumber *> |// - //| The index of the region in the region list |// - //| array. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| pointCount = GetRegionCount(regionNumber) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - int GetRegionCount(int); - - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - //<--------------------------------------------------->|// - //| |// - //| Method Name: |// - //| ============ |// - //| * Get Region Indeces * |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Description: |// - //| ============ |// - //| |// - //| Returns a pointer to a set of grid location ind- |// - //| eces specifying the data points belonging to a |// - //| specified region. |// - //| |// - //| Its arguments are: |// - //| |// - //| <* regionNumber *> |// - //| The index of the region in the region list |// - //| array. |// - //| |// - //<--------------------------------------------------->|// - //| |// - //| Usage: |// - //| ====== |// - //| indeces = GetRegionIndeces(regionNumber) |// - //| |// - //<--------------------------------------------------->|// - //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// - - int*GetRegionIndeces(int); - -private: - - /*/\/\/\/\/\/\/\/\/\/\/\*/ - /* Class Error Handler */ - /*\/\/\/\/\/\/\/\/\/\/\/*/ - - void ErrorHandler(char*, char*, ErrorType); - - //============================= - // *** Private Data Members *** - //============================= - - //##################################### - //### REGION LIST PARTITIONED ARRAY ### - //##################################### - - REGION *regionList; //array of maxRegions regions - int minRegion; - - int maxRegions; //defines the number maximum number of regions - //allowed (determined by user during class construction) - int numRegions; //the number of regions currently stored by the - //region list - int freeRegion; //an index into the regionList pointing to the next - //available region in the regionList - - //##################################### - //### INDEX TABLE ### - //##################################### - - int *indexTable; //an array of indexes that point into an external structure - //specifying which points belong to a region - int freeBlockLoc; //points to the next free block of memory in the indexTable - - //##################################### - //### INPUT DATA PARAMETERS ### - //##################################### - - //Dimension of data set - int N; //dimension of data set being classified by region list - //class - - //Length of the data set - int L; //number of points contained by the data set being classified by - //region list class - -}; - -#endif - - - +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Region List Class: + ================= + + During segmentation, data regions are defined. The + RegionList class provides a mechanism for doing so, as + well as defines some basic operations, such as region + growing or small region pruning, on the defined regions. + The prototype for the RegionList class is provided below. It + is defined in "region.cc". + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + +#ifndef RLIST_H +#define RLIST_H + +//include global type definitions +#include "tdef.h" + +//define region structure +struct REGION { + int label; + int pointCount; + int region; + +}; + +//region class prototype... +class RegionList { + +public: + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Class Constructor and Destructor */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Class Constructor * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Constructs a region list object. |// + //| |// + //| Its arguments are: |// + //| |// + //| <* maxRegions *> |// + //| The maximum amount of regions that can be class- |// + //| ified by the region list. |// + //| |// + //| <* L *> |// + //| The length of the input data set being class- |// + //| ified by the region list object. |// + //| |// + //| <* N *> |// + //| The dimension of the input data set being class- |// + //| ified by the region list object. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| RegionList(maxRegions, L, N) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + RegionList(int, int, int); + + // Class Destructor + ~RegionList( void ); + + /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ + /* Region List Manipulation */ + /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Add Region * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Adds a region to the region list. |// + //| |// + //| Its arguments are: |// + //| |// + //| <* label *> |// + //| |// + //| A positive integer used to uniquely identify |// + //| a region. |// + //| |// + //| <* pointCount *> |// + //| A positive integer that specifies the number of |// + //| N-dimensional data points that exist in the re- |// + //| gion being classified. |// + //| |// + //| <* indeces *> |// + //| An integer array that specifies the set of ind- |// + //| eces of the data points that are contianed with- |// + //| in this region. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| AddRegion(label, pointCount, indeces) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void AddRegion(int, int, int*); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Reset * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Resets the region list for re-use (for new |// + //| classification). |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + void Reset( void ); + + /*/\/\/\/\/\/\/\/\/\/\*/ + /* Query Region List */ + /*\/\/\/\/\/\/\/\/\/\/*/ + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Get Number of Regions * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns the number of regions stored by the |// + //| region list. |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + int GetNumRegions ( void ); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Get Label * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns the label of a specified region. |// + //| |// + //| Its arguments are: |// + //| |// + //| <* regionNumber *> |// + //| The index of the region in the region list |// + //| array. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| label = GetLabel(regionNumber) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + int GetLabel(int); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Get Region Count * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns number of data points contained by a sp- |// + //| ecified region. |// + //| |// + //| Its arguments are: |// + //| |// + //| <* regionNumber *> |// + //| The index of the region in the region list |// + //| array. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| pointCount = GetRegionCount(regionNumber) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + int GetRegionCount(int); + + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + //<--------------------------------------------------->|// + //| |// + //| Method Name: |// + //| ============ |// + //| * Get Region Indeces * |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Description: |// + //| ============ |// + //| |// + //| Returns a pointer to a set of grid location ind- |// + //| eces specifying the data points belonging to a |// + //| specified region. |// + //| |// + //| Its arguments are: |// + //| |// + //| <* regionNumber *> |// + //| The index of the region in the region list |// + //| array. |// + //| |// + //<--------------------------------------------------->|// + //| |// + //| Usage: |// + //| ====== |// + //| indeces = GetRegionIndeces(regionNumber) |// + //| |// + //<--------------------------------------------------->|// + //--\\||//--\\||//--\\||//--\\||//--\\||//--\\||//--\\||// + + int*GetRegionIndeces(int); + +private: + + /*/\/\/\/\/\/\/\/\/\/\/\*/ + /* Class Error Handler */ + /*\/\/\/\/\/\/\/\/\/\/\/*/ + + void ErrorHandler(char*, char*, ErrorType); + + //============================= + // *** Private Data Members *** + //============================= + + //##################################### + //### REGION LIST PARTITIONED ARRAY ### + //##################################### + + REGION *regionList; //array of maxRegions regions + int minRegion; + + int maxRegions; //defines the number maximum number of regions + //allowed (determined by user during class construction) + int numRegions; //the number of regions currently stored by the + //region list + int freeRegion; //an index into the regionList pointing to the next + //available region in the regionList + + //##################################### + //### INDEX TABLE ### + //##################################### + + int *indexTable; //an array of indexes that point into an external structure + //specifying which points belong to a region + int freeBlockLoc; //points to the next free block of memory in the indexTable + + //##################################### + //### INPUT DATA PARAMETERS ### + //##################################### + + //Dimension of data set + int N; //dimension of data set being classified by region list + //class + + //Length of the data set + int L; //number of points contained by the data set being classified by + //region list class + +}; + +#endif + + + diff --git a/Utilities/otbedison/segm/tdef.h b/Utilities/otbedison/segm/tdef.h old mode 100755 new mode 100644 index 3eae02c28b90ed82e2e064f2c3679fe8f2b09172..9b225b3b84a5fae9504701c5a77e5cf9069d3c91 --- a/Utilities/otbedison/segm/tdef.h +++ b/Utilities/otbedison/segm/tdef.h @@ -1,51 +1,51 @@ -/******************************************************* - - Mean Shift Analysis Library - ============================================= - - The mean shift library is a collection of routines - that use the mean shift algorithm. Using this algorithm, - the necessary output will be generated needed - to analyze a given input set of data. - - Type Defintions: - =============== - - This header file contains the type defintions and - enumerations shared among the various classes of the mean - shift library. - -The theory is described in the papers: - - D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature - space analysis. - - C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. - -and they are is available at: - http://www.caip.rutgers.edu/riul/research/papers/ - -Implemented by Chris M. Christoudias, Bogdan Georgescu -********************************************************/ - -#ifndef TDEF_H -#define TDEF_H - -/*/\/\/\/\/\/\/\/\/\/\/\*/ -/* Define Enumerations */ -/*\/\/\/\/\/\/\/\/\/\/\/*/ - -//Kernel -enum kernelType {Uniform, Gaussian, UserDefined}; - -// kd-Tree -enum childType {LEFT, RIGHT}; - -// Speed Up Level -enum SpeedUpLevel {NO_SPEEDUP, MED_SPEEDUP, HIGH_SPEEDUP}; - -// Error Handler -enum ErrorLevel {EL_OKAY, EL_ERROR, EL_HALT}; -enum ErrorType {NONFATAL, FATAL}; - -#endif +/******************************************************* + + Mean Shift Analysis Library + ============================================= + + The mean shift library is a collection of routines + that use the mean shift algorithm. Using this algorithm, + the necessary output will be generated needed + to analyze a given input set of data. + + Type Defintions: + =============== + + This header file contains the type defintions and + enumerations shared among the various classes of the mean + shift library. + +The theory is described in the papers: + + D. Comaniciu, P. Meer: Mean Shift: A robust approach toward feature + space analysis. + + C. Christoudias, B. Georgescu, P. Meer: Synergism in low level vision. + +and they are is available at: + http://www.caip.rutgers.edu/riul/research/papers/ + +Implemented by Chris M. Christoudias, Bogdan Georgescu +********************************************************/ + +#ifndef TDEF_H +#define TDEF_H + +/*/\/\/\/\/\/\/\/\/\/\/\*/ +/* Define Enumerations */ +/*\/\/\/\/\/\/\/\/\/\/\/*/ + +//Kernel +enum kernelType {Uniform, Gaussian, UserDefined}; + +// kd-Tree +enum childType {LEFT, RIGHT}; + +// Speed Up Level +enum SpeedUpLevel {NO_SPEEDUP, MED_SPEEDUP, HIGH_SPEEDUP}; + +// Error Handler +enum ErrorLevel {EL_OKAY, EL_ERROR, EL_HALT}; +enum ErrorType {NONFATAL, FATAL}; + +#endif