# ImageTransformation and corresponding points

I have identified a list of corresponding points on two different images manually. I have found the geometrical transformation between such sets of points using FindGeometricTransform and I would now like to transform one of my images according to such transformation. When I do so, however, Mathematica gives me a completely black image and I don't understand how to get the first image transformed.

Here are the images:

I import them with:

i10 = Import["https://i.stack.imgur.com/cdx00.jpg"];
i15 = Import["https://i.stack.imgur.com/XApmx.jpg"];


The lists of corresponding points are:

pts10 = {{1934.77615025538,
1576.1190734112033}, {2058.4519305241565,
1405.2746195470152}, {1594.8656770702503,
1522.0661370677385}, {1717.5432392405596,
1641.0491448965918}};

pts15 = {{1821.159315341623,
2432.200159743154}, {1935.081765338483,
2254.0263438834454}, {1476.992138438835,
2391.701747362471}, {1604.3856168362227, 2505.453543001129}};


This command finds the transformation:

f = FindGeometricTransform[pts15, pts10, TransformationClass -> "Rigid"][]


The following command, however, gives a black image:

ImageTransformation[i10, f]


Am I doing something wrong? Thanks

• I think the major point can be found in the details section of ImageTransformation: "In 2D, the range of the coordinate system for the input image is assumed to be {{0,1},{0,a}}, where a is the aspect ratio. The bottom-left corner of the image corresponds to coordinates {0,0} by default." So while you found the transformation in pixel coordinates, ImageTransformation works as if a squared image (of any size) is in [0,1]^2. – halirutan Aug 16 '17 at 3:38
• That being said, you see a black image, because your transformation doesn't move the image a tiny bit like you assume. It moves the image way out of the region where you could see anything leaving only the black background that is filled in. – halirutan Aug 16 '17 at 3:39
• I suspect this question is a duplicate. In any case @sjoerd's solution is a great resource if you plan on performing this function regularly. – bobthechemist Sep 16 '17 at 21:45

I get different corresponding points when evaluating: pts=ImageCorrespondingPoints[i10,i15]? See: MapThread[HighlightImage[#1, #2] &, {{i10, i15}, ImageCorrespondingPoints[i10, i15]}].

You probably selected them manually? Since you are working with pixel positions I would propose that you display a plot of the coordinates, e.g. of pts10, pts15 and transformed data of pts10.

pts10 = {{1934.77615025538,
1576.1190734112033}, {2058.4519305241565,
1405.2746195470152}, {1594.8656770702503,
1522.0661370677385}, {1717.5432392405596,
1641.0491448965918}};

pts15 = {{1821.159315341623,
2432.200159743154}, {1935.081765338483,
2254.0263438834454}, {1476.992138438835,
2391.701747362471}, {1604.3856168362227, 2505.453543001129}};


I use here for demonstration TransformationClass -> "Translation":

{e, t} = FindGeometricTransform[pts15, pts10, TransformationClass -> "Translation"];

transformedData = t[pts10]

(* {{1818.89,2430.52},{1934.78,2254.31},{1476.9,2391.75},{1604.78,2505.12}} *)

symbolPlus = Graphics[{Blue, Line[{{{-1, 0}, {1, 0}}, {{0, -1}, {0, 1}}}]}];
symbolCross = Graphics[{Line[{{{-1, -1}, {1, 1}}, {{-1, 1}, {1, -1}}}]}];

ListPlot[{pts10, transformedData, pts15},
PlotMarkers -> {{symbolPlus, 0.04}, {symbolCross, 0.04}, {symbolCross, 0.04}}, Frame -> True,
PlotStyle -> {Blue, Red, Green}, FrameLabel -> {{"y (pixels)", ""}, {"x (pixels)", ""}},
BaseStyle -> {FontWeight -> "Bold", FontSize -> 15, FontFamily -> "Calibri"}, ImageSize -> 600,
AspectRatio -> Automatic, PlotRange -> {{1400, 2100}, {1300, 2600}}] When I use another TransformationClass then the transformed data of pts10 (red) and the data pts15 (green) fit nearly exactly on top of each other. The blue plus signs correspond to the orginal points pts10.

Assuming that corresponding points are found correctly, you may still see black image because transformed image is out of frame of original image. To fix that, I suggest adding following options:

ImageTransformation[i10, f, DataRange -> Full, PlotRange -> All]


This should ensure that no data points are lost and field of view covers them all.