static int pix_abs8_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h) { int s = 0, i; for (i = 0; i < h; i++) { s += abs(pix1[0] - avg2(pix2[0], pix2[1])); s += abs(pix1[1] - avg2(pix2[1], pix2[2])); s += abs(pix1[2] - avg2(pix2[2], pix2[3])); s += abs(pix1[3] - avg2(pix2[3], pix2[4])); s += abs(pix1[4] - avg2(pix2[4], pix2[5])); s += abs(pix1[5] - avg2(pix2[5], pix2[6])); s += abs(pix1[6] - avg2(pix2[6], pix2[7])); s += abs(pix1[7] - avg2(pix2[7], pix2[8])); pix1 += stride; pix2 += stride; } return s; }
/****************************************************************************//** * * *******************************************************************************/ int main(int argc, char *argv[]) { typedef double TFLOAT; if (argc<5 || argc>8) { std::cerr << "Usage: " << (argc?argv[0]:"average") << " CONFIG_FILE FTEMPLATES FPARTICLES [LOGFILE] [DO_FSC] [WEDGE_THRESHOLD]" "\n" "compiled at " __DATE__ " " __TIME__ " from " __FILE__ "\n" " CONFIG_FILE : filename of the parallel correlation program." "\n" " FTEMPLATES : filename of the textfile with the names of the templates." "\n" " FPARTICLES : filename of the textfile with the names of the particles." "\n" " ANGLES : filename of the textfile with the angles." "\n" " LOGFILE : optional parameter for the log file. '-' for STDOUT." "\n" " DO_FSC : optional parameter to decide whether to compute the FSC (yes or no)." "\n" " WEDGE_THRESHOLD : Voxels of the averaged wedge are set to zero if they are SMALLER then WEDGE_THRESHOLD% of the number of particles (default 0 == no cutoff)." << std::endl; return -1; } double use_threshold = 0.005; if (argc >= 8) { try { use_threshold = boost::lexical_cast<double>(argv[7]); } catch (boost::bad_lexical_cast &) { throw std::invalid_argument("The WEDGE_THRESHOLD must be a floating point number."); } if (use_threshold > 1 && use_threshold <= 100) { use_threshold = use_threshold/100.; } if (use_threshold > 1 || use_threshold <= 0) { throw std::invalid_argument("WEDGE_THRESHOLD must be either a prozentual value ]1, 100] or relative between ]0.0, 1.0]."); } } bool do_fourier_shell = true; if (argc >= 7) { std::string p(argv[6]); std::transform(p.begin(), p.end(), p.begin(), &toupper); if (p=="YES" || p=="1" || p=="FSC" || p=="TRUE") { do_fourier_shell = true; } else if (p=="NO" || p=="0" || p=="FALSE") { do_fourier_shell = false; } else { std::cerr << "Argument 6 (do_fsc) must be either \"yes\" or \"no\"." << std::endl; return -2; } } std::size_t itemplate, iparticle, ntemplates, nparticles, i; std::vector<std::string> ftemplates, fparticles; std::vector<boost::shared_ptr<tom::Volume<double> > > angles; std::vector<helper::triple<double, double, double> > anglesv; std::vector<boost::shared_ptr<tom::WedgeDescriptor<TFLOAT> > > wedge_templates, wedge_particles; std::vector<tom::cc_peak<TFLOAT> > peak_list; tom::corr::ConfigDataServer c; std::string outputdir; std::stringstream clog; std::auto_ptr<std::ofstream> f; std::auto_ptr<helper::ostream_swapper> stream_swapper; clog.precision(20); clog << "# start " << (argc>0?argv[0]:"average") << " at " << helper::now2str() << " (compiled at " __DATE__ " " __TIME__ ")." << std::endl; // Parse the input files. clog << "# parse configuration (" << argv[1] << ")" << std::endl; c.read_from_conf(argv[1]); clog << "# parse filelist for templates (" << argv[2] << ")" << std::endl; tom::corr::parse_filelist(argv[2], ftemplates, wedge_templates, 1); ntemplates = ftemplates.size(); clog << "# " << ntemplates << " templates read.\n" "# parse filelist for particles (" << argv[3] << ")" << std::endl; tom::corr::parse_filelist(argv[3], fparticles, wedge_particles, 1); nparticles = fparticles.size(); clog << "# " << nparticles << " particles read.\n" "# parse the list of angles (" << argv[4] << ")" << std::endl; tom::corr::parse_angleslist(argv[4], ntemplates, nparticles, angles); clog << "# parse peak list (" << c.peakfilename << ")" << std::endl; tom::corr::parse_peaklist(c.peakfilename, peak_list, anglesv, ntemplates, nparticles); clog << "#\n# use a threshold for the wedge of " << use_threshold << "\n# (values in the summed wedge are set to zero if they are smaller then the relative threshold compared to the number of particles).\n" << std::endl; tom::avg::filename_generator f_gen(c.outputdir); // open the logfile. { std::ostream *use_log = &std::clog; std::string logfilename(argc>=6 ? argv[5] : "-"); if (logfilename != "-") { f.reset(new std::ofstream(logfilename.c_str(), std::ios::out | std::ios::trunc)); if (!f->good()) { f.reset(NULL); clog << "# ERROR: could not open log-file \"" << logfilename << "\" for writing. Use CERR instead." << std::endl; } else { use_log = f.get(); } } *use_log << clog.rdbuf() << std::flush; clog.clear(); stream_swapper.reset(new helper::ostream_swapper(clog, *use_log)); } // Find out, which particles average to which template. std::vector<std::vector<std::size_t> > use_particles(ntemplates), use_particles1(ntemplates), use_particles2(ntemplates), use_particles3(ntemplates); for (iparticle=0; iparticle<nparticles; iparticle++) { std::size_t max_index = ntemplates; double max_ccvalue = - std::numeric_limits<double>::infinity(); for (itemplate=0; itemplate<ntemplates; itemplate++) { i = itemplate * nparticles + iparticle; if (angles[i].get()) { assert(angles[i]->getSizeX()==3 && angles[i]->getSizeZ()==1); if (peak_list[i].angle_idx < 0) { clog << "# WARNING: no peak found for template #" << itemplate << ", particle #" << iparticle << "." << std::endl; continue; } else { if (static_cast<std::size_t>(peak_list[i].angle_idx) >= angles[i]->getSizeY()) { clog << "# WARNING: peak-index for template #" << itemplate << ", particle #" << iparticle << " is larger then the entire angle-list (" << peak_list[i].angle_idx << " vs. " << angles[i]->getSizeY() << "). Using peak from file." << std::endl; } else { boost::tuples::tuple<double &, double &, double &> a = boost::tuples::tie(angles[i]->get(0, peak_list[i].angle_idx, 0), angles[i]->get(0, peak_list[i].angle_idx, 0), angles[i]->get(0, peak_list[i].angle_idx, 0)); if (fabs(a.get<0>()-anglesv[i].x)>1e-7 || fabs(a.get<0>()-anglesv[i].x)>1e-7 || fabs(a.get<0>()-anglesv[i].x)>1e-7) { clog << "# WARNING: peak-index for template #" << itemplate << ", particle #" << iparticle << " differs from angles list and peakfile: (" << a.get<0>() << " vs. " << anglesv[i].x << "; " << a.get<0>() << " vs. " << anglesv[i].x << "; " << a.get<0>() << " vs. " << anglesv[i].x << "). Take from peak-file." << std::endl; } } } } else { if (peak_list[i].angle_idx >= 0) { clog << "# WARNING: peak-index for template #" << itemplate << ", particle #" << iparticle << " given, but the angles list is empty. Using peak from file." << std::endl; } else { // everything is fine. continue; } } const double shiftx = - peak_list[i].x; const double shifty = - peak_list[i].y; const double shiftz = - peak_list[i].z; if (fabs(shiftx) > c.volsize/2 || fabs(shifty) > c.volsize/2 || fabs(shiftz) > c.volsize/2) { clog << "# WARNING: the shift of template #" << itemplate << ", particle #" << iparticle << " is too large for the volume of size " << c.volsize << " (" << shiftx << "," << shifty << "," << shiftz << ")." << std::endl; continue; } if (max_index==ntemplates || max_ccvalue<peak_list[i].val) { max_ccvalue = peak_list[i].val; max_index = itemplate; } } if (max_index != ntemplates) { use_particles[max_index].push_back(iparticle); } } // Split the list of particles in two sets for the FSC. if (do_fourier_shell) { for (itemplate=0; itemplate<ntemplates; itemplate++) { std::size_t size = use_particles[itemplate].size(); if (size >= 2) { const std::vector<std::size_t> &v_ = use_particles [itemplate]; std::vector<std::size_t> &v1 = use_particles1[itemplate]; std::vector<std::size_t> &v2 = use_particles2[itemplate]; std::vector<std::size_t> &v3 = use_particles3[itemplate]; v1.resize(0); v2.resize(0); v3.resize(0); if (size%2) { size--; v3.push_back(v_[size]); } v1.reserve(size/2); v2.reserve(size/2); for (iparticle=0; iparticle<size; iparticle+=2) { v1.push_back(v_[iparticle]); } for (iparticle=1; iparticle<size; iparticle+=2) { v2.push_back(v_[iparticle]); } } } } else { clog << "# don't compute the Fourier Shell Correlation." << std::endl; } // Init the spheremask std::auto_ptr<const tom::Volume<TFLOAT> > mask_sphere; if (c.sphere_mask_inner_radius>0 || c.sphere_mask_sigma>0) { tom::Volume<TFLOAT> *p; mask_sphere.reset(p = new tom::Volume<TFLOAT>(c.volsize, c.volsize, c.volsize, NULL,NULL)); tom::init_spheremask(*p, c.sphere_mask_inner_radius, c.sphere_mask_sigma, c.sphere_mask_cutoff_radius); } tom::Volume<TFLOAT> avg(c.volsize, c.volsize, c.volsize, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>()); tom::Volume<TFLOAT> avgwedge(c.volsize, c.volsize, c.volsize, NULL,NULL); tom::Volume<TFLOAT> avgwedge_half(avgwedge, NULL, c.volsize, c.volsize, c.volsize/2+1, avgwedge.getStrideX(), avgwedge.getStrideY(), avgwedge.getStrideZ()); tom::Volume<TFLOAT> avgwedge_sqrtn(c.volsize, c.volsize, c.volsize, NULL,NULL); tom::Volume<TFLOAT> avgwedge_sqrtn_half(avgwedge_sqrtn, NULL, c.volsize, c.volsize, c.volsize/2+1, avgwedge.getStrideX(), avgwedge.getStrideY(), avgwedge.getStrideZ()); tom::Volume<TFLOAT> avg2(c.volsize, c.volsize, c.volsize, NULL,NULL); tom::Volume<TFLOAT> avgwedge2(c.volsize, c.volsize, c.volsize, NULL,NULL); tom::Volume<TFLOAT> avgwedge2_half(avgwedge2, NULL, c.volsize, c.volsize, c.volsize/2+1, avgwedge2.getStrideX(), avgwedge2.getStrideY(), avgwedge2.getStrideZ()); tom::Volume<std::complex<TFLOAT> > avg_ft(c.volsize, c.volsize, c.volsize/2+1, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>()); tom::Volume<std::complex<TFLOAT> > avg_ft2(c.volsize, c.volsize, c.volsize/2+1, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>()); tom::fftw::Plan<TFLOAT> plan_fwd(avg2, avg_ft, c.fftw_flag | FFTW_DESTROY_INPUT); tom::fftw::Plan<TFLOAT> plan_bwd(avg_ft, avg2, c.fftw_flag | FFTW_DESTROY_INPUT); std::auto_ptr<tom::Volume<TFLOAT> > vtemplate; tom::Volume<std::complex<TFLOAT> > vtemplate_ft(c.volsize, c.volsize, c.volsize/2+1, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>()); tom::fftw::Plan<TFLOAT> plan_vtemplate(avg, vtemplate_ft, c.fftw_flag | FFTW_DESTROY_INPUT); // Volumes for the fourier shell correlation. std::auto_ptr<tom::Volume<TFLOAT> > FSC_v, FSC_w2; std::auto_ptr<tom::Volume<std::complex<TFLOAT> > > FSC_f1, FSC_f2, FSC_f1_half, FSC_f2_half; std::auto_ptr<tom::fftw::Plan<TFLOAT> > FSC_plan1, FSC_plan2; if (do_fourier_shell) { FSC_v.reset( new tom::Volume<TFLOAT>(c.volsize, c.volsize, c.volsize, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>())); FSC_f1.reset( new tom::Volume<std::complex<TFLOAT> >(c.volsize, c.volsize, c.volsize, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>())); FSC_f2.reset( new tom::Volume<std::complex<TFLOAT> >(c.volsize, c.volsize, c.volsize, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>())); FSC_f1_half.reset( new tom::Volume<std::complex<TFLOAT> >(*FSC_f1, NULL, c.volsize, c.volsize, c.volsize/2+1, FSC_f1->getStrideX(), FSC_f1->getStrideY(), FSC_f1->getStrideZ())); FSC_f2_half.reset( new tom::Volume<std::complex<TFLOAT> >(*FSC_f2, NULL, c.volsize, c.volsize, c.volsize/2+1, FSC_f2->getStrideX(), FSC_f2->getStrideY(), FSC_f2->getStrideZ())); FSC_plan1.reset( new tom::fftw::Plan<TFLOAT>(*FSC_v, *FSC_f1_half, c.fftw_flag | FFTW_DESTROY_INPUT)); FSC_plan2.reset( new tom::fftw::Plan<TFLOAT>(*FSC_v, *FSC_f2_half, c.fftw_flag | FFTW_DESTROY_INPUT)); FSC_w2.reset( new tom::Volume<TFLOAT>(c.volsize, c.volsize, c.volsize/2+1, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>())); } double mean, variance; std::vector<std::size_t>::const_iterator culvit; // Const Unsigned Long Vector ITerator std::vector<tom::avg::st_average_result> av(ntemplates); double threshold = 1; // Now compute the average, the FSC, the CC and save it to file. for (itemplate=0; itemplate<ntemplates; itemplate++) { const std::vector<std::size_t> &v_ = use_particles [itemplate]; const std::vector<std::size_t> &v1 = use_particles1[itemplate]; const std::vector<std::size_t> &v2 = use_particles2[itemplate]; const std::vector<std::size_t> &v3 = use_particles3[itemplate]; threshold = v_.size()*use_threshold; // cut off. assert(std::set<std::size_t>(v_.begin(), v_.end()).size() == v_.size() && (!do_fourier_shell || (v_.size()<2 || v_.size()==(v1.size()+v2.size()+v3.size())))); if (v_.empty()) { continue; } tom::avg::st_average_result &ar = av[itemplate]; ar.use_idx = v_; // Read the original template from file. try { tom::Volume<TFLOAT> *p; tom::read_from_em(p, ftemplates[itemplate], NULL,NULL,NULL, NULL, NULL,NULL); vtemplate.reset(p); } catch (std::exception &e) { std::stringstream ss; ss << "# The template #" << itemplate << " (" << ftemplates[itemplate] << ") does not exist."; if (c.force_files_exist) { clog << ss.str() << " ABORT"; throw; } clog << ss << " SKIP CC correlation."; vtemplate.reset(NULL); } if (vtemplate.get()) { // normalise it and compute its fourier transformation. vtemplate->stat(mean, variance, false); vtemplate->shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); avg.setValues(*vtemplate); plan_vtemplate.execute(avg, vtemplate_ft); } // Average the particles. if (!v1.empty() && v1.size()==v2.size()) { assert(do_fourier_shell); tom::avg::average(c.volsize, fparticles, wedge_particles, v1, itemplate, mask_sphere.get(), peak_list, anglesv, c.force_files_exist, &clog, avg, avgwedge_half); tom::avg::average(c.volsize, fparticles, wedge_particles, v2, itemplate, mask_sphere.get(), peak_list, anglesv, c.force_files_exist, &clog, avg2, avgwedge2_half); std::vector<double> res; std::size_t n_shells = c.volsize/2; FSC_w2->setValues(avgwedge_half); tom::element_wise_set_below_threshold<TFLOAT>(*FSC_w2, threshold*v1.size()/static_cast<double>(v_.size()), 0); tom::avg::apply_avgwedge(avg, *FSC_w2, mask_sphere.get(), c.fftw_flag, *FSC_v); //FSC_v->setValues(avg); //FSC_v->write_to_em("FSC_v1.em", NULL); FSC_plan1->execute(*FSC_v, *FSC_f1_half); FSC_w2->setValues(avgwedge2_half); tom::element_wise_set_below_threshold<TFLOAT>(*FSC_w2, threshold*v2.size()/static_cast<double>(v_.size()), 0); tom::avg::apply_avgwedge(avg2, *FSC_w2, mask_sphere.get(), c.fftw_flag, *FSC_v); //FSC_v->setValues(avg2); //FSC_v->write_to_em("FSC_v2.em", NULL); FSC_plan2->execute(*FSC_v, *FSC_f2_half); tom::fourier_shell_correlation(*FSC_f1_half, false, *FSC_f2_half, false, c.volsize, n_shells, res); ar.fsc.resize(n_shells); for (std::size_t i=0; i<n_shells; i++) { ar.fsc[i].first = res[i+n_shells*1]; ar.fsc[i].second = res[i+n_shells*7]; } //tom::Volume<double>(&res[0], n_shells, 11, 1, 0,0,0, false, NULL).write_to_em("FSC_cc.em", NULL); tom::element_wise_add<TFLOAT, TFLOAT>(avg, avg2); tom::element_wise_add<TFLOAT, TFLOAT>(avgwedge_half, avgwedge2_half); if (!v3.empty()) { // Add the missing partivle to the average. tom::avg::average(c.volsize, fparticles, wedge_particles, v3, itemplate, mask_sphere.get(), peak_list, anglesv, c.force_files_exist, &clog, avg2, avgwedge2_half); tom::element_wise_add<TFLOAT, TFLOAT>(avg, avg2); tom::element_wise_add<TFLOAT, TFLOAT>(avgwedge_half, avgwedge2_half); } } else { tom::avg::average(c.volsize, fparticles, wedge_particles, v_, itemplate, mask_sphere.get(), peak_list, anglesv, c.force_files_exist, &clog, avg, avgwedge_half); } //////////////////////////////////////////////////////////////////////// // Save the average volume (the pure sum): avg_s avg.write_to_em(f_gen.get_avg_s(itemplate), NULL); tom::hermitian_symmetry_to_full(avgwedge); tom::fftshift(avgwedge, avgwedge2, true); avgwedge2.write_to_em(f_gen.get_avgwedge_s(itemplate), NULL); if (vtemplate.get()) { // Compute the correlation with the original template. avg.stat(mean, variance, false); if (variance) { avg2.setValues(avg); // make a copy for normalising. avg2.shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); plan_fwd.execute(avg2, avg_ft); tom::element_wise_conj_multiply<std::complex<TFLOAT>, std::complex<TFLOAT> >(avg_ft, vtemplate_ft); plan_bwd.execute(avg_ft, avg2); ar.ccval_s.reset(new double((avg2.get(0,0,0)/avg2.numel())/avg2.numel())); } } //////////////////////////////////////////////////////////////////////// // Set values below threshold in volume to 0 tom::element_wise_set_below_threshold<TFLOAT>(avgwedge_half, threshold, 0); tom::hermitian_symmetry_to_full(avgwedge); avg2.setValues(avg); plan_fwd.execute(avg2, avg_ft); avg_ft2.setValues(avg_ft); //////////////////////////////////////////////////////////////////////// // Compute the average with frequencies weighted by N set_where_binary_mask_not_set<std::complex<TFLOAT>, TFLOAT>(avg_ft, avgwedge_half, 0); avg_ft.get(0,0,0) = 0; plan_bwd.execute(avg_ft, avg2); if (mask_sphere.get()) { tom::norm_mask<TFLOAT, TFLOAT, double>(avg2, *mask_sphere, tom::norm::NORM_STDDEV_1, NULL, true); } else { if ((variance=avg2.variance_mean_free(false))) { avg2.shift_scale<TFLOAT>(0, 1./sqrt(variance)); } } avg2.write_to_em(f_gen.get_avg_n(itemplate), NULL); tom::fftshift(avgwedge, avgwedge2, true); avgwedge2.write_to_em(f_gen.get_avgwedge_n(itemplate), NULL); if (vtemplate.get()) { // Compute the correlation with the original template. avg2.stat(mean, variance, false); if (variance) { avg2.shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); plan_fwd.execute(avg2, avg_ft); tom::element_wise_conj_multiply<std::complex<TFLOAT>, std::complex<TFLOAT> >(avg_ft, vtemplate_ft); plan_bwd.execute(avg_ft, avg2); ar.ccval_n.reset(new double((avg2.get(0,0,0)/avg2.numel())/avg2.numel())); } } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Compute the average with frequencies weighted by sqrt(N) avgwedge_sqrtn_half.setValues(avgwedge_half); tom::element_wise_operation(avgwedge_sqrtn_half, &tom::math::sqrt<TFLOAT>); avg_ft.setValues(avg_ft2); tom::element_wise_div<std::complex<TFLOAT>, TFLOAT>(avg_ft, avgwedge_sqrtn_half, std::complex<TFLOAT>(0,0)); avg_ft.get(0,0,0) = 0; plan_bwd.execute(avg_ft, avg2); if (mask_sphere.get()) { tom::norm_mask<TFLOAT, TFLOAT, double>(avg2, *mask_sphere, tom::norm::NORM_STDDEV_1, NULL, true); } else { if ((variance=avg2.variance_mean_free(false))) { avg2.shift_scale<TFLOAT>(0, 1./sqrt(variance)); } } avg2.write_to_em(f_gen.get_avg_sqrtn(itemplate), NULL); tom::hermitian_symmetry_to_full(avgwedge_sqrtn); tom::fftshift(avgwedge_sqrtn, avgwedge2, true); avgwedge2.write_to_em(f_gen.get_avgwedge_sqrtn(itemplate), NULL); if (vtemplate.get()) { // Compute the correlation with the original template. avg2.stat(mean, variance, false); if (variance) { avg2.shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); plan_fwd.execute(avg2, avg_ft); tom::element_wise_conj_multiply<std::complex<TFLOAT>, std::complex<TFLOAT> >(avg_ft, vtemplate_ft); plan_bwd.execute(avg_ft, avg2); ar.ccval_sqrtn.reset(new double((avg2.get(0,0,0)/avg2.numel())/avg2.numel())); } } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Compute the average with frequencies weighted by 1 avgwedge2_half.setValues(avgwedge_half); avg_ft.setValues(avg_ft2); tom::element_wise_div<std::complex<TFLOAT>, TFLOAT>(avg_ft, avgwedge2_half, std::complex<TFLOAT>(0,0)); avg_ft.get(0,0,0) = 0; plan_bwd.execute(avg_ft, avg2); if (mask_sphere.get()) { tom::norm_mask<TFLOAT, TFLOAT, double>(avg2, *mask_sphere, tom::norm::NORM_STDDEV_1, NULL, true); } else { if ((variance=avg2.variance_mean_free(false))) { avg2.shift_scale<TFLOAT>(0, 1./sqrt(variance)); } } avg2.write_to_em(f_gen.get_avg_1(itemplate), NULL); tom::make_binary(avgwedge2); tom::hermitian_symmetry_to_full(avgwedge2); tom::fftshift(avgwedge2, avgwedge, true); avgwedge.write_to_em(f_gen.get_avgwedge_1(itemplate), NULL); if (vtemplate.get()) { // Compute the correlation with the original template. avg2.stat(mean, variance, false); if (variance) { avg2.shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); plan_fwd.execute(avg2, avg_ft); tom::element_wise_conj_multiply<std::complex<TFLOAT>, std::complex<TFLOAT> >(avg_ft, vtemplate_ft); plan_bwd.execute(avg_ft, avg2); ar.ccval_1.reset(new double((avg2.get(0,0,0)/avg2.numel())/avg2.numel())); } } //////////////////////////////////////////////////////////////////////// } tom::avg::write_average_to_log(clog, ftemplates, fparticles, av, c.outputdir); clog << "# finished at " << helper::now2str() << std::endl; return 0; }
static int pix_abs16_y2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h) { int s = 0, i; uint8_t *pix3 = pix2 + stride; for (i = 0; i < h; i++) { s += abs(pix1[0] - avg2(pix2[0], pix3[0])); s += abs(pix1[1] - avg2(pix2[1], pix3[1])); s += abs(pix1[2] - avg2(pix2[2], pix3[2])); s += abs(pix1[3] - avg2(pix2[3], pix3[3])); s += abs(pix1[4] - avg2(pix2[4], pix3[4])); s += abs(pix1[5] - avg2(pix2[5], pix3[5])); s += abs(pix1[6] - avg2(pix2[6], pix3[6])); s += abs(pix1[7] - avg2(pix2[7], pix3[7])); s += abs(pix1[8] - avg2(pix2[8], pix3[8])); s += abs(pix1[9] - avg2(pix2[9], pix3[9])); s += abs(pix1[10] - avg2(pix2[10], pix3[10])); s += abs(pix1[11] - avg2(pix2[11], pix3[11])); s += abs(pix1[12] - avg2(pix2[12], pix3[12])); s += abs(pix1[13] - avg2(pix2[13], pix3[13])); s += abs(pix1[14] - avg2(pix2[14], pix3[14])); s += abs(pix1[15] - avg2(pix2[15], pix3[15])); pix1 += stride; pix2 += stride; pix3 += stride; } return s; }
void Calib::computeProjectionMatrix() { std::cout << "1111111111***********************************************************************************\n"; // for(int i = 0;i < imagePoints.size();i++) // { // std::cout<<" imagePoints[i]= "<< imagePoints[i]<<std::endl; // std::cout<<" objectPoints[i]= "<< objectPoints[i]<<std::endl; // } if (objectPoints.size() != imagePoints.size()) return; int n = objectPoints.size(); Eigen::Vector2d avg2; Eigen::Vector3d avg3; for (unsigned int i = 0; i < n; i++) { avg2 += imagePoints[i]; avg3 += objectPoints[i]; std::cout << i << " " << objectPoints[i](0) << " " << objectPoints[i](1) << " " << objectPoints[i](2) << std::endl; } avg2 = avg2 / n; avg3 = avg3 / n; std::cout << "avg2 = " << avg2 << std::endl; std::cout << "avg3 = " << avg3 << std::endl; /* ******************************************************************************* * Data normalization * Translates and normalises a set of 2D homogeneous points so that their centroid is at the origin and their mean distance from the origin is sqrt(2). */ float meandist2 = 0; float meandist3 = 0; imagePoints_t.resize(n); objectPoints_t.resize(n); for (unsigned int i = 0; i < n; i++) { imagePoints_t[i] = imagePoints[i] - avg2; objectPoints_t[i] = objectPoints[i] - avg3; // std::cout << "1 imagePoints_t[i] = " << imagePoints_t[i] << std::endl; // std::cout << "1 objectPoints_t[i] = " << objectPoints_t[i] << std::endl; meandist2 += sqrt(imagePoints_t[i](0) * imagePoints_t[i](0) + imagePoints_t[i](1) * imagePoints_t[i](1)); meandist3 += sqrt(objectPoints_t[i](0) * objectPoints_t[i](0) + objectPoints_t[i](1) * objectPoints_t[i](1) + objectPoints_t[i](2) * objectPoints_t[i](2)); } meandist2 /= n; meandist3 /= n; std::cout << "meandist2 = " << meandist2 << std::endl; std::cout << "meandist3 = " << meandist3 << std::endl; float scale2 = sqrt(2) / meandist2; float scale3 = sqrt(3) / meandist3; std::cout << "2222222222222***********************************************************************************\n"; for (unsigned int i = 0; i < n; i++) { imagePoints_t[i] = scale2 * imagePoints_t[i]; objectPoints_t[i] = scale3 * objectPoints_t[i]; // std::cout << "imagePoints_t[i] = " << imagePoints_t[i] << std::endl; // std::cout << "objectPoints_t[i] = " << objectPoints_t[i] << std::endl; } // std::cout<<avg3<<std::endl; /* ******************************************************************************* * Similarity transformation T1 to normalize the image points, * and a second similarity transformation T2 to normalize the space points. * Page 181 in Multiple_View_Geometry_in_Computer_Vision__2nd_Edition */ Eigen::Matrix3d T1; T1 << scale2, 0, -scale2 * avg2(0), 0, scale2, -scale2 * avg2(1), 0, 0, 1; Eigen::MatrixXd T2(4, 4); T2 << scale3, 0, 0, -scale3 * avg3(0), 0, scale3, 0, -scale3 * avg3(1), 0, 0, scale3, -scale3 * avg3(2), 0, 0, 0, 1; // use Eigen Eigen::MatrixXd A(2 * n, 12); A.setZero(2 * n, 12); for (int i = 0; i < n; i++) { A(2 * i, 0) = objectPoints_t[i](0); A(2 * i, 1) = objectPoints_t[i](1); A(2 * i, 2) = objectPoints_t[i](2); A(2 * i, 3) = 1; A(2 * i, 4) = 0; A(2 * i, 5) = 0; A(2 * i, 6) = 0; A(2 * i, 7) = 0; A(2 * i, 8) = -imagePoints_t[i](0) * objectPoints_t[i](0); A(2 * i, 9) = -imagePoints_t[i](0) * objectPoints_t[i](1); A(2 * i, 10) = -imagePoints_t[i](0) * objectPoints_t[i](2); A(2 * i, 11) = -imagePoints_t[i](0) * 1; A(2 * i + 1, 0) = 0; A(2 * i + 1, 1) = 0; A(2 * i + 1, 2) = 0; A(2 * i + 1, 3) = 0; A(2 * i + 1, 4) = 1 * objectPoints_t[i](0); A(2 * i + 1, 5) = 1 * objectPoints_t[i](1); A(2 * i + 1, 6) = 1 * objectPoints_t[i](2); A(2 * i + 1, 7) = 1; A(2 * i + 1, 8) = -imagePoints_t[i](1) * objectPoints_t[i](0); A(2 * i + 1, 9) = -imagePoints_t[i](1) * objectPoints_t[i](1); A(2 * i + 1, 10) = -imagePoints_t[i](1) * objectPoints_t[i](2); A(2 * i + 1, 11) = -imagePoints_t[i](1) * 1; } Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeFullU | Eigen::ComputeFullV); const Eigen::VectorXd & v1 = svd.matrixV().col(11); this->Pt << v1(0), v1(1), v1(2), v1(3), v1(4), v1(5), v1(6), v1(7), v1(8), v1(9), v1(10), v1(11); // std::cout<<"A= \n"<< A<<std::endl; // std::cout<<Pt<<std::endl; P = T1.inverse() * Pt * T2; //Decompose the projection matrix cv::Mat Pr(3, 4, cv::DataType<float>::type); cv::Mat Mt(3, 3, cv::DataType<float>::type); cv::Mat Rt(3, 3, cv::DataType<float>::type); cv::Mat Tt(4, 1, cv::DataType<float>::type); for (unsigned i = 0; i < 3; i++) { for (unsigned int j = 0; j < 4; j++) { Pr.at<float> (i, j) = P(i, j); } } cv::decomposeProjectionMatrix(Pr, Mt, Rt, Tt); //scale: Mt(2,2) should = 1; so update the projection matrix and decomposition again float k = (1 / (Mt.at<float> (2, 2))); /* **************************************************************************************** * Upate the projection matrix * Decomposition again to get new intrinsic matrix and rotation matrix */ this->P = k * P; cv::Mat Pro(3, 4, cv::DataType<float>::type); cv::Mat Mc(3, 3, cv::DataType<float>::type); // intrinsic parameter matrix cv::Mat Rc(3, 3, cv::DataType<float>::type); // rotation matrix cv::Mat Tc(4, 1, cv::DataType<float>::type); // translation vector for (unsigned i = 0; i < 3; i++) { for (unsigned int j = 0; j < 4; j++) { Pro.at<float> (i, j) = P(i, j); } } cv::decomposeProjectionMatrix(Pro, Mc, Rc, Tc); // Change from OpenCV varibles to Eigen for (unsigned i = 0; i < 3; i++) { for (unsigned int j = 0; j < 3; j++) { M(i, j) = Mc.at<float> (i, j) ; } } /* **************************************************************************************** * Compute te rotation matrix R and translation vector T */ P_temp = M.inverse() * P; this->R = this->P_temp.block(0,0,3,3); this->T = this->P_temp.block(0,3,3,1); std::cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"; // std::cout << "T1 =\n " << T2 << std::endl; // std::cout << "T2 =\n " << T1 << std::endl; // std::cout << "A =\n " << A << std::endl; // std::cout << "svd.matrixV() =\n " << svd.matrixV() << std::endl; // std::cout << "Pt =\n " << Pt << std::endl; std::cout << "P =\n " << P << std::endl; std::cout << "M =\n " << M << std::endl; std::cout << "R =\n " << R << std::endl; std::cout << "Rc =\n " << Rc << std::endl; std::cout << "T =\n " << T << std::endl; std::cout << "Mt(2,2) = " << Mt.at<float> (2, 2) << std::endl; }