Package: imgreg
imgregAn image registration library for python including a simple interface for building new models. Currently two image registration models for linear transformations based on scikit have been implemented as part of a toolchain in the context of particle image velocimetry (PIV). Tested for Python 3.7 to Python 3.9.InstallationExamplesRecover the rotation and translation between two imagesBatch image processingStore recovered values to .csvLoad the recovered values from .csvSave the reconstructed imagesA word on the modelsTutorialsDocumentationTestingLicenseInstallationimgreg is directly available frompypi:pipinstallimgregalternatively clone therepository, and install with:gitclonehttps://gitlab.com/DigonIO/imgreg.gitcdimgreg
pythonsetup.pyinstallExamplesThe following examples give a short introduction into the available models. For further reading the directorydoc/tutorialprovides a good starting point. The full documentation is availableonline.Recover the rotation and translation between two imagesFirst import the model (here based on the logpolar and fourier transformation) and load the image files into the model:importnumpyasnpimportimgreg.dataasdatafromimgreg.models.logpolarimportLogPolarSolverref_img=np.array(data.ref_img())mod_img=np.array(data.mod_img())lps=LogPolarSolver(ref_img,mod_img)The images can be displayed with:lps.display([lps.REF_IMG,lps.MOD_IMG])To access the recovered rotation angle and lower error bound in degrees use:lps.RECOVERED_ROTATION.value# array([-13.06730769,   0.11259774])The recovered x,y translation and lower error bound given in number of pixels is accessed with:lps.RECOVERED_TRANSLATION.value# array([-17.98318062,  31.037803  ,   0.42407651])The recovered scaling factor is available with:lps.RECOVERED_SCALE.value# array([1.        , 1.00187429])A comparision between the recovered and the reference image can be displayed with:lps.display([lps.RECOVERED_ROT_SCALE_TR_IMG,lps.REF_IMG])Batch image processingFirst import the required modules (here we use the less general domain specificRadonSolvermodel, if not suitable for your application, repace with theLogPolarSolveras in the previous example):importosimportpandasaspdimportmatplotlib.pyplotaspltimportnumpyasnpfromPILimportImagefromimgreg.models.radonimportRadonSolverfromimgreg.util.helpersimportimage_save_back_tf,rot_tr_gen,solver_genfromimgreg.util.ioimportDirectoryViewDefine the location to your reference image according to your usecase by replacing<path/to/reference/image.jpg>, then replace the location of your source<src>and destination<dest>paths. Adjust thefile_patternandstepvariables to your needs, the latter can be used to skip images for faster computation.image_path_ref="<path/to/reference/image.jpg>"image_path_src="<src>"image_path_dest="<dest>"file_pattern="*.jpg"step=10Create a directory view from which the solver generates its input:d_view=DirectoryView(image_path_src,file_pattern=file_pattern)fnames=[filefori,fileinenumerate(sorted(d_view.files))ifnoti%step]Load the reference image:ref_img=np.array(Image.open(image_path_ref))Initialize and configure a suitable solver:ras=RadonSolver(ref_img=ref_img)ras.UPSAMPLING.value=20Generate an array containing the recovered translation and rotation parameters for the given images:radg=solver_gen(d_view,ras,step)rad_rot_tr_arr=np.array(list(rot_tr_gen(radg)))Display the relative normNormRel_L2over the image series as an indicator for the goodness of the recovered values:plt.plot(rad_rot_tr_arr[:,-1])plt.xlabel("# image")plt.ylabel("NormRel_L2")plt.show()Store recovered values to .csvdf_out=pd.DataFrame(rad_rot_tr_arr,index=fnames,columns=["tr_x","tr_y","tr_err","rot","rot_err","NormRel_L2",],)df_out.to_csv(f"radon-{step}.csv")df_outtr_xtr_ytr_errrotrot_errNormRel_L2test00001.jpg-26.450947.32580.405569-20.55560.2828430.41641test00011.jpg-26.333947.15610.405386-20.55560.2828430.415555test00021.jpg-26.234447.03320.405536-20.55560.2828430.415513test00031.jpg-22.807142.62370.385188-18.44440.2828430.396469test00041.jpg-18.496136.56840.366198-160.2828430.379106test00051.jpg-14.705630.91440.343007-13.55560.2828430.35666test00061.jpg-11.76825.85130.316403-11.24690.2828430.329185test00071.jpg-8.6682720.36340.288842-8.802470.2828430.300223test00081.jpg-6.0293815.06850.258316-6.444440.2828430.267387test00091.jpg-3.509239.327930.220809-40.2828430.227255test00101.jpg-1.195963.518830.172761-1.555560.2828430.175223test00111.jpg0.575633-1.857730.1290570.7530860.2828430.126313test00121.jpg2.41049-7.946830.1671343.197530.2828430.16156test00131.jpg3.81275-13.22140.2008975.444440.2828430.198397test00141.jpg5.16611-19.40110.2341467.950620.2828430.240847test00151.jpg6.11063-24.77320.26457610.19750.2828430.289057test00161.jpg6.97132-31.26010.2912112.75310.2828430.335311test00171.jpg7.47346-36.63250.317422150.2828430.387218test00181.jpg7.68796-41.72070.34348170.2828430.426283test00191.jpg7.70654-41.8310.345591170.2828430.42826test00201.jpg7.69192-41.87880.349477170.2828430.4287test00211.jpg7.65427-39.26520.33876715.95060.2828430.405673test00221.jpg7.37055-33.8220.32586913.75310.2828430.370918test00231.jpg7.39534-33.9310.32703413.75310.2828430.372402test00241.jpg7.38345-33.97950.3301413.75310.2828430.375312test00251.jpg7.11119-31.54810.32118812.75310.2828430.357117Load the recovered values from .csvdf_in=pd.read_csv(f"radon-{step}.csv",index_col=0,sep=",")rad_rot_tr_arr=df_in.to_numpy()fnames=df_in.indexIf desired an offset can be applied to a column of the data for plotting:rad_rot_tr_arr[:,3]-=15plt.plot(rad_rot_tr_arr[:,3])plt.xlabel("# image")plt.ylabel("angle")plt.show()Save the reconstructed imagesFinally the table of reconstructed parameters can be used to save the backtransformed images.image_save_back_tf(rad_rot_tr_arr,fnames,image_path_src,image_path_dest)A word on the modelsThe implemented models differ in some of the internal parameters. As the construction of a model also defines the dependency tree of its parameters, we can display a representation of the dependency tree as follows for every model (shown for the RadonSolver):fromimgreg.models.radonimportRadonSolverras=RadonSolver()ras.dot_graph()TutorialsFurther interactive examples are available asjupyter-notebooksindoc/tutorial.DocumentationThe API documentation can either be viewedonlineor be generated using Sphinx withnumpydocformatting. To build, run:sphinx-build-bhtmldoc/doc/_build/htmlTestingTesting is done usingpytest. Withpytest-covandcoveragea report for the tests can be generated with:pytest--cov=imgreg/tests/
coveragehtmlTo test the examples in the documentation run:pytest--doctest-modulesimgreg/LicenseThis software is published under theGPLv3 license.