I need to align two (actually hundreds of) images and I'm at a loss on how to do that in Python with OpenCV (which I have never heard of before). It looks like I should first estimate the transformation to apply as follows, and then apply it to one of the image (rinse and repeat hundreds of times). However even the simplest
import cv2
img1 = cv2.imread("img1.jpg", cv2.IMREAD_COLOR)
img2 = cv2.imread("img2.jpg", cv2.IMREAD_COLOR)
cv2.estimateAffinePartial2D(img1, img2)
fails with
cv2.error: OpenCV(4.9.0) /io/opencv/modules/calib3d/src/ptsetreg.cpp:1108: error: (-215:Assertion failed) count >= 0 && to.checkVector(2) == count in function 'estimateAffinePartial2D'
Stack overflow and OpenCV forum has a few questions about this problem but no solution, other than the one mentioned at OpenCV estimateAffine3D failes with cryptic error message (which is even more cryptic than the error message itself).
How to do that estimation in Python?
EDIT:
$ python
Python 3.8.18 (default, Aug 25 2023, 13:20:30)
[GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.9.0'
Fixing this in OpenCV is more work than I wanted. Probably after that effort it could always work well, but it's a steep curve and for my purpose I wanted something quick-and-dirty.
A simpler solution (which might or might not work depending on the images to align, with mine it worked about 60% of the times, which was good enough) is to use https://diplib.org/PyDIP.html or https://github.com/keflavich/image_registration as follows:
from image_registration import chi2_shift
from image_registration.fft_tools import shift
xoff, yoff, exoff, eyoff = chi2_shift(img1, img2)
moved_img = shift.shiftnd(img2, (-yoff, -xoff))
or
import diplib as dip
matrix = dip.FourierMellinMatch2D(img1, img2, out=out, correlationMethod="don't normalize")
moved_img = dip.Image()
dip.AffineTransform(img2, out=moved_img, matrix=matrix)
A minor nuisance for both is that the images must be monochrome and nparray-like