parent
295e0fa6af
commit
605e81389e
@ -0,0 +1,160 @@
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "gui.h"
|
||||
#include "filter.h"
|
||||
|
||||
extern Filter filter;
|
||||
gboolean cb_filtertemp_thread (gpointer data);
|
||||
gboolean cb_filterout_thread (gpointer data);
|
||||
|
||||
//
|
||||
// C / C++ Wrapper for the thread function
|
||||
//
|
||||
gpointer _FilterThread (gpointer data) {
|
||||
filter.Thread ();
|
||||
return NULL;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Filter::Filter() { // @suppress("Class members should be properly initialized")
|
||||
g_mutex_init (&mutexin);
|
||||
g_mutex_init (&mutexout);
|
||||
g_mutex_init (&mutextmp);
|
||||
g_mutex_init (&mutex);
|
||||
running = 1;
|
||||
inFrame.SetSize(64, 64);
|
||||
oldFrame.SetSize(64, 64);
|
||||
temp.SetSize(64, 64);
|
||||
tempgtk.SetSize(64, 64);
|
||||
image.SetSize(64, 64);
|
||||
imagegtk.SetSize(64, 64);
|
||||
thread = NULL;
|
||||
thread = g_thread_new("Filter", _FilterThread, NULL);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Filter::~Filter() {
|
||||
running = 0;
|
||||
if (thread) {
|
||||
g_thread_join (thread);
|
||||
thread = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int Filter::NewFrame(VideoFrame *newframe) {
|
||||
LockInMutex();
|
||||
inFrame.CopyFrom(newframe);
|
||||
inFrameNew = 1;
|
||||
UnLockInMutex();
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// NewFrame: will set new frame
|
||||
// Thread: newFrame |------> Find Object --- not found ---> send gui information
|
||||
void Filter::Thread() {
|
||||
while (running) {
|
||||
// check for new frame
|
||||
LockInMutex();
|
||||
if (inFrameNew == 1) {
|
||||
inFrameNew = 0;
|
||||
|
||||
//
|
||||
// do some input detection improvement
|
||||
InputDetect();
|
||||
|
||||
oldFrame.CopyFrom(&inFrame);
|
||||
UnLockInMutex();
|
||||
|
||||
// copy temporary image for gtk
|
||||
LockTempMutex();
|
||||
tempgtk.CopyFrom(&temp);
|
||||
UnLockTempMutex();
|
||||
gdk_threads_add_idle(cb_filtertemp_thread , &tempgtk);
|
||||
|
||||
//
|
||||
// do some other stuff use if possible only the oldFrame data
|
||||
ComposeOutput();
|
||||
|
||||
// copy output image for gtk
|
||||
LockOutMutex();
|
||||
imagegtk.CopyFrom(&image);
|
||||
UnLockOutMutex();
|
||||
gdk_threads_add_idle(cb_filterout_thread , &imagegtk);
|
||||
}
|
||||
else
|
||||
UnLockInMutex();
|
||||
|
||||
usleep (10000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Filter::InputDetect() {
|
||||
int x, y;
|
||||
float vo, v;
|
||||
unsigned char *pxs, *pxso, *pxstemp;
|
||||
unsigned char pixel;
|
||||
int idx;
|
||||
FloatImage fi;;
|
||||
float fmin, fmax;
|
||||
|
||||
temp.SetSize (inFrame.w, inFrame.h);
|
||||
fi.SetSize (inFrame.w, inFrame.h);
|
||||
pxs = inFrame.data;
|
||||
pxso = oldFrame.data;
|
||||
pxstemp = temp.data;
|
||||
|
||||
for (x = 0; x < temp.w && x < inFrame.w && x < oldFrame.w; x++)
|
||||
for (y = 0; y < temp.h && y < inFrame.h && y < oldFrame.h; y++) {
|
||||
idx = (inFrame.w * y + x);
|
||||
vo = pxso[3*idx+0] + pxso[3*idx+1] + pxso[3*idx+2];
|
||||
v = pxs[3*idx+0] + pxs[3*idx+1] + pxs[3*idx+2];
|
||||
fi.data[idx] = v - vo;
|
||||
|
||||
if (idx == 0 || fmin > fi.data[idx]) fmin = fi.data[idx];
|
||||
if (idx == 0 || fmax < fi.data[idx]) fmax = fi.data[idx];
|
||||
}
|
||||
|
||||
for (x = 0; x < temp.w && x < inFrame.w && x < oldFrame.w; x++)
|
||||
for (y = 0; y < temp.h && y < inFrame.h && y < oldFrame.h; y++) {
|
||||
idx = (inFrame.w * y + x);
|
||||
pixel = (unsigned char)((float)( (fi.data[idx]-fmin) / (fmax-fmin)) * 256.0);
|
||||
pxstemp[3*idx+0] = pixel;
|
||||
pxstemp[3*idx+1] = pixel;
|
||||
pxstemp[3*idx+2] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define FACTOR 100.0
|
||||
void Filter::ComposeOutput() {
|
||||
int x, y, idx, i;
|
||||
float *pixd; // destination
|
||||
unsigned char *pixs; // source
|
||||
|
||||
image.SetSize(oldFrame.w, oldFrame.h);
|
||||
pixd = image.data;
|
||||
pixs = oldFrame.data;
|
||||
|
||||
for (x = 0; x < temp.w && x < inFrame.w && x < oldFrame.w; x++)
|
||||
for (y = 0; y < temp.h && y < inFrame.h && y < oldFrame.h; y++) {
|
||||
idx = 3 * (oldFrame.w * y + x);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
pixd[idx+i] = (FACTOR * pixd[idx+i]/FACTOR) + (pixs[idx+i] / FACTOR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,74 @@
|
||||
/***************************************************************************************
|
||||
*
|
||||
* filter.h is part of SimpleSkyCam.
|
||||
*
|
||||
*****************************************************************************************/
|
||||
|
||||
|
||||
#ifndef _FILTER_H_
|
||||
#define _FILTER_H_
|
||||
|
||||
#include "gui.h"
|
||||
#include "config.h"
|
||||
#include "video.h"
|
||||
#include "videoframe.h"
|
||||
|
||||
|
||||
class Filter {
|
||||
private:
|
||||
int running;
|
||||
VideoFrame inFrame; // input frame
|
||||
int inFrameNew; // new input frame;
|
||||
VideoFrame oldFrame; // oldinput frame
|
||||
VideoFrame temp; // temporary image
|
||||
VideoFrame tempgtk; // temp image for gtk
|
||||
FloatImage image; // output image
|
||||
VideoFrame imagegtk; // output image -- send to gtk
|
||||
GMutex mutexout;
|
||||
GMutex mutexin;
|
||||
GMutex mutextmp; // for access the temp image
|
||||
GMutex mutex; // general mutex for changing settings
|
||||
GThread *thread;
|
||||
|
||||
int objectW; // object Image Size Width
|
||||
int objectH; // object Image Size Height
|
||||
|
||||
float *fpixels; //
|
||||
|
||||
void InputDetect();
|
||||
void ComposeOutput();
|
||||
|
||||
public:
|
||||
Filter();
|
||||
~Filter();
|
||||
|
||||
int NewFrame (VideoFrame *newframe);
|
||||
|
||||
//
|
||||
// Thread Releated Functions (maybe soon private?)
|
||||
int TryLockInMutex() { return g_mutex_trylock(&mutextmp); };
|
||||
void LockInMutex() { g_mutex_lock(&mutextmp);};
|
||||
void UnLockInMutex() { g_mutex_unlock(&mutextmp);};
|
||||
|
||||
int TryLockTempMutex() { return g_mutex_trylock(&mutextmp); };
|
||||
void LockTempMutex() { g_mutex_lock(&mutextmp);};
|
||||
void UnLockTempMutex() { g_mutex_unlock(&mutextmp);};
|
||||
|
||||
int TryLockOutMutex() { return g_mutex_trylock(&mutexout); };
|
||||
void LockOutMutex() { g_mutex_lock(&mutexout);};
|
||||
void UnLockOutMutex() { g_mutex_unlock(&mutexout);};
|
||||
|
||||
void LockMutex() { g_mutex_lock(&mutex);};
|
||||
void UnLockMutex() { g_mutex_unlock(&mutex);};
|
||||
|
||||
|
||||
//
|
||||
// Object functions
|
||||
void SetObjectSize (int neww, int newh);
|
||||
void SetObject (VideoFrame objFrame, int newx, int newy);
|
||||
void GetObjectPos (int *x, int *y);
|
||||
|
||||
void Thread();
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,142 @@
|
||||
|
||||
#include "video.h"
|
||||
#include "config.h"
|
||||
#include "gui.h"
|
||||
|
||||
#define VIDEOFRAME_DEPTH_BYTES 3
|
||||
|
||||
VideoFrame::VideoFrame() {
|
||||
data = NULL;
|
||||
w = 0;
|
||||
h = 0;
|
||||
size = 0;
|
||||
};
|
||||
|
||||
|
||||
VideoFrame::~VideoFrame() {
|
||||
if (data) {
|
||||
free (data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
w = 0;
|
||||
h = 0;
|
||||
size = 0;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// we will only allocate a new image if the needed size increases
|
||||
void VideoFrame::SetSize(int nw, int nh) {
|
||||
uint32_t newsize = VIDEOFRAME_DEPTH_BYTES * h * w;
|
||||
|
||||
if (newsize > size || data == NULL) {
|
||||
unsigned char *newdata = (unsigned char *) malloc (newsize);
|
||||
if (data != NULL) free (data);
|
||||
data = newdata;
|
||||
size = newsize;
|
||||
}
|
||||
w = nw;
|
||||
h = nh;
|
||||
};
|
||||
|
||||
|
||||
VideoFrame VideoFrame::operator=(VideoFrame rightside) {
|
||||
w = rightside.w;
|
||||
h = rightside.h;
|
||||
size = rightside.size;
|
||||
if (size > 0) data = (unsigned char *) malloc (rightside.size);
|
||||
if (rightside.data != NULL && size > 0) {
|
||||
memcpy (data, rightside.data, size);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void VideoFrame::CopyFrom(VideoFrame *source) {
|
||||
SetSize (source->w, source->h);
|
||||
memcpy(data, source->data, VIDEOFRAME_DEPTH_BYTES * w * h);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void VideoFrame::CopyFrom(FloatImage *source) {
|
||||
float min, max;
|
||||
int x, y, i, idx;
|
||||
unsigned char v;
|
||||
|
||||
SetSize (source->w, source->h);
|
||||
|
||||
// find min max;
|
||||
min = source->data[0];
|
||||
max = source->data[0];
|
||||
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
|
||||
for (i = 0; i < 3; i++) {
|
||||
idx = 3 * (y * w + x);
|
||||
if (min > source->data[idx+i]) min = source->data[idx+i];
|
||||
if (max < source->data[idx+i]) max = source->data[idx+i];
|
||||
}
|
||||
|
||||
for (y = 0; y < h; y++) for (x = 0; x < w; x++)
|
||||
for (i = 0; i < 3; i++) {
|
||||
idx = 3 * (y * w + x);
|
||||
v = (float)(256.0 * (source->data[idx+i]-min) / (max-min));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FloatImage::FloatImage() {
|
||||
data = NULL;
|
||||
w = 0;
|
||||
h = 0;
|
||||
size = 0;
|
||||
};
|
||||
|
||||
|
||||
FloatImage::~FloatImage() {
|
||||
if (data) {
|
||||
free (data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
w = 0;
|
||||
h = 0;
|
||||
size = 0;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// we will only allocate a new image if the needed size increases
|
||||
void FloatImage::SetSize(int nw, int nh) {
|
||||
uint32_t newsize = 3 * h * w * sizeof(float);
|
||||
|
||||
if (newsize > size || data == NULL) {
|
||||
float *newdata = (float *) malloc (newsize);
|
||||
if (data != NULL) free (data);
|
||||
data = newdata;
|
||||
size = newsize;
|
||||
}
|
||||
w = nw;
|
||||
h = nh;
|
||||
};
|
||||
|
||||
|
||||
FloatImage FloatImage::operator=(FloatImage rightside) {
|
||||
w = rightside.w;
|
||||
h = rightside.h;
|
||||
size = rightside.size;
|
||||
if (size > 0) data = (float *) malloc (rightside.size);
|
||||
if (rightside.data != NULL && size > 0) {
|
||||
memcpy (data, rightside.data, size);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void FloatImage::CopyFrom(FloatImage *source) {
|
||||
SetSize (source->w, source->h);
|
||||
memcpy(data, source->data, 3 * w * h);
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
#ifndef _VIDEOFRAME_H_
|
||||
#define _VIDEOFRAME_H_
|
||||
|
||||
#include "gui.h"
|
||||
#include "config.h"
|
||||
|
||||
|
||||
|
||||
|
||||
class FloatImage {
|
||||
public:
|
||||
int w;
|
||||
int h;
|
||||
uint32_t size;
|
||||
float *data;
|
||||
|
||||
FloatImage();
|
||||
~FloatImage();
|
||||
|
||||
FloatImage operator=(FloatImage rightside);
|
||||
|
||||
void SetSize(int nw, int nh);
|
||||
void SetW(int nw) { SetSize(nw, h); };
|
||||
void SetH(int nh) { SetSize(w, nh); };
|
||||
void CopyFrom(FloatImage *source);
|
||||
};
|
||||
|
||||
|
||||
class VideoFrame {
|
||||
public:
|
||||
int w;
|
||||
int h;
|
||||
uint32_t size;
|
||||
unsigned char *data;
|
||||
|
||||
VideoFrame();
|
||||
~VideoFrame();
|
||||
|
||||
VideoFrame operator=(VideoFrame rightside);
|
||||
|
||||
void SetSize(int nw, int nh);
|
||||
void SetW(int nw) { SetSize(nw, h); };
|
||||
void SetH(int nh) { SetSize(w, nh); };
|
||||
void CopyFrom(VideoFrame *source);
|
||||
void CopyFrom(FloatImage *source);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in new issue