@@ -281,6 +281,130 @@ struct ProjectionErrorFunctor
281281 ceres::DynamicCostFunctionToFunctorTmp _intrinsicFunctor;
282282};
283283
284+ struct ProjectionRelativeErrorFunctor
285+ {
286+ explicit ProjectionRelativeErrorFunctor (const sfmData::Observation& obs
287+ , const std::shared_ptr<camera::IntrinsicBase>& intrinsics
288+ , bool noPose)
289+ : _intrinsicFunctor(new CostIntrinsicsProject(obs, intrinsics))
290+ , withoutPose(noPose)
291+ {
292+ }
293+
294+ template <typename T>
295+ bool operator ()(T const * const * parameters, T* residuals) const
296+ {
297+ const T* parameter_intrinsics = parameters[0 ];
298+ const T* parameter_distortion = parameters[1 ];
299+
300+
301+ T transformedPoint[3 ];
302+ if (withoutPose)
303+ {
304+ // withoutPose is used if reference view and current view are the same views
305+ const T* parameter_relativepoint = parameters[2 ];
306+ transformedPoint[0 ] = parameter_relativepoint[0 ];
307+ transformedPoint[1 ] = parameter_relativepoint[1 ];
308+ transformedPoint[2 ] = parameter_relativepoint[2 ];
309+ }
310+ else
311+ {
312+ const T* parameter_pose = parameters[2 ];
313+ const T* parameter_refpose = parameters[3 ];
314+ const T* parameter_relativepoint = parameters[4 ];
315+
316+ // Retrieve point
317+ T relpoint[3 ];
318+ relpoint[0 ] = parameter_relativepoint[0 ];
319+ relpoint[1 ] = parameter_relativepoint[1 ];
320+ relpoint[2 ] = parameter_relativepoint[2 ];
321+
322+ const T* refcam_R = parameter_refpose;
323+ const T* refcam_t = ¶meter_refpose[3 ];
324+
325+ // Apply transformation such that the point
326+ // Which was defined in the camera geometric frame
327+ // is now defined in the world frame
328+ relpoint[0 ] = relpoint[0 ] - refcam_t [0 ];
329+ relpoint[1 ] = relpoint[1 ] - refcam_t [1 ];
330+ relpoint[2 ] = relpoint[2 ] - refcam_t [2 ];
331+
332+ T invrefcam_R[3 ];
333+ invrefcam_R[0 ] = -refcam_R[0 ];
334+ invrefcam_R[1 ] = -refcam_R[1 ];
335+ invrefcam_R[2 ] = -refcam_R[2 ];
336+
337+ T absolutePoint[3 ];
338+ ceres::AngleAxisRotatePoint (invrefcam_R, relpoint, absolutePoint);
339+
340+ // --
341+ // Apply external parameters (Pose)
342+ // --
343+ const T* cam_R = parameter_pose;
344+ const T* cam_t = ¶meter_pose[3 ];
345+
346+
347+ // Rotate the point according the camera rotation
348+ ceres::AngleAxisRotatePoint (cam_R, absolutePoint, transformedPoint);
349+
350+ // Apply the camera translation
351+ transformedPoint[0 ] += cam_t [0 ];
352+ transformedPoint[1 ] += cam_t [1 ];
353+ transformedPoint[2 ] += cam_t [2 ];
354+ }
355+
356+ const T * innerParameters[3 ];
357+ innerParameters[0 ] = parameter_intrinsics;
358+ innerParameters[1 ] = parameter_distortion;
359+ innerParameters[2 ] = transformedPoint;
360+
361+ return _intrinsicFunctor (innerParameters, residuals);
362+ }
363+
364+ /* *
365+ * @brief Create the appropriate cost functor according the provided input camera intrinsic model
366+ * @param[in] intrinsicPtr The intrinsic pointer
367+ * @param[in] observation The corresponding observation
368+ * @param[in] withoutPose When reference view and current view are the same, poses must be ignored
369+ * @return cost functor
370+ */
371+ inline static ceres::CostFunction* createCostFunction (
372+ const std::shared_ptr<camera::IntrinsicBase> intrinsic,
373+ const sfmData::Observation& observation,
374+ bool withoutPose)
375+ {
376+ auto costFunction = new ceres::DynamicAutoDiffCostFunction<ProjectionRelativeErrorFunctor>(new ProjectionRelativeErrorFunctor (observation, intrinsic, withoutPose));
377+
378+ int distortionSize = 1 ;
379+ auto isod = camera::IntrinsicScaleOffsetDisto::cast (intrinsic);
380+ if (isod)
381+ {
382+ auto distortion = isod->getDistortion ();
383+ if (distortion)
384+ {
385+ distortionSize = distortion->getParameters ().size ();
386+ }
387+ }
388+
389+ costFunction->AddParameterBlock (intrinsic->getParameters ().size ());
390+ costFunction->AddParameterBlock (distortionSize);
391+
392+ if (!withoutPose)
393+ {
394+ costFunction->AddParameterBlock (6 );
395+ costFunction->AddParameterBlock (6 );
396+ }
397+
398+ costFunction->AddParameterBlock (3 );
399+ costFunction->SetNumResiduals (2 );
400+
401+ return costFunction;
402+ }
403+
404+ ceres::DynamicCostFunctionToFunctorTmp _intrinsicFunctor;
405+ bool withoutPose;
406+ };
407+
284408
285409} // namespace sfm
286410} // namespace aliceVision
0 commit comments