code cleanup, movement vector should be working now

test16bit
Steffen Pohle 4 years ago
parent eb49eb8399
commit 0f4146f6a7

@ -1,4 +1,10 @@
2021-10-25:
- adding position/movement vector in the top left corner
- saving/loading the default config is working now
- saving and recalling presetbuttons are working
- some code cleanup
2021-10-10:
- basic object detection and image filter added
- save image works

@ -110,8 +110,6 @@ void Configuration::SaveConfig(std::string filename) {
void Configuration::LoadConfig(std::string filename) {
JSONParse jp;
string vstr;
float vf;
int vi;
int i;
JSONElement je;
@ -121,7 +119,6 @@ void Configuration::LoadConfig(std::string filename) {
}
else {
printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
// config in jp loaded, setup all the GUI fields
//
// set resolution and video stream mode

@ -74,7 +74,6 @@ int Detect::NewFrame(VideoFrame *newframe) {
// Thread: newFrame |------> Find Object --- not found ---> send gui information
void Detect::Thread() {
DetectOutput output;
int errorinputtype = -1, x, y;
objectX = -1;
objectY = -1;
@ -176,11 +175,6 @@ void Detect::InputDetect(int *posx, int *posy) {
int x, y, i, dx, dy, sy;
unsigned char *pxs, *pxi;
int idx, didx;
struct timeval t1, t2;
float f;
f = get_cycletime(&t1);
t2 = t1;
image.SetSize (objectW, objectH);
SetInputSize(inFrame.w, inFrame.h);
@ -189,10 +183,6 @@ void Detect::InputDetect(int *posx, int *posy) {
*posx = 0;
*posy = 0;
#ifdef DEBUGTIMES
f = get_cycletime(&t1);
printf ("%s:%d setup memory time needed:%f\n", __FILE__, __LINE__, f);
#endif
//
// maximum brightness
for (x = 0; x < posmaxx; x++) maxx[x] = 0.0;
@ -203,17 +193,8 @@ void Detect::InputDetect(int *posx, int *posy) {
maxx[x] += pow(pxs[idx+0] + pxs[idx+1] + pxs[idx+2], POWERVAL);
maxy[y] += pow(pxs[idx+0] + pxs[idx+1] + pxs[idx+2], POWERVAL);
}
#ifdef DEBUGTIMES
f = get_cycletime(&t1);
printf ("%s:%d calculated maximum:%f\n", __FILE__, __LINE__, f);
// select maximum
#endif
for (x = 1; x < inFrame.w; x++) if (maxx[x] > maxx[*posx]) *posx = x;
for (y = 1; y < inFrame.h; y++) if (maxy[y] > maxy[*posy]) *posy = y;
#ifdef DEBUGTIMES
f = get_cycletime(&t1);
printf ("%s:%d selected maximum:%f\n", __FILE__, __LINE__, f);
#endif
// select start corner
if (*posx < (objectW / 2)) x = 0;
@ -228,18 +209,8 @@ void Detect::InputDetect(int *posx, int *posy) {
for (dy = 0, y = sy; dy < image.h && y < inFrame.h; y++, dy++) {
idx = 3* (inFrame.w * y + x);
didx = 3* (image.w * dy + dx);
// printf ("[%d , %d] --> [%d, %d] idx: %d --> %d Value:%d\n", x, y, dx, dy, idx, didx, pxs[idx+i]);
for (i = 0; i < 3; i++) pxi[didx+i] = pxs[idx+i];
}
// printf ("%s:%d %s pos: %d,%d \n", __FILE__, __LINE__, __FUNCTION__, *posx, *posy);
#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
}
inline float calc_vector(uint8_t a1, uint8_t a2, uint8_t b1, uint8_t b2, uint8_t c1, uint8_t c2, uint8_t d1, uint8_t d2) {
@ -254,15 +225,12 @@ inline float calc_vector(uint8_t a1, uint8_t a2, uint8_t b1, uint8_t b2, uint8_t
#define OBJSIZE 50
#define MAXSHIFT 20
// #define DEBUGTIMES 1
void Detect::InputDetectCrossC(int *posx, int *posy) {
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;
int shiftx, shifty, x, y, ini, oldi, mxi, mxx, mxy;
float f;
if (oldFrame.h != inFrame.h || oldFrame.w != inFrame.w || *posx == -1 || *posy == -1) {
@ -271,10 +239,6 @@ void Detect::InputDetectCrossC(int *posx, int *posy) {
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__,
@ -288,19 +252,11 @@ void Detect::InputDetectCrossC(int *posx, int *posy) {
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++) {
@ -315,7 +271,6 @@ void Detect::InputDetectCrossC(int *posx, int *posy) {
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]);
f += calc_vector( pxo[oldi+0], pxi[ini+0],
pxo[oldi+3], pxi[ini+3],
pxo[oldi+6], pxi[ini+6],
@ -332,19 +287,9 @@ void Detect::InputDetectCrossC(int *posx, int *posy) {
}
}
// 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);
CopyObjectImage (*posx, *posy);
#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
}

@ -10,6 +10,7 @@
#endif
#include <stdio.h>
#include <list>
#include <math.h>
#include "gui.h"
#include "config.h"
#include "video.h"
@ -25,6 +26,7 @@ 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;
detect_movement detectedpos_data = {0};
GtkWidget *detect_da = NULL;
GdkPixbuf *detect_pixbuf = NULL;
@ -139,7 +141,7 @@ gboolean cb_thread_detect (gpointer data) {
GtkWidget *e_x = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-posx"));
GtkWidget *e_y = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-posy"));
DetectOutput *dout = (DetectOutput *) data;
int pix_h, pix_w;
int pix_h, pix_w, x, y;
if (detect_da == NULL)
detect_da = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "temp-da"));
@ -147,10 +149,12 @@ gboolean cb_thread_detect (gpointer data) {
if (dout == NULL) return false;
if (dout->image == NULL) return false;
detect.LockImageMutex();
gtk_entry_set_text(GTK_ENTRY(e_x), std::to_string(dout->posx).c_str());
gtk_entry_set_text(GTK_ENTRY(e_y), std::to_string(dout->posy).c_str());
detect.LockImageMutex();
x = dout->posx; // save value for later use (unlocked image data)
y = dout->posy;
if (detect_pixbuf) {
pix_h = gdk_pixbuf_get_height(detect_pixbuf);
@ -172,6 +176,34 @@ gboolean cb_thread_detect (gpointer data) {
detect.UnLockImageMutex();
//
// detect movements, by creating a ring buffer and we comptare the current
// position with the one DETECT_MOVEMENT_SAMPLES frames ago.
//
struct timeval tv = detectedpos_data.samples[0].ts;
float ftime = get_cycletime(&tv);
float fdist = sqrtf ( (x-detectedpos_data.samples[DETECT_MOVEMENT_SAMPLES-1].x) *
(x-detectedpos_data.samples[DETECT_MOVEMENT_SAMPLES-1].x) +
(y-detectedpos_data.samples[DETECT_MOVEMENT_SAMPLES-1].y) *
(y-detectedpos_data.samples[DETECT_MOVEMENT_SAMPLES-1].y));
if (fdist > 20.0) {
for (int i = 0; i < DETECT_MOVEMENT_SAMPLES; i++) {
detectedpos_data.samples[i].x = x;
detectedpos_data.samples[i].y = y;
detectedpos_data.samples[i].ts = tv;
}
}
detectedpos_data.dx = (float)(x-detectedpos_data.samples[0].x) / ftime;
detectedpos_data.dy = (float)(y-detectedpos_data.samples[0].y) / ftime;
for (int i = 1; i < DETECT_MOVEMENT_SAMPLES; i++)
detectedpos_data.samples[i-1] = detectedpos_data.samples[i];
detectedpos_data.samples[DETECT_MOVEMENT_SAMPLES-1].ts = tv;
detectedpos_data.samples[DETECT_MOVEMENT_SAMPLES-1].x = x;
detectedpos_data.samples[DETECT_MOVEMENT_SAMPLES-1].y = y;
return false;
};
@ -180,7 +212,6 @@ gboolean cb_thread_detect (gpointer data) {
void cb_imagetempda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data) {
int clientw, clienth, pixbufw, pixbufh;
float clientar, pixbufar;
GdkRGBA color;
GdkPixbuf *pixbuf = NULL;
GdkPixbuf *src = NULL;
@ -279,7 +310,6 @@ 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"));
double value;
value = gtk_range_get_value(range);

12
gui.h

@ -27,6 +27,18 @@ struct {
int y;
} typedef position_2d;
#define DETECT_MOVEMENT_SAMPLES 50
struct {
struct {
struct timeval ts;
int x;
int y;
} samples[DETECT_MOVEMENT_SAMPLES];
float dx;
float dy;
} typedef detect_movement;
void displayerror (std::string error);
#ifdef __cplusplus

@ -48,9 +48,8 @@ int JSONParse::Set(string json) {
Clear();
// find start and read until end
for (step = STEP_NONE, i = 0, ignorenext = false; i < json.length(); i++) {
for (step = STEP_NONE, i = 0, ignorenext = false; (unsigned int)i < json.length(); i++) {
// need to copy next character
// debug (0, "JSONParse: step:%d i:%d name:'%s' value:'%s'", step, i, jelement.name.c_str(), jelement.value.c_str());
if (ignorenext) {
ignorenext = false;
if (step == STEP_NAME) jelement.name += json[i];
@ -160,9 +159,7 @@ int JSONParse::Set(string json) {
// another element?
if (step == STEP_END) {
if (json[i] == ',') {
// debug (0, "* JSON.Set Add name:%s", jelement.name.c_str());
if (jelement.type != JSON_T_NONE) {
// debug (0, "%s:%d json add element type:%d", __FILE__, __LINE__, jelement.type);
names.push_back (jelement);
}
jelement.Clear();
@ -171,9 +168,7 @@ int JSONParse::Set(string json) {
continue;
}
}
// debug (0, "* JSON.Set Add name:%s", jelement.name.c_str());
if (jelement.type != JSON_T_NONE) {
// debug (0, "%s:%d json add element type:%d", __FILE__, __LINE__, jelement.type);
names.push_back (jelement);
}
@ -242,12 +237,9 @@ int JSONParse::GetIdx(string src, int idx, string *dest) {
int i = 0, rcnt = 0, cnt = 0;
(*dest) = "";
// printf("\n***************************************idx:%d\n", idx);
for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0;
for (i = 0; i < src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
// printf ("i:%d rcnt:%d['%c'] cnt:%d char:'%c' ous:'%s'\n",
// i, rcnt, recursive[rcnt], cnt, src[i], dest->c_str());
for (i = 0; (unsigned int) i < src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
if (src[i] == '[') {
recursive[rcnt++] = src[i];
continue;
@ -273,9 +265,6 @@ int JSONParse::GetIdx(string src, int idx, string *dest) {
}
}
// printf("\n***************************************idx:%d cnt:%d\n", idx, cnt);
// printf("in:'%s'\n***\nout:'%s'\n\n*****\n", src.c_str(), dest->c_str());
//
// final checks
if (cnt == 0 && idx == 0 && // empty source/array?

@ -38,12 +38,6 @@ int main (int argc, char **argv) {
gtk_builder_add_from_file (builder, BUILDER_FILE, NULL);
gtk_builder_connect_signals(builder, builder);
//
// #if defined _WIN32 || defined _WIN64 || defined __CYGWIN__
// #else
// #endif
//
window = gtk_builder_get_object (builder, "window-main");
if(window == NULL) {
printf("ERROR: gtk_builder_get_object() failed\n");

@ -22,6 +22,7 @@ extern GtkBuilder *_builder_; // work around for threads
extern Detect detect;
extern int video_enterdata;
extern position_2d video_enterdata_pos;
extern detect_movement detectedpos_data;
extern Configuration config;
gboolean videoctrl_update(gpointer data) {
@ -75,6 +76,8 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data)
int clientw, clienth, pixbufw, pixbufh;
float clientar, pixbufar;
GdkPixbuf *pixbuf = NULL;
char txt1[255];
char txt2[255];
GdkRGBA color;
GtkWidget *e_x = GTK_WIDGET(gtk_builder_get_object (GTK_BUILDER(_builder_), "detect-entry-posx"));
@ -101,9 +104,6 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data)
pixbuf = gdk_pixbuf_scale_simple (video_pixbuf, clientw, clienth, GDK_INTERP_NEAREST);
//cairo_move_to(cr, 30, 30);
//cairo_set_font_size(cr,15);
//cairo_show_text(cr, "hello world");
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
cairo_paint(cr);
cairo_fill (cr);
@ -186,6 +186,47 @@ void cb_videoda_draw(GtkWidget *area, cairo_t *cr, int w, int h, gpointer data)
cairo_stroke(cr);
}
}
// draw movement vector to screen
snprintf (txt1, 255, "%f", detectedpos_data.dx);
snprintf (txt2, 255, "%f", detectedpos_data.dy);
for (int i = 0; i < 5; i++) {
int dx, dy;
switch (i) {
case 0:
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
dx = -1;
dy = 0;
break;
case 1:
dx = +1;
dy = 0;
break;
case 2:
dx = 0;
dy = -1;
break;
case 3:
dx = 0;
dy = +1;
break;
case 4:
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
dx = 0;
dy = 0;
break;
}
cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 12);
cairo_move_to (cr, 10+dx, 15+dy);
cairo_show_text(cr, txt1);
cairo_stroke(cr);
cairo_move_to (cr, 10+dx, 30+dy);
cairo_show_text(cr, txt2);
cairo_stroke(cr);
}
};

@ -469,8 +469,8 @@ int VideoDev::OpenInit() {
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 1920;
fmt.fmt.pix.height = 1080;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
// fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
// fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) {

Loading…
Cancel
Save