Introduction
With the last step we know where the bottom edges of the pawn are located on the image, we just need to find a way to transform the coordinates of those pixels into game field coordinates.
Given a point $p' $ from the Image plane, we’d like to transform it into $ p$ from the Game field plane. We can write:
$ p = H \cdot p'$
We observe that straight lines are kept straight, thus H is called the homography matrix which can be computed if at least 4 different matching points are given for both planes. $ (p1 \leftrightarrow p1', p2 \leftrightarrow p2', p3 \leftrightarrow p3', p4 \leftrightarrow p4')$
It’s worth noticing that both $ p$ and $ p'$ points are given in homogeneus coordinates.
Algorithm and code

 In order to compute H, the homography matrix. We use the ready to use openCV’s function: findHomography.
// Create a column vector with the coordinates of each point (on the field plane)
cv::Mat xField;
xField.create(4, 1, CV_32FC2);
xField.at<Point2f>(0) = ( cv::Point2f(x1, y1) );
xField.at<Point2f>(1) = ( cv::Point2f(x2, y2) );
xField.at<Point2f>(2) = ( cv::Point2f(x3, y3) );
xField.at<Point2f>(3) = ( cv::Point2f(x4, y4) );
// same thing for xImage but with the pixel coordinates instead of the field coordinates, same order as in xField
cv::Mat xImage;
xImage.at<Point2f>(0) = ( cv::Point2f(x1_bis, y1_bis) );
...
// Compute the homography matrix
cv::Mat H = cv::findHomography( xImage, xField );

 Whenever we want to find the coordinates of a point on the game field, given a pixel $ p'(x,y)$ on an image. We only need to transform $ p'$ into $ p$:
// pImage = p'(x,y)
// pImage is in the projective plane
cv::Mat pImage = (cv::Mat_(3,1) << x, y, 1);
cv::Mat pField = H * pImage;
// pField is in the projective plane (homogeneous coordinates): (X, Y, W). Transform it back to the euclidean plane: (X', Y', 1)
pField /= pField.at(2);
// p(xField, yField) represent the same point as p'(x, y) but in different planes.
double xField = pField.at(0);
double yField = pField.at(1);
Optimizations
Because (2) is used really often we can avoid doing matrix products during run time by precalculating all possible transformations of the image. All game field points corresponding to every pixel of the image are computed in advance and saved into an bidimensional array for efficient access. To correlate $ p'$ to $ p$ we do:
p = pixelsToMeters.at(p')
Just for fun
Using the pixelsToMeters array we can print the area the camera sees of the field:
What’s next
You guessed right we now have the full ‘toolkit’ to precisely link pawns on the image to their positions on the game field plane. How to do it is the subject of the next post.