void blur_edge(cv::Mat img, cv::Mat blurred, int d){ int height = img.rows; int width = img.cols; cv::Mat img_pad(height + 2 * d, width + 2 * d, CV_32FC1); cv::Mat img_blur(height + 2 * d, width + 2 * d, CV_32FC1); cv::copyMakeBorder(img, img_pad, d, d, d, d, cv::BORDER_WRAP); cv::GaussianBlur(img_pad, img_blur, cvSize(2 * d + 1, 2 * d + 1), -1); img_blur = img_blur(cv::Range(d, height + d), cv::Range(d, width + d)); cv::Mat blur_mat(height, width, CV_32FC1); cv::Mat inv_blur_mat(height, width, CV_32FC1); int arr[4]; float tmp; for (int i = 0; i < blurred.rows; i++){ for (int j = 0; j < blurred.cols; j++){ arr[0] = i; arr[1] = height - 1 - i; arr[2] = j; arr[3] = width - 1 - j; tmp = (float)(Min(arr, 4)) / d; tmp = (tmp < 1.0) ? tmp : (float)(1.0); blur_mat.at<float>(i, j) = tmp; inv_blur_mat.at<float>(i, j) = (float)(1.0) - tmp; } } try{ cv::multiply(img, blur_mat, blurred); cv::multiply(img_blur, inv_blur_mat, blur_mat); cv::add(blurred, blur_mat, blurred); } catch (cv::Exception const& e) { std::cerr << "OpenCV exception at blur_edge: " << e.what() << std::endl; } img_pad.release(); img_blur.release(); blur_mat.release(); inv_blur_mat.release(); }
/** * Initialize all structures. * * @param tld learning structures */ void tldInit(TldStruct& tld) { // initialize lucas kanade lkInit(); // get initial bounding box Eigen::Vector4d bb; bb = tld.cfg->init; Eigen::Vector2i imsize; imsize(0) = tld.imgsize.m; imsize(1) = tld.imgsize.n; bb_scan(tld, bb, imsize, tld.model->min_win); // Features tldGenerateFeatures(tld, tld.model->num_trees, tld.model->num_features); // Initialize Detector fern0(); ImgType im0; img_init(*(tld.cfg)); im0.input = img_get(); im0.blur = cvCloneImage(im0.input); im0.blur = img_blur(im0.blur); // allocate structures fern1(im0.input, tld.grid, tld.features, tld.scales); // Temporal structures Tmp temporal; temporal.conf = Eigen::VectorXd::Zero(tld.nGrid); temporal.patt = Eigen::Matrix<double, 10, Eigen::Dynamic>::Zero(tld.model->num_trees, tld.nGrid); tld.tmp = temporal; // RESULTS ================================================================= // Initialize Trajectory tld.prevBB = Eigen::Vector4d::Constant( std::numeric_limits<double>::quiet_NaN()); tld.currentImg = im0; tld.currentBB = bb; tld.conf = 1; tld.currentValid = 1; tld.size = 1; // TRAIN DETECTOR ========================================================== // Initialize structures tld.imgsize.m = DIMY; tld.imgsize.n = DIMX; Eigen::RowVectorXd overlap = bb_overlap(tld.currentBB, tld.nGrid, tld.grid.topRows(4)); tld.target = img_patch(tld.currentImg.input, tld.currentBB); // Generate Positive Examples Eigen::Matrix<double, NTREES, Eigen::Dynamic> pX; // pX: 10 rows Eigen::Matrix<double, (PATCHSIZE * PATCHSIZE), Eigen::Dynamic> pEx; tld.currentBB = tldGeneratePositiveData(tld, overlap, tld.currentImg, tld.p_par_init, pX, pEx); Eigen::MatrixXd pY = Eigen::MatrixXd::Ones(1, pX.cols()); // Generate Negative Examples Eigen::Matrix<double, NTREES, Eigen::Dynamic> nX; // nX: 10 rows Eigen::Matrix<double, (PATCHSIZE * PATCHSIZE), Eigen::Dynamic> nEx; tldGenerateNegativeData(tld, overlap, tld.currentImg, nX, nEx); // Split Negative Data to Training set and Validation set Eigen::Matrix<double, NTREES, Eigen::Dynamic> spnX; Eigen::Matrix<double, (PATCHSIZE * PATCHSIZE), Eigen::Dynamic> spnEx; tldSplitNegativeData(nX, nEx, spnX, spnEx); Eigen::MatrixXd nY1 = Eigen::MatrixXd::Zero(1, spnX.cols() / 2); Eigen::MatrixXd xCombined(pX.rows(), pX.cols() + spnX.cols() / 2); xCombined << pX, spnX.leftCols(spnX.cols() / 2); Eigen::MatrixXd yCombined(pY.rows(), pY.cols() + nY1.cols()); yCombined << pY, nY1; Eigen::RowVectorXd idx(xCombined.cols()); for (int i = 0; i < xCombined.cols(); i++) idx(i) = i; idx = permutate_cols(idx); Eigen::MatrixXd permX(xCombined.rows(), xCombined.cols()); Eigen::VectorXd permY(yCombined.cols()); for (int i = 0; i < idx.cols(); i++) { permX.col(i) = xCombined.col(idx(i)); permY(i) = yCombined(0, idx(i)); } // Train using training set ------------------------------------------------ // Fern unsigned char bootstrap = 2; Eigen::VectorXd dummy(1); dummy(0) = -1; fern2(permX, permY, tld.model->thr_fern, bootstrap, dummy); // Nearest Neighbour tld.npex = 0; tld.nnex = 0; tldTrainNN(pEx, spnEx.leftCols(spnEx.cols() / 2), tld); tld.model->num_init = tld.npex; // Estimate thresholds on validation set ---------------------------------- // Fern unsigned int ferninsize = spnX.cols() / 2; Eigen::RowVectorXd conf_fern(ferninsize); Eigen::Matrix<double, 10, Eigen::Dynamic> fernin(10, ferninsize); fernin.leftCols(ferninsize) = spnX.rightCols(ferninsize); conf_fern = fern3(fernin, ferninsize); tld.model->thr_fern = std::max(conf_fern.maxCoeff() / tld.model->num_trees, tld.model->thr_fern); // Nearest neighbor Eigen::MatrixXd conf_nn(3, 3); conf_nn = tldNN(spnEx.rightCols(spnEx.cols() / 2), tld); tld.model->thr_nn = std::max(tld.model->thr_nn, conf_nn.block(0, 0, 1, conf_nn.cols() / 3).maxCoeff()); tld.model->thr_nn_valid = std::max(tld.model->thr_nn_valid, tld.model->thr_nn); }