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