简体   繁体   English

如何在 Python PIL(枕头)中计算特定点的位置?

[英]How can I compute the location of a specific point after a mesh transformation in Python PIL (Pillow)?

If I transform image using:如果我使用以下方法转换图像:

This code was taken from here: https://stackoverflow.com/a/37350619/259757此代码取自此处: https://stackoverflow.com/a/37350619/259757

im_transformed = im.transform(im.size, Image.MESH, mesh)

Given a specific coordinate (x,y) from my original image how can I compute what the new coordinates would be in im_transformed?给定原始图像中的特定坐标 (x,y),我如何计算 im_transformed 中的新坐标? Basically could I apply the same transformation to a specific single point like is possible with affine transformations?基本上我可以像仿射变换一样将相同的变换应用于特定的单点吗?

My reason for wanting to do this is that lets say I have the location known of a smily face in the image.我想要这样做的原因是,可以说我知道图像中一张笑脸的位置。 In the second image that has been transformed/warped I want to make a prediction where where that smily face is and compare the prediction to where it should be.在已经转换/扭曲的第二张图像中,我想预测那个笑脸在哪里,并将预测与它应该在哪里进行比较。 I know its not exact but the idea is that I can generate clean image with known locations of smily face, warp them and have a new location in x,y where the smily face should be in the warped image.我知道它不准确,但我的想法是我可以生成具有已知位置的笑脸的干净图像,扭曲它们并在 x,y 中有一个新位置,笑脸应该在扭曲的图像中。 This will allow me to generate training data for a machine learning model.这将允许我为机器学习 model 生成训练数据。

With an affine transformation this is pretty straightforward but with a mesh transformation I do not know how to do this.对于仿射变换,这非常简单,但对于网格变换,我不知道该怎么做。

So after a little digging in PIL code this is what i could find:因此,在对 PIL 代码进行了一些挖掘之后,这就是我能找到的:

A MESH transform is just a multiple application of QUAD transforms. MESH 变换只是 QUAD 变换的多重应用。

Each QUAD transform maps a quadrilateral in the source image to a rectangle in the destination.每个 QUAD 变换将源图像中的四边形映射到目标图像中的矩形。

So lets see what a QUAD transform is: PIL quad transform那么让我们看看什么是 QUAD 变换: PIL quad transform

   quad_transform(double* xin, double* yin, int x, int y, void* data) {

    double* a = (double*) data;
    double a0 = a[0]; double a1 = a[1]; double a2 = a[2]; double a3 = a[3];
    double a4 = a[4]; double a5 = a[5]; double a6 = a[6]; double a7 = a[7];

    xin[0] = a0 + a1*x + a2*y + a3*x*y;
    yin[0] = a4 + a5*x + a6*y + a7*x*y;

    return 1;
}

This is an inverse mapping that tells how to sample a point in the source image to get the pixel in the location xin,yin in the target image.这是一个逆映射,它告诉如何对源图像中的一个点进行采样以获得目标图像中位置 xin,yin 的像素。

The parameters are calculated in the following way and i rewrote it so it looks nicer:参数是按以下方式计算的,我重写了它,使它看起来更好:

def get_parameters(rectangle, quadrilateral):
 w = rectangle[2] - rectangle[0]
 h = rectangle[3] - rectangle[1]

 nw = quadrilateral[0:2]  # The quadrilateral coordinates
 sw = quadrilateral[2:4]  # The quadrilateral coordinates
 se = quadrilateral[4:6]  # The quadrilateral coordinates
 ne = quadrilateral[6:8]  # The quadrilateral coordinates
 x0, y0 = nw
 As = 1.0 / w
 At = 1.0 / h
 parameters = (
    x0,  # a0
    (ne[0] - x0) * As,  # a1,
    (sw[0] - x0) * At,  # a2
    (se[0] - sw[0] - ne[0] + x0) * As * At,  # a3
    y0,  # a4
    (ne[1] - y0) * As,  # a5
    (sw[1] - y0) * At,  # a6
    (se[1] - sw[1] - ne[1] + y0) * As * At,  # a7
 )
 return parameters

The problem is that you want the transformation from the point in the QUAD to the resulted point in the rectangle.问题是您希望将 QUAD 中的点转换为矩形中的结果点。

So you need to solve the following equations for x and y (not for x_rect and y_rect:!!!):因此,您需要为 x 和 y 求解以下方程(不适用于 x_rect 和 y_rect:!!!):

x_rect = a0 + a1*x + a2*y + a3*x*y;
y_rect = a4 + a5*x + a6*y + a7*x*y;

This inversion is not the nicest and gives you a quadratic equation in x and y so you will need to decide which solution to take according to the resulting coordinates.这种反演不是最好的,它会为您提供 x 和 y 的二次方程,因此您需要根据结果坐标决定采用哪种解决方案。

For a full explanation please look at Answer有关完整说明,请查看答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM