diff --git a/detect.cc b/detect.cc index a5fc60f..09706c4 100644 --- a/detect.cc +++ b/detect.cc @@ -33,13 +33,16 @@ Detect::Detect() { // @suppress("Class members should be properly initialized") thread = g_thread_new("Detect", _DetectThread, NULL); objectW = 300; objectH = 300; + objectX = -1; + objectY = -1; posmaxx = 0; posmaxy = 0; maxx = NULL; maxy = NULL; detmatrix = NULL; detmatrixv2 = NULL; - autodetecttype = 2; + autodetecttype = 0; + autofollowtype = 0; }; @@ -69,8 +72,10 @@ int Detect::NewFrame(VideoFrame *newframe) { // Thread: newFrame |------> Find Object --- not found ---> send gui information void Detect::Thread() { DetectOutput output; - int errorinputtype = -1; - int posx = -1, posy = -1; + int errorinputtype = -1, x, y; + + objectX = -1; + objectY = -1; while (running) { // check for new frame @@ -83,36 +88,31 @@ void Detect::Thread() { // // 1. if no position of the object is known, search brightest // object on the inFrame image. + if (objectX < objectW/2 || objectX > (inFrame.w-objectW/2) || + objectY < objectH/2 || objectY > (inFrame.h-objectH/2)) + { + switch (autodetecttype) { + case AUTODETECT_BRIGHT: + InputDetect(&objectX, &objectY); + break; + default: + break; + } + } + // // 2. check near the last known position. - - switch (autodetecttype) { - case -1: - // no detection - break; - - case 0: - InputDetect(&posx, &posy); - break; - - case 1: - if (posx < objectW/2 || posy < objectH/2 || - posx > (inFrame.w-objectW/2) || posy > (inFrame.h-objectH/2)) - InputDetect(&posx, &posy); - else InputDetectCrossC(&posx, &posy); - break; - - case 2: - if (posx < objectW/2 || posy < objectH/2 || - posx > (inFrame.w-objectW/2) || posy > (inFrame.h-objectH/2)) - InputDetect(&posx, &posy); - else InputDetectCrossCv2(&posx, &posy); - break; - - default: - if (errorinputtype != autodetecttype) - printf ("%s:%d %s error: autodetecttype (%d) not found\n", __FILE__, __LINE__, __FUNCTION__, autodetecttype); - errorinputtype = autodetecttype; - break; + // + else { + switch (autofollowtype) { + case AUTOFOLLOW_BRIGHT: + InputDetect(&objectX, &objectY); + break; + case AUTOFOLLOW_CROSSC: + InputDetectCrossC(&objectX, &objectY); + break; + default: + break; + } } oldFrame.CopyFrom(&inFrame); @@ -123,11 +123,12 @@ void Detect::Thread() { imagegtk.CopyFrom(&image); UnLockImageMutex(); + output.posx = objectX; + output.posy = objectY; + output.image = &imagegtk; + UnLockMutex(); // unlock Config - output.posx = posx; - output.posy = posy; - output.image = &imagegtk; gdk_threads_add_idle(cb_thread_detect , &output); } else @@ -148,15 +149,22 @@ void Detect::SetInputSize (int nw, int nh) { maxy = (float*) malloc (nh * sizeof (float)); } - if ((posmaxx * posmaxy) < (nw * nh) || detmatrix != NULL) { - free (detmatrix); - free (detmatrixv2); + if ((posmaxx * posmaxy) < (nw * nh)) { + printf ("%s:%d %s reset Object Position (%d,%d) < (%d,%d) detmatrix:%p\n", __FILE__, __LINE__, __FUNCTION__, + posmaxx, posmaxy, nw, nh, detmatrix); + + if (detmatrix != NULL) { + free (detmatrix); + free (detmatrixv2); + } detmatrix = (float*) malloc (sizeof(float) * nw * nh); detmatrixv2 = (uint16_t*) malloc (sizeof(uint16_t) * nw * nh); + + objectX = nw/2; + objectY = nw/2; + posmaxx = nw; + posmaxy = nh; } - - posmaxx = nw; - posmaxy = nh; } @@ -234,7 +242,7 @@ void Detect::InputDetect(int *posx, int *posy) { #define OBJSIZE 50 -#define MAXSHIFT 40 +#define MAXSHIFT 20 // #define DEBUGTIMES 1 void Detect::InputDetectCrossC(int *posx, int *posy) { unsigned char *pxi; // input image @@ -284,16 +292,16 @@ void Detect::InputDetectCrossC(int *posx, int *posy) { // fixme: help help f = 0.0; - for (y = 0; y < objectH; y++) { - oldx = (*posx)- objectW/2; - oldy = (*posy)- objectH/2 + y; + for (y = 0; y < OBJSIZE; y++) { + oldx = (*posx)- OBJSIZE/2; + oldy = (*posy)- OBJSIZE/2 + y; oldi = 3 * (oldx + oldFrame.w * oldy); inx = oldx + shiftx - MAXSHIFT/2; iny = oldy + shifty - MAXSHIFT/2; ini = 3* (inx + inFrame.w * iny); - for (x = 0; x < objectW; x++, oldi += 3, ini += 3, oldx++, inx++) { + for (x = 0; x < OBJSIZE; x++, oldi += 3, ini += 3, oldx++, inx++) { if (oldx >= 0 && oldy >= 0 && oldx < oldFrame.w && oldy <= oldFrame.h && inx >= 0 && inx < inFrame.w && iny >= 0 && iny < inFrame.h) { f += (float)(pxo[oldi+0])*(float)(pxi[ini+0]); @@ -313,18 +321,7 @@ void Detect::InputDetectCrossC(int *posx, int *posy) { *posx += (mxx-MAXSHIFT/2); *posy += (mxy-MAXSHIFT/2); - - // - // copy image data to destination - for (x = 0; x < objectW; x++) for (y = 0; y < objectH; y++) { - desti = 3*(x + y * objectW); - ini = 3*((x + *posx - objectW/2) + (y + *posy - objectH/2) * inFrame.w); - if (desti < 0 || desti > objectW*objectH*3) continue; - if (ini < 0 || ini > inFrame.w*inFrame.h*3) continue; - pxd[desti+0] = pxi[ini+0]; - pxd[desti+1] = pxi[ini+1]; - pxd[desti+2] = pxi[ini+2]; - } + CopyObjectImage (*posx, *posy); #ifdef DEBUGTIMES f = get_cycletime(&t1); @@ -335,118 +332,57 @@ void Detect::InputDetectCrossC(int *posx, int *posy) { } -#define OBJSIZE 50 -#define MAXSHIFT 20 -// #define DEBUGTIMES 1 -void Detect::InputDetectCrossCv2(int *posx, int *posy) { +void Detect::CopyObjectImage(int objx, int objy) { + int x, y, desti, ini; unsigned char *pxi; // input image unsigned char *pxd; // destination image - unsigned char *pxo; // old image - int inx, iny, oldx, oldy; - - struct timeval t1, t2; - int shiftx, shifty, x, y, ini, oldi, desti, mxi, mxx, mxy; - float f; - - if (oldFrame.h != inFrame.h || oldFrame.w != inFrame.w || *posx == -1 || *posy == -1) { - *posx = -1; - *posy = -1; - return; - } - -#ifdef DEBUGTIMES - f = get_cycletime(&t1); - t2 = t1; -#endif - if (objectW > inFrame.w || objectH > inFrame.h) { - printf ("%s:%d %s objectW,H (%d,%d) > inFrame.W,H (%d, %d)\n", __FILE__, __LINE__, __FUNCTION__, - objectW, objectH, inFrame.w, inFrame.h); - *posx = -1; - *posy = -1; - return; - } - - image.SetSize (objectW, objectH); - SetInputSize(inFrame.w, inFrame.h); pxi = inFrame.data; - pxo = oldFrame.data; pxd = image.data; -#ifdef DEBUGTIMES - f = get_cycletime(&t1); - printf ("%s:%d setup memory time needed:%f\n", __FILE__, __LINE__, f); -#endif - - mxx = mxy = 0; - for (shifty = 0; shifty < MAXSHIFT; shifty++) { - // printf ("%s:%d %s shift (%d)\n", __FILE__, __LINE__, __FUNCTION__, shifty); - mxi = shifty * objectW; - for (shiftx = 0; shiftx < MAXSHIFT; shiftx++, mxi++) { - // fixme: help help - f = 0.0; - - for (y = 0; y < OBJSIZE; y++) { - oldx = (*posx)- OBJSIZE/2; - oldy = (*posy)- OBJSIZE/2 + y; - oldi = 3 * (oldx + oldFrame.w * oldy); - - inx = oldx + shiftx - MAXSHIFT/2; - iny = oldy + shifty - MAXSHIFT/2; - ini = 3* (inx + inFrame.w * iny); - - for (x = 0; x < OBJSIZE; x++, oldi += 3, ini += 3, oldx++, inx++) { - if (oldx >= 0 && oldy >= 0 && oldx < oldFrame.w && oldy <= oldFrame.h && - inx >= 0 && inx < inFrame.w && iny >= 0 && iny < inFrame.h) { - f += (float)(pxo[oldi+0])*(float)(pxi[ini+0]); - } - } - } - detmatrix[mxi] = f; - if (detmatrix[mxx + (mxy * objectW)] < f) { - mxx = shiftx; - mxy = shifty; - } - } - } - -// printf ("%s:%d %s pos (%d,%d) dpos (%d,%d) newpos (%d,%d)\n", __FILE__, __LINE__, __FUNCTION__, -// *posx, *posy, (mxx-MAXSHIFT/2), (mxy-MAXSHIFT/2), *posx - (mxx-MAXSHIFT/2), *posy - (mxy-MAXSHIFT/2)); - - *posx += (mxx-MAXSHIFT/2); - *posy += (mxy-MAXSHIFT/2); - // // copy image data to destination for (x = 0; x < objectW; x++) for (y = 0; y < objectH; y++) { desti = 3*(x + y * objectW); - ini = 3*((x + *posx - objectW/2) + (y + *posy - objectH/2) * inFrame.w); + ini = 3*((x + objx - objectW/2) + (y + objy - objectH/2) * inFrame.w); if (desti < 0 || desti > objectW*objectH*3) continue; if (ini < 0 || ini > inFrame.w*inFrame.h*3) continue; pxd[desti+0] = pxi[ini+0]; pxd[desti+1] = pxi[ini+1]; pxd[desti+2] = pxi[ini+2]; } +} -#ifdef DEBUGTIMES - f = get_cycletime(&t1); - printf ("%s:%d copy output:%f\n", __FILE__, __LINE__, f); - f = get_cycletime(&t2); - printf ("%s:%d time needed:%f\n", __FILE__, __LINE__, f); -#endif + +// +// set/get the automatic follow mode +void Detect::SetFollowType(int intype) { + LockMutex(); + autofollowtype = intype; + UnLockMutex(); } +int Detect::GetFollowType() { + int i; + + LockMutex(); + i = autofollowtype; + UnLockMutex(); + return i; +} -void Detect::SetInputType(int intype) { + +// set/get the automatic detection mode +void Detect::SetDetectType(int intype) { LockMutex(); autodetecttype = intype; UnLockMutex(); } -int Detect::GetInputType() { +int Detect::GetDetectType() { int i; LockMutex(); @@ -509,4 +445,20 @@ int Detect::GetMinBrightness() { +void Detect::GetObjectPos(int *x, int *y) { + LockMutex(); + *x = objectX; + *y = objectY; + UnLockMutex(); +} + +void Detect::SetObjectPos(int x, int y) { + LockMutex(); + image.SetSize (objectW, objectH); + SetInputSize(inFrame.w, inFrame.h); + objectX = x; + objectY = y; + CopyObjectImage (objectX, objectY); + UnLockMutex(); +} diff --git a/detect.h b/detect.h index aa7a01e..325784e 100644 --- a/detect.h +++ b/detect.h @@ -13,6 +13,17 @@ #include "video.h" #include "videoframe.h" +enum { + AUTODETECT_OFF = 0, + AUTODETECT_BRIGHT +}; + +enum { + AUTOFOLLOW_OFF = 0, + AUTOFOLLOW_BRIGHT, + AUTOFOLLOW_CROSSC +}; + struct { VideoFrame *image; // detected image @@ -42,16 +53,19 @@ private: float *detmatrix; uint16_t *detmatrixv2; + int objectX; // current object position + int objectY; // current object position int objectW; // object Image Size Width int objectH; // object Image Size Height int minBright; // min brightness int autodetecttype; // input detection type to use + int autofollowtype; // input detection type to use void InputDetect (int *posx, int *posy); void InputDetectCrossC (int *posx, int *posy); - void InputDetectCrossCv2 (int *posx, int *posy); // MMX optimiert void SetInputSize (int nw, int nh); + void CopyObjectImage(int objx, int objy); public: Detect(); @@ -80,9 +94,13 @@ public: void SetMinBrightness (int value); int GetMinBrightness(); - void SetInputType(int intype); - int GetInputType(); + void SetFollowType(int intype); + int GetFollowType(); + + void SetDetectType(int intype); + int GetDetectType(); + void SetObjectPos (int x, int y); void GetObjectPos (int *x, int *y); void Thread(); diff --git a/gui.cc b/gui.cc index b70a87f..0b8ffd6 100644 --- a/gui.cc +++ b/gui.cc @@ -16,10 +16,15 @@ #include "filter.h" #include "detect.h" -extern GtkBuilder *_builder_; // work around for threads +extern GtkBuilder *_builder_; // work around for threads extern Filter filter; extern Detect detect; +// +// defines what should happen on clicking a point on the input videodata +int video_enterdata = VID_ENTERDATA_NONE; // see VID_ENTERDATA_xxxxx +position_2d video_enterdata_pos; + GtkWidget *detect_da = NULL; GdkPixbuf *detect_pixbuf = NULL; @@ -46,14 +51,20 @@ void cb_window_show (GtkWidget *widget, gpointer data) { GtkWidget *btnstop = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "btn-video-stop")); GtkWidget *w = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-w")); GtkWidget *h = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-h")); + GtkWidget *rboff = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-pos-cboff")); + GtkWidget *rbcrossc = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-type-indet2")); + + // changing the value, will cause the 'change' event to be triggered + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rboff), true); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rbcrossc), true); - printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); gtk_widget_set_sensitive(btnstart, true); gtk_widget_set_sensitive(btnstop, false); gtk_entry_set_text(GTK_ENTRY(w),"300"); gtk_entry_set_text(GTK_ENTRY(h),"300"); + detect.SetObjectSize(300, 300); g_timeout_add(2000, videoctrl_update, NULL); @@ -262,7 +273,7 @@ void cb_image_btnsave (GtkWidget *widget, gpointer data) { void cb_detect_bright (GtkRange *range, gpointer data) { - GtkWidget *scale = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-adj-bright")); +// GtkWidget *scale = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-adj-bright")); double value; value = gtk_range_get_value(range); @@ -270,14 +281,36 @@ void cb_detect_bright (GtkRange *range, gpointer data) { }; -void cb_detect_inputtype (GtkWidget *widget, gpointer data) { +void cb_detect_followtype (GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)) == 1) { + if (widget == GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-type-indet0"))) + detect.SetFollowType(AUTOFOLLOW_OFF); if (widget == GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-type-indet1"))) - detect.SetInputType(0); + detect.SetFollowType(AUTOFOLLOW_BRIGHT); if (widget == GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-type-indet2"))) - detect.SetInputType(1); - if (widget == GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-type-indet3"))) - detect.SetInputType(2); + detect.SetFollowType(AUTOFOLLOW_CROSSC); + } +}; + + +void cb_detect_detecttype (GtkWidget *widget, gpointer data) { + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)) == 1) { + if (widget == GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-pos-cboff"))) + detect.SetDetectType(AUTODETECT_OFF); + if (widget == GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-pos-cbbright"))) + detect.SetDetectType(AUTODETECT_BRIGHT); } }; + + +void cb_detect_btnsetpos (GtkWidget *widget, gpointer data) { + GtkWidget *rboff = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-pos-cboff")); + + // changing the value, will cause the 'change' event to be triggered + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rboff), true); + + video_enterdata = VID_ENTERDATA_POS; +}; + + diff --git a/gui.h b/gui.h index aead4af..c89e9b3 100644 --- a/gui.h +++ b/gui.h @@ -15,8 +15,18 @@ #include #include +enum { + VID_ENTERDATA_NONE = 0, + VID_ENTERDATA_POS +}; + #define BUILDER_FILE "simpleskycam.ui" +struct { + int x; + int y; +} typedef position_2d; + void displayerror (std::string error); #ifdef __cplusplus @@ -40,7 +50,9 @@ G_MODULE_EXPORT void cb_video_btnrec (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_video_btnstop (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data); G_MODULE_EXPORT gboolean video_display(gpointer data); - +G_MODULE_EXPORT void cb_videoda_motionevent (GtkWidget *widget, GdkEvent *event, gpointer data); +G_MODULE_EXPORT void cb_videoda_btnpress (GtkWidget *widget, GdkEvent *event, gpointer data); +G_MODULE_EXPORT void cb_videoda_btnrelease (GtkWidget *widget, GdkEvent *event, gpointer data); G_MODULE_EXPORT void cb_vidctrl_entry_change (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_vidctrl_scale_change (GtkRange *range, gpointer data); gboolean videoctrl_update(gpointer data); @@ -65,7 +77,8 @@ G_MODULE_EXPORT void cb_detect_bright (GtkRange *range, gpointer data); // detection elements G_MODULE_EXPORT void cb_detect_btnsetpos (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void cb_detect_btnsetsize (GtkWidget *widget, gpointer data); -G_MODULE_EXPORT void cb_detect_inputtype (GtkWidget *widget, gpointer data); +G_MODULE_EXPORT void cb_detect_followtype (GtkWidget *widget, gpointer data); +G_MODULE_EXPORT void cb_detect_detecttype (GtkWidget *widget, gpointer data); #ifdef __cplusplus } diff --git a/simpleskycam.ui b/simpleskycam.ui index bda9c7b..5816306 100644 --- a/simpleskycam.ui +++ b/simpleskycam.ui @@ -2,7 +2,7 @@ - + 255.99 50 1 @@ -34,7 +34,13 @@ True False + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK | GDK_TOUCHPAD_GESTURE_MASK | GDK_TABLET_PAD_MASK + True + True + + + False @@ -224,17 +230,14 @@ True False + start vertical + 2 + top - - + True False - 8 - 8 - 8 - 8 - 8 True @@ -243,57 +246,18 @@ 8 8 8 - Position - - - 0 - 0 - - - - - True - False - Size: + Position: - 0 - 1 - - - - - True - False - 8 - 8 - 8 - 8 - 4 - 4 - X: - - - 1 - 0 - - - - - True - False - 4 - 4 - W: - - - 1 - 1 + False + True + 0 True + False True 4 4 @@ -307,70 +271,85 @@ digits - 2 - 0 + False + True + 1 - + True - True - 4 - 4 - 4 - 4 - 4 + False + center + 3 4 - 5 - 5 + , - 2 - 1 + False + True + 2 - + True - False + False + True + 4 + 4 + 4 + 4 4 4 - Y: + 5 + 5 - 3 - 0 + False + True + 3 - + + Set Pos True - False + True + True + 8 + 8 + 8 + 8 4 4 - H: + + - 3 - 1 + False + False + 4 - + + Set Size True True - 4 - 4 - 4 - 4 + True + 8 + 8 4 4 - 5 - 5 + + - 4 - 0 + False + False + end + 5 @@ -387,76 +366,58 @@ 5 - 4 - 1 - - - - - Auto - True - True - False - 10 - 8 - 10 - 8 - True - - - 5 - 0 + False + True + end + 6 - - Set Size + True - True - True - 8 - 8 - 8 - 8 + False 4 4 - - + x - 6 - 1 + False + True + end + 7 - - Set Pos + True True - True - 8 - 8 - 8 - 8 + 4 + 4 + 4 + 4 4 4 - - + 5 + 5 - 6 - 0 + False + True + end + 8 True False - _ + Size: - 5 - 1 + False + True + end + 9 @@ -470,83 +431,32 @@ True False - True - - - True - False - start - - - True - False - 8 - 8 - Helligkeit Grenze: - - - False - True - 0 - - - - - True - True - detect-adj-bright - on - on - True - 255 - 1 - - - - True - True - 1 - - - - - False - True - 0 - - + vertical + top - + True - False - 8 - 8 - 8 - 8 - 0 - etched-out + True - + True False - 8 - 8 - 12 True False - vertical + start + True + True - - InputDetect + True - True - False - True - True - detect-type-indet2 - + False + 8 + 8 + 8 + 8 + Helligkeit Grenze: False @@ -555,40 +465,77 @@ - - InputDetect + InputDetectCrossC + + True + True + detect-pos-adjbright + on + on + True + 255 + 1 + + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + vertical + + + Off True True False - True True - detect-type-indet1 - + detect-pos-cbbright + False True - 1 + 0 - - neu InputDetect + InputDetectCrossCv2 + + Brightest Point True True False - True True - detect-type-indet1 - + detect-pos-cboff + False True - 2 + 1 + + + + + False + True + 8 + 1 + @@ -596,37 +543,125 @@ True False - Detection Type + start + start + Detect Object False - True - 4 + False + 0 + + + + + True + True + start + start + + + True + False + vertical + + + OFF + True + True + False + True + True + detect-type-indet1 + + + + False + True + 0 + + + + + Brightest Point + True + True + False + start + True + True + detect-type-indet0 + + + + False + True + 1 + + + + + InputDetectCrossC + True + True + False + start + True + True + detect-type-indet0 + + + + False + True + 2 + + + + + + + + + + True + False + Follow Object + + + + + False + False 1 False - True + False 1 + + + 1 + False True False - Detection + Detection/Follow 1 @@ -695,6 +730,7 @@ True False + True diff --git a/video.cc b/video.cc index ba9f46c..3b699e2 100644 --- a/video.cc +++ b/video.cc @@ -18,6 +18,9 @@ GtkWidget *video_da = NULL; GdkPixbuf *video_pixbuf = NULL; extern GtkBuilder *_builder_; // work around for threads extern Detect detect; +extern int video_enterdata; +extern position_2d video_enterdata_pos; + gboolean videoctrl_update(gpointer data) { GtkWidget *grid = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "vidctrl-grid")); @@ -60,7 +63,6 @@ void videoframe_to_pixbuf(GdkPixbuf* dest, VideoFrame *src) { desth = src->h; } - memcpy (destpixel, src->data, 3*destw*desth); } @@ -106,46 +108,79 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) g_object_unref (pixbuf); + // + // need to draw the select new position cross + if (video_enterdata == VID_ENTERDATA_POS) { + color.blue = 1.0; + color.red = 0.0; + color.green = 1.0; + color.alpha = 1.0; + gdk_cairo_set_source_rgba(cr, &color); + + cairo_move_to(cr, S_X(video_enterdata_pos.x)-10, S_Y(video_enterdata_pos.y)-10); + cairo_line_to(cr, S_X(video_enterdata_pos.x)+10, S_Y(video_enterdata_pos.y)+10); + cairo_move_to(cr, S_X(video_enterdata_pos.x)+10, S_Y(video_enterdata_pos.y)-10); + cairo_line_to(cr, S_X(video_enterdata_pos.x)-10, S_Y(video_enterdata_pos.y)+10); + + cairo_move_to(cr, S_X(video_enterdata_pos.x)-15, S_Y(video_enterdata_pos.y)-20); + cairo_line_to(cr, S_X(video_enterdata_pos.x)-20, S_Y(video_enterdata_pos.y)-20); + cairo_line_to(cr, S_X(video_enterdata_pos.x)-20, S_Y(video_enterdata_pos.y)-15); + + cairo_move_to(cr, S_X(video_enterdata_pos.x)+15, S_Y(video_enterdata_pos.y)-20); + cairo_line_to(cr, S_X(video_enterdata_pos.x)+20, S_Y(video_enterdata_pos.y)-20); + cairo_line_to(cr, S_X(video_enterdata_pos.x)+20, S_Y(video_enterdata_pos.y)-15); + + cairo_move_to(cr, S_X(video_enterdata_pos.x)-15, S_Y(video_enterdata_pos.y)+20); + cairo_line_to(cr, S_X(video_enterdata_pos.x)-20, S_Y(video_enterdata_pos.y)+20); + cairo_line_to(cr, S_X(video_enterdata_pos.x)-20, S_Y(video_enterdata_pos.y)+15); + + cairo_move_to(cr, S_X(video_enterdata_pos.x)+15, S_Y(video_enterdata_pos.y)+20); + cairo_line_to(cr, S_X(video_enterdata_pos.x)+20, S_Y(video_enterdata_pos.y)+20); + cairo_line_to(cr, S_X(video_enterdata_pos.x)+20, S_Y(video_enterdata_pos.y)+15); + + cairo_stroke(cr); + } + else { + // + // draw red cross + cairo_set_line_width(cr, 1.0); + color.blue = 0.0; + color.red = 1.0; + color.green = 0.0; + color.alpha = 1.0; + gdk_cairo_set_source_rgba(cr, &color); + + x = atoi (gtk_entry_get_text(GTK_ENTRY(e_x))); + y = atoi (gtk_entry_get_text(GTK_ENTRY(e_y))); + w1 = atoi (gtk_entry_get_text(GTK_ENTRY(e_w))); + h1 = atoi (gtk_entry_get_text(GTK_ENTRY(e_h))); + + cairo_move_to(cr, S_X(x), S_Y(y)-10); + cairo_line_to(cr, S_X(x), S_Y(y)+10); + cairo_move_to(cr, S_X(x)-10, S_Y(y)); + cairo_line_to(cr, S_X(x)+10, S_Y(y)); + cairo_stroke(cr); - // - // draw red cross - cairo_set_line_width(cr, 1.0); - color.blue = 0.0; - color.red = 1.0; - color.green = 0.0; - color.alpha = 1.0; - gdk_cairo_set_source_rgba(cr, &color); - - x = atoi (gtk_entry_get_text(GTK_ENTRY(e_x))); - y = atoi (gtk_entry_get_text(GTK_ENTRY(e_y))); - w1 = atoi (gtk_entry_get_text(GTK_ENTRY(e_w))); - h1 = atoi (gtk_entry_get_text(GTK_ENTRY(e_h))); - - cairo_move_to(cr, S_X(x), S_Y(y)-10); - cairo_line_to(cr, S_X(x), S_Y(y)+10); - cairo_move_to(cr, S_X(x)-10, S_Y(y)); - cairo_line_to(cr, S_X(x)+10, S_Y(y)); - cairo_stroke(cr); - - // - // green width border - color.blue = 0.0; - color.red = 0.0; - color.green = 1.0; - color.alpha = 1.0; - gdk_cairo_set_source_rgba(cr, &color); - - cairo_move_to(cr, S_X(x-w1/2), S_Y(y-h1/2)+10); - cairo_line_to(cr, S_X(x-w1/2), S_Y(y-h1/2)); - cairo_line_to(cr, S_X(x+w1/2), S_Y(y-h1/2)); - cairo_line_to(cr, S_X(x+w1/2), S_Y(y-h1/2)+10); - - cairo_move_to(cr, S_X(x-w1/2), S_Y(y+h1/2)-10); - cairo_line_to(cr, S_X(x-w1/2), S_Y(y+h1/2)); - cairo_line_to(cr, S_X(x+w1/2), S_Y(y+h1/2)); - cairo_line_to(cr, S_X(x+w1/2), S_Y(y+h1/2)-10); - - cairo_stroke(cr); + // + // green width border + color.blue = 0.0; + color.red = 0.0; + color.green = 1.0; + color.alpha = 1.0; + gdk_cairo_set_source_rgba(cr, &color); + + cairo_move_to(cr, S_X(x-w1/2), S_Y(y-h1/2)+10); + cairo_line_to(cr, S_X(x-w1/2), S_Y(y-h1/2)); + cairo_line_to(cr, S_X(x+w1/2), S_Y(y-h1/2)); + cairo_line_to(cr, S_X(x+w1/2), S_Y(y-h1/2)+10); + + cairo_move_to(cr, S_X(x-w1/2), S_Y(y+h1/2)-10); + cairo_line_to(cr, S_X(x-w1/2), S_Y(y+h1/2)); + cairo_line_to(cr, S_X(x+w1/2), S_Y(y+h1/2)); + cairo_line_to(cr, S_X(x+w1/2), S_Y(y+h1/2)-10); + + cairo_stroke(cr); + } }; @@ -325,6 +360,7 @@ void videoctrl_set(std::string name, int value) { videodev.SetCtrlValue(name, value); } + // // callback video control scale change void cb_vidctrl_scale_change (GtkRange *range, gpointer data) { @@ -360,3 +396,50 @@ void cb_vidctrl_entry_change (GtkWidget *widget, gpointer data) { videoctrl_set((std::string)gtk_label_get_text(GTK_LABEL(label)), (int)value); }; + +void cb_videoda_motionevent (GtkWidget *widget, GdkEvent *event, gpointer data) { + int dw, dh, sw, sh; + float sar, dar; + + if (video_pixbuf != NULL) { + sh = gtk_widget_get_allocated_height(video_da); + sw = gtk_widget_get_allocated_width(video_da); + + dw = gdk_pixbuf_get_width(video_pixbuf); + dh = gdk_pixbuf_get_height(video_pixbuf); + + sar = (float)sw/(float)sh; + dar = (float)dw/(float)dh; + + if (dar < sar) { + sw = (dar * (float) sh); + } + else { + sh = ((float) sw / dar); + } + + video_enterdata_pos.x = event->motion.x * dw / sw; + video_enterdata_pos.y = event->motion.y * dh / sh; + + gdk_window_invalidate_rect(gtk_widget_get_window(video_da), NULL, true); + } +}; + + +void cb_videoda_btnpress (GtkWidget *widget, GdkEvent *event, gpointer data) { + int x = event->motion.x; + int y = event->motion.y; + + printf ("%s:%d %s %d, %d\n", __FILE__, __LINE__, __FUNCTION__, x, y); +}; + + +void cb_videoda_btnrelease (GtkWidget *widget, GdkEvent *event, gpointer data) { + if (video_enterdata == VID_ENTERDATA_POS) { + detect.SetObjectPos(video_enterdata_pos.x, video_enterdata_pos.y); + video_enterdata = VID_ENTERDATA_NONE; + } +}; + + +