From: Good Guy Date: Fri, 22 Sep 2017 22:52:42 +0000 (-0600) Subject: proxy bug fixes, add moveobj, sams icons, ladspa fixes, pot sigfpe X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=8d1431081df60da0719db2c77e4c56830521c7e8;p=goodguy%2Fhistory.git proxy bug fixes, add moveobj, sams icons, ladspa fixes, pot sigfpe --- diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 0334fd02..7a1f59be 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -2566,12 +2566,11 @@ SET_TRACE SET_TRACE //printf("MWindow::show_plugin 1\n"); - if(!done) - { - if(!plugin->track) - { - printf("MWindow::show_plugin track not defined.\n"); - } + if( !done && !plugin->track ) { + printf("MWindow::show_plugin track not defined.\n"); + done = 1; + } + if( !done ) { PluginServer *server = scan_plugindb(plugin->title, plugin->track->data_type); @@ -2958,6 +2957,8 @@ void MWindow::update_project(int load_mode) if(load_mode == LOADMODE_REPLACE || load_mode == LOADMODE_REPLACE_CONCATENATE) { + edl->session->proxy_scale = 1; + edl->session->proxy_use_scaler = 0; gui->load_panes(); } diff --git a/cinelerra-5.1/cinelerra/pluginaclientlad.C b/cinelerra-5.1/cinelerra/pluginaclientlad.C index 982492ba..91c19275 100644 --- a/cinelerra-5.1/cinelerra/pluginaclientlad.C +++ b/cinelerra-5.1/cinelerra/pluginaclientlad.C @@ -69,28 +69,15 @@ int PluginAClientConfig::equivalent(PluginAClientConfig &that) // Need PluginServer to do this. void PluginAClientConfig::copy_from(PluginAClientConfig &that) { - if(total_ports != that.total_ports) - { - delete_objects(); - total_ports = that.total_ports; - port_data = new LADSPA_Data[total_ports]; - port_type = new int[total_ports]; - } - - for(int i = 0; i < total_ports; i++) - { + int n = bmin(total_ports, that.total_ports); + for( int i=0; ilad_descriptor; const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors; - const LADSPA_PortRangeHint *lad_hint = lad_desc->PortRangeHints; int port_count = lad_desc->PortCount; for(int i = 0; i < port_count; i++) { if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue; @@ -115,15 +101,14 @@ void PluginAClientConfig::initialize(PluginServer *server) for(int port = 0, i = 0; i < port_count; i++) { if( !LADSPA_IS_PORT_INPUT(port_desc[i]) ) continue; if( !LADSPA_IS_PORT_CONTROL(port_desc[i]) ) continue; + const LADSPA_PortRangeHint *lad_hint = &lad_desc->PortRangeHints[i]; + LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor; // Convert LAD default to default value float value = 0.0; - LADSPA_PortRangeHintDescriptor hint_desc = lad_hint->HintDescriptor; // Store type of port for GUI use port_type[port] = PORT_NORMAL; - if( LADSPA_IS_HINT_SAMPLE_RATE(hint_desc) /* && - LADSPA_IS_HINT_BOUNDED_ABOVE(hint_desc) && - LADSPA_IS_HINT_BOUNDED_BELOW(hint_desc) */ ) // LAD frequency table + if( LADSPA_IS_HINT_SAMPLE_RATE(hint_desc) ) port_type[port] = PORT_FREQ_INDEX; else if(LADSPA_IS_HINT_TOGGLED(hint_desc)) port_type[port] = PORT_TOGGLE; @@ -138,8 +123,7 @@ void PluginAClientConfig::initialize(PluginServer *server) else if( LADSPA_IS_HINT_DEFAULT_100(hint_desc) ) value = 100.0; else if( LADSPA_IS_HINT_DEFAULT_440(hint_desc) ) - value = port_type[port] == PORT_FREQ_INDEX ? - 440.0 / 44100 : 440.0; + value = 440.0; else if( LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint_desc) ) value = lad_hint->UpperBound; else if( LADSPA_IS_HINT_DEFAULT_MINIMUM(hint_desc) ) @@ -493,7 +477,7 @@ void PluginAClientLAD::read_data(KeyFrame *keyframe) char string[BCTEXTLEN]; input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); - config.initialize(server); + if( !config.port_data ) config.initialize(server); while(! input.read_tag() ) { //printf("PluginAClientLAD::read_data %s\n", input.tag.get_title()); @@ -539,6 +523,10 @@ void PluginAClientLAD::delete_plugin() void PluginAClientLAD::init_plugin(int total_in, int total_out, int size) { int need_reconfigure = !lad_instance ? 1 : 0; + if( !config.port_data ) { + config.initialize(server); + need_reconfigure = 1; + } if(buffer_allocation && buffer_allocation < size) { delete_buffers(); need_reconfigure = 1; diff --git a/cinelerra-5.1/cinelerra/pluginclient.C b/cinelerra-5.1/cinelerra/pluginclient.C index bc6ca8eb..03e8c3f1 100644 --- a/cinelerra-5.1/cinelerra/pluginclient.C +++ b/cinelerra-5.1/cinelerra/pluginclient.C @@ -337,14 +337,8 @@ int PluginClient::show_gui() thread->start(); thread->init_complete->lock("PluginClient::show_gui"); // Must wait before sending any hide_gui - if(thread->window) - { - thread->window->init_wait(); - } - else - { - return 1; - } + if( !thread->window ) return 1; + thread->window->init_wait(); return 0; } diff --git a/cinelerra-5.1/cinelerra/proxy.C b/cinelerra-5.1/cinelerra/proxy.C index 537fc40a..d126cf14 100644 --- a/cinelerra-5.1/cinelerra/proxy.C +++ b/cinelerra-5.1/cinelerra/proxy.C @@ -80,6 +80,7 @@ ProxyThread::ProxyThread(MWindow *mwindow) ProxyThread::~ProxyThread() { for( int i=0; iremove_user(); } BC_Window* ProxyThread::new_gui() @@ -121,9 +122,14 @@ void ProxyThread::calculate_sizes() int orig_h = mwindow->edl->session->output_h * orig_scale; if( !use_scaler ) { +// w,h should stay even for yuv + int ow = orig_w, oh = orig_h; + if( BC_CModels::is_yuv(mwindow->edl->session->color_model) ) { + ow /= 2; oh /= 2; + } for( int i=2; ivideo_data = 1; proxy_asset->layers = 1; proxy_asset->width = orig_asset->width / new_scale; + if( proxy_asset->width & 1 ) ++proxy_asset->width; proxy_asset->actual_width = proxy_asset->width; proxy_asset->height = orig_asset->height / new_scale; + if( proxy_asset->height & 1 ) ++proxy_asset->height; proxy_asset->actual_height = proxy_asset->height; proxy_asset->frame_rate = orig_asset->frame_rate; proxy_asset->video_length = orig_asset->video_length; @@ -473,8 +481,11 @@ void ProxyWindow::update() // thread->orig_scale, thread->new_scale); int orig_w = mwindow->edl->session->output_w * thread->orig_scale; int orig_h = mwindow->edl->session->output_h * thread->orig_scale; - sprintf(string, "%dx%d", - orig_w / thread->new_scale, orig_h / thread->new_scale); + int new_w = orig_w / thread->new_scale; + if( new_w & 1 ) ++new_w; + int new_h = orig_h / thread->new_scale; + if( new_h & 1 ) ++new_h; + sprintf(string, "%dx%d", new_w, new_h); new_dimensions->update(string); thread->scale_to_text(string, thread->new_scale); scale_factor->set_text(string); diff --git a/cinelerra-5.1/doc/shortcuts.html b/cinelerra-5.1/doc/shortcuts.html index 3bcd3c71..1e875fb7 100644 --- a/cinelerra-5.1/doc/shortcuts.html +++ b/cinelerra-5.1/doc/shortcuts.html @@ -468,6 +468,12 @@ 'Shift-P' Open preferences setup menu + + Pulldown + Proxy Settings + 'Alt-P' + Bring up Proxy settings window +
- Edit labels diff --git a/cinelerra-5.1/guicast/bcpot.C b/cinelerra-5.1/guicast/bcpot.C index 7417e79e..e934fc53 100644 --- a/cinelerra-5.1/guicast/bcpot.C +++ b/cinelerra-5.1/guicast/bcpot.C @@ -460,7 +460,8 @@ const char* BC_FPot::get_caption() float BC_FPot::get_percentage() { - return (value - minvalue) / (maxvalue - minvalue); + float range = maxvalue - minvalue; + return range > 0 ? (value - minvalue) / range : minvalue; } int BC_FPot::percentage_to_value(float percentage) @@ -549,7 +550,8 @@ const char* BC_IPot::get_caption() float BC_IPot::get_percentage() { - return ((float)value - minvalue) / (maxvalue - minvalue); + float range = maxvalue - minvalue; + return range > 0 ? ((float)value - minvalue) / range : minvalue; } int BC_IPot::percentage_to_value(float percentage) @@ -633,7 +635,8 @@ const char* BC_QPot::get_caption() float BC_QPot::get_percentage() { - return ((float)value - minvalue) / (maxvalue - minvalue); + float range = maxvalue - minvalue; + return range > 0 ? ((float)value - minvalue) / range : 0; } int BC_QPot::percentage_to_value(float percentage) @@ -709,7 +712,8 @@ const char* BC_PercentagePot::get_caption() float BC_PercentagePot::get_percentage() { - return (value - minvalue) / (maxvalue - minvalue); + float range = maxvalue - minvalue; + return range > 0 ? (value - minvalue) / range : minvalue; } int BC_PercentagePot::percentage_to_value(float percentage) diff --git a/cinelerra-5.1/picon_cinfinity/ff_chromakey.png b/cinelerra-5.1/picon_cinfinity/ff_chromakey.png new file mode 100644 index 00000000..c9d6b109 Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_chromakey.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_ciescope.png b/cinelerra-5.1/picon_cinfinity/ff_ciescope.png new file mode 100644 index 00000000..d93ad8bb Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_ciescope.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_colorbalance.png b/cinelerra-5.1/picon_cinfinity/ff_colorbalance.png new file mode 100644 index 00000000..803a5ead Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colorbalance.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_colorchannelmixer.png b/cinelerra-5.1/picon_cinfinity/ff_colorchannelmixer.png new file mode 100644 index 00000000..d4ef5409 Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colorchannelmixer.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_colorkey.png b/cinelerra-5.1/picon_cinfinity/ff_colorkey.png new file mode 100644 index 00000000..a9100536 Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colorkey.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_colorlevels.png b/cinelerra-5.1/picon_cinfinity/ff_colorlevels.png new file mode 100644 index 00000000..5a9ca921 Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colorlevels.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_colormatrix.png b/cinelerra-5.1/picon_cinfinity/ff_colormatrix.png new file mode 100644 index 00000000..0c659f67 Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_colormatrix.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_cover_rect.png b/cinelerra-5.1/picon_cinfinity/ff_cover_rect.png new file mode 100644 index 00000000..d987875e Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_cover_rect.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_crop.png b/cinelerra-5.1/picon_cinfinity/ff_crop.png new file mode 100644 index 00000000..626f8fc9 Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_crop.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_cropdetect.png b/cinelerra-5.1/picon_cinfinity/ff_cropdetect.png new file mode 100644 index 00000000..593c40ef Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_cropdetect.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_datascope.png b/cinelerra-5.1/picon_cinfinity/ff_datascope.png new file mode 100644 index 00000000..91a9663f Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_datascope.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_deband.png b/cinelerra-5.1/picon_cinfinity/ff_deband.png new file mode 100644 index 00000000..9711aed8 Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_deband.png differ diff --git a/cinelerra-5.1/picon_cinfinity/ff_deflate.png b/cinelerra-5.1/picon_cinfinity/ff_deflate.png new file mode 100644 index 00000000..7238f071 Binary files /dev/null and b/cinelerra-5.1/picon_cinfinity/ff_deflate.png differ diff --git a/cinelerra-5.1/plugins/moveobj/Makefile b/cinelerra-5.1/plugins/moveobj/Makefile new file mode 100644 index 00000000..256f85ec --- /dev/null +++ b/cinelerra-5.1/plugins/moveobj/Makefile @@ -0,0 +1,21 @@ +default: all + +TOPDIR?=../.. +include $(TOPDIR)/plugin_defs + +PLUGIN = moveobj + +OBJS := \ + $(OBJDIR)/moveobj.o \ + $(OBJDIR)/moveobjwindow.o \ + +want_var:=$(WANT_FINDOBJECT) +include $(TOPDIR)/opencv_build +include $(TOPDIR)/plugin_config + +all: opencv + +make $(OUTPUT) + +$(OBJDIR)/moveobj.o: moveobj.C moveobj.h moveobjwindow.h +$(OBJDIR)/moveobjwindow.o: moveobjwindow.C moveobj.h moveobjwindow.h + diff --git a/cinelerra-5.1/plugins/moveobj/moveobj.C b/cinelerra-5.1/plugins/moveobj/moveobj.C new file mode 100644 index 00000000..b40e5f6b --- /dev/null +++ b/cinelerra-5.1/plugins/moveobj/moveobj.C @@ -0,0 +1,353 @@ +/* + * CINELERRA + * Copyright (C) 1997-2014 Adam Williams + * + * 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 "clip.h" +#include "filexml.h" +#include "moveobj.h" +#include "moveobjwindow.h" +#include "language.h" +#include "transportque.inc" + +REGISTER_PLUGIN(MoveObj) + +#define MAX_COUNT 250 +#define WIN_SIZE 20 + +MoveObjConfig::MoveObjConfig() +{ + draw_vectors = 0; + do_stabilization = 1; + block_size = 20; + search_radius = 10; + settling_speed = 5; +} + +int MoveObjConfig::equivalent(MoveObjConfig &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 MoveObjConfig::copy_from(MoveObjConfig &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 MoveObjConfig::interpolate( MoveObjConfig &prev, MoveObjConfig &next, + long prev_frame, long next_frame, long current_frame) +{ + copy_from(next); +} + +void MoveObjConfig::limits() +{ + bclamp(block_size, 5, 100); + bclamp(search_radius, 1, 100); + bclamp(settling_speed, 0, 100); +} + + +MoveObj::MoveObj(PluginServer *server) + : PluginVClient(server) +{ + affine = 0; + prev_position = next_position = -1; + x_accum = y_accum = 0; + angle_accum = 0; + prev_corners = 0; + next_corners = 0; +} + +MoveObj::~MoveObj() +{ + delete affine; + delete prev_corners; + delete next_corners; +} + +const char* MoveObj::plugin_title() { return N_("MoveObj"); } +int MoveObj::is_realtime() { return 1; } + +NEW_WINDOW_MACRO(MoveObj, MoveObjWindow); +LOAD_CONFIGURATION_MACRO(MoveObj, MoveObjConfig) + +void MoveObj::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("MOVEOBJ"); + 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("/MOVEOBJ"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +} + +void MoveObj::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("MOVEOBJ") ) { + 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("/MOVEOBJ") ) + result = 1; + } +} + +void MoveObj::update_gui() +{ + if( !thread ) return; + if( !load_configuration() ) return; + thread->window->lock_window("MoveObj::update_gui"); + MoveObjWindow *window = (MoveObjWindow*)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 MoveObj::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; yget_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); +} + +int MoveObj::process_buffer(VFrame *frame, int64_t start_position, double frame_rate) +{ + + //int need_reconfigure = + load_configuration(); + VFrame *input = get_input(0), *output = get_output(0); + int w = input->get_w(), h = input->get_h(); + int color_model = input->get_color_model(); + + if( accum_matrix.empty() ) { + accum_matrix = Mat::eye(3,3, CV_64F); + } + if( !affine ) { + int cpus1 = PluginClient::get_project_smp() + 1; + affine = new AffineEngine(cpus1, cpus1); + } + 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, w,h, 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 = !config.do_stabilization ? input : new_temp(w,h, color_model); + read_frame(iframe, 0, start_position, frame_rate, 0); + to_mat(next_mat, w,h, iframe, 0,0, BC_GREY8); + + int corner_count = MAX_COUNT; + int search_radius = 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, + 0, // use_harris + 0.04); // k + + ptV pt1, pt2; + 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)); + } + if( !prev_mat.empty() && prev_corners->size() > 3 ) { +// optical flow + Mat st, err; + ptV &prev = *prev_corners, &next = *next_corners; + calcOpticalFlowPyrLK(prev_mat, next_mat, prev, next, + st, err, Size(WIN_SIZE, WIN_SIZE), 5, + cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.3), 0); + float fails = 0.5 * w + 1; + uint8_t *stp = st.ptr(); + float *errp = err.ptr(); + for( int i=0,n=next_corners->size(); i fails ) continue; + pt1.push_back(next[i]); + pt2.push_back(prev[i]); + } + } + + int points = pt1.size(); + if( points > 0 && !skip_current ) { + if( config.draw_vectors ) { + int sz = bmin(w,h) / 222 + 2; + for( int i = 0; i < points; ++i ) + iframe->draw_arrow(pt1[i].x,pt1[i].y, pt2[i].x,pt2[i].y, sz); + } +#ifdef _RANSAC +// ransac + int ninliers = 0; + Mat_ translationM = + estimateGlobalMotionRansac(pt1, pt2, MM_TRANSLATION, + RansacParams::default2dMotion(MM_TRANSLATION), + 0, &ninliers); + Mat_ rotationM = + estimateGlobalMotionRansac(pt1, pt2, MM_ROTATION, + RansacParams::default2dMotion(MM_ROTATION), + 0, &ninliers); + + double temp[9]; + Mat temp_matrix = Mat(3, 3, CV_64F, temp); + for( int i=0; i<9; ++i ) + temp[i] = i == 2 || i == 5 ? + translationM(i / 3, i % 3) : + rotationM(i / 3, i % 3); + accum_matrix = temp_matrix * accum_matrix; +#else +// homography + + Mat M1(1, points, CV_32FC2, &pt1[0].x); + Mat M2(1, points, CV_32FC2, &pt2[0].x); + +//M2 = H*M1 , old = H*current + Mat H = findHomography(M1, M2, CV_RANSAC, 2); + if( !H.dims || !H.rows || !H.cols ) + printf("MoveObj::process_buffer %d: Find Homography Fail!\n", __LINE__); + else + accum_matrix = H * accum_matrix; +#endif + } + + double *amat = accum_matrix.ptr(); +// deglitch +// if( EQUIV(amat[0], 0) ) { +//printf("MoveObj::process_buffer %d\n", __LINE__); +// accum_matrix = Mat::eye(3,3, CV_64F); +// } + + if( config.do_stabilization ) { + Mat identity = Mat::eye(3,3, CV_64F); + double w0 = config.settling_speed/100., w1 = 1.-w0; +// interpolate with identity matrix + accum_matrix = w0*identity + w1*accum_matrix; + + AffineMatrix matrix; + for( int i=0,k=0; i<3; ++i ) + for( int j=0; j<3; ++j ) + matrix.values[i][j] = amat[k++]; + +//printf("MoveObj::process_buffer %d %jd matrix=\n", __LINE__, start_position); +//matrix.dump(); + + affine->set_matrix(&matrix); +// iframe is always temp, if we get here + output->clear_frame(); + affine->process(output, iframe, 0, AffineEngine::TRANSFORM, + 0,0, w,0, w,h, 0,h, 1); + } + + return 0; +} diff --git a/cinelerra-5.1/plugins/moveobj/moveobj.h b/cinelerra-5.1/plugins/moveobj/moveobj.h new file mode 100644 index 00000000..d82d0f68 --- /dev/null +++ b/cinelerra-5.1/plugins/moveobj/moveobj.h @@ -0,0 +1,91 @@ +/* + * CINELERRA + * Copyright (C) 1997-2014 Adam Williams + * + * 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 MOVEOBJ_H +#define MOVEOBJ_H + +#include "affine.inc" +#include "pluginvclient.h" + +#include "opencv2/core/types.hpp" +#include "opencv2/core/mat.hpp" +#include "opencv2/calib3d.hpp" +#include "opencv2/video/video.hpp" + +#include + +using namespace std; +using namespace cv; + +//#define _RANSAC +#ifdef _RANSAC +#include +#include + +using namespace videostab; +#endif + +class MoveObjConfig +{ +public: + MoveObjConfig(); + + int equivalent(MoveObjConfig &that); + void copy_from(MoveObjConfig &that); + void interpolate(MoveObjConfig &prev, MoveObjConfig &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 MoveObj : public PluginVClient +{ +public: + MoveObj(PluginServer *server); + ~MoveObj(); +// required for all realtime plugins + PLUGIN_CLASS_MEMBERS2(MoveObjConfig) + 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); + AffineEngine *affine; + void to_mat(Mat &mat, int mcols, int mrows, + VFrame *inp, int ix,int iy, BC_CModel mcolor_model); + + long prev_position, next_position; + +//opencv + typedef vector 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 diff --git a/cinelerra-5.1/plugins/moveobj/moveobjwindow.C b/cinelerra-5.1/plugins/moveobj/moveobjwindow.C new file mode 100644 index 00000000..aac65d69 --- /dev/null +++ b/cinelerra-5.1/plugins/moveobj/moveobjwindow.C @@ -0,0 +1,132 @@ +/* + * CINELERRA + * Copyright (C) 2014 Adam Williams + * + * 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 "moveobj.h" +#include "moveobjwindow.h" +#include "theme.h" + +MoveObjWindow::MoveObjWindow(MoveObj *plugin) + : PluginClientWindow(plugin, 320, 240, 320, 240, 0) +{ + this->plugin = plugin; +} + +MoveObjWindow::~MoveObjWindow() +{ +} + +void MoveObjWindow::create_objects() +{ + int x = 10, y = 10; + int margin = plugin->get_theme()->widget_border; + BC_Title *title; + + add_subwindow(vectors = new MoveObjVectors(this, x, y)); + y += vectors->get_h() + margin; + add_subwindow(do_stabilization = new MoveObjDoStabilization(this, + x, y)); + y += do_stabilization->get_h() + margin; + add_subwindow(title = new BC_Title(x, y, _("Block size:"))); + add_subwindow(block_size = new MoveObjBlockSize(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 MoveObjSearchRadius(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 MoveObjSettling(this, + x + title->get_w() + margin, y)); + + show_window(1); +} + +MoveObjVectors::MoveObjVectors(MoveObjWindow *gui, int x, int y) + : BC_CheckBox(x, y, gui->plugin->config.draw_vectors, _("Draw vectors")) +{ + this->gui = gui; +} + +int MoveObjVectors::handle_event() +{ + gui->plugin->config.draw_vectors = get_value(); + gui->plugin->send_configure_change(); + return 1; +} + + +MoveObjDoStabilization::MoveObjDoStabilization(MoveObjWindow *gui, int x, int y) + : BC_CheckBox(x, y, gui->plugin->config.do_stabilization, _("Do stabilization")) +{ + this->gui = gui; +} + +int MoveObjDoStabilization::handle_event() +{ + gui->plugin->config.do_stabilization = get_value(); + gui->plugin->send_configure_change(); + return 1; +} + + +MoveObjBlockSize::MoveObjBlockSize(MoveObjWindow *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 MoveObjBlockSize::handle_event() +{ + gui->plugin->config.block_size = (int)get_value(); + gui->plugin->send_configure_change(); + return 1; +} + + +MoveObjSearchRadius::MoveObjSearchRadius(MoveObjWindow *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 MoveObjSearchRadius::handle_event() +{ + gui->plugin->config.search_radius = (int)get_value(); + gui->plugin->send_configure_change(); + return 1; +} + + +MoveObjSettling::MoveObjSettling(MoveObjWindow *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 MoveObjSettling::handle_event() +{ + gui->plugin->config.settling_speed = (int)get_value(); + gui->plugin->send_configure_change(); + return 1; +} + diff --git a/cinelerra-5.1/plugins/moveobj/moveobjwindow.h b/cinelerra-5.1/plugins/moveobj/moveobjwindow.h new file mode 100644 index 00000000..c672da61 --- /dev/null +++ b/cinelerra-5.1/plugins/moveobj/moveobjwindow.h @@ -0,0 +1,97 @@ +/* + * CINELERRA + * Copyright (C) 2008-2014 Adam Williams + * + * 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 MOVEOBJWINDOW_H +#define MOVEOBJWINDOW_H + + +#include "guicast.h" + +class MoveObj; +class MoveObjWindow; + + +class MoveObjVectors : public BC_CheckBox +{ +public: + MoveObjVectors(MoveObjWindow *gui, int x, int y); + int handle_event(); + MoveObjWindow *gui; +}; + +class MoveObjDoStabilization : public BC_CheckBox +{ +public: + MoveObjDoStabilization(MoveObjWindow *gui, int x, int y); + int handle_event(); + MoveObjWindow *gui; +}; + +class MoveObjBlockSize : public BC_IPot +{ +public: + MoveObjBlockSize(MoveObjWindow *gui, int x, int y); + int handle_event(); + MoveObjWindow *gui; +}; + +class MoveObjSearchRadius : public BC_IPot +{ +public: + MoveObjSearchRadius(MoveObjWindow *gui, int x, int y); + int handle_event(); + MoveObjWindow *gui; +}; + +class MoveObjMaxMovement : public BC_IPot +{ +public: + MoveObjMaxMovement(MoveObjWindow *gui, int x, int y); + int handle_event(); + MoveObjWindow *gui; +}; + +class MoveObjSettling : public BC_IPot +{ +public: + MoveObjSettling(MoveObjWindow *gui, int x, int y); + int handle_event(); + MoveObjWindow *gui; +}; + +class MoveObjWindow : public PluginClientWindow +{ +public: + MoveObjWindow(MoveObj *plugin); + ~MoveObjWindow(); + + void create_objects(); + + MoveObj *plugin; + MoveObjVectors *vectors; + MoveObjDoStabilization *do_stabilization; + MoveObjBlockSize *block_size; + MoveObjSearchRadius *search_radius; +// not implemented +// MoveObjMaxMovement *max_movement; + MoveObjSettling *settling_speed; +}; + +#endif