Ceres Solver: A non-linear optimization library developed by Google

Ceres Solver is an open source C++ library for modeling and solving large, complicated optimization problems. Here is its tutorial about Non-linear Least Squares.

2,9,3 in the following codes represent the dimension of residual, the dimension of camera, the dimension of point.

// Factory to hide the construction of the CostFunction object from
// the client code.
static ceres::CostFunction* Create(const double observed_x,
                                   const double observed_y) {
return (new ceres::AutoDiffCostFunction<SnavelyReprojectionError, 2, 9, 3>(
                 new SnavelyReprojectionError(observed_x, observed_y)));
}

Their definitions can be found in the latest source code (autodiff_cost_function.h).

//   CostFunction* cost_function
//       = new AutoDiffCostFunction<MyScalarCostFunctor, 1, 2, 2>(
//            new MyScalarCostFunctor(1.0));             ^  ^  ^
//                                                       |  |  |
//                            Dimension of residual -----+  |  |
//                            Dimension of x ---------------+  |
//                            Dimension of y ------------------+

The latest code is using variadic template or template parameter pack which was introduced since C++11 to define the number of parameters.

template <typename CostFunctor,
          int kNumResiduals,  // Number of residuals, or ceres::DYNAMIC.
          int... Ns>          // Number of parameters in each parameter block.
class AutoDiffCostFunction : public SizedCostFunction<kNumResiduals, Ns...>

Before that, in the version 1.14.0 released on March 24, 2018, it was using 10 parameters directly.

template <typename CostFunctor,
          int kNumResiduals,  // Number of residuals, or ceres::DYNAMIC.
          int N0,       // Number of parameters in block 0.
          int N1 = 0,   // Number of parameters in block 1.
          int N2 = 0,   // Number of parameters in block 2.
          int N3 = 0,   // Number of parameters in block 3.
          int N4 = 0,   // Number of parameters in block 4.
          int N5 = 0,   // Number of parameters in block 5.
          int N6 = 0,   // Number of parameters in block 6.
          int N7 = 0,   // Number of parameters in block 7.
          int N8 = 0,   // Number of parameters in block 8.
          int N9 = 0>   // Number of parameters in block 9.
class AutoDiffCostFunction : public SizedCostFunction<kNumResiduals,
                                                      N0, N1, N2, N3, N4,
                                                      N5, N6, N7, N8, N9> {

Here are their differences.

Build ImageJ using Ant

A simplest way to build ImageJ is using Apache Ant.

For example,

./apache-ant/bin/ant -buildfile build.xml

But before that, JAVA_HOME should be set first.

export JAVA_HOME=/usr/java/jdk-12.0.1/
export PATH=$JAVA_HOME:$PATH

If not sure where the jdk is, use the following command to find it:

readlink -f $(which java)

Troubleshoots

When use jdk-12 to build the latest ImageJA (ImageJA is the old ImageJ, the new ImageJ is different with ImageJA), there will be some issues.

  • Source option 6 is no longer supported. Use 7 or later
    [javac] warning: [options] bootstrap class path not set in conjunction with -source 6
    [javac] error: Source option 6 is no longer supported. Use 7 or later.
    [javac] error: Target option 6 is no longer supported. Use 7 or later.

SOLUTION: Change ‘source’ and ‘target’ in build.xml from 1.6 to 1.7

source="1.7" target="1.7"

Sure, another alternative is to use the lower version jdk, and it does work in my another machine which installs jdk8 (1.8). Here is the java version history.

  • Could not find file …/IJ_Props.txt to copy.

Actually, not only this file cannot be found, but there are more files that cannot be found. ImageJA’s code has already been restructured, but not sure why build.xml has not been updated.

SOLUTION: Update those files’ path.

  <target name="build" depends="compile" description="Build ij.jar.">
    <!-- Copy needed files into the build directory. -->
    <copy file="src/main/resources/IJ_Props.txt" todir="build" />
    <copy file="src/main/resources/microscope.gif" tofile="build/microscope.gif" />
    <copy file="src/main/resources/about.jpg" tofile="build/about.jpg" />
	<!--<copy file="plugins/MacAdapter.class" tofile="build/MacAdapter.class" /> -->
    <copy todir="build/macros"><fileset dir="src/main/resources/macros"/></copy>
    <!-- Build ij.jar. -->
    <jar jarfile="ij.jar" basedir="build"
         manifest="src/main/resources/META-INF/MANIFEST.MF" />
  </target>

After fixing these two issues, the code should be able to be built.

ant -buildfile build.xml
...
BUILD SUCCESSFUL

Then run the built result ij.jar:

java -jar ij.jar

Use libpng to read and write png file

As for libpng, here is an example about how to use it to read and write a png. But actually the read() method can be simplified as below.

...
png_read_png( png, info, PNG_TRANSFORM_IDENTITY, NULL );
png_bytepp row_pointers = png_get_rows( png, info );

auto width = png_get_image_width( png, info );
auto height = png_get_image_height( png, info );
...

Note, png_read_png() must be called first before calling png_get_rows(), otherwise the return pointer row_pointers would be invalid. Its manual says:

After you have called png_read_png(), you can retrieve the image data with

   row_pointers = png_get_rows(png_ptr, info_ptr);