Solves the FoE problem using Ceres and post-processes it to make sure the solution stays within [0, 255].
| 209 | // Solves the FoE problem using Ceres and post-processes it to make sure the |
| 210 | // solution stays within [0, 255]. |
| 211 | void SolveProblem(Problem* problem, PGMImage<double>* solution) { |
| 212 | // These parameters may be experimented with. For example, ceres::DOGLEG tends |
| 213 | // to be faster for 2x2 filters, but gives solutions with slightly higher |
| 214 | // objective function value. |
| 215 | ceres::Solver::Options options; |
| 216 | SetMinimizerOptions(&options); |
| 217 | SetLinearSolver(&options); |
| 218 | options.function_tolerance = 1e-3; // Enough for denoising. |
| 219 | |
| 220 | if (options.linear_solver_type == ceres::CGNR && |
| 221 | options.preconditioner_type == ceres::SUBSET) { |
| 222 | std::vector<ResidualBlockId> residual_blocks; |
| 223 | problem->GetResidualBlocks(&residual_blocks); |
| 224 | |
| 225 | // To use the SUBSET preconditioner we need to provide a list of |
| 226 | // residual blocks (rows of the Jacobian). The denoising problem |
| 227 | // has fairly general sparsity, and there is no apriori reason to |
| 228 | // select one residual block over another, so we will randomly |
| 229 | // subsample the residual blocks with probability subset_fraction. |
| 230 | std::default_random_engine engine; |
| 231 | std::uniform_real_distribution<> distribution(0, 1); // rage 0 - 1 |
| 232 | for (auto residual_block : residual_blocks) { |
| 233 | if (distribution(engine) <= CERES_GET_FLAG(FLAGS_subset_fraction)) { |
| 234 | options.residual_blocks_for_subset_preconditioner.insert( |
| 235 | residual_block); |
| 236 | } |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | ceres::Solver::Summary summary; |
| 241 | ceres::Solve(options, problem, &summary); |
| 242 | std::cout << summary.FullReport() << "\n"; |
| 243 | |
| 244 | // Make the solution stay in [0, 255]. |
| 245 | for (int x = 0; x < solution->width(); ++x) { |
| 246 | for (int y = 0; y < solution->height(); ++y) { |
| 247 | *solution->MutablePixel(x, y) = |
| 248 | std::min(255.0, std::max(0.0, solution->Pixel(x, y))); |
| 249 | } |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | } // namespace |
| 254 | } // namespace ceres::examples |
no test coverage detected