3 * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "gaborobjwindow.h"
28 REGISTER_PLUGIN(GaborObj)
31 GaborObjConfig::GaborObjConfig()
35 int GaborObjConfig::equivalent(GaborObjConfig &that)
40 void GaborObjConfig::copy_from(GaborObjConfig &that)
44 void GaborObjConfig::interpolate( GaborObjConfig &prev, GaborObjConfig &next,
45 long prev_frame, long next_frame, long current_frame)
50 void GaborObjConfig::limits()
55 GaborObj::GaborObj(PluginServer *server)
56 : PluginVClient(server)
60 for( int i=0; i<steps; ++i ) {
61 double theta = i * M_PI/steps;
62 Mat kern = getGaborKernel(ksize, 4.0, theta, 10.0, 0.5, 0, CV_32F);
64 for( int k=0; k<kern.rows; ++k ) {
65 float *kp = kern.ptr<float>(k);
66 for( int j=0; j<kern.cols; ++j ) sum += *kp++;
69 filters.push_back(kern);
72 remap_lock = new ::Mutex("GaborObj::remap_lock");
81 const char* GaborObj::plugin_title() { return N_("GaborObj"); }
82 int GaborObj::is_realtime() { return 1; }
84 NEW_WINDOW_MACRO(GaborObj, GaborObjWindow);
85 LOAD_CONFIGURATION_MACRO(GaborObj, GaborObjConfig)
87 void GaborObj::save_data(KeyFrame *keyframe)
91 // cause data to be stored directly in text
92 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
93 output.tag.set_title("GABOROBJ");
95 output.append_newline();
96 output.tag.set_title("/GABOROBJ");
98 output.append_newline();
99 output.terminate_string();
102 void GaborObj::read_data(KeyFrame *keyframe)
105 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
108 while( !(result = input.read_tag()) ) {
109 if( input.tag.title_is("GABOROBJ") ) {
112 else if( input.tag.title_is("/GABOROBJ") )
117 void GaborObj::update_gui()
119 if( !thread ) return;
120 if( !load_configuration() ) return;
121 thread->window->lock_window("GaborObj::update_gui");
122 GaborObjWindow *window = (GaborObjWindow*)thread->window;
123 window->unlock_window();
126 void GaborObj::to_mat(Mat &mat, int mcols, int mrows,
127 VFrame *inp, int ix,int iy, int mcolor_model)
129 int mcomp = BC_CModels::components(mcolor_model);
130 int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
131 int psz = mbpp / mcomp;
132 int mdepth = psz < 2 ? CV_8U : psz < 4 ? CV_16U : CV_32F;
133 if( mat.dims != 2 || mat.depth() != mdepth || mat.channels() != mcomp ||
134 mat.cols != mcols || mat.rows != mrows ) {
138 int type = CV_MAKETYPE(mdepth, mcomp);
139 mat.create(mrows, mcols, type);
141 uint8_t *mat_rows[mrows];
142 for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
143 uint8_t **inp_rows = inp->get_rows();
144 int ibpl = inp->get_bytes_per_line(), mbpl = mcols * mbpp;
145 int icolor_model = inp->get_color_model();
146 BC_CModels::transfer(mat_rows, mcolor_model, 0,0, mcols,mrows, mbpl,
147 inp_rows, icolor_model, ix,iy, mcols,mrows, ibpl, 0);
148 // VFrame vfrm(mat_rows[0], -1, mcols,mrows, mcolor_model, mat_rows[1]-mat_rows[0]);
149 // static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/idat/%06d.png", vfrm_no++);
150 // vfrm.write_png(vfn);
153 void GaborObj::from_mat(VFrame *out, int ox, int oy, int ow, int oh, Mat &mat, int mcolor_model)
155 int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
156 int mrows = mat.rows, mcols = mat.cols;
157 uint8_t *mat_rows[mrows];
158 for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
159 uint8_t **out_rows = out->get_rows();
160 int obpl = out->get_bytes_per_line(), mbpl = mcols * mbpp;
161 int ocolor_model = out->get_color_model();
162 BC_CModels::transfer(out_rows, ocolor_model, ox,oy, ow,oh, obpl,
163 mat_rows, mcolor_model, 0,0, mcols,mrows, mbpl, 0);
164 // static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/odat/%06d.png", vfrm_no++);
165 // out->write_png(vfn);
169 int GaborObj::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
172 //int need_reconfigure =
173 load_configuration();
174 input = get_input(0);
175 output = get_output(0);
176 width = input->get_w();
177 height = input->get_h();
178 color_model = input->get_color_model();
181 VFrame *iframe = new_temp(width,height, color_model);
182 read_frame(iframe, 0, start_position, frame_rate, 0);
184 to_mat(next_img, width,height, iframe, 0,0, color_model);
186 gabor_engine = new GaborObjFilterEngine(this, PluginClient::smp + 1);
188 output->clear_frame();
189 gabor_engine->process_packages();
194 GaborObjFilterPackage::GaborObjFilterPackage()
199 GaborObjFilterUnit::GaborObjFilterUnit(GaborObjFilterEngine *engine, GaborObj *plugin)
202 this->plugin = plugin;
205 GaborObjFilterUnit::~GaborObjFilterUnit()
209 void GaborObjFilterUnit::process_package(LoadPackage *package)
211 GaborObjFilterPackage *pkg = (GaborObjFilterPackage*)package;
215 void GaborObjFilterUnit::process_filter(GaborObjFilterPackage *pkg)
217 int color_model = plugin->color_model;
218 int w = plugin->output->get_w(), h = plugin->output->get_h();
219 int ddepth = CV_8UC3;
221 switch( color_model ) {
222 case BC_RGB888: ddepth = CV_8UC3; break;
223 case BC_RGBA8888: ddepth = CV_8UC4; break;
224 case BC_RGB_FLOAT: ddepth = CV_32FC3; break;
225 case BC_RGBA_FLOAT: ddepth = CV_32FC4; break;
226 case BC_YUV888: ddepth = CV_8UC3; break;
227 case BC_YUVA8888: ddepth = CV_8UC4; break;
230 Mat &src = plugin->next_img, dst;
231 Mat &kern = plugin->filters[pkg->i];
232 filter2D(src, dst, ddepth, kern);
234 #define GABOR_OBJ_REMAP(type, components) { \
235 type **out_rows = (type**)plugin->output->get_rows(); \
237 for( int y=0; y<h; ++y ) { \
238 type *out_row = out_rows[y]; \
239 type *dst_row = (type *)dst.ptr<type>(y); \
240 for( int x=0; x<w; ++x ) { \
241 for( int i=0; i<components; ++i ) { \
242 *out_row = bmax(*out_row, *dst_row); \
243 ++out_row; ++dst_row; \
248 // technically, this is needed... but it really can slow it down.
249 // plugin->remap_lock->lock("GaborObjFilterUnit::process_filter");
250 switch( color_model ) {
251 case BC_RGB888: GABOR_OBJ_REMAP(unsigned char, 3); break;
252 case BC_RGBA8888: GABOR_OBJ_REMAP(unsigned char, 4); break;
253 case BC_RGB_FLOAT: GABOR_OBJ_REMAP(float, 3); break;
254 case BC_RGBA_FLOAT: GABOR_OBJ_REMAP(float, 4); break;
255 case BC_YUV888: GABOR_OBJ_REMAP(unsigned char, 3); break;
256 case BC_YUVA8888: GABOR_OBJ_REMAP(unsigned char, 4); break;
258 // plugin->remap_lock->unlock();
262 GaborObjFilterEngine::GaborObjFilterEngine(GaborObj *plugin, int cpus)
263 : LoadServer(cpus+1, plugin->filters.size())
265 this->plugin = plugin;
268 GaborObjFilterEngine::~GaborObjFilterEngine()
272 void GaborObjFilterEngine::init_packages()
274 int n = LoadServer::get_total_packages();
275 for( int i=0; i<n; ++i ) {
276 GaborObjFilterPackage *pkg = (GaborObjFilterPackage*)LoadServer::get_package(i);
281 LoadClient* GaborObjFilterEngine::new_client()
283 return new GaborObjFilterUnit(this, plugin);
286 LoadPackage* GaborObjFilterEngine::new_package()
288 return new GaborObjFilterPackage();