CHECK_LIB([DL], [dl], [dlopen])])
CHECK_WANT([EXR], [auto], [use exr], [])
-CHECK_WANT([FINDOBJECT], [no], [findobject=sys/sta/dyn], [
- WANT_FINDOBJECT="$withval"
+CHECK_WANT([OPENCV], [no], [opencv=sys/sta/dyn,git/tar=url], [
+ WANT_OPENCV="$withval"
])
CHECK_WANT([NUMA], [auto], [system has libnuma], [
echo " using: with-browser = $WANT_CIN_BROWSER"
echo " using: with-plugin-dir = $WANT_PLUGIN_DIR"
echo " using: with-ladspa-dir = $WANT_LADSPA_DIR"
-echo " using: with-findobject = $WANT_FINDOBJECT"
+echo " using: with-opencv = $WANT_OPENCV"
echo ""
echo " using: single-user = $WANT_CINBIN_BUILD"
echo " using: static-build = $WANT_STATIC_BUILD"
ifeq ($(WANT_DVB), yes)
LIVEDVB = liveaudio livevideo
endif
-ifneq ($(WANT_FINDOBJECT), no)
-FINDOBJECT = findobject
+ifneq ($(WANT_OPENCV), no)
+want_var:=$(WANT_OPENCV)
+include $(TOPDIR)/opencv_build
+OPENCV_OBJS := findobj flowobj gaborobj moveobj
+$(OPENCV_OBJS): opencv
endif
# burn must come before any other effecttv plugin
# parametric must come before fourier plugins
# motion must come before perspective
-DIRS = \
+DIRS = $(OPENCV_OBJS) \
1080to480 \
1080to540 \
720to480 \
echo \
echocancel \
fieldframe \
- $(FINDOBJECT) \
flash \
flip \
framefield \
--- /dev/null
+default: all
+
+TOPDIR?=../..
+include $(TOPDIR)/plugin_defs
+
+PLUGIN = findobj
+
+OBJS := \
+ $(OBJDIR)/findobj.o \
+ $(OBJDIR)/findobjwindow.o \
+
+want_var:=$(WANT_OPENCV)
+include $(TOPDIR)/opencv_build
+include $(TOPDIR)/plugin_config
+
+all: opencv
+ +make $(OUTPUT)
+
+$(OBJDIR)/findobj.o: findobj.C findobj.h findobjwindow.h
+$(OBJDIR)/findobjwindow.o: findobjwindow.C findobj.h findobjwindow.h
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "affine.h"
+#include "cicolors.h"
+#include "clip.h"
+#include "filexml.h"
+#include "language.h"
+#include "findobj.h"
+#include "findobjwindow.h"
+#include "mutex.h"
+#include "overlayframe.h"
+
+#include <errno.h>
+#include <exception>
+#include <unistd.h>
+
+REGISTER_PLUGIN(FindObjMain)
+
+FindObjConfig::FindObjConfig()
+{
+ algorithm = NO_ALGORITHM;
+ use_flann = 1;
+ draw_keypoints = 0;
+ draw_border = 0;
+ replace_object = 0;
+ draw_object_border = 0;
+ object_x = 50; object_y = 50;
+ object_w = 100; object_h = 100;
+ scene_x = 50; scene_y = 50;
+ scene_w = 100; scene_h = 100;
+ scene_layer = 0;
+ object_layer = 1;
+ replace_layer = 2;
+ blend = 100;
+}
+
+void FindObjConfig::boundaries()
+{
+ bclamp(object_x, 0, 100); bclamp(object_y, 0, 100);
+ bclamp(object_w, 0, 100); bclamp(object_h, 0, 100);
+ bclamp(scene_x, 0, 100); bclamp(scene_y, 0, 100);
+ bclamp(scene_w, 0, 100); bclamp(scene_h, 0, 100);
+ bclamp(object_layer, MIN_LAYER, MAX_LAYER);
+ bclamp(replace_layer, MIN_LAYER, MAX_LAYER);
+ bclamp(scene_layer, MIN_LAYER, MAX_LAYER);
+ bclamp(blend, MIN_BLEND, MAX_BLEND);
+}
+
+int FindObjConfig::equivalent(FindObjConfig &that)
+{
+ int result =
+ algorithm == that.algorithm &&
+ use_flann == that.use_flann &&
+ draw_keypoints == that.draw_keypoints &&
+ draw_border == that.draw_border &&
+ replace_object == that.replace_object &&
+ draw_object_border == that.draw_object_border &&
+ object_x == that.object_x && object_y == that.object_y &&
+ object_w == that.object_w && object_h == that.object_h &&
+ scene_x == that.scene_x && scene_y == that.scene_y &&
+ scene_w == that.scene_w && scene_h == that.scene_h &&
+ object_layer == that.object_layer &&
+ replace_layer == that.replace_layer &&
+ scene_layer == that.scene_layer &&
+ blend == that.blend;
+ return result;
+}
+
+void FindObjConfig::copy_from(FindObjConfig &that)
+{
+ algorithm = that.algorithm;
+ use_flann = that.use_flann;
+ draw_keypoints = that.draw_keypoints;
+ draw_border = that.draw_border;
+ replace_object = that.replace_object;
+ draw_object_border = that.draw_object_border;
+ object_x = that.object_x; object_y = that.object_y;
+ object_w = that.object_w; object_h = that.object_h;
+ scene_x = that.scene_x; scene_y = that.scene_y;
+ scene_w = that.scene_w; scene_h = that.scene_h;
+ object_layer = that.object_layer;
+ replace_layer = that.replace_layer;
+ scene_layer = that.scene_layer;
+ blend = that.blend;
+}
+
+void FindObjConfig::interpolate(FindObjConfig &prev, FindObjConfig &next,
+ int64_t prev_frame, int64_t next_frame, int64_t current_frame)
+{
+ copy_from(prev);
+}
+
+
+FindObjMain::FindObjMain(PluginServer *server)
+ : PluginVClient(server)
+{
+ affine = 0;
+ overlayer = 0;
+
+ cvmodel = BC_RGB888;
+ w = h = 0;
+ object = scene = replace = 0;
+ object_x = object_y = 0;
+ object_w = object_h = 0;
+ scene_x = scene_y = 0;
+ scene_w = scene_h = 0;
+ object_layer = 0;
+ scene_layer = 1;
+ replace_layer = 2;
+
+ border_x1 = 0; border_y1 = 0;
+ border_x2 = 0; border_y2 = 0;
+ border_x3 = 0; border_y3 = 0;
+ border_x4 = 0; border_y4 = 0;
+
+ obj_x1 = 0; obj_y1 = 0;
+ obj_x2 = 0; obj_y2 = 0;
+ obj_x3 = 0; obj_y3 = 0;
+ obj_x4 = 0; obj_y4 = 0;
+
+ init_border = 1;
+}
+
+FindObjMain::~FindObjMain()
+{
+ delete affine;
+ delete overlayer;
+}
+
+const char* FindObjMain::plugin_title() { return _("Find Object"); }
+int FindObjMain::is_realtime() { return 1; }
+int FindObjMain::is_multichannel() { return 1; }
+
+NEW_WINDOW_MACRO(FindObjMain, FindObjWindow)
+LOAD_CONFIGURATION_MACRO(FindObjMain, FindObjConfig)
+
+void FindObjMain::update_gui()
+{
+ if( !thread ) return;
+ if( !load_configuration() ) return;
+ FindObjWindow *window = (FindObjWindow*)thread->window;
+ window->lock_window("FindObjMain::update_gui");
+ window->algorithm->set_text(FindObjAlgorithm::to_text(config.algorithm));
+ window->use_flann->update(config.use_flann);
+ window->object_x->update(config.object_x);
+ window->object_x_text->update((float)config.object_x);
+ window->object_y->update(config.object_y);
+ window->object_y_text->update((float)config.object_y);
+ window->object_w->update(config.object_w);
+ window->object_w_text->update((float)config.object_w);
+ window->object_h->update(config.object_h);
+ window->object_h_text->update((float)config.object_h);
+ window->scene_x->update(config.scene_x);
+ window->scene_x_text->update((float)config.scene_x);
+ window->scene_y->update(config.scene_y);
+ window->scene_y_text->update((float)config.scene_y);
+ window->scene_w->update(config.scene_w);
+ window->scene_w_text->update((float)config.scene_w);
+ window->scene_h->update(config.scene_h);
+ window->scene_h_text->update((float)config.scene_h);
+ window->draw_keypoints->update(config.draw_keypoints);
+ window->draw_border->update(config.draw_border);
+ window->replace_object->update(config.replace_object);
+ window->draw_object_border->update(config.draw_object_border);
+ window->object_layer->update( (int64_t)config.object_layer);
+ window->replace_layer->update( (int64_t)config.replace_layer);
+ window->scene_layer->update( (int64_t)config.scene_layer);
+ window->blend->update( (int64_t)config.blend);
+ window->flush();
+ window->unlock_window();
+}
+
+void FindObjMain::save_data(KeyFrame *keyframe)
+{
+ FileXML output;
+
+// cause data to be stored directly in text
+ output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+ output.tag.set_title("FINDOBJ");
+ output.tag.set_property("ALGORITHM", config.algorithm);
+ output.tag.set_property("USE_FLANN", config.use_flann);
+ output.tag.set_property("OBJECT_X", config.object_x);
+ output.tag.set_property("OBJECT_Y", config.object_y);
+ output.tag.set_property("OBJECT_W", config.object_w);
+ output.tag.set_property("OBJECT_H", config.object_h);
+ output.tag.set_property("SCENE_X", config.scene_x);
+ output.tag.set_property("SCENE_Y", config.scene_y);
+ output.tag.set_property("SCENE_W", config.scene_w);
+ output.tag.set_property("SCENE_H", config.scene_h);
+ output.tag.set_property("DRAW_KEYPOINTS", config.draw_keypoints);
+ output.tag.set_property("DRAW_BORDER", config.draw_border);
+ output.tag.set_property("REPLACE_OBJECT", config.replace_object);
+ output.tag.set_property("DRAW_OBJECT_BORDER", config.draw_object_border);
+ output.tag.set_property("OBJECT_LAYER", config.object_layer);
+ output.tag.set_property("REPLACE_LAYER", config.replace_layer);
+ output.tag.set_property("SCENE_LAYER", config.scene_layer);
+ output.tag.set_property("BLEND", config.blend);
+ output.append_tag();
+ output.tag.set_title("/FINDOBJ");
+ output.append_tag();
+ output.append_newline();
+ output.terminate_string();
+}
+
+void FindObjMain::read_data(KeyFrame *keyframe)
+{
+ FileXML input;
+
+ input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+ int result = 0;
+
+ while( !(result = input.read_tag()) ) {
+ if( input.tag.title_is("FINDOBJ") ) {
+ config.algorithm = input.tag.get_property("ALGORITHM", config.algorithm);
+ config.use_flann = input.tag.get_property("USE_FLANN", config.use_flann);
+ config.object_x = input.tag.get_property("OBJECT_X", config.object_x);
+ config.object_y = input.tag.get_property("OBJECT_Y", config.object_y);
+ config.object_w = input.tag.get_property("OBJECT_W", config.object_w);
+ config.object_h = input.tag.get_property("OBJECT_H", config.object_h);
+ config.scene_x = input.tag.get_property("SCENE_X", config.scene_x);
+ config.scene_y = input.tag.get_property("SCENE_Y", config.scene_y);
+ config.scene_w = input.tag.get_property("SCENE_W", config.scene_w);
+ config.scene_h = input.tag.get_property("SCENE_H", config.scene_h);
+ config.draw_keypoints = input.tag.get_property("DRAW_KEYPOINTS", config.draw_keypoints);
+ config.draw_border = input.tag.get_property("DRAW_BORDER", config.draw_border);
+ config.replace_object = input.tag.get_property("REPLACE_OBJECT", config.replace_object);
+ config.draw_object_border = input.tag.get_property("DRAW_OBJECT_BORDER", config.draw_object_border);
+ config.object_layer = input.tag.get_property("OBJECT_LAYER", config.object_layer);
+ config.replace_layer = input.tag.get_property("REPLACE_LAYER", config.replace_layer);
+ config.scene_layer = input.tag.get_property("SCENE_LAYER", config.scene_layer);
+ config.blend = input.tag.get_property("BLEND", config.blend);
+ }
+ }
+
+ config.boundaries();
+}
+
+void FindObjMain::draw_line(VFrame *vframe, int x1, int y1, int x2, int y2)
+{
+ vframe->draw_line(x1, y1, x2, y2);
+}
+
+void FindObjMain::draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2)
+{
+ draw_line(vframe, x1, y1, x2, y1);
+ draw_line(vframe, x2, y1 + 1, x2, y2);
+ draw_line(vframe, x2 - 1, y2, x1, y2);
+ draw_line(vframe, x1, y2 - 1, x1, y1 + 1);
+}
+
+void FindObjMain::draw_circle(VFrame *vframe, int x, int y, int r)
+{
+ int x1 = x-r, x2 = x+r;
+ int y1 = y-r, y2 = y+r;
+ vframe->draw_smooth(x1,y, x1,y1, x,y1);
+ vframe->draw_smooth(x,y1, x2,y1, x2,y);
+ vframe->draw_smooth(x2,y, x2,y2, x,y2);
+ vframe->draw_smooth(x,y2, x1,y2, x1,y);
+}
+
+void FindObjMain::filter_matches(ptV &p1, ptV &p2, double ratio)
+{
+ DMatches::iterator it;
+ for( it=pairs.begin(); it!=pairs.end(); ++it ) {
+ DMatchV &m = *it;
+ if( m.size() == 2 && m[0].distance < m[1].distance*ratio ) {
+ p1.push_back(obj_keypts[m[0].queryIdx].pt);
+ p2.push_back(scn_keypts[m[0].trainIdx].pt);
+ }
+ }
+}
+
+void FindObjMain::to_mat(Mat &mat, int mcols, int mrows,
+ VFrame *inp, int ix,int iy, BC_CModel mcolor_model)
+{
+ int mcomp = BC_CModels::components(mcolor_model);
+ int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
+ int psz = mbpp / mcomp;
+ int mdepth = psz < 2 ? CV_8U : CV_16U;
+ if( mat.dims != 2 || mat.depth() != mdepth || mat.channels() != mcomp ||
+ mat.cols != mcols || mat.rows != mrows ) {
+ mat.release();
+ }
+ if( mat.empty() ) {
+ int type = CV_MAKETYPE(mdepth, mcomp);
+ mat.create(mrows, mcols, type);
+ }
+ uint8_t *mat_rows[mrows];
+ for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
+ uint8_t **inp_rows = inp->get_rows();
+ int ibpl = inp->get_bytes_per_line(), obpl = mcols * mbpp;
+ int icolor_model = inp->get_color_model();
+ BC_CModels::transfer(mat_rows, mcolor_model, 0,0, mcols,mrows, obpl,
+ inp_rows, icolor_model, ix,iy, mcols,mrows, ibpl, 0);
+// VFrame vfrm(mat_rows[0], -1, mcols,mrows, mcolor_model, mat_rows[1]-mat_rows[0]);
+// static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/dat/%06d.png", vfrm_no++);
+// vfrm.write_png(vfn);
+}
+
+void FindObjMain::detect(Mat &mat, KeyPointV &keypts,Mat &descrs)
+{
+ keypts.clear();
+ descrs.release();
+ try {
+ detector->detectAndCompute(mat, noArray(), keypts, descrs);
+ } catch(std::exception e) { printf(_("detector exception: %s\n"), e.what()); }
+}
+
+void FindObjMain::match()
+{
+ pairs.clear();
+ try {
+ matcher->knnMatch(obj_descrs, scn_descrs, pairs, 2);
+ } catch(std::exception e) { printf(_("match execption: %s\n"), e.what()); }
+}
+
+Ptr<DescriptorMatcher> FindObjMain::flann_kdtree_matcher()
+{ // trees=5
+ const Ptr<flann::IndexParams>& indexParams =
+ makePtr<flann::KDTreeIndexParams>(5);
+ const Ptr<flann::SearchParams>& searchParams =
+ makePtr<flann::SearchParams>();
+ return makePtr<FlannBasedMatcher>(indexParams, searchParams);
+}
+Ptr<DescriptorMatcher> FindObjMain::flann_lshidx_matcher()
+{ // table_number = 6#12, key_size = 12#20, multi_probe_level = 1#2
+ const Ptr<flann::IndexParams>& indexParams =
+ makePtr<flann::LshIndexParams>(6, 12, 1);
+ const Ptr<flann::SearchParams>& searchParams =
+ makePtr<flann::SearchParams>();
+ return makePtr<FlannBasedMatcher>(indexParams, searchParams);
+}
+Ptr<DescriptorMatcher> FindObjMain::bf_matcher_norm_l2()
+{
+ return BFMatcher::create(NORM_L2);
+}
+Ptr<DescriptorMatcher> FindObjMain::bf_matcher_norm_hamming()
+{
+ return BFMatcher::create(NORM_HAMMING);
+}
+
+#ifdef _SIFT
+void FindObjMain::set_sift()
+{
+ cvmodel = BC_GREY8;
+ detector = SIFT::create();
+ matcher = config.use_flann ?
+ flann_kdtree_matcher() : bf_matcher_norm_l2();
+}
+#endif
+#ifdef _SURF
+void FindObjMain::set_surf()
+{
+ cvmodel = BC_GREY8;
+ detector = SURF::create(800);
+ matcher = config.use_flann ?
+ flann_kdtree_matcher() : bf_matcher_norm_l2();
+}
+#endif
+#ifdef _ORB
+void FindObjMain::set_orb()
+{
+ cvmodel = BC_GREY8;
+ detector = ORB::create();
+ matcher = config.use_flann ?
+ flann_lshidx_matcher() : bf_matcher_norm_hamming();
+}
+#endif
+#ifdef _AKAZE
+void FindObjMain::set_akaze()
+{
+ cvmodel = BC_GREY8;
+ detector = AKAZE::create();
+ matcher = config.use_flann ?
+ flann_lshidx_matcher() : bf_matcher_norm_hamming();
+}
+#endif
+#ifdef _BRISK
+void FindObjMain::set_brisk()
+{
+ cvmodel = BC_GREY8;
+ detector = BRISK::create();
+ matcher = config.use_flann ?
+ flann_lshidx_matcher() : bf_matcher_norm_hamming();
+}
+#endif
+
+void FindObjMain::process_match()
+{
+ if( config.algorithm == NO_ALGORITHM ) return;
+ if( !config.replace_object &&
+ !config.draw_border &&
+ !config.draw_keypoints ) return;
+
+ if( detector.empty() ) {
+ switch( config.algorithm ) {
+#ifdef _SIFT
+ case ALGORITHM_SIFT: set_sift(); break;
+#endif
+#ifdef _SURF
+ case ALGORITHM_SURF: set_surf(); break;
+#endif
+#ifdef _ORB
+ case ALGORITHM_ORB: set_orb(); break;
+#endif
+#ifdef _AKAZE
+ case ALGORITHM_AKAZE: set_akaze(); break;
+#endif
+#ifdef _BRISK
+ case ALGORITHM_BRISK: set_brisk(); break;
+#endif
+ }
+ obj_keypts.clear(); obj_descrs.release();
+ to_mat(object_mat, object_w,object_h, object, object_x,object_y, cvmodel);
+ detect(object_mat, obj_keypts, obj_descrs);
+//printf("detect obj %d features\n", (int)obj_keypts.size());
+ }
+
+ to_mat(scene_mat, scene_w,scene_h, scene, scene_x,scene_y, cvmodel);
+ detect(scene_mat, scn_keypts, scn_descrs);
+//printf("detect scn %d features\n", (int)scn_keypts.size());
+ match();
+ ptV p1, p2;
+ filter_matches(p1, p2);
+ if( p1.size() < 4 ) return;
+ Mat H = findHomography(p1, p2, RANSAC, 5.0);
+ if( !H.dims || !H.rows || !H.cols ) {
+//printf("fail, size p1=%d,p2=%d\n",(int)p1.size(),(int)p2.size());
+ return;
+ }
+
+ ptV src, dst;
+ float obj_x1 = 0, obj_x2 = object_w;
+ float obj_y1 = 0, obj_y2 = object_h;
+ src.push_back(Point2f(obj_x1,obj_y1));
+ src.push_back(Point2f(obj_x2,obj_y1));
+ src.push_back(Point2f(obj_x2,obj_y2));
+ src.push_back(Point2f(obj_x1,obj_y2));
+ perspectiveTransform(src, dst, H);
+
+ border_x1 = dst[0].x + scene_x; border_y1 = dst[0].y + scene_y;
+ border_x2 = dst[1].x + scene_x; border_y2 = dst[1].y + scene_y;
+ border_x3 = dst[2].x + scene_x; border_y3 = dst[2].y + scene_y;
+ border_x4 = dst[3].x + scene_x; border_y4 = dst[3].y + scene_y;
+//printf("src %f,%f %f,%f %f,%f %f,%f\n",
+// src[0].x,src[0].y, src[1].x,src[1].y, src[2].x,src[2].y, src[3].x,src[3].y);
+//printf("dst %f,%f %f,%f %f,%f %f,%f\n",
+// dst[0].x,dst[0].y, dst[1].x,dst[1].y, dst[2].x,dst[2].y, dst[3].x,dst[3].y);
+}
+
+int FindObjMain::process_buffer(VFrame **frame, int64_t start_position, double frame_rate)
+{
+ int prev_algorithm = config.algorithm;
+ int prev_use_flann = config.use_flann;
+
+ if( load_configuration() )
+ init_border = 1;
+
+ if( prev_algorithm != config.algorithm ||
+ prev_use_flann != config.use_flann ) {
+ detector.release();
+ matcher.release();
+ }
+
+ w = frame[0]->get_w();
+ h = frame[0]->get_h();
+
+ object_layer = config.object_layer;
+ scene_layer = config.scene_layer;
+ replace_layer = config.replace_layer;
+
+ int max_layer = PluginClient::get_total_buffers() - 1;
+ object_layer = bclip(config.object_layer, 0, max_layer);
+ scene_layer = bclip(config.scene_layer, 0, max_layer);
+ replace_layer = bclip(config.replace_layer, 0, max_layer);
+
+ int cfg_w, cfg_h, cfg_x1, cfg_y1, cfg_x2, cfg_y2;
+ cfg_w = (int)(config.object_w * w / 100);
+ cfg_h = (int)(config.object_h * h / 100);
+ cfg_x1 = (int)(config.object_x * w / 100 - cfg_w / 2);
+ cfg_y1 = (int)(config.object_y * h / 100 - cfg_h / 2);
+ cfg_x2 = cfg_x1 + cfg_w;
+ cfg_y2 = cfg_y1 + cfg_h;
+ bclamp(cfg_x1, 0, w); object_x = cfg_x1;
+ bclamp(cfg_y1, 0, h); object_y = cfg_y1;
+ bclamp(cfg_x2, 0, w); object_w = cfg_x2 - cfg_x1;
+ bclamp(cfg_y2, 0, h); object_h = cfg_y2 - cfg_y1;
+
+ cfg_w = (int)(config.scene_w * w / 100);
+ cfg_h = (int)(config.scene_h * h / 100);
+ cfg_x1 = (int)(config.scene_x * w / 100 - cfg_w / 2);
+ cfg_y1 = (int)(config.scene_y * h / 100 - cfg_h / 2);
+ cfg_x2 = cfg_x1 + cfg_w;
+ cfg_y2 = cfg_y1 + cfg_h;
+ bclamp(cfg_x1, 0, w); scene_x = cfg_x1;
+ bclamp(cfg_y1, 0, h); scene_y = cfg_y1;
+ bclamp(cfg_x2, 0, w); scene_w = cfg_x2 - cfg_x1;
+ bclamp(cfg_y2, 0, h); scene_h = cfg_y2 - cfg_y1;
+
+// Read in the input frames
+ for( int i = 0; i < PluginClient::get_total_buffers(); i++ ) {
+ read_frame(frame[i], i, start_position, frame_rate, 0);
+ }
+
+ object = frame[object_layer];
+ scene = frame[scene_layer];
+ replace = frame[replace_layer];
+
+ border_x1 = obj_x1; border_y1 = obj_y1;
+ border_x2 = obj_x2; border_y2 = obj_y2;
+ border_x3 = obj_x3; border_y3 = obj_y3;
+ border_x4 = obj_x4; border_y4 = obj_y4;
+
+ if( scene_w > 0 && scene_h > 0 && object_w > 0 && object_h > 0 ) {
+ process_match();
+ }
+
+ double w0 = init_border ? 1. : config.blend/100., w1 = 1. - w0;
+ obj_x1 = border_x1*w0 + obj_x1*w1; obj_y1 = border_y1*w0 + obj_y1*w1;
+ obj_x2 = border_x2*w0 + obj_x2*w1; obj_y2 = border_y2*w0 + obj_y2*w1;
+ obj_x3 = border_x3*w0 + obj_x3*w1; obj_y3 = border_y3*w0 + obj_y3*w1;
+ obj_x4 = border_x4*w0 + obj_x4*w1; obj_y4 = border_y4*w0 + obj_y4*w1;
+
+// Replace object in the scene layer
+ if( config.replace_object ) {
+ int cpus1 = get_project_smp() + 1;
+ if( !affine )
+ affine = new AffineEngine(cpus1, cpus1);
+ if( !overlayer )
+ overlayer = new OverlayFrame(cpus1);
+
+ VFrame *temp = new_temp(scene->get_w(), scene->get_h(), scene->get_color_model());
+ temp->clear_frame();
+ float sx = 100./w, sy = 100./h;
+ float x1 = sx * obj_x1, y1 = sy * obj_y1;
+ float x2 = sx * obj_x2, y2 = sy * obj_y2;
+ float x3 = sx * obj_x3, y3 = sy * obj_y3;
+ float x4 = sx * obj_x4, y4 = sy * obj_y4;
+ affine->process(temp, replace, 0, AffineEngine::PERSPECTIVE,
+ x1,y1, x2,y2, x3,y3, x4,y4, 1);
+ overlayer->overlay(scene, temp, 0,0, w,h, 0,0, w,h,
+ 1, TRANSFER_NORMAL, NEAREST_NEIGHBOR);
+
+ }
+
+ if( config.draw_border ) {
+ int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
+ scene->set_pixel_color(WHITE); scene->set_stiple(ss*2);
+ draw_line(scene, obj_x1, obj_y1, obj_x2, obj_y2);
+ draw_line(scene, obj_x2, obj_y2, obj_x3, obj_y3);
+ draw_line(scene, obj_x3, obj_y3, obj_x4, obj_y4);
+ draw_line(scene, obj_x4, obj_y4, obj_x1, obj_y1);
+ }
+
+ if( config.draw_keypoints ) {
+ scene->set_pixel_color(RED); scene->set_stiple(0);
+ for( int i=0,n=scn_keypts.size(); i<n; ++i ) {
+ Point2f &pt = scn_keypts[i].pt;
+ int r = scn_keypts[i].size * 1.2/9 * 2;
+ int x = pt.x + scene_x, y = pt.y + scene_y;
+ draw_circle(scene, x, y, r);
+ }
+ }
+
+// Draw object outline in the object layer
+ if( config.draw_object_border ) {
+ int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
+ scene->set_pixel_color(YELLOW); scene->set_stiple(ss*3);
+ int x1 = object_x, x2 = x1 + object_w - 1;
+ int y1 = object_y, y2 = y1 + object_h - 1;
+ draw_rect(scene, x1, y1, x2, y2);
+ scene->set_pixel_color(GREEN); scene->set_stiple(0);
+ x1 = scene_x, x2 = x1 + scene_w - 1;
+ y1 = scene_y, y2 = y1 + scene_h - 1;
+ draw_rect(scene, x1, y1, x2, y2);
+ }
+
+ scene->set_pixel_color(BLACK);
+ scene->set_stiple(0);
+ return 0;
+}
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+
+// This is mainly a test for object tracking
+
+
+
+
+#ifndef FINDOBJ_H
+#define FINDOBJ_H
+
+//#include "config.h"
+
+#include <math.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "affine.inc"
+#include "bccmodels.h"
+#include "bchash.inc"
+#include "filexml.inc"
+#include "keyframe.inc"
+#include "findobj.inc"
+#include "overlayframe.inc"
+#include "pluginvclient.h"
+#include "vframe.inc"
+
+#include "opencv2/core/types.hpp"
+#include "opencv2/core/mat.hpp"
+#include "opencv2/imgproc/imgproc.hpp"
+#include "opencv2/xfeatures2d.hpp"
+#include "opencv2/calib3d.hpp"
+#include "opencv2/flann/defines.h"
+#include "opencv2/flann/params.h"
+
+#include <vector>
+
+using namespace std;
+using namespace cv;
+using namespace cv::xfeatures2d;
+using namespace cvflann;
+
+// enabled detectors
+#define _SIFT
+#define _SURF
+#define _ORB
+#define _AKAZE
+#define _BRISK
+
+// Limits of global range in percent
+#define MIN_RADIUS 1
+#define MAX_RADIUS 200
+
+// Limits of block size in percent.
+#define MIN_BLOCK 1
+#define MAX_BLOCK 100
+
+#define MIN_LAYER 0
+#define MAX_LAYER 255
+
+#define MIN_BLEND 1
+#define MAX_BLEND 100
+
+#define NO_ALGORITHM 0
+#define ALGORITHM_SIFT 1
+#define ALGORITHM_SURF 2
+#define ALGORITHM_ORB 3
+#define ALGORITHM_AKAZE 4
+#define ALGORITHM_BRISK 5
+
+class FindObjConfig
+{
+public:
+ FindObjConfig();
+
+ int equivalent(FindObjConfig &that);
+ void copy_from(FindObjConfig &that);
+ void interpolate(FindObjConfig &prev, FindObjConfig &next,
+ int64_t prev_frame, int64_t next_frame, int64_t current_frame);
+ void boundaries();
+
+ int algorithm, use_flann;
+ float object_x, object_y, object_w, object_h;
+ float scene_x, scene_y, scene_w, scene_h;
+
+ int draw_keypoints;
+ int draw_border;
+ int replace_object;
+ int draw_object_border;
+
+ int object_layer;
+ int replace_layer;
+ int scene_layer;
+ int blend;
+};
+
+class FindObjMain : public PluginVClient
+{
+public:
+ FindObjMain(PluginServer *server);
+ ~FindObjMain();
+
+ int process_buffer(VFrame **frame, int64_t start_position, double frame_rate);
+#ifdef _SIFT
+ void set_sift();
+#endif
+#ifdef _SURF
+ void set_surf();
+#endif
+#ifdef _ORB
+ void set_orb();
+#endif
+#ifdef _AKAZE
+ void set_akaze();
+#endif
+#ifdef _BRISK
+ void set_brisk();
+#endif
+ void process_match();
+
+ void draw_vectors(VFrame *frame);
+ int is_multichannel();
+ int is_realtime();
+ void save_data(KeyFrame *keyframe);
+ void read_data(KeyFrame *keyframe);
+ void update_gui();
+
+ PLUGIN_CLASS_MEMBERS2(FindObjConfig)
+
+ AffineEngine *affine;
+ OverlayFrame *overlayer;
+ VFrame *object, *scene, *replace;
+
+ static void draw_line(VFrame *vframe, int x1, int y1, int x2, int y2);
+ static void draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2);
+ static void draw_circle(VFrame *vframe, int x, int y, int r);
+
+ int object_x, object_y, object_w, object_h;
+ int scene_x, scene_y, scene_w, scene_h;
+
+ int w, h;
+ int object_layer;
+ int scene_layer;
+ int replace_layer;
+
+// Latest coordinates of object in scene
+ int border_x1, border_y1;
+ int border_x2, border_y2;
+ int border_x3, border_y3;
+ int border_x4, border_y4;
+// Coordinates of object in scene with blending
+ float obj_x1, obj_y1;
+ float obj_x2, obj_y2;
+ float obj_x3, obj_y3;
+ float obj_x4, obj_y4;
+ int init_border;
+
+//opencv
+ typedef vector<DMatch> DMatchV;
+ typedef vector<DMatchV> DMatches;
+ typedef vector<KeyPoint> KeyPointV;
+ typedef vector<Point2f> ptV;
+
+ BC_CModel cvmodel;
+ Mat object_mat, scene_mat;
+ Mat obj_descrs; KeyPointV obj_keypts;
+ Mat scn_descrs; KeyPointV scn_keypts;
+ DMatches pairs;
+
+ static void to_mat(Mat &mat, int mcols, int mrows,
+ VFrame *inp, int ix,int iy, BC_CModel mcolor_model);
+ void detect(Mat &mat, KeyPointV &keypts, Mat &descrs);
+ void match();
+ void filter_matches(ptV &p1, ptV &p2, double ratio=0.75);
+
+ Ptr<Feature2D> detector;
+ Ptr<DescriptorMatcher> matcher;
+ Ptr<DescriptorMatcher> flann_kdtree_matcher();
+ Ptr<DescriptorMatcher> flann_lshidx_matcher();
+ Ptr<DescriptorMatcher> bf_matcher_norm_l2();
+ Ptr<DescriptorMatcher> bf_matcher_norm_hamming();
+};
+
+#endif
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef FINDOBJ_INC
+#define FINDOBJ_INC
+
+class FindObjConfig;
+class FindObjMain;
+
+#endif
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "bcdisplayinfo.h"
+#include "clip.h"
+#include "language.h"
+#include "findobj.h"
+#include "findobjwindow.h"
+#include "theme.h"
+
+
+FindObjWindow::FindObjWindow(FindObjMain *plugin)
+ : PluginClientWindow(plugin, 340, 660, 340, 660, 0)
+{
+ this->plugin = plugin;
+}
+
+FindObjWindow::~FindObjWindow()
+{
+}
+
+void FindObjWindow::create_objects()
+{
+ int x = 10, y = 10, x1 = x, x2 = get_w()/2;
+ plugin->load_configuration();
+
+ BC_Title *title;
+ add_subwindow(title = new BC_Title(x1, y, _("Algorithm:")));
+ add_subwindow(algorithm = new FindObjAlgorithm(plugin, this,
+ x1 + title->get_w() + 10, y));
+ algorithm->create_objects();
+ y += algorithm->get_h() + plugin->get_theme()->widget_border;
+
+ add_subwindow(use_flann = new FindObjUseFlann(plugin, this, x, y));
+ y += use_flann->get_h() + plugin->get_theme()->widget_border + 20;
+
+ int x0 = x + 200;
+ add_subwindow(title = new BC_Title(x, y, _("Output/scene layer:")));
+ scene_layer = new FindObjLayer(plugin, this, x0, y,
+ &plugin->config.scene_layer);
+ scene_layer->create_objects();
+ y += scene_layer->get_h() + plugin->get_theme()->widget_border;
+
+ add_subwindow(title = new BC_Title(x, y, _("Object layer:")));
+ object_layer = new FindObjLayer(plugin, this, x0, y,
+ &plugin->config.object_layer);
+ object_layer->create_objects();
+ y += object_layer->get_h() + plugin->get_theme()->widget_border;
+
+ add_subwindow(title = new BC_Title(x, y, _("Replacement object layer:")));
+ replace_layer = new FindObjLayer(plugin, this, x0, y,
+ &plugin->config.replace_layer);
+ replace_layer->create_objects();
+ y += replace_layer->get_h() + plugin->get_theme()->widget_border + 10;
+
+ add_subwindow(title = new BC_Title(x+15, y, _("Units: 0 to 100 percent")));
+ y += title->get_h();
+
+ int y1 = y;
+ add_subwindow(new BC_Title(x1, y + 10, _("Scene X:")));
+ y += title->get_h() + 15;
+ add_subwindow(scene_x = new FindObjScanFloat(plugin, this,
+ x1, y, &plugin->config.scene_x));
+ add_subwindow(scene_x_text = new FindObjScanFloatText(plugin, this,
+ x1 + scene_x->get_w() + 10, y + 10, &plugin->config.scene_x));
+ scene_x->center_text = scene_x_text;
+ scene_x_text->center = scene_x;
+
+ y += 40;
+ add_subwindow(title = new BC_Title(x1, y + 10, _("Scene Y:")));
+ y += title->get_h() + 15;
+ add_subwindow(scene_y = new FindObjScanFloat(plugin, this,
+ x1, y, &plugin->config.scene_y));
+ add_subwindow(scene_y_text = new FindObjScanFloatText(plugin, this,
+ x1 + scene_y->get_w() + 10, y + 10, &plugin->config.scene_y));
+ scene_y->center_text = scene_y_text;
+ scene_y_text->center = scene_y;
+
+ y += 40;
+ add_subwindow(new BC_Title(x1, y + 10, _("Scene W:")));
+ y += title->get_h() + 15;
+ add_subwindow(scene_w = new FindObjScanFloat(plugin, this,
+ x1, y, &plugin->config.scene_w));
+ add_subwindow(scene_w_text = new FindObjScanFloatText(plugin, this,
+ x1 + scene_w->get_w() + 10, y + 10, &plugin->config.scene_w));
+ scene_w->center_text = scene_w_text;
+ scene_w_text->center = scene_w;
+
+ y += 40;
+ add_subwindow(title = new BC_Title(x1, y + 10, _("Scene H:")));
+ y += title->get_h() + 15;
+ add_subwindow(scene_h = new FindObjScanFloat(plugin, this,
+ x1, y, &plugin->config.scene_h));
+ add_subwindow(scene_h_text = new FindObjScanFloatText(plugin, this,
+ x1 + scene_h->get_w() + 10, y + 10,
+ &plugin->config.scene_h));
+ scene_h->center_text = scene_h_text;
+ scene_h_text->center = scene_h;
+
+ y = y1;
+ add_subwindow(new BC_Title(x2, y + 10, _("Object X:")));
+ y += title->get_h() + 15;
+ add_subwindow(object_x = new FindObjScanFloat(plugin, this,
+ x2, y, &plugin->config.object_x));
+ add_subwindow(object_x_text = new FindObjScanFloatText(plugin, this,
+ x2 + object_x->get_w() + 10, y + 10, &plugin->config.object_x));
+ object_x->center_text = object_x_text;
+ object_x_text->center = object_x;
+
+ y += 40;
+ add_subwindow(title = new BC_Title(x2, y + 10, _("Object Y:")));
+ y += title->get_h() + 15;
+ add_subwindow(object_y = new FindObjScanFloat(plugin, this,
+ x2, y, &plugin->config.object_y));
+ add_subwindow(object_y_text = new FindObjScanFloatText(plugin, this,
+ x2 + object_y->get_w() + 10, y + 10, &plugin->config.object_y));
+ object_y->center_text = object_y_text;
+ object_y_text->center = object_y;
+
+ y += 40;
+ add_subwindow(new BC_Title(x2, y + 10, _("Object W:")));
+ y += title->get_h() + 15;
+ add_subwindow(object_w = new FindObjScanFloat(plugin, this,
+ x2, y, &plugin->config.object_w));
+ add_subwindow(object_w_text = new FindObjScanFloatText(plugin, this,
+ x2 + object_w->get_w() + 10, y + 10, &plugin->config.object_w));
+ object_w->center_text = object_w_text;
+ object_w_text->center = object_w;
+
+ y += 40;
+ add_subwindow(title = new BC_Title(x2, y + 10, _("Object H:")));
+ y += title->get_h() + 15;
+ add_subwindow(object_h = new FindObjScanFloat(plugin, this,
+ x2, y, &plugin->config.object_h));
+ add_subwindow(object_h_text = new FindObjScanFloatText(plugin, this,
+ x2 + object_h->get_w() + 10, y + 10,
+ &plugin->config.object_h));
+ object_h->center_text = object_h_text;
+ object_h_text->center = object_h;
+
+ y += 40 + 15;
+ add_subwindow(draw_keypoints = new FindObjDrawKeypoints(plugin, this, x, y));
+ y += draw_keypoints->get_h() + plugin->get_theme()->widget_border;
+ add_subwindow(draw_border = new FindObjDrawBorder(plugin, this, x, y));
+ y += draw_border->get_h() + plugin->get_theme()->widget_border;
+ add_subwindow(replace_object = new FindObjReplace(plugin, this, x, y));
+ y += replace_object->get_h() + plugin->get_theme()->widget_border;
+ add_subwindow(draw_object_border = new FindObjDrawObjectBorder(plugin, this, x, y));
+ y += draw_object_border->get_h() + plugin->get_theme()->widget_border;
+
+ add_subwindow(title = new BC_Title(x, y + 10, _("Object blend amount:")));
+ add_subwindow(blend = new FindObjBlend(plugin,
+ x + title->get_w() + plugin->get_theme()->widget_border, y,
+ &plugin->config.blend));
+ y += blend->get_h();
+
+ show_window(1);
+}
+
+
+FindObjScanFloat::FindObjScanFloat(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y, float *value)
+ : BC_FPot(x, y, *value, (float)0, (float)100)
+{
+ this->plugin = plugin;
+ this->gui = gui;
+ this->value = value;
+ this->center_text = 0;
+ set_precision(0.1);
+}
+
+int FindObjScanFloat::handle_event()
+{
+ *value = get_value();
+ center_text->update(*value);
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+FindObjScanFloatText::FindObjScanFloatText(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y, float *value)
+ : BC_TextBox(x, y, 75, 1, *value)
+{
+ this->plugin = plugin;
+ this->gui = gui;
+ this->value = value;
+ this->center = 0;
+ set_precision(1);
+}
+
+int FindObjScanFloatText::handle_event()
+{
+ *value = atof(get_text());
+ center->update(*value);
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+FindObjDrawBorder::FindObjDrawBorder(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y)
+ : BC_CheckBox(x, y, plugin->config.draw_border, _("Draw border"))
+{
+ this->gui = gui;
+ this->plugin = plugin;
+}
+
+int FindObjDrawBorder::handle_event()
+{
+ plugin->config.draw_border = get_value();
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+FindObjDrawKeypoints::FindObjDrawKeypoints(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y)
+ : BC_CheckBox(x, y, plugin->config.draw_keypoints, _("Draw keypoints"))
+{
+ this->gui = gui;
+ this->plugin = plugin;
+}
+
+int FindObjDrawKeypoints::handle_event()
+{
+ plugin->config.draw_keypoints = get_value();
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+FindObjReplace::FindObjReplace(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y)
+ : BC_CheckBox(x, y, plugin->config.replace_object, _("Replace object"))
+{
+ this->gui = gui;
+ this->plugin = plugin;
+}
+
+int FindObjReplace::handle_event()
+{
+ plugin->config.replace_object = get_value();
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+FindObjDrawObjectBorder::FindObjDrawObjectBorder(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y)
+ : BC_CheckBox(x, y, plugin->config.draw_object_border, _("Draw object border"))
+{
+ this->gui = gui;
+ this->plugin = plugin;
+}
+
+int FindObjDrawObjectBorder::handle_event()
+{
+ plugin->config.draw_object_border = get_value();
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+FindObjAlgorithm::FindObjAlgorithm(FindObjMain *plugin, FindObjWindow *gui, int x, int y)
+ : BC_PopupMenu(x, y, calculate_w(gui), to_text(plugin->config.algorithm))
+{
+ this->plugin = plugin;
+ this->gui = gui;
+}
+
+int FindObjAlgorithm::handle_event()
+{
+ plugin->config.algorithm = from_text(get_text());
+ plugin->send_configure_change();
+ return 1;
+}
+
+void FindObjAlgorithm::create_objects()
+{
+ add_item(new BC_MenuItem(to_text(NO_ALGORITHM)));
+#ifdef _SIFT
+ add_item(new BC_MenuItem(to_text(ALGORITHM_SIFT)));
+#endif
+#ifdef _SURF
+ add_item(new BC_MenuItem(to_text(ALGORITHM_SURF)));
+#endif
+#ifdef _ORB
+ add_item(new BC_MenuItem(to_text(ALGORITHM_ORB)));
+#endif
+#ifdef _AKAZE
+ add_item(new BC_MenuItem(to_text(ALGORITHM_AKAZE)));
+#endif
+#ifdef _BRISK
+ add_item(new BC_MenuItem(to_text(ALGORITHM_BRISK)));
+#endif
+}
+
+int FindObjAlgorithm::from_text(char *text)
+{
+#ifdef _SIFT
+ if(!strcmp(text, _("SIFT"))) return ALGORITHM_SIFT;
+#endif
+#ifdef _SURF
+ if(!strcmp(text, _("SURF"))) return ALGORITHM_SURF;
+#endif
+#ifdef _ORB
+ if(!strcmp(text, _("ORB"))) return ALGORITHM_ORB;
+#endif
+#ifdef _AKAZE
+ if(!strcmp(text, _("AKAZE"))) return ALGORITHM_AKAZE;
+#endif
+#ifdef _BRISK
+ if(!strcmp(text, _("BRISK"))) return ALGORITHM_BRISK;
+#endif
+ return NO_ALGORITHM;
+}
+
+char* FindObjAlgorithm::to_text(int mode)
+{
+ switch( mode ) {
+#ifdef _SIFT
+ case ALGORITHM_SIFT: return _("SIFT");
+#endif
+#ifdef _SURF
+ case ALGORITHM_SURF: return _("SURF");
+#endif
+#ifdef _ORB
+ case ALGORITHM_ORB: return _("ORB");
+#endif
+#ifdef _AKAZE
+ case ALGORITHM_AKAZE: return _("AKAZE");
+#endif
+#ifdef _BRISK
+ case ALGORITHM_BRISK: return _("BRISK");
+#endif
+ }
+ return _("Don't Calculate");
+}
+
+int FindObjAlgorithm::calculate_w(FindObjWindow *gui)
+{
+ int result = 0;
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(NO_ALGORITHM)));
+#ifdef _SIFT
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_SIFT)));
+#endif
+#ifdef _SURF
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_SURF)));
+#endif
+#ifdef _ORB
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_ORB)));
+#endif
+#ifdef _AKAZE
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_AKAZE)));
+#endif
+#ifdef _BRISK
+ result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_BRISK)));
+#endif
+ return result + 50;
+}
+
+
+FindObjUseFlann::FindObjUseFlann(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y)
+ : BC_CheckBox(x, y, plugin->config.use_flann, _("Use FLANN"))
+{
+ this->gui = gui;
+ this->plugin = plugin;
+}
+
+int FindObjUseFlann::handle_event()
+{
+ plugin->config.use_flann = get_value();
+ plugin->send_configure_change();
+ return 1;
+}
+
+
+FindObjLayer::FindObjLayer(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y, int *value)
+ : BC_TumbleTextBox(gui, *value, MIN_LAYER, MAX_LAYER, x, y, calculate_w(gui))
+{
+ this->plugin = plugin;
+ this->gui = gui;
+ this->value = value;
+}
+
+int FindObjLayer::handle_event()
+{
+ *value = atoi(get_text());
+ plugin->send_configure_change();
+ return 1;
+}
+
+int FindObjLayer::calculate_w(FindObjWindow *gui)
+{
+ int result = 0;
+ result = gui->get_text_width(MEDIUMFONT, "000");
+ return result + 50;
+}
+
+
+FindObjBlend::FindObjBlend(FindObjMain *plugin,
+ int x,
+ int y,
+ int *value)
+ : BC_IPot(x,
+ y,
+ (int64_t)*value,
+ (int64_t)MIN_BLEND,
+ (int64_t)MAX_BLEND)
+{
+ this->plugin = plugin;
+ this->value = value;
+}
+
+int FindObjBlend::handle_event()
+{
+ *value = (int)get_value();
+ plugin->send_configure_change();
+ return 1;
+}
+
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#ifndef __FINDOBJWINDOW_H__
+#define __FINDOBJWINDOW_H__
+
+#include "guicast.h"
+#include "findobj.inc"
+
+class FindObjLayer;
+class FindObjScanFloat;
+class FindObjScanFloatText;
+class FindObjDrawBorder;
+class FindObjDrawKeypoints;
+class FindObjReplace;
+class FindObjDrawObjectBorder;
+class FindObjAlgorithm;
+class FindObjBlend;
+class FindObjWindow;
+
+class FindObjLayer : public BC_TumbleTextBox
+{
+public:
+ FindObjLayer(FindObjMain *plugin, FindObjWindow *gui,
+ int x, int y, int *value);
+ int handle_event();
+ static int calculate_w(FindObjWindow *gui);
+ FindObjMain *plugin;
+ FindObjWindow *gui;
+ int *value;
+};
+
+class FindObjScanFloat : public BC_FPot
+{
+public:
+ FindObjScanFloat(FindObjMain *plugin, FindObjWindow *gui, int x, int y, float *value);
+ int handle_event();
+ FindObjMain *plugin;
+ FindObjWindow *gui;
+ FindObjScanFloatText *center_text;
+ float *value;
+};
+
+class FindObjScanFloatText : public BC_TextBox
+{
+public:
+ FindObjScanFloatText(FindObjMain *plugin, FindObjWindow *gui, int x, int y, float *value);
+ int handle_event();
+ FindObjWindow *gui;
+ FindObjMain *plugin;
+ FindObjScanFloat *center;
+ float *value;
+};
+
+
+class FindObjDrawBorder : public BC_CheckBox
+{
+public:
+ FindObjDrawBorder(FindObjMain *plugin, FindObjWindow *gui, int x, int y);
+ int handle_event();
+ FindObjMain *plugin;
+ FindObjWindow *gui;
+};
+
+class FindObjDrawKeypoints : public BC_CheckBox
+{
+public:
+ FindObjDrawKeypoints(FindObjMain *plugin, FindObjWindow *gui, int x, int y);
+ int handle_event();
+ FindObjMain *plugin;
+ FindObjWindow *gui;
+};
+
+class FindObjReplace : public BC_CheckBox
+{
+public:
+ FindObjReplace(FindObjMain *plugin, FindObjWindow *gui, int x, int y);
+ int handle_event();
+ FindObjMain *plugin;
+ FindObjWindow *gui;
+};
+
+class FindObjDrawObjectBorder : public BC_CheckBox
+{
+public:
+ FindObjDrawObjectBorder(FindObjMain *plugin, FindObjWindow *gui, int x, int y);
+ int handle_event();
+ FindObjMain *plugin;
+ FindObjWindow *gui;
+};
+
+class FindObjAlgorithm : public BC_PopupMenu
+{
+public:
+ FindObjAlgorithm(FindObjMain *plugin, FindObjWindow *gui, int x, int y);
+ int handle_event();
+ void create_objects();
+ static int calculate_w(FindObjWindow *gui);
+ static int from_text(char *text);
+ static char* to_text(int mode);
+ FindObjMain *plugin;
+ FindObjWindow *gui;
+};
+
+class FindObjUseFlann : public BC_CheckBox
+{
+public:
+ FindObjUseFlann(FindObjMain *plugin, FindObjWindow *gui, int x, int y);
+ int handle_event();
+ FindObjMain *plugin;
+ FindObjWindow *gui;
+};
+
+class FindObjBlend : public BC_IPot
+{
+public:
+ FindObjBlend(FindObjMain *plugin, int x, int y, int *value);
+ int handle_event();
+ FindObjMain *plugin;
+ int *value;
+};
+
+class FindObjWindow : public PluginClientWindow
+{
+public:
+ FindObjWindow(FindObjMain *plugin);
+ ~FindObjWindow();
+ void create_objects();
+
+ FindObjAlgorithm *algorithm;
+ FindObjUseFlann *use_flann;
+ FindObjScanFloat *object_x, *object_y, *object_w, *object_h;
+ FindObjScanFloatText *object_x_text, *object_y_text, *object_w_text, *object_h_text;
+ FindObjScanFloat *scene_x, *scene_y, *scene_w, *scene_h;
+ FindObjScanFloatText *scene_x_text, *scene_y_text, *scene_w_text, *scene_h_text;
+ FindObjDrawKeypoints *draw_keypoints;
+ FindObjDrawBorder *draw_border;
+ FindObjReplace *replace_object;
+ FindObjDrawObjectBorder *draw_object_border;
+ FindObjLayer *object_layer;
+ FindObjLayer *scene_layer;
+ FindObjLayer *replace_layer;
+ FindObjBlend *blend;
+ FindObjMain *plugin;
+};
+
+#endif
--- /dev/null
+
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef FINDOBJWINDOW_INC
+#define FINDOBJWINDOW_INC
+
+class FindObjLayer;
+class FindObjScanFloat;
+class FindObjScanFloatText;
+class FindObjDrawBorder;
+class FindObjDrawKeypoints;
+class FindObjReplace;
+class FindObjDrawObjectBorder;
+class FindObjAlgorithm;
+class FindObjUseFlann;
+class FindObjBlend;
+class FindObjWindow;
+
+#endif
+++ /dev/null
-default: all
-
-TOPDIR?=../..
-include $(TOPDIR)/plugin_defs
-
-PLUGIN = findobject
-
-OBJS := \
- $(OBJDIR)/findobject.o \
- $(OBJDIR)/findobjectwindow.o \
-
-want_var:=$(WANT_FINDOBJECT)
-include $(TOPDIR)/opencv_build
-include $(TOPDIR)/plugin_config
-
-all: opencv
- +make $(OUTPUT)
-
-$(OBJDIR)/findobject.o: findobject.C findobject.h findobjectwindow.h
-$(OBJDIR)/findobjectwindow.o: findobjectwindow.C findobject.h findobjectwindow.h
-
+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "affine.h"
-#include "cicolors.h"
-#include "clip.h"
-#include "filexml.h"
-#include "language.h"
-#include "findobject.h"
-#include "findobjectwindow.h"
-#include "mutex.h"
-#include "overlayframe.h"
-
-#include <errno.h>
-#include <exception>
-#include <unistd.h>
-
-REGISTER_PLUGIN(FindObjectMain)
-
-FindObjectConfig::FindObjectConfig()
-{
- algorithm = NO_ALGORITHM;
- use_flann = 1;
- draw_keypoints = 0;
- draw_border = 0;
- replace_object = 0;
- draw_object_border = 0;
- object_x = 50; object_y = 50;
- object_w = 100; object_h = 100;
- scene_x = 50; scene_y = 50;
- scene_w = 100; scene_h = 100;
- scene_layer = 0;
- object_layer = 1;
- replace_layer = 2;
- blend = 100;
-}
-
-void FindObjectConfig::boundaries()
-{
- bclamp(object_x, 0, 100); bclamp(object_y, 0, 100);
- bclamp(object_w, 0, 100); bclamp(object_h, 0, 100);
- bclamp(scene_x, 0, 100); bclamp(scene_y, 0, 100);
- bclamp(scene_w, 0, 100); bclamp(scene_h, 0, 100);
- bclamp(object_layer, MIN_LAYER, MAX_LAYER);
- bclamp(replace_layer, MIN_LAYER, MAX_LAYER);
- bclamp(scene_layer, MIN_LAYER, MAX_LAYER);
- bclamp(blend, MIN_BLEND, MAX_BLEND);
-}
-
-int FindObjectConfig::equivalent(FindObjectConfig &that)
-{
- int result =
- algorithm == that.algorithm &&
- use_flann == that.use_flann &&
- draw_keypoints == that.draw_keypoints &&
- draw_border == that.draw_border &&
- replace_object == that.replace_object &&
- draw_object_border == that.draw_object_border &&
- object_x == that.object_x && object_y == that.object_y &&
- object_w == that.object_w && object_h == that.object_h &&
- scene_x == that.scene_x && scene_y == that.scene_y &&
- scene_w == that.scene_w && scene_h == that.scene_h &&
- object_layer == that.object_layer &&
- replace_layer == that.replace_layer &&
- scene_layer == that.scene_layer &&
- blend == that.blend;
- return result;
-}
-
-void FindObjectConfig::copy_from(FindObjectConfig &that)
-{
- algorithm = that.algorithm;
- use_flann = that.use_flann;
- draw_keypoints = that.draw_keypoints;
- draw_border = that.draw_border;
- replace_object = that.replace_object;
- draw_object_border = that.draw_object_border;
- object_x = that.object_x; object_y = that.object_y;
- object_w = that.object_w; object_h = that.object_h;
- scene_x = that.scene_x; scene_y = that.scene_y;
- scene_w = that.scene_w; scene_h = that.scene_h;
- object_layer = that.object_layer;
- replace_layer = that.replace_layer;
- scene_layer = that.scene_layer;
- blend = that.blend;
-}
-
-void FindObjectConfig::interpolate(FindObjectConfig &prev, FindObjectConfig &next,
- int64_t prev_frame, int64_t next_frame, int64_t current_frame)
-{
- copy_from(prev);
-}
-
-
-FindObjectMain::FindObjectMain(PluginServer *server)
- : PluginVClient(server)
-{
- affine = 0;
- overlayer = 0;
-
- cvmodel = BC_RGB888;
- w = h = 0;
- object = scene = replace = 0;
- object_x = object_y = 0;
- object_w = object_h = 0;
- scene_x = scene_y = 0;
- scene_w = scene_h = 0;
- object_layer = 0;
- scene_layer = 1;
- replace_layer = 2;
-
- border_x1 = 0; border_y1 = 0;
- border_x2 = 0; border_y2 = 0;
- border_x3 = 0; border_y3 = 0;
- border_x4 = 0; border_y4 = 0;
-
- obj_x1 = 0; obj_y1 = 0;
- obj_x2 = 0; obj_y2 = 0;
- obj_x3 = 0; obj_y3 = 0;
- obj_x4 = 0; obj_y4 = 0;
-
- init_border = 1;
-}
-
-FindObjectMain::~FindObjectMain()
-{
- delete affine;
- delete overlayer;
-}
-
-const char* FindObjectMain::plugin_title() { return _("Find Object"); }
-int FindObjectMain::is_realtime() { return 1; }
-int FindObjectMain::is_multichannel() { return 1; }
-
-NEW_WINDOW_MACRO(FindObjectMain, FindObjectWindow)
-LOAD_CONFIGURATION_MACRO(FindObjectMain, FindObjectConfig)
-
-void FindObjectMain::update_gui()
-{
- if( !thread ) return;
- if( !load_configuration() ) return;
- FindObjectWindow *window = (FindObjectWindow*)thread->window;
- window->lock_window("FindObjectMain::update_gui");
- window->algorithm->set_text(FindObjectAlgorithm::to_text(config.algorithm));
- window->use_flann->update(config.use_flann);
- window->object_x->update(config.object_x);
- window->object_x_text->update((float)config.object_x);
- window->object_y->update(config.object_y);
- window->object_y_text->update((float)config.object_y);
- window->object_w->update(config.object_w);
- window->object_w_text->update((float)config.object_w);
- window->object_h->update(config.object_h);
- window->object_h_text->update((float)config.object_h);
- window->scene_x->update(config.scene_x);
- window->scene_x_text->update((float)config.scene_x);
- window->scene_y->update(config.scene_y);
- window->scene_y_text->update((float)config.scene_y);
- window->scene_w->update(config.scene_w);
- window->scene_w_text->update((float)config.scene_w);
- window->scene_h->update(config.scene_h);
- window->scene_h_text->update((float)config.scene_h);
- window->draw_keypoints->update(config.draw_keypoints);
- window->draw_border->update(config.draw_border);
- window->replace_object->update(config.replace_object);
- window->draw_object_border->update(config.draw_object_border);
- window->object_layer->update( (int64_t)config.object_layer);
- window->replace_layer->update( (int64_t)config.replace_layer);
- window->scene_layer->update( (int64_t)config.scene_layer);
- window->blend->update( (int64_t)config.blend);
- window->flush();
- window->unlock_window();
-}
-
-void FindObjectMain::save_data(KeyFrame *keyframe)
-{
- FileXML output;
-
-// cause data to be stored directly in text
- output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
- output.tag.set_title("FINDOBJECT");
- output.tag.set_property("ALGORITHM", config.algorithm);
- output.tag.set_property("USE_FLANN", config.use_flann);
- output.tag.set_property("OBJECT_X", config.object_x);
- output.tag.set_property("OBJECT_Y", config.object_y);
- output.tag.set_property("OBJECT_W", config.object_w);
- output.tag.set_property("OBJECT_H", config.object_h);
- output.tag.set_property("SCENE_X", config.scene_x);
- output.tag.set_property("SCENE_Y", config.scene_y);
- output.tag.set_property("SCENE_W", config.scene_w);
- output.tag.set_property("SCENE_H", config.scene_h);
- output.tag.set_property("DRAW_KEYPOINTS", config.draw_keypoints);
- output.tag.set_property("DRAW_BORDER", config.draw_border);
- output.tag.set_property("REPLACE_OBJECT", config.replace_object);
- output.tag.set_property("DRAW_OBJECT_BORDER", config.draw_object_border);
- output.tag.set_property("OBJECT_LAYER", config.object_layer);
- output.tag.set_property("REPLACE_LAYER", config.replace_layer);
- output.tag.set_property("SCENE_LAYER", config.scene_layer);
- output.tag.set_property("BLEND", config.blend);
- output.append_tag();
- output.tag.set_title("/FINDOBJECT");
- output.append_tag();
- output.append_newline();
- output.terminate_string();
-}
-
-void FindObjectMain::read_data(KeyFrame *keyframe)
-{
- FileXML input;
-
- input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
-
- int result = 0;
-
- while( !(result = input.read_tag()) ) {
- if( input.tag.title_is("FINDOBJECT") ) {
- config.algorithm = input.tag.get_property("ALGORITHM", config.algorithm);
- config.use_flann = input.tag.get_property("USE_FLANN", config.use_flann);
- config.object_x = input.tag.get_property("OBJECT_X", config.object_x);
- config.object_y = input.tag.get_property("OBJECT_Y", config.object_y);
- config.object_w = input.tag.get_property("OBJECT_W", config.object_w);
- config.object_h = input.tag.get_property("OBJECT_H", config.object_h);
- config.scene_x = input.tag.get_property("SCENE_X", config.scene_x);
- config.scene_y = input.tag.get_property("SCENE_Y", config.scene_y);
- config.scene_w = input.tag.get_property("SCENE_W", config.scene_w);
- config.scene_h = input.tag.get_property("SCENE_H", config.scene_h);
- config.draw_keypoints = input.tag.get_property("DRAW_KEYPOINTS", config.draw_keypoints);
- config.draw_border = input.tag.get_property("DRAW_BORDER", config.draw_border);
- config.replace_object = input.tag.get_property("REPLACE_OBJECT", config.replace_object);
- config.draw_object_border = input.tag.get_property("DRAW_OBJECT_BORDER", config.draw_object_border);
- config.object_layer = input.tag.get_property("OBJECT_LAYER", config.object_layer);
- config.replace_layer = input.tag.get_property("REPLACE_LAYER", config.replace_layer);
- config.scene_layer = input.tag.get_property("SCENE_LAYER", config.scene_layer);
- config.blend = input.tag.get_property("BLEND", config.blend);
- }
- }
-
- config.boundaries();
-}
-
-void FindObjectMain::draw_line(VFrame *vframe, int x1, int y1, int x2, int y2)
-{
- vframe->draw_line(x1, y1, x2, y2);
-}
-
-void FindObjectMain::draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2)
-{
- draw_line(vframe, x1, y1, x2, y1);
- draw_line(vframe, x2, y1 + 1, x2, y2);
- draw_line(vframe, x2 - 1, y2, x1, y2);
- draw_line(vframe, x1, y2 - 1, x1, y1 + 1);
-}
-
-void FindObjectMain::draw_circle(VFrame *vframe, int x, int y, int r)
-{
- int x1 = x-r, x2 = x+r;
- int y1 = y-r, y2 = y+r;
- vframe->draw_smooth(x1,y, x1,y1, x,y1);
- vframe->draw_smooth(x,y1, x2,y1, x2,y);
- vframe->draw_smooth(x2,y, x2,y2, x,y2);
- vframe->draw_smooth(x,y2, x1,y2, x1,y);
-}
-
-void FindObjectMain::filter_matches(ptV &p1, ptV &p2, double ratio)
-{
- DMatches::iterator it;
- for( it=pairs.begin(); it!=pairs.end(); ++it ) {
- DMatchV &m = *it;
- if( m.size() == 2 && m[0].distance < m[1].distance*ratio ) {
- p1.push_back(obj_keypts[m[0].queryIdx].pt);
- p2.push_back(scn_keypts[m[0].trainIdx].pt);
- }
- }
-}
-
-void FindObjectMain::to_mat(Mat &mat, int mcols, int mrows,
- VFrame *inp, int ix,int iy, BC_CModel mcolor_model)
-{
- int mcomp = BC_CModels::components(mcolor_model);
- int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
- int psz = mbpp / mcomp;
- int mdepth = psz < 2 ? CV_8U : CV_16U;
- if( mat.dims != 2 || mat.depth() != mdepth || mat.channels() != mcomp ||
- mat.cols != mcols || mat.rows != mrows ) {
- mat.release();
- }
- if( mat.empty() ) {
- int type = CV_MAKETYPE(mdepth, mcomp);
- mat.create(mrows, mcols, type);
- }
- uint8_t *mat_rows[mrows];
- for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
- uint8_t **inp_rows = inp->get_rows();
- int ibpl = inp->get_bytes_per_line(), obpl = mcols * mbpp;
- int icolor_model = inp->get_color_model();
- BC_CModels::transfer(mat_rows, mcolor_model, 0,0, mcols,mrows, obpl,
- inp_rows, icolor_model, ix,iy, mcols,mrows, ibpl, 0);
-// VFrame vfrm(mat_rows[0], -1, mcols,mrows, mcolor_model, mat_rows[1]-mat_rows[0]);
-// static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/dat/%06d.png", vfrm_no++);
-// vfrm.write_png(vfn);
-}
-
-void FindObjectMain::detect(Mat &mat, KeyPointV &keypts,Mat &descrs)
-{
- keypts.clear();
- descrs.release();
- try {
- detector->detectAndCompute(mat, noArray(), keypts, descrs);
- } catch(std::exception e) { printf(_("detector exception: %s\n"), e.what()); }
-}
-
-void FindObjectMain::match()
-{
- pairs.clear();
- try {
- matcher->knnMatch(obj_descrs, scn_descrs, pairs, 2);
- } catch(std::exception e) { printf(_("match execption: %s\n"), e.what()); }
-}
-
-Ptr<DescriptorMatcher> FindObjectMain::flann_kdtree_matcher()
-{ // trees=5
- const Ptr<flann::IndexParams>& indexParams =
- makePtr<flann::KDTreeIndexParams>(5);
- const Ptr<flann::SearchParams>& searchParams =
- makePtr<flann::SearchParams>();
- return makePtr<FlannBasedMatcher>(indexParams, searchParams);
-}
-Ptr<DescriptorMatcher> FindObjectMain::flann_lshidx_matcher()
-{ // table_number = 6#12, key_size = 12#20, multi_probe_level = 1#2
- const Ptr<flann::IndexParams>& indexParams =
- makePtr<flann::LshIndexParams>(6, 12, 1);
- const Ptr<flann::SearchParams>& searchParams =
- makePtr<flann::SearchParams>();
- return makePtr<FlannBasedMatcher>(indexParams, searchParams);
-}
-Ptr<DescriptorMatcher> FindObjectMain::bf_matcher_norm_l2()
-{
- return BFMatcher::create(NORM_L2);
-}
-Ptr<DescriptorMatcher> FindObjectMain::bf_matcher_norm_hamming()
-{
- return BFMatcher::create(NORM_HAMMING);
-}
-
-#ifdef _SIFT
-void FindObjectMain::set_sift()
-{
- cvmodel = BC_GREY8;
- detector = SIFT::create();
- matcher = config.use_flann ?
- flann_kdtree_matcher() : bf_matcher_norm_l2();
-}
-#endif
-#ifdef _SURF
-void FindObjectMain::set_surf()
-{
- cvmodel = BC_GREY8;
- detector = SURF::create(800);
- matcher = config.use_flann ?
- flann_kdtree_matcher() : bf_matcher_norm_l2();
-}
-#endif
-#ifdef _ORB
-void FindObjectMain::set_orb()
-{
- cvmodel = BC_GREY8;
- detector = ORB::create();
- matcher = config.use_flann ?
- flann_lshidx_matcher() : bf_matcher_norm_hamming();
-}
-#endif
-#ifdef _AKAZE
-void FindObjectMain::set_akaze()
-{
- cvmodel = BC_GREY8;
- detector = AKAZE::create();
- matcher = config.use_flann ?
- flann_lshidx_matcher() : bf_matcher_norm_hamming();
-}
-#endif
-#ifdef _BRISK
-void FindObjectMain::set_brisk()
-{
- cvmodel = BC_GREY8;
- detector = BRISK::create();
- matcher = config.use_flann ?
- flann_lshidx_matcher() : bf_matcher_norm_hamming();
-}
-#endif
-
-void FindObjectMain::process_match()
-{
- if( config.algorithm == NO_ALGORITHM ) return;
- if( !config.replace_object &&
- !config.draw_border &&
- !config.draw_keypoints ) return;
-
- if( detector.empty() ) {
- switch( config.algorithm ) {
-#ifdef _SIFT
- case ALGORITHM_SIFT: set_sift(); break;
-#endif
-#ifdef _SURF
- case ALGORITHM_SURF: set_surf(); break;
-#endif
-#ifdef _ORB
- case ALGORITHM_ORB: set_orb(); break;
-#endif
-#ifdef _AKAZE
- case ALGORITHM_AKAZE: set_akaze(); break;
-#endif
-#ifdef _BRISK
- case ALGORITHM_BRISK: set_brisk(); break;
-#endif
- }
- obj_keypts.clear(); obj_descrs.release();
- to_mat(object_mat, object_w,object_h, object, object_x,object_y, cvmodel);
- detect(object_mat, obj_keypts, obj_descrs);
-//printf("detect obj %d features\n", (int)obj_keypts.size());
- }
-
- to_mat(scene_mat, scene_w,scene_h, scene, scene_x,scene_y, cvmodel);
- detect(scene_mat, scn_keypts, scn_descrs);
-//printf("detect scn %d features\n", (int)scn_keypts.size());
- match();
- ptV p1, p2;
- filter_matches(p1, p2);
- if( p1.size() < 4 ) return;
- Mat H = findHomography(p1, p2, RANSAC, 5.0);
- if( !H.dims || !H.rows || !H.cols ) {
-//printf("fail, size p1=%d,p2=%d\n",(int)p1.size(),(int)p2.size());
- return;
- }
-
- ptV src, dst;
- float obj_x1 = 0, obj_x2 = object_w;
- float obj_y1 = 0, obj_y2 = object_h;
- src.push_back(Point2f(obj_x1,obj_y1));
- src.push_back(Point2f(obj_x2,obj_y1));
- src.push_back(Point2f(obj_x2,obj_y2));
- src.push_back(Point2f(obj_x1,obj_y2));
- perspectiveTransform(src, dst, H);
-
- border_x1 = dst[0].x + scene_x; border_y1 = dst[0].y + scene_y;
- border_x2 = dst[1].x + scene_x; border_y2 = dst[1].y + scene_y;
- border_x3 = dst[2].x + scene_x; border_y3 = dst[2].y + scene_y;
- border_x4 = dst[3].x + scene_x; border_y4 = dst[3].y + scene_y;
-//printf("src %f,%f %f,%f %f,%f %f,%f\n",
-// src[0].x,src[0].y, src[1].x,src[1].y, src[2].x,src[2].y, src[3].x,src[3].y);
-//printf("dst %f,%f %f,%f %f,%f %f,%f\n",
-// dst[0].x,dst[0].y, dst[1].x,dst[1].y, dst[2].x,dst[2].y, dst[3].x,dst[3].y);
-}
-
-int FindObjectMain::process_buffer(VFrame **frame, int64_t start_position, double frame_rate)
-{
- int prev_algorithm = config.algorithm;
- int prev_use_flann = config.use_flann;
-
- if( load_configuration() )
- init_border = 1;
-
- if( prev_algorithm != config.algorithm ||
- prev_use_flann != config.use_flann ) {
- detector.release();
- matcher.release();
- }
-
- w = frame[0]->get_w();
- h = frame[0]->get_h();
-
- object_layer = config.object_layer;
- scene_layer = config.scene_layer;
- replace_layer = config.replace_layer;
-
- int max_layer = PluginClient::get_total_buffers() - 1;
- object_layer = bclip(config.object_layer, 0, max_layer);
- scene_layer = bclip(config.scene_layer, 0, max_layer);
- replace_layer = bclip(config.replace_layer, 0, max_layer);
-
- int cfg_w, cfg_h, cfg_x1, cfg_y1, cfg_x2, cfg_y2;
- cfg_w = (int)(config.object_w * w / 100);
- cfg_h = (int)(config.object_h * h / 100);
- cfg_x1 = (int)(config.object_x * w / 100 - cfg_w / 2);
- cfg_y1 = (int)(config.object_y * h / 100 - cfg_h / 2);
- cfg_x2 = cfg_x1 + cfg_w;
- cfg_y2 = cfg_y1 + cfg_h;
- bclamp(cfg_x1, 0, w); object_x = cfg_x1;
- bclamp(cfg_y1, 0, h); object_y = cfg_y1;
- bclamp(cfg_x2, 0, w); object_w = cfg_x2 - cfg_x1;
- bclamp(cfg_y2, 0, h); object_h = cfg_y2 - cfg_y1;
-
- cfg_w = (int)(config.scene_w * w / 100);
- cfg_h = (int)(config.scene_h * h / 100);
- cfg_x1 = (int)(config.scene_x * w / 100 - cfg_w / 2);
- cfg_y1 = (int)(config.scene_y * h / 100 - cfg_h / 2);
- cfg_x2 = cfg_x1 + cfg_w;
- cfg_y2 = cfg_y1 + cfg_h;
- bclamp(cfg_x1, 0, w); scene_x = cfg_x1;
- bclamp(cfg_y1, 0, h); scene_y = cfg_y1;
- bclamp(cfg_x2, 0, w); scene_w = cfg_x2 - cfg_x1;
- bclamp(cfg_y2, 0, h); scene_h = cfg_y2 - cfg_y1;
-
-// Read in the input frames
- for( int i = 0; i < PluginClient::get_total_buffers(); i++ ) {
- read_frame(frame[i], i, start_position, frame_rate, 0);
- }
-
- object = frame[object_layer];
- scene = frame[scene_layer];
- replace = frame[replace_layer];
-
- border_x1 = obj_x1; border_y1 = obj_y1;
- border_x2 = obj_x2; border_y2 = obj_y2;
- border_x3 = obj_x3; border_y3 = obj_y3;
- border_x4 = obj_x4; border_y4 = obj_y4;
-
- if( scene_w > 0 && scene_h > 0 && object_w > 0 && object_h > 0 ) {
- process_match();
- }
-
- double w0 = init_border ? 1. : config.blend/100., w1 = 1. - w0;
- obj_x1 = border_x1*w0 + obj_x1*w1; obj_y1 = border_y1*w0 + obj_y1*w1;
- obj_x2 = border_x2*w0 + obj_x2*w1; obj_y2 = border_y2*w0 + obj_y2*w1;
- obj_x3 = border_x3*w0 + obj_x3*w1; obj_y3 = border_y3*w0 + obj_y3*w1;
- obj_x4 = border_x4*w0 + obj_x4*w1; obj_y4 = border_y4*w0 + obj_y4*w1;
-
-// Replace object in the scene layer
- if( config.replace_object ) {
- int cpus1 = get_project_smp() + 1;
- if( !affine )
- affine = new AffineEngine(cpus1, cpus1);
- if( !overlayer )
- overlayer = new OverlayFrame(cpus1);
-
- VFrame *temp = new_temp(scene->get_w(), scene->get_h(), scene->get_color_model());
- temp->clear_frame();
- float sx = 100./w, sy = 100./h;
- float x1 = sx * obj_x1, y1 = sy * obj_y1;
- float x2 = sx * obj_x2, y2 = sy * obj_y2;
- float x3 = sx * obj_x3, y3 = sy * obj_y3;
- float x4 = sx * obj_x4, y4 = sy * obj_y4;
- affine->process(temp, replace, 0, AffineEngine::PERSPECTIVE,
- x1,y1, x2,y2, x3,y3, x4,y4, 1);
- overlayer->overlay(scene, temp, 0,0, w,h, 0,0, w,h,
- 1, TRANSFER_NORMAL, NEAREST_NEIGHBOR);
-
- }
-
- if( config.draw_border ) {
- int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
- scene->set_pixel_color(WHITE); scene->set_stiple(ss*2);
- draw_line(scene, obj_x1, obj_y1, obj_x2, obj_y2);
- draw_line(scene, obj_x2, obj_y2, obj_x3, obj_y3);
- draw_line(scene, obj_x3, obj_y3, obj_x4, obj_y4);
- draw_line(scene, obj_x4, obj_y4, obj_x1, obj_y1);
- }
-
- if( config.draw_keypoints ) {
- scene->set_pixel_color(RED); scene->set_stiple(0);
- for( int i=0,n=scn_keypts.size(); i<n; ++i ) {
- Point2f &pt = scn_keypts[i].pt;
- int r = scn_keypts[i].size * 1.2/9 * 2;
- int x = pt.x + scene_x, y = pt.y + scene_y;
- draw_circle(scene, x, y, r);
- }
- }
-
-// Draw object outline in the object layer
- if( config.draw_object_border ) {
- int wh = (w+h)>>8, ss = 1; while( wh>>=1 ) ss<<=1;
- scene->set_pixel_color(YELLOW); scene->set_stiple(ss*3);
- int x1 = object_x, x2 = x1 + object_w - 1;
- int y1 = object_y, y2 = y1 + object_h - 1;
- draw_rect(scene, x1, y1, x2, y2);
- scene->set_pixel_color(GREEN); scene->set_stiple(0);
- x1 = scene_x, x2 = x1 + scene_w - 1;
- y1 = scene_y, y2 = y1 + scene_h - 1;
- draw_rect(scene, x1, y1, x2, y2);
- }
-
- scene->set_pixel_color(BLACK);
- scene->set_stiple(0);
- return 0;
-}
-
+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-
-
-// This is mainly a test for object tracking
-
-
-
-
-#ifndef FINDOBJECT_H
-#define FINDOBJECT_H
-
-//#include "config.h"
-
-#include <math.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "affine.inc"
-#include "bccmodels.h"
-#include "bchash.inc"
-#include "filexml.inc"
-#include "keyframe.inc"
-#include "findobject.inc"
-#include "overlayframe.inc"
-#include "pluginvclient.h"
-#include "vframe.inc"
-
-#include "opencv2/core/types.hpp"
-#include "opencv2/core/mat.hpp"
-#include "opencv2/imgproc/imgproc.hpp"
-#include "opencv2/xfeatures2d.hpp"
-#include "opencv2/calib3d.hpp"
-#include "opencv2/flann/defines.h"
-#include "opencv2/flann/params.h"
-
-#include <vector>
-
-using namespace std;
-using namespace cv;
-using namespace cv::xfeatures2d;
-using namespace cvflann;
-
-// enabled detectors
-#define _SIFT
-#define _SURF
-#define _ORB
-#define _AKAZE
-#define _BRISK
-
-// Limits of global range in percent
-#define MIN_RADIUS 1
-#define MAX_RADIUS 200
-
-// Limits of block size in percent.
-#define MIN_BLOCK 1
-#define MAX_BLOCK 100
-
-#define MIN_LAYER 0
-#define MAX_LAYER 255
-
-#define MIN_BLEND 1
-#define MAX_BLEND 100
-
-#define NO_ALGORITHM 0
-#define ALGORITHM_SIFT 1
-#define ALGORITHM_SURF 2
-#define ALGORITHM_ORB 3
-#define ALGORITHM_AKAZE 4
-#define ALGORITHM_BRISK 5
-
-class FindObjectConfig
-{
-public:
- FindObjectConfig();
-
- int equivalent(FindObjectConfig &that);
- void copy_from(FindObjectConfig &that);
- void interpolate(FindObjectConfig &prev, FindObjectConfig &next,
- int64_t prev_frame, int64_t next_frame, int64_t current_frame);
- void boundaries();
-
- int algorithm, use_flann;
- float object_x, object_y, object_w, object_h;
- float scene_x, scene_y, scene_w, scene_h;
-
- int draw_keypoints;
- int draw_border;
- int replace_object;
- int draw_object_border;
-
- int object_layer;
- int replace_layer;
- int scene_layer;
- int blend;
-};
-
-class FindObjectMain : public PluginVClient
-{
-public:
- FindObjectMain(PluginServer *server);
- ~FindObjectMain();
-
- int process_buffer(VFrame **frame, int64_t start_position, double frame_rate);
-#ifdef _SIFT
- void set_sift();
-#endif
-#ifdef _SURF
- void set_surf();
-#endif
-#ifdef _ORB
- void set_orb();
-#endif
-#ifdef _AKAZE
- void set_akaze();
-#endif
-#ifdef _BRISK
- void set_brisk();
-#endif
- void process_match();
-
- void draw_vectors(VFrame *frame);
- int is_multichannel();
- int is_realtime();
- void save_data(KeyFrame *keyframe);
- void read_data(KeyFrame *keyframe);
- void update_gui();
-
- PLUGIN_CLASS_MEMBERS2(FindObjectConfig)
-
- AffineEngine *affine;
- OverlayFrame *overlayer;
- VFrame *object, *scene, *replace;
-
- static void draw_line(VFrame *vframe, int x1, int y1, int x2, int y2);
- static void draw_rect(VFrame *vframe, int x1, int y1, int x2, int y2);
- static void draw_circle(VFrame *vframe, int x, int y, int r);
-
- int object_x, object_y, object_w, object_h;
- int scene_x, scene_y, scene_w, scene_h;
-
- int w, h;
- int object_layer;
- int scene_layer;
- int replace_layer;
-
-// Latest coordinates of object in scene
- int border_x1, border_y1;
- int border_x2, border_y2;
- int border_x3, border_y3;
- int border_x4, border_y4;
-// Coordinates of object in scene with blending
- float obj_x1, obj_y1;
- float obj_x2, obj_y2;
- float obj_x3, obj_y3;
- float obj_x4, obj_y4;
- int init_border;
-
-//opencv
- typedef vector<DMatch> DMatchV;
- typedef vector<DMatchV> DMatches;
- typedef vector<KeyPoint> KeyPointV;
- typedef vector<Point2f> ptV;
-
- BC_CModel cvmodel;
- Mat object_mat, scene_mat;
- Mat obj_descrs; KeyPointV obj_keypts;
- Mat scn_descrs; KeyPointV scn_keypts;
- DMatches pairs;
-
- static void to_mat(Mat &mat, int mcols, int mrows,
- VFrame *inp, int ix,int iy, BC_CModel mcolor_model);
- void detect(Mat &mat, KeyPointV &keypts, Mat &descrs);
- void match();
- void filter_matches(ptV &p1, ptV &p2, double ratio=0.75);
-
- Ptr<Feature2D> detector;
- Ptr<DescriptorMatcher> matcher;
- Ptr<DescriptorMatcher> flann_kdtree_matcher();
- Ptr<DescriptorMatcher> flann_lshidx_matcher();
- Ptr<DescriptorMatcher> bf_matcher_norm_l2();
- Ptr<DescriptorMatcher> bf_matcher_norm_hamming();
-};
-
-#endif
+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef FINDOBJECT_INC
-#define FINDOBJECT_INC
-
-class FindObjectConfig;
-class FindObjectMain;
-
-#endif
+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "bcdisplayinfo.h"
-#include "clip.h"
-#include "language.h"
-#include "findobject.h"
-#include "findobjectwindow.h"
-#include "theme.h"
-
-
-FindObjectWindow::FindObjectWindow(FindObjectMain *plugin)
- : PluginClientWindow(plugin, 340, 660, 340, 660, 0)
-{
- this->plugin = plugin;
-}
-
-FindObjectWindow::~FindObjectWindow()
-{
-}
-
-void FindObjectWindow::create_objects()
-{
- int x = 10, y = 10, x1 = x, x2 = get_w()/2;
- plugin->load_configuration();
-
- BC_Title *title;
- add_subwindow(title = new BC_Title(x1, y, _("Algorithm:")));
- add_subwindow(algorithm = new FindObjectAlgorithm(plugin, this,
- x1 + title->get_w() + 10, y));
- algorithm->create_objects();
- y += algorithm->get_h() + plugin->get_theme()->widget_border;
-
- add_subwindow(use_flann = new FindObjectUseFlann(plugin, this, x, y));
- y += use_flann->get_h() + plugin->get_theme()->widget_border + 20;
-
- int x0 = x + 200;
- add_subwindow(title = new BC_Title(x, y, _("Output/scene layer:")));
- scene_layer = new FindObjectLayer(plugin, this, x0, y,
- &plugin->config.scene_layer);
- scene_layer->create_objects();
- y += scene_layer->get_h() + plugin->get_theme()->widget_border;
-
- add_subwindow(title = new BC_Title(x, y, _("Object layer:")));
- object_layer = new FindObjectLayer(plugin, this, x0, y,
- &plugin->config.object_layer);
- object_layer->create_objects();
- y += object_layer->get_h() + plugin->get_theme()->widget_border;
-
- add_subwindow(title = new BC_Title(x, y, _("Replacement object layer:")));
- replace_layer = new FindObjectLayer(plugin, this, x0, y,
- &plugin->config.replace_layer);
- replace_layer->create_objects();
- y += replace_layer->get_h() + plugin->get_theme()->widget_border + 10;
-
- add_subwindow(title = new BC_Title(x+15, y, _("Units: 0 to 100 percent")));
- y += title->get_h();
-
- int y1 = y;
- add_subwindow(new BC_Title(x1, y + 10, _("Scene X:")));
- y += title->get_h() + 15;
- add_subwindow(scene_x = new FindObjectScanFloat(plugin, this,
- x1, y, &plugin->config.scene_x));
- add_subwindow(scene_x_text = new FindObjectScanFloatText(plugin, this,
- x1 + scene_x->get_w() + 10, y + 10, &plugin->config.scene_x));
- scene_x->center_text = scene_x_text;
- scene_x_text->center = scene_x;
-
- y += 40;
- add_subwindow(title = new BC_Title(x1, y + 10, _("Scene Y:")));
- y += title->get_h() + 15;
- add_subwindow(scene_y = new FindObjectScanFloat(plugin, this,
- x1, y, &plugin->config.scene_y));
- add_subwindow(scene_y_text = new FindObjectScanFloatText(plugin, this,
- x1 + scene_y->get_w() + 10, y + 10, &plugin->config.scene_y));
- scene_y->center_text = scene_y_text;
- scene_y_text->center = scene_y;
-
- y += 40;
- add_subwindow(new BC_Title(x1, y + 10, _("Scene W:")));
- y += title->get_h() + 15;
- add_subwindow(scene_w = new FindObjectScanFloat(plugin, this,
- x1, y, &plugin->config.scene_w));
- add_subwindow(scene_w_text = new FindObjectScanFloatText(plugin, this,
- x1 + scene_w->get_w() + 10, y + 10, &plugin->config.scene_w));
- scene_w->center_text = scene_w_text;
- scene_w_text->center = scene_w;
-
- y += 40;
- add_subwindow(title = new BC_Title(x1, y + 10, _("Scene H:")));
- y += title->get_h() + 15;
- add_subwindow(scene_h = new FindObjectScanFloat(plugin, this,
- x1, y, &plugin->config.scene_h));
- add_subwindow(scene_h_text = new FindObjectScanFloatText(plugin, this,
- x1 + scene_h->get_w() + 10, y + 10,
- &plugin->config.scene_h));
- scene_h->center_text = scene_h_text;
- scene_h_text->center = scene_h;
-
- y = y1;
- add_subwindow(new BC_Title(x2, y + 10, _("Object X:")));
- y += title->get_h() + 15;
- add_subwindow(object_x = new FindObjectScanFloat(plugin, this,
- x2, y, &plugin->config.object_x));
- add_subwindow(object_x_text = new FindObjectScanFloatText(plugin, this,
- x2 + object_x->get_w() + 10, y + 10, &plugin->config.object_x));
- object_x->center_text = object_x_text;
- object_x_text->center = object_x;
-
- y += 40;
- add_subwindow(title = new BC_Title(x2, y + 10, _("Object Y:")));
- y += title->get_h() + 15;
- add_subwindow(object_y = new FindObjectScanFloat(plugin, this,
- x2, y, &plugin->config.object_y));
- add_subwindow(object_y_text = new FindObjectScanFloatText(plugin, this,
- x2 + object_y->get_w() + 10, y + 10, &plugin->config.object_y));
- object_y->center_text = object_y_text;
- object_y_text->center = object_y;
-
- y += 40;
- add_subwindow(new BC_Title(x2, y + 10, _("Object W:")));
- y += title->get_h() + 15;
- add_subwindow(object_w = new FindObjectScanFloat(plugin, this,
- x2, y, &plugin->config.object_w));
- add_subwindow(object_w_text = new FindObjectScanFloatText(plugin, this,
- x2 + object_w->get_w() + 10, y + 10, &plugin->config.object_w));
- object_w->center_text = object_w_text;
- object_w_text->center = object_w;
-
- y += 40;
- add_subwindow(title = new BC_Title(x2, y + 10, _("Object H:")));
- y += title->get_h() + 15;
- add_subwindow(object_h = new FindObjectScanFloat(plugin, this,
- x2, y, &plugin->config.object_h));
- add_subwindow(object_h_text = new FindObjectScanFloatText(plugin, this,
- x2 + object_h->get_w() + 10, y + 10,
- &plugin->config.object_h));
- object_h->center_text = object_h_text;
- object_h_text->center = object_h;
-
- y += 40 + 15;
- add_subwindow(draw_keypoints = new FindObjectDrawKeypoints(plugin, this, x, y));
- y += draw_keypoints->get_h() + plugin->get_theme()->widget_border;
- add_subwindow(draw_border = new FindObjectDrawBorder(plugin, this, x, y));
- y += draw_border->get_h() + plugin->get_theme()->widget_border;
- add_subwindow(replace_object = new FindObjectReplace(plugin, this, x, y));
- y += replace_object->get_h() + plugin->get_theme()->widget_border;
- add_subwindow(draw_object_border = new FindObjectDrawObjectBorder(plugin, this, x, y));
- y += draw_object_border->get_h() + plugin->get_theme()->widget_border;
-
- add_subwindow(title = new BC_Title(x, y + 10, _("Object blend amount:")));
- add_subwindow(blend = new FindObjectBlend(plugin,
- x + title->get_w() + plugin->get_theme()->widget_border, y,
- &plugin->config.blend));
- y += blend->get_h();
-
- show_window(1);
-}
-
-
-FindObjectScanFloat::FindObjectScanFloat(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y, float *value)
- : BC_FPot(x, y, *value, (float)0, (float)100)
-{
- this->plugin = plugin;
- this->gui = gui;
- this->value = value;
- this->center_text = 0;
- set_precision(0.1);
-}
-
-int FindObjectScanFloat::handle_event()
-{
- *value = get_value();
- center_text->update(*value);
- plugin->send_configure_change();
- return 1;
-}
-
-
-FindObjectScanFloatText::FindObjectScanFloatText(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y, float *value)
- : BC_TextBox(x, y, 75, 1, *value)
-{
- this->plugin = plugin;
- this->gui = gui;
- this->value = value;
- this->center = 0;
- set_precision(1);
-}
-
-int FindObjectScanFloatText::handle_event()
-{
- *value = atof(get_text());
- center->update(*value);
- plugin->send_configure_change();
- return 1;
-}
-
-
-FindObjectDrawBorder::FindObjectDrawBorder(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y)
- : BC_CheckBox(x, y, plugin->config.draw_border, _("Draw border"))
-{
- this->gui = gui;
- this->plugin = plugin;
-}
-
-int FindObjectDrawBorder::handle_event()
-{
- plugin->config.draw_border = get_value();
- plugin->send_configure_change();
- return 1;
-}
-
-
-FindObjectDrawKeypoints::FindObjectDrawKeypoints(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y)
- : BC_CheckBox(x, y, plugin->config.draw_keypoints, _("Draw keypoints"))
-{
- this->gui = gui;
- this->plugin = plugin;
-}
-
-int FindObjectDrawKeypoints::handle_event()
-{
- plugin->config.draw_keypoints = get_value();
- plugin->send_configure_change();
- return 1;
-}
-
-
-FindObjectReplace::FindObjectReplace(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y)
- : BC_CheckBox(x, y, plugin->config.replace_object, _("Replace object"))
-{
- this->gui = gui;
- this->plugin = plugin;
-}
-
-int FindObjectReplace::handle_event()
-{
- plugin->config.replace_object = get_value();
- plugin->send_configure_change();
- return 1;
-}
-
-
-FindObjectDrawObjectBorder::FindObjectDrawObjectBorder(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y)
- : BC_CheckBox(x, y, plugin->config.draw_object_border, _("Draw object border"))
-{
- this->gui = gui;
- this->plugin = plugin;
-}
-
-int FindObjectDrawObjectBorder::handle_event()
-{
- plugin->config.draw_object_border = get_value();
- plugin->send_configure_change();
- return 1;
-}
-
-
-FindObjectAlgorithm::FindObjectAlgorithm(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y)
- : BC_PopupMenu(x, y, calculate_w(gui), to_text(plugin->config.algorithm))
-{
- this->plugin = plugin;
- this->gui = gui;
-}
-
-int FindObjectAlgorithm::handle_event()
-{
- plugin->config.algorithm = from_text(get_text());
- plugin->send_configure_change();
- return 1;
-}
-
-void FindObjectAlgorithm::create_objects()
-{
- add_item(new BC_MenuItem(to_text(NO_ALGORITHM)));
-#ifdef _SIFT
- add_item(new BC_MenuItem(to_text(ALGORITHM_SIFT)));
-#endif
-#ifdef _SURF
- add_item(new BC_MenuItem(to_text(ALGORITHM_SURF)));
-#endif
-#ifdef _ORB
- add_item(new BC_MenuItem(to_text(ALGORITHM_ORB)));
-#endif
-#ifdef _AKAZE
- add_item(new BC_MenuItem(to_text(ALGORITHM_AKAZE)));
-#endif
-#ifdef _BRISK
- add_item(new BC_MenuItem(to_text(ALGORITHM_BRISK)));
-#endif
-}
-
-int FindObjectAlgorithm::from_text(char *text)
-{
-#ifdef _SIFT
- if(!strcmp(text, _("SIFT"))) return ALGORITHM_SIFT;
-#endif
-#ifdef _SURF
- if(!strcmp(text, _("SURF"))) return ALGORITHM_SURF;
-#endif
-#ifdef _ORB
- if(!strcmp(text, _("ORB"))) return ALGORITHM_ORB;
-#endif
-#ifdef _AKAZE
- if(!strcmp(text, _("AKAZE"))) return ALGORITHM_AKAZE;
-#endif
-#ifdef _BRISK
- if(!strcmp(text, _("BRISK"))) return ALGORITHM_BRISK;
-#endif
- return NO_ALGORITHM;
-}
-
-char* FindObjectAlgorithm::to_text(int mode)
-{
- switch( mode ) {
-#ifdef _SIFT
- case ALGORITHM_SIFT: return _("SIFT");
-#endif
-#ifdef _SURF
- case ALGORITHM_SURF: return _("SURF");
-#endif
-#ifdef _ORB
- case ALGORITHM_ORB: return _("ORB");
-#endif
-#ifdef _AKAZE
- case ALGORITHM_AKAZE: return _("AKAZE");
-#endif
-#ifdef _BRISK
- case ALGORITHM_BRISK: return _("BRISK");
-#endif
- }
- return _("Don't Calculate");
-}
-
-int FindObjectAlgorithm::calculate_w(FindObjectWindow *gui)
-{
- int result = 0;
- result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(NO_ALGORITHM)));
-#ifdef _SIFT
- result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_SIFT)));
-#endif
-#ifdef _SURF
- result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_SURF)));
-#endif
-#ifdef _ORB
- result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_ORB)));
-#endif
-#ifdef _AKAZE
- result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_AKAZE)));
-#endif
-#ifdef _BRISK
- result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(ALGORITHM_BRISK)));
-#endif
- return result + 50;
-}
-
-
-FindObjectUseFlann::FindObjectUseFlann(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y)
- : BC_CheckBox(x, y, plugin->config.use_flann, _("Use FLANN"))
-{
- this->gui = gui;
- this->plugin = plugin;
-}
-
-int FindObjectUseFlann::handle_event()
-{
- plugin->config.use_flann = get_value();
- plugin->send_configure_change();
- return 1;
-}
-
-
-FindObjectLayer::FindObjectLayer(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y, int *value)
- : BC_TumbleTextBox(gui, *value, MIN_LAYER, MAX_LAYER, x, y, calculate_w(gui))
-{
- this->plugin = plugin;
- this->gui = gui;
- this->value = value;
-}
-
-int FindObjectLayer::handle_event()
-{
- *value = atoi(get_text());
- plugin->send_configure_change();
- return 1;
-}
-
-int FindObjectLayer::calculate_w(FindObjectWindow *gui)
-{
- int result = 0;
- result = gui->get_text_width(MEDIUMFONT, "000");
- return result + 50;
-}
-
-
-FindObjectBlend::FindObjectBlend(FindObjectMain *plugin,
- int x,
- int y,
- int *value)
- : BC_IPot(x,
- y,
- (int64_t)*value,
- (int64_t)MIN_BLEND,
- (int64_t)MAX_BLEND)
-{
- this->plugin = plugin;
- this->value = value;
-}
-
-int FindObjectBlend::handle_event()
-{
- *value = (int)get_value();
- plugin->send_configure_change();
- return 1;
-}
-
+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-
-#ifndef __FINDOBJECTWINDOW_H__
-#define __FINDOBJECTWINDOW_H__
-
-#include "guicast.h"
-#include "findobject.inc"
-
-class FindObjectLayer;
-class FindObjectScanFloat;
-class FindObjectScanFloatText;
-class FindObjectDrawBorder;
-class FindObjectDrawKeypoints;
-class FindObjectReplace;
-class FindObjectDrawObjectBorder;
-class FindObjectAlgorithm;
-class FindObjectBlend;
-class FindObjectWindow;
-
-class FindObjectLayer : public BC_TumbleTextBox
-{
-public:
- FindObjectLayer(FindObjectMain *plugin, FindObjectWindow *gui,
- int x, int y, int *value);
- int handle_event();
- static int calculate_w(FindObjectWindow *gui);
- FindObjectMain *plugin;
- FindObjectWindow *gui;
- int *value;
-};
-
-class FindObjectScanFloat : public BC_FPot
-{
-public:
- FindObjectScanFloat(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y, float *value);
- int handle_event();
- FindObjectMain *plugin;
- FindObjectWindow *gui;
- FindObjectScanFloatText *center_text;
- float *value;
-};
-
-class FindObjectScanFloatText : public BC_TextBox
-{
-public:
- FindObjectScanFloatText(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y, float *value);
- int handle_event();
- FindObjectWindow *gui;
- FindObjectMain *plugin;
- FindObjectScanFloat *center;
- float *value;
-};
-
-
-class FindObjectDrawBorder : public BC_CheckBox
-{
-public:
- FindObjectDrawBorder(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y);
- int handle_event();
- FindObjectMain *plugin;
- FindObjectWindow *gui;
-};
-
-class FindObjectDrawKeypoints : public BC_CheckBox
-{
-public:
- FindObjectDrawKeypoints(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y);
- int handle_event();
- FindObjectMain *plugin;
- FindObjectWindow *gui;
-};
-
-class FindObjectReplace : public BC_CheckBox
-{
-public:
- FindObjectReplace(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y);
- int handle_event();
- FindObjectMain *plugin;
- FindObjectWindow *gui;
-};
-
-class FindObjectDrawObjectBorder : public BC_CheckBox
-{
-public:
- FindObjectDrawObjectBorder(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y);
- int handle_event();
- FindObjectMain *plugin;
- FindObjectWindow *gui;
-};
-
-class FindObjectAlgorithm : public BC_PopupMenu
-{
-public:
- FindObjectAlgorithm(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y);
- int handle_event();
- void create_objects();
- static int calculate_w(FindObjectWindow *gui);
- static int from_text(char *text);
- static char* to_text(int mode);
- FindObjectMain *plugin;
- FindObjectWindow *gui;
-};
-
-class FindObjectUseFlann : public BC_CheckBox
-{
-public:
- FindObjectUseFlann(FindObjectMain *plugin, FindObjectWindow *gui, int x, int y);
- int handle_event();
- FindObjectMain *plugin;
- FindObjectWindow *gui;
-};
-
-class FindObjectBlend : public BC_IPot
-{
-public:
- FindObjectBlend(FindObjectMain *plugin, int x, int y, int *value);
- int handle_event();
- FindObjectMain *plugin;
- int *value;
-};
-
-class FindObjectWindow : public PluginClientWindow
-{
-public:
- FindObjectWindow(FindObjectMain *plugin);
- ~FindObjectWindow();
- void create_objects();
-
- FindObjectAlgorithm *algorithm;
- FindObjectUseFlann *use_flann;
- FindObjectScanFloat *object_x, *object_y, *object_w, *object_h;
- FindObjectScanFloatText *object_x_text, *object_y_text, *object_w_text, *object_h_text;
- FindObjectScanFloat *scene_x, *scene_y, *scene_w, *scene_h;
- FindObjectScanFloatText *scene_x_text, *scene_y_text, *scene_w_text, *scene_h_text;
- FindObjectDrawKeypoints *draw_keypoints;
- FindObjectDrawBorder *draw_border;
- FindObjectReplace *replace_object;
- FindObjectDrawObjectBorder *draw_object_border;
- FindObjectLayer *object_layer;
- FindObjectLayer *scene_layer;
- FindObjectLayer *replace_layer;
- FindObjectBlend *blend;
- FindObjectMain *plugin;
-};
-
-#endif
+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 1997-2012 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef FINDOBJECTWINDOW_INC
-#define FINDOBJECTWINDOW_INC
-
-class FindObjectLayer;
-class FindObjectScanFloat;
-class FindObjectScanFloatText;
-class FindObjectDrawBorder;
-class FindObjectDrawKeypoints;
-class FindObjectReplace;
-class FindObjectDrawObjectBorder;
-class FindObjectAlgorithm;
-class FindObjectUseFlann;
-class FindObjectBlend;
-class FindObjectWindow;
-
-#endif
--- /dev/null
+default: all
+
+TOPDIR?=../..
+include $(TOPDIR)/plugin_defs
+
+PLUGIN = flowobj
+
+OBJS := \
+ $(OBJDIR)/flowobj.o \
+ $(OBJDIR)/flowobjwindow.o \
+
+want_var:=$(WANT_OPENCV)
+include $(TOPDIR)/opencv_build
+include $(TOPDIR)/plugin_config
+
+all: opencv
+ +make $(OUTPUT)
+
+$(OBJDIR)/flowobj.o: flowobj.C flowobj.h flowobjwindow.h
+$(OBJDIR)/flowobjwindow.o: flowobjwindow.C flowobj.h flowobjwindow.h
+
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "clip.h"
+#include "filexml.h"
+#include "flowobj.h"
+#include "flowobjwindow.h"
+#include "language.h"
+#include "transportque.inc"
+
+REGISTER_PLUGIN(FlowObj)
+
+#define MAX_COUNT 250
+#define WIN_SIZE 20
+
+FlowObjConfig::FlowObjConfig()
+{
+ draw_vectors = 0;
+ do_stabilization = 1;
+ block_size = 20;
+ search_radius = 10;
+ settling_speed = 5;
+}
+
+int FlowObjConfig::equivalent(FlowObjConfig &that)
+{
+ return draw_vectors == that.draw_vectors &&
+ do_stabilization == that.do_stabilization &&
+ block_size == that.block_size &&
+ search_radius == that.search_radius &&
+ settling_speed == that.settling_speed;
+}
+
+void FlowObjConfig::copy_from(FlowObjConfig &that)
+{
+ draw_vectors = that.draw_vectors;
+ do_stabilization = that.do_stabilization;
+ block_size = that.block_size;
+ search_radius = that.search_radius;
+ settling_speed = that.settling_speed;
+}
+
+void FlowObjConfig::interpolate( FlowObjConfig &prev, FlowObjConfig &next,
+ long prev_frame, long next_frame, long current_frame)
+{
+ copy_from(next);
+}
+
+void FlowObjConfig::limits()
+{
+ bclamp(block_size, 5, 100);
+ bclamp(search_radius, 1, 100);
+ bclamp(settling_speed, 0, 100);
+}
+
+
+FlowObj::FlowObj(PluginServer *server)
+ : PluginVClient(server)
+{
+ flow_engine = 0;
+ overlay = 0;
+ accum = 0;
+ prev_position = next_position = -1;
+ x_accum = y_accum = 0;
+ angle_accum = 0;
+ prev_corners = 0;
+ next_corners = 0;
+}
+
+FlowObj::~FlowObj()
+{
+ delete flow_engine;
+ delete overlay;
+ delete prev_corners;
+ delete next_corners;
+}
+
+const char* FlowObj::plugin_title() { return N_("FlowObj"); }
+int FlowObj::is_realtime() { return 1; }
+
+NEW_WINDOW_MACRO(FlowObj, FlowObjWindow);
+LOAD_CONFIGURATION_MACRO(FlowObj, FlowObjConfig)
+
+void FlowObj::save_data(KeyFrame *keyframe)
+{
+ FileXML output;
+
+// cause data to be stored directly in text
+ output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+ output.tag.set_title("FLOWOBJ");
+ output.tag.set_property("DRAW_VECTORS", config.draw_vectors);
+ output.tag.set_property("DO_STABILIZATION", config.do_stabilization);
+ output.tag.set_property("BLOCK_SIZE", config.block_size);
+ output.tag.set_property("SEARCH_RADIUS", config.search_radius);
+ output.tag.set_property("SETTLING_SPEED", config.settling_speed);
+ output.append_tag();
+ output.append_newline();
+ output.tag.set_title("/FLOWOBJ");
+ output.append_tag();
+ output.append_newline();
+ output.terminate_string();
+}
+
+void FlowObj::read_data(KeyFrame *keyframe)
+{
+ FileXML input;
+ input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+ int result = 0;
+ while( !(result = input.read_tag()) ) {
+ if( input.tag.title_is("FLOWOBJ") ) {
+ config.draw_vectors = input.tag.get_property("DRAW_VECTORS", config.draw_vectors);
+ config.do_stabilization = input.tag.get_property("DO_STABILIZATION", config.do_stabilization);
+ config.block_size = input.tag.get_property("BLOCK_SIZE", config.block_size);
+ config.search_radius = input.tag.get_property("SEARCH_RADIUS", config.search_radius);
+ config.settling_speed = input.tag.get_property("SETTLING_SPEED", config.settling_speed);
+ config.limits();
+ }
+ else if( input.tag.title_is("/FLOWOBJ") )
+ result = 1;
+ }
+}
+
+void FlowObj::update_gui()
+{
+ if( !thread ) return;
+ if( !load_configuration() ) return;
+ thread->window->lock_window("FlowObj::update_gui");
+ FlowObjWindow *window = (FlowObjWindow*)thread->window;
+
+ window->vectors->update(config.draw_vectors);
+ window->do_stabilization->update(config.do_stabilization);
+ window->block_size->update(config.block_size);
+ window->search_radius->update(config.search_radius);
+ window->settling_speed->update(config.settling_speed);
+
+ thread->window->unlock_window();
+}
+
+void FlowObj::to_mat(Mat &mat, int mcols, int mrows,
+ VFrame *inp, int ix,int iy, int mcolor_model)
+{
+ int mcomp = BC_CModels::components(mcolor_model);
+ int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
+ int psz = mbpp / mcomp;
+ int mdepth = psz < 2 ? CV_8U : psz < 4 ? CV_16U : CV_32F;
+ if( mat.dims != 2 || mat.depth() != mdepth || mat.channels() != mcomp ||
+ mat.cols != mcols || mat.rows != mrows ) {
+ mat.release();
+ }
+ if( mat.empty() ) {
+ int type = CV_MAKETYPE(mdepth, mcomp);
+ mat.create(mrows, mcols, type);
+ }
+ uint8_t *mat_rows[mrows];
+ for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
+ uint8_t **inp_rows = inp->get_rows();
+ int ibpl = inp->get_bytes_per_line(), mbpl = mcols * mbpp;
+ int icolor_model = inp->get_color_model();
+ BC_CModels::transfer(mat_rows, mcolor_model, 0,0, mcols,mrows, mbpl,
+ inp_rows, icolor_model, ix,iy, mcols,mrows, ibpl, 0);
+// VFrame vfrm(mat_rows[0], -1, mcols,mrows, mcolor_model, mat_rows[1]-mat_rows[0]);
+// static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/idat/%06d.png", vfrm_no++);
+// vfrm.write_png(vfn);
+}
+
+void FlowObj::from_mat(VFrame *out, int ox, int oy, int ow, int oh, Mat &mat, int mcolor_model)
+{
+ int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
+ int mrows = mat.rows, mcols = mat.cols;
+ uint8_t *mat_rows[mrows];
+ for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
+ uint8_t **out_rows = out->get_rows();
+ int obpl = out->get_bytes_per_line(), mbpl = mcols * mbpp;
+ int ocolor_model = out->get_color_model();
+ BC_CModels::transfer(out_rows, ocolor_model, ox,oy, ow,oh, obpl,
+ mat_rows, mcolor_model, 0,0, mcols,mrows, mbpl, 0);
+// static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/odat/%06d.png", vfrm_no++);
+// out->write_png(vfn);
+}
+
+
+int FlowObj::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
+{
+
+ //int need_reconfigure =
+ load_configuration();
+ input = get_input(0);
+ output = get_output(0);
+ width = input->get_w();
+ height = input->get_h();
+ color_model = input->get_color_model();
+
+ if( accum_matrix.empty() ) {
+ accum_matrix = Mat::eye(3,3, CV_64F);
+ }
+ if( !prev_corners ) prev_corners = new ptV();
+ if( !next_corners ) next_corners = new ptV();
+
+// Get the position of previous reference frame.
+ int64_t actual_previous_number = start_position;
+ int skip_current = 0;
+ if( get_direction() == PLAY_REVERSE ) {
+ if( ++actual_previous_number < get_source_start() + get_total_len() ) {
+ KeyFrame *keyframe = get_next_keyframe(start_position, 1);
+ if( keyframe->position > 0 &&
+ actual_previous_number >= keyframe->position )
+ skip_current = 1;
+ }
+ else
+ skip_current = 1;
+ }
+ else {
+ if( --actual_previous_number >= get_source_start() ) {
+ KeyFrame *keyframe = get_prev_keyframe(start_position, 1);
+ if( keyframe->position > 0 &&
+ actual_previous_number < keyframe->position)
+ skip_current = 1;
+ }
+ else
+ skip_current = 1;
+ }
+
+
+// move currrent image to previous position
+ if( next_position >= 0 && next_position == actual_previous_number ) {
+ Mat mat = prev_mat; prev_mat = next_mat; next_mat = mat;
+ ptV *pts = prev_corners; prev_corners = next_corners; next_corners = pts;
+ prev_position = next_position;
+ }
+ else
+// load previous image
+ if( actual_previous_number >= 0 ) {
+ read_frame(input, 0, actual_previous_number, frame_rate, 0);
+ to_mat(prev_mat, width,height, input, 0,0, BC_GREY8);
+ }
+
+ if( skip_current || prev_position != actual_previous_number ) {
+ skip_current = 1;
+ accum_matrix = Mat::eye(3,3, CV_64F);
+ }
+
+
+// load next image
+ next_position = start_position;
+ VFrame *iframe = new_temp(width,height, color_model);
+ read_frame(iframe, 0, start_position, frame_rate, 0);
+ input = iframe;
+ to_mat(next_mat, width,height, iframe, 0,0, BC_GREY8);
+
+ int corner_count = MAX_COUNT;
+ int block_size = config.block_size;
+ int min_distance = config.search_radius;
+
+ goodFeaturesToTrack(next_mat,
+ *next_corners, corner_count, 0.01, // quality_level
+ min_distance, noArray(), block_size,
+ 0, // use_harris
+ 0.04); // k
+
+ if( !next_mat.empty() && next_corners->size() > 3 ) {
+ cornerSubPix(next_mat, *next_corners, Size(WIN_SIZE, WIN_SIZE), Size(-1,-1),
+ cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03));
+ }
+
+ Mat flow;
+ if( !prev_mat.empty() && prev_corners->size() > 3 ) {
+// optical flow
+ calcOpticalFlowFarneback(prev_mat, next_mat, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
+ }
+
+ if( config.do_stabilization && !flow.empty() ) {
+ if( !flow_engine )
+ flow_engine = new FlowObjRemapEngine(this, PluginClient::smp);
+ flow_mat = &flow;
+ flow_engine->process_packages();
+ }
+ else
+ output->copy_from(input);
+
+ if( config.settling_speed > 0 ) {
+ if( accum && (accum->get_color_model() != color_model ||
+ accum->get_w() != width || accum->get_h() != height) ) {
+ delete accum; accum = 0;
+ }
+ if( !accum ) {
+ accum = new VFrame(width, height, color_model);
+ accum->clear_frame();
+ }
+ if( !overlay )
+ overlay = new OverlayFrame(PluginClient::smp + 1);
+ float alpha = 1 - config.settling_speed/100.;
+ overlay->overlay(accum, output,
+ 0,0, width,height, 0,0, width, height,
+ alpha, TRANSFER_NORMAL, NEAREST_NEIGHBOR);
+ output->copy_from(accum);
+ }
+
+ if( !flow.empty() && config.draw_vectors ) {
+ output->set_pixel_color(GREEN);
+ int nv = 24; float s = 2;
+ int gw = width/nv + 1, gh = height/nv + 1;
+ int sz = bmin(width,height) / 200 + 4;
+ for( int y=gh/2; y<height; y+=gh ) {
+ Point2f *row = (Point2f *)flow.ptr(y);
+ for( int x=gw/2; x<width; x+=gw ) {
+ Point2f *ds = row + x;
+ float x0 = x+.5, x1 = x+s*ds->x, y0 = y+.5, y1 = y+s*ds->y;
+ output->draw_arrow(x0,y0, x1,y1, sz);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+FlowObjRemapPackage::FlowObjRemapPackage()
+ : LoadPackage()
+{
+}
+
+FlowObjRemapUnit::FlowObjRemapUnit(FlowObjRemapEngine *engine, FlowObj *plugin)
+ : LoadClient(engine)
+{
+ this->plugin = plugin;
+}
+
+FlowObjRemapUnit::~FlowObjRemapUnit()
+{
+}
+
+void FlowObjRemapUnit::process_package(LoadPackage *package)
+{
+ FlowObjRemapPackage *pkg = (FlowObjRemapPackage*)package;
+ process_remap(pkg);
+}
+
+void FlowObjRemapUnit::process_remap(FlowObjRemapPackage *pkg)
+{
+ int row1 = pkg->row1;
+ int row2 = pkg->row2;
+ int w = plugin->width, h = plugin->height;
+ int w1 = w-1, h1 = h-1;
+ int color_model = plugin->color_model;
+ int bpp = BC_CModels::calculate_pixelsize(color_model);
+
+#define FLOW_OBJ_REMAP(type, components) { \
+ unsigned char **in_rows = plugin->input->get_rows(); \
+ type **out_rows = (type**)plugin->output->get_rows(); \
+ \
+ for( int y=row1; y<row2; ++y ) { \
+ Point2f *ipt = (Point2f *)plugin->flow_mat->ptr(y); \
+ type *out_row = out_rows[y]; \
+ for( int x=0; x<w; ++x,++ipt ) { \
+ int ix = x - ipt->x, iy = y - ipt->y; \
+ bclamp(ix, 0, w1); bclamp(iy, 0, h1); \
+ type *inp_row = (type *)(in_rows[iy] + ix*bpp); \
+ for( int i=0; i<components; ++i ) \
+ *out_row++ = *inp_row++; \
+ } \
+ } \
+}
+ switch( color_model ) {
+ case BC_RGB888: FLOW_OBJ_REMAP(unsigned char, 3); break;
+ case BC_RGBA8888: FLOW_OBJ_REMAP(unsigned char, 4); break;
+ case BC_RGB_FLOAT: FLOW_OBJ_REMAP(float, 3); break;
+ case BC_RGBA_FLOAT: FLOW_OBJ_REMAP(float, 4); break;
+ case BC_YUV888: FLOW_OBJ_REMAP(unsigned char, 3); break;
+ case BC_YUVA8888: FLOW_OBJ_REMAP(unsigned char, 4); break;
+ }
+}
+
+
+FlowObjRemapEngine::FlowObjRemapEngine(FlowObj *plugin, int cpus)
+ : LoadServer(cpus+1, cpus+1)
+{
+ this->plugin = plugin;
+}
+
+FlowObjRemapEngine::~FlowObjRemapEngine()
+{
+}
+
+void FlowObjRemapEngine::init_packages()
+{
+ int row1 = 0, row2 = 0, n = LoadServer::get_total_packages();
+ for( int i=0; i<n; row1=row2 ) {
+ FlowObjRemapPackage *package = (FlowObjRemapPackage*)LoadServer::get_package(i);
+ row2 = plugin->get_input()->get_h() * ++i / n;
+ package->row1 = row1; package->row2 = row2;
+ }
+}
+
+LoadClient* FlowObjRemapEngine::new_client()
+{
+ return new FlowObjRemapUnit(this, plugin);
+}
+
+LoadPackage* FlowObjRemapEngine::new_package()
+{
+ return new FlowObjRemapPackage();
+}
+
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef FLOWOBJ_H
+#define FLOWOBJ_H
+
+#include "pluginvclient.h"
+#include "loadbalance.h"
+#include "overlayframe.h"
+
+#include "opencv2/core/types.hpp"
+#include "opencv2/core/mat.hpp"
+#include "opencv2/calib3d.hpp"
+#include "opencv2/video/video.hpp"
+
+#include <vector>
+
+using namespace std;
+using namespace cv;
+
+//#define _RANSAC
+#ifdef _RANSAC
+#include <opencv2/videostab/motion_core.hpp>
+#include <opencv2/videostab/global_motion.hpp>
+
+using namespace videostab;
+#endif
+
+class FlowObjConfig;
+class FlowObjRemapPackage;
+class FlowObjRemapEngine;
+class FlowObjRemapUnit;
+class FlowObj;
+
+
+class FlowObjConfig
+{
+public:
+ FlowObjConfig();
+
+ int equivalent(FlowObjConfig &that);
+ void copy_from(FlowObjConfig &that);
+ void interpolate(FlowObjConfig &prev, FlowObjConfig &next,
+ long prev_frame, long next_frame, long current_frame);
+ void limits();
+ int draw_vectors;
+ int do_stabilization;
+ int settling_speed;
+// percent
+ int block_size;
+ int search_radius;
+};
+
+class FlowObjRemapPackage : public LoadPackage
+{
+public:
+ FlowObjRemapPackage();
+
+ int row1, row2;
+};
+
+class FlowObjRemapEngine : public LoadServer
+{
+public:
+ FlowObjRemapEngine(FlowObj *plugin, int cpus);
+ ~FlowObjRemapEngine();
+
+ void init_packages();
+ LoadClient* new_client();
+ LoadPackage* new_package();
+
+ FlowObj *plugin;
+};
+
+class FlowObjRemapUnit : public LoadClient
+{
+public:
+ FlowObjRemapUnit(FlowObjRemapEngine *engine, FlowObj *plugin);
+ ~FlowObjRemapUnit();
+
+ void process_package(LoadPackage *pkg);
+ void process_remap(FlowObjRemapPackage *pkg);
+
+ FlowObjRemapEngine *engine;
+ FlowObj *plugin;
+};
+
+class FlowObj : public PluginVClient
+{
+public:
+ FlowObj(PluginServer *server);
+ ~FlowObj();
+// required for all realtime plugins
+ PLUGIN_CLASS_MEMBERS2(FlowObjConfig)
+ int is_realtime();
+ void update_gui();
+ void save_data(KeyFrame *keyframe);
+ void read_data(KeyFrame *keyframe);
+ int process_buffer(VFrame *frame, int64_t start_position, double frame_rate);
+ void to_mat(Mat &mat, int mcols, int mrows,
+ VFrame *inp, int ix,int iy, int mcolor_model);
+ void from_mat(VFrame *out, int ox, int oy, int ow, int oh,
+ Mat &mat, int mcolor_model);
+
+ long prev_position, next_position;
+ int width, height, color_model;
+ VFrame *input, *output, *accum;
+
+ Mat *flow_mat;
+ FlowObjRemapEngine *flow_engine;
+ OverlayFrame *overlay;
+
+//opencv
+ typedef vector<Point2f> ptV;
+
+ BC_CModel cvmodel;
+ Mat accum_matrix;
+ double accum_matrix_mem[9];
+ double x_accum, y_accum, angle_accum;
+ Mat prev_mat, next_mat;
+ ptV *prev_corners, *next_corners;
+};
+
+#endif
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "bcdisplayinfo.h"
+#include "clip.h"
+#include "language.h"
+#include "flowobj.h"
+#include "flowobjwindow.h"
+#include "theme.h"
+
+FlowObjWindow::FlowObjWindow(FlowObj *plugin)
+ : PluginClientWindow(plugin, 320, 240, 320, 240, 0)
+{
+ this->plugin = plugin;
+}
+
+FlowObjWindow::~FlowObjWindow()
+{
+}
+
+void FlowObjWindow::create_objects()
+{
+ int x = 10, y = 10;
+ int margin = plugin->get_theme()->widget_border;
+ BC_Title *title;
+
+ add_subwindow(vectors = new FlowObjVectors(this, x, y));
+ y += vectors->get_h() + margin;
+ add_subwindow(do_stabilization = new FlowObjDoStabilization(this,
+ x, y));
+ y += do_stabilization->get_h() + margin;
+ add_subwindow(title = new BC_Title(x, y, _("Block size:")));
+ add_subwindow(block_size = new FlowObjBlockSize(this,
+ x + title->get_w() + margin, y));
+ y += block_size->get_h() + margin;
+ add_subwindow(title = new BC_Title(x, y, _("Search radius:")));
+ add_subwindow(search_radius = new FlowObjSearchRadius(this,
+ x + title->get_w() + margin, y));
+ y += search_radius->get_h() + margin;
+ add_subwindow(title = new BC_Title(x, y, _("Settling speed:")));
+ add_subwindow(settling_speed = new FlowObjSettling(this,
+ x + title->get_w() + margin, y));
+
+ show_window(1);
+}
+
+FlowObjVectors::FlowObjVectors(FlowObjWindow *gui, int x, int y)
+ : BC_CheckBox(x, y, gui->plugin->config.draw_vectors, _("Draw vectors"))
+{
+ this->gui = gui;
+}
+
+int FlowObjVectors::handle_event()
+{
+ gui->plugin->config.draw_vectors = get_value();
+ gui->plugin->send_configure_change();
+ return 1;
+}
+
+
+FlowObjDoStabilization::FlowObjDoStabilization(FlowObjWindow *gui, int x, int y)
+ : BC_CheckBox(x, y, gui->plugin->config.do_stabilization, _("Do stabilization"))
+{
+ this->gui = gui;
+}
+
+int FlowObjDoStabilization::handle_event()
+{
+ gui->plugin->config.do_stabilization = get_value();
+ gui->plugin->send_configure_change();
+ return 1;
+}
+
+
+FlowObjBlockSize::FlowObjBlockSize(FlowObjWindow *gui, int x, int y)
+ : BC_IPot(x, y, (int64_t)gui->plugin->config.block_size, (int64_t)5, (int64_t)100)
+{
+ this->gui = gui;
+}
+
+int FlowObjBlockSize::handle_event()
+{
+ gui->plugin->config.block_size = (int)get_value();
+ gui->plugin->send_configure_change();
+ return 1;
+}
+
+
+FlowObjSearchRadius::FlowObjSearchRadius(FlowObjWindow *gui, int x, int y)
+ : BC_IPot(x, y, (int64_t)gui->plugin->config.search_radius, (int64_t)1, (int64_t)100)
+{
+ this->gui = gui;
+}
+
+int FlowObjSearchRadius::handle_event()
+{
+ gui->plugin->config.search_radius = (int)get_value();
+ gui->plugin->send_configure_change();
+ return 1;
+}
+
+
+FlowObjSettling::FlowObjSettling(FlowObjWindow *gui, int x, int y)
+ : BC_IPot(x, y, (int64_t)gui->plugin->config.settling_speed, (int64_t)0, (int64_t)100)
+{
+ this->gui = gui;
+}
+
+int FlowObjSettling::handle_event()
+{
+ gui->plugin->config.settling_speed = (int)get_value();
+ gui->plugin->send_configure_change();
+ return 1;
+}
+
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 2008-2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef FLOWOBJWINDOW_H
+#define FLOWOBJWINDOW_H
+
+
+#include "guicast.h"
+
+class FlowObj;
+class FlowObjWindow;
+
+
+class FlowObjVectors : public BC_CheckBox
+{
+public:
+ FlowObjVectors(FlowObjWindow *gui, int x, int y);
+ int handle_event();
+ FlowObjWindow *gui;
+};
+
+class FlowObjDoStabilization : public BC_CheckBox
+{
+public:
+ FlowObjDoStabilization(FlowObjWindow *gui, int x, int y);
+ int handle_event();
+ FlowObjWindow *gui;
+};
+
+class FlowObjBlockSize : public BC_IPot
+{
+public:
+ FlowObjBlockSize(FlowObjWindow *gui, int x, int y);
+ int handle_event();
+ FlowObjWindow *gui;
+};
+
+class FlowObjSearchRadius : public BC_IPot
+{
+public:
+ FlowObjSearchRadius(FlowObjWindow *gui, int x, int y);
+ int handle_event();
+ FlowObjWindow *gui;
+};
+
+class FlowObjMaxMovement : public BC_IPot
+{
+public:
+ FlowObjMaxMovement(FlowObjWindow *gui, int x, int y);
+ int handle_event();
+ FlowObjWindow *gui;
+};
+
+class FlowObjSettling : public BC_IPot
+{
+public:
+ FlowObjSettling(FlowObjWindow *gui, int x, int y);
+ int handle_event();
+ FlowObjWindow *gui;
+};
+
+class FlowObjWindow : public PluginClientWindow
+{
+public:
+ FlowObjWindow(FlowObj *plugin);
+ ~FlowObjWindow();
+
+ void create_objects();
+
+ FlowObj *plugin;
+ FlowObjVectors *vectors;
+ FlowObjDoStabilization *do_stabilization;
+ FlowObjBlockSize *block_size;
+ FlowObjSearchRadius *search_radius;
+// not implemented
+// FlowObjMaxMovement *max_movement;
+ FlowObjSettling *settling_speed;
+};
+
+#endif
--- /dev/null
+default: all
+
+TOPDIR?=../..
+include $(TOPDIR)/plugin_defs
+
+PLUGIN = gaborobj
+
+OBJS := \
+ $(OBJDIR)/gaborobj.o \
+ $(OBJDIR)/gaborobjwindow.o \
+
+want_var:=$(WANT_OPENCV)
+include $(TOPDIR)/opencv_build
+include $(TOPDIR)/plugin_config
+
+all: opencv
+ +make $(OUTPUT)
+
+$(OBJDIR)/gaborobj.o: gaborobj.C gaborobj.h gaborobjwindow.h
+$(OBJDIR)/gaborobjwindow.o: gaborobjwindow.C gaborobj.h gaborobjwindow.h
+
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "clip.h"
+#include "filexml.h"
+#include "gaborobj.h"
+#include "gaborobjwindow.h"
+#include "language.h"
+#include "mutex.h"
+
+REGISTER_PLUGIN(GaborObj)
+
+
+GaborObjConfig::GaborObjConfig()
+{
+}
+
+int GaborObjConfig::equivalent(GaborObjConfig &that)
+{
+ return 1;
+}
+
+void GaborObjConfig::copy_from(GaborObjConfig &that)
+{
+}
+
+void GaborObjConfig::interpolate( GaborObjConfig &prev, GaborObjConfig &next,
+ long prev_frame, long next_frame, long current_frame)
+{
+ copy_from(next);
+}
+
+void GaborObjConfig::limits()
+{
+}
+
+
+GaborObj::GaborObj(PluginServer *server)
+ : PluginVClient(server)
+{
+ int steps = 16;
+ Size ksize(31, 31);
+ for( int i=0; i<steps; ++i ) {
+ double theta = i * M_PI/steps;
+ Mat kern = getGaborKernel(ksize, 4.0, theta, 10.0, 0.5, 0, CV_32F);
+ float sum = 0;
+ for( int k=0; k<kern.rows; ++k ) {
+ float *kp = kern.ptr<float>(k);
+ for( int j=0; j<kern.cols; ++j ) sum += *kp++;
+ }
+ kern /= 1.5*sum;
+ filters.push_back(kern);
+ }
+ gabor_engine = 0;
+ remap_lock = new ::Mutex("GaborObj::remap_lock");
+}
+
+GaborObj::~GaborObj()
+{
+ delete gabor_engine;
+ delete remap_lock;
+}
+
+const char* GaborObj::plugin_title() { return N_("GaborObj"); }
+int GaborObj::is_realtime() { return 1; }
+
+NEW_WINDOW_MACRO(GaborObj, GaborObjWindow);
+LOAD_CONFIGURATION_MACRO(GaborObj, GaborObjConfig)
+
+void GaborObj::save_data(KeyFrame *keyframe)
+{
+ FileXML output;
+
+// cause data to be stored directly in text
+ output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+ output.tag.set_title("GABOROBJ");
+ output.append_tag();
+ output.append_newline();
+ output.tag.set_title("/GABOROBJ");
+ output.append_tag();
+ output.append_newline();
+ output.terminate_string();
+}
+
+void GaborObj::read_data(KeyFrame *keyframe)
+{
+ FileXML input;
+ input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+ int result = 0;
+ while( !(result = input.read_tag()) ) {
+ if( input.tag.title_is("GABOROBJ") ) {
+ config.limits();
+ }
+ else if( input.tag.title_is("/GABOROBJ") )
+ result = 1;
+ }
+}
+
+void GaborObj::update_gui()
+{
+ if( !thread ) return;
+ if( !load_configuration() ) return;
+ thread->window->lock_window("GaborObj::update_gui");
+ GaborObjWindow *window = (GaborObjWindow*)thread->window;
+ window->unlock_window();
+}
+
+void GaborObj::to_mat(Mat &mat, int mcols, int mrows,
+ VFrame *inp, int ix,int iy, int mcolor_model)
+{
+ int mcomp = BC_CModels::components(mcolor_model);
+ int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
+ int psz = mbpp / mcomp;
+ int mdepth = psz < 2 ? CV_8U : psz < 4 ? CV_16U : CV_32F;
+ if( mat.dims != 2 || mat.depth() != mdepth || mat.channels() != mcomp ||
+ mat.cols != mcols || mat.rows != mrows ) {
+ mat.release();
+ }
+ if( mat.empty() ) {
+ int type = CV_MAKETYPE(mdepth, mcomp);
+ mat.create(mrows, mcols, type);
+ }
+ uint8_t *mat_rows[mrows];
+ for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
+ uint8_t **inp_rows = inp->get_rows();
+ int ibpl = inp->get_bytes_per_line(), mbpl = mcols * mbpp;
+ int icolor_model = inp->get_color_model();
+ BC_CModels::transfer(mat_rows, mcolor_model, 0,0, mcols,mrows, mbpl,
+ inp_rows, icolor_model, ix,iy, mcols,mrows, ibpl, 0);
+// VFrame vfrm(mat_rows[0], -1, mcols,mrows, mcolor_model, mat_rows[1]-mat_rows[0]);
+// static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/idat/%06d.png", vfrm_no++);
+// vfrm.write_png(vfn);
+}
+
+void GaborObj::from_mat(VFrame *out, int ox, int oy, int ow, int oh, Mat &mat, int mcolor_model)
+{
+ int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
+ int mrows = mat.rows, mcols = mat.cols;
+ uint8_t *mat_rows[mrows];
+ for( int y=0; y<mrows; ++y ) mat_rows[y] = mat.ptr(y);
+ uint8_t **out_rows = out->get_rows();
+ int obpl = out->get_bytes_per_line(), mbpl = mcols * mbpp;
+ int ocolor_model = out->get_color_model();
+ BC_CModels::transfer(out_rows, ocolor_model, ox,oy, ow,oh, obpl,
+ mat_rows, mcolor_model, 0,0, mcols,mrows, mbpl, 0);
+// static int vfrm_no = 0; char vfn[64]; sprintf(vfn,"/tmp/odat/%06d.png", vfrm_no++);
+// out->write_png(vfn);
+}
+
+
+int GaborObj::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
+{
+
+ //int need_reconfigure =
+ load_configuration();
+ input = get_input(0);
+ output = get_output(0);
+ width = input->get_w();
+ height = input->get_h();
+ color_model = input->get_color_model();
+
+// load next image
+ VFrame *iframe = new_temp(width,height, color_model);
+ read_frame(iframe, 0, start_position, frame_rate, 0);
+ input = iframe;
+ to_mat(next_img, width,height, iframe, 0,0, color_model);
+ if( !gabor_engine )
+ gabor_engine = new GaborObjFilterEngine(this, PluginClient::smp + 1);
+
+ output->clear_frame();
+ gabor_engine->process_packages();
+ return 0;
+}
+
+
+GaborObjFilterPackage::GaborObjFilterPackage()
+ : LoadPackage()
+{
+}
+
+GaborObjFilterUnit::GaborObjFilterUnit(GaborObjFilterEngine *engine, GaborObj *plugin)
+ : LoadClient(engine)
+{
+ this->plugin = plugin;
+}
+
+GaborObjFilterUnit::~GaborObjFilterUnit()
+{
+}
+
+void GaborObjFilterUnit::process_package(LoadPackage *package)
+{
+ GaborObjFilterPackage *pkg = (GaborObjFilterPackage*)package;
+ process_filter(pkg);
+}
+
+void GaborObjFilterUnit::process_filter(GaborObjFilterPackage *pkg)
+{
+ int color_model = plugin->color_model;
+ int w = plugin->output->get_w(), h = plugin->output->get_h();
+ int ddepth = CV_8UC3;
+
+ switch( color_model ) {
+ case BC_RGB888: ddepth = CV_8UC3; break;
+ case BC_RGBA8888: ddepth = CV_8UC4; break;
+ case BC_RGB_FLOAT: ddepth = CV_32FC3; break;
+ case BC_RGBA_FLOAT: ddepth = CV_32FC4; break;
+ case BC_YUV888: ddepth = CV_8UC3; break;
+ case BC_YUVA8888: ddepth = CV_8UC4; break;
+ }
+
+ Mat &src = plugin->next_img, dst;
+ Mat &kern = plugin->filters[pkg->i];
+ filter2D(src, dst, ddepth, kern);
+
+#define GABOR_OBJ_REMAP(type, components) { \
+ type **out_rows = (type**)plugin->output->get_rows(); \
+ \
+ for( int y=0; y<h; ++y ) { \
+ type *out_row = out_rows[y]; \
+ type *dst_row = (type *)dst.ptr<type>(y); \
+ for( int x=0; x<w; ++x ) { \
+ for( int i=0; i<components; ++i ) { \
+ *out_row = bmax(*out_row, *dst_row); \
+ ++out_row; ++dst_row; \
+ } \
+ } \
+ } \
+}
+// technically, this is needed... but it really can slow it down.
+// plugin->remap_lock->lock("GaborObjFilterUnit::process_filter");
+ switch( color_model ) {
+ case BC_RGB888: GABOR_OBJ_REMAP(unsigned char, 3); break;
+ case BC_RGBA8888: GABOR_OBJ_REMAP(unsigned char, 4); break;
+ case BC_RGB_FLOAT: GABOR_OBJ_REMAP(float, 3); break;
+ case BC_RGBA_FLOAT: GABOR_OBJ_REMAP(float, 4); break;
+ case BC_YUV888: GABOR_OBJ_REMAP(unsigned char, 3); break;
+ case BC_YUVA8888: GABOR_OBJ_REMAP(unsigned char, 4); break;
+ }
+// plugin->remap_lock->unlock();
+}
+
+
+GaborObjFilterEngine::GaborObjFilterEngine(GaborObj *plugin, int cpus)
+ : LoadServer(cpus+1, plugin->filters.size())
+{
+ this->plugin = plugin;
+}
+
+GaborObjFilterEngine::~GaborObjFilterEngine()
+{
+}
+
+void GaborObjFilterEngine::init_packages()
+{
+ int n = LoadServer::get_total_packages();
+ for( int i=0; i<n; ++i ) {
+ GaborObjFilterPackage *pkg = (GaborObjFilterPackage*)LoadServer::get_package(i);
+ pkg->i = i;
+ }
+}
+
+LoadClient* GaborObjFilterEngine::new_client()
+{
+ return new GaborObjFilterUnit(this, plugin);
+}
+
+LoadPackage* GaborObjFilterEngine::new_package()
+{
+ return new GaborObjFilterPackage();
+}
+
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef GABOROBJ_H
+#define GABOROBJ_H
+
+#include "pluginvclient.h"
+#include "loadbalance.h"
+#include "mutex.inc"
+
+#include "opencv2/core/types.hpp"
+#include "opencv2/core/mat.hpp"
+#include "opencv2/calib3d.hpp"
+#include "opencv2/video/video.hpp"
+
+#include <vector>
+
+using namespace std;
+using namespace cv;
+
+
+class GaborObjConfig;
+class GaborObj;
+
+
+class GaborObjConfig
+{
+public:
+ GaborObjConfig();
+
+ int equivalent(GaborObjConfig &that);
+ void copy_from(GaborObjConfig &that);
+ void interpolate(GaborObjConfig &prev, GaborObjConfig &next,
+ long prev_frame, long next_frame, long current_frame);
+ void limits();
+};
+
+class GaborObjFilterPackage : public LoadPackage
+{
+public:
+ GaborObjFilterPackage();
+ int i;
+};
+
+class GaborObjFilterEngine : public LoadServer
+{
+public:
+ GaborObjFilterEngine(GaborObj *plugin, int cpus);
+ ~GaborObjFilterEngine();
+
+ void init_packages();
+ LoadClient* new_client();
+ LoadPackage* new_package();
+
+ GaborObj *plugin;
+};
+
+class GaborObjFilterUnit : public LoadClient
+{
+public:
+ GaborObjFilterUnit(GaborObjFilterEngine *engine, GaborObj *plugin);
+ ~GaborObjFilterUnit();
+
+ void process_package(LoadPackage *pkg);
+ void process_filter(GaborObjFilterPackage *pkg);
+
+ GaborObjFilterEngine *engine;
+ GaborObj *plugin;
+};
+
+class GaborObj : public PluginVClient
+{
+public:
+ GaborObj(PluginServer *server);
+ ~GaborObj();
+ PLUGIN_CLASS_MEMBERS2(GaborObjConfig)
+ int is_realtime();
+ void update_gui();
+ void save_data(KeyFrame *keyframe);
+ void read_data(KeyFrame *keyframe);
+ int process_buffer(VFrame *frame, int64_t start_position, double frame_rate);
+ void to_mat(Mat &mat, int mcols, int mrows,
+ VFrame *inp, int ix,int iy, int mcolor_model);
+ void from_mat(VFrame *out, int ox, int oy, int ow, int oh,
+ Mat &mat, int mcolor_model);
+
+ int width, height, color_model;
+ VFrame *input, *output, *accum;
+ ::Mutex *remap_lock;
+
+ Mat next_img;
+ vector<Mat> filters;
+ GaborObjFilterEngine *gabor_engine;
+};
+
+#endif
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "bcdisplayinfo.h"
+#include "clip.h"
+#include "language.h"
+#include "gaborobj.h"
+#include "gaborobjwindow.h"
+#include "theme.h"
+
+GaborObjWindow::GaborObjWindow(GaborObj *plugin)
+ : PluginClientWindow(plugin, 320, 240, 320, 240, 0)
+{
+ this->plugin = plugin;
+}
+
+GaborObjWindow::~GaborObjWindow()
+{
+}
+
+void GaborObjWindow::create_objects()
+{
+ int x = 10, y = 10;
+ BC_Title *title = new BC_Title(x, y, _("GaborObj"));
+ add_subwindow(title);
+ show_window(1);
+}
+
--- /dev/null
+/*
+ * CINELERRA
+ * Copyright (C) 2008-2014 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef GABOROBJWINDOW_H
+#define GABOROBJWINDOW_H
+
+
+#include "guicast.h"
+
+class GaborObj;
+class GaborObjWindow;
+
+class GaborObjWindow : public PluginClientWindow
+{
+public:
+ GaborObjWindow(GaborObj *plugin);
+ ~GaborObjWindow();
+
+ void create_objects();
+
+ GaborObj *plugin;
+};
+
+#endif
$(OBJDIR)/moveobj.o \
$(OBJDIR)/moveobjwindow.o \
-want_var:=$(WANT_FINDOBJECT)
+want_var:=$(WANT_OPENCV)
include $(TOPDIR)/opencv_build
include $(TOPDIR)/plugin_config
}
void MoveObj::to_mat(Mat &mat, int mcols, int mrows,
- VFrame *inp, int ix,int iy, BC_CModel mcolor_model)
+ VFrame *inp, int ix,int iy, int mcolor_model)
{
int mcomp = BC_CModels::components(mcolor_model);
int mbpp = BC_CModels::calculate_pixelsize(mcolor_model);
int psz = mbpp / mcomp;
- int mdepth = psz < 2 ? CV_8U : CV_16U;
+ int mdepth = psz < 2 ? CV_8U : psz < 4 ? CV_16U : CV_32F;
if( mat.dims != 2 || mat.depth() != mdepth || mat.channels() != mcomp ||
mat.cols != mcols || mat.rows != mrows ) {
mat.release();
to_mat(next_mat, w,h, iframe, 0,0, BC_GREY8);
int corner_count = MAX_COUNT;
- int search_radius = config.block_size;
+ int block_size = config.block_size;
int min_distance = config.search_radius;
goodFeaturesToTrack(next_mat,
*next_corners, corner_count, 0.01, // quality_level
- min_distance, noArray(), search_radius,
+ min_distance, noArray(), block_size,
0, // use_harris
0.04); // k
int process_buffer(VFrame *frame, int64_t start_position, double frame_rate);
AffineEngine *affine;
void to_mat(Mat &mat, int mcols, int mrows,
- VFrame *inp, int ix,int iy, BC_CModel mcolor_model);
+ VFrame *inp, int ix,int iy, int mcolor_model);
long prev_position, next_position;