是否有一个用于图像变形/图像变形的库,用于控制点的python?

时间:2011-02-21 20:45:12

标签: python image-processing image-manipulation

您将拍摄图像并标记特定点(例如,标记人眼睛,鼻子,嘴巴等周围的区域),然后将它们转换为标记为另一图像的点。类似的东西:

transform(original_image, marked_points_in_the_original, marked_points_in_the_reference)

我似乎找不到描述它的算法,也找不到任何库。我也愿意自己做,只要我能找到好的/易于遵循的材料。我知道这是可能的,因为我已经看到一些不完整的(不能真正解释如何做到这一点).pdfs在谷歌与它。

以下是标记点和转换的示例,因为您要求澄清。虽然我之前说的这个没有使用2个人。


编辑:我设法使im.transform方法有效,但参数是((box_x, box_y, box_width, box_height), (x0, y0, x1, y1, x2, y2, x3, y3))的列表,第一个点是NW,第二个SW,第三个NE和第四个SE。据我所知,(0,0)是屏幕最左上角。如果我做的一切都正确,那么这种方法并不能真正做到我所需要的。

3 个答案:

答案 0 :(得分:8)

Blender提供的示例代码对我不起作用。此外,im.transform的PIL文档含糊不清。所以我深入研究PIL源代码,最后弄清楚如何使用该接口。这是我的完整用法:

import numpy as np
from PIL import Image

def quad_as_rect(quad):
    if quad[0] != quad[2]: return False
    if quad[1] != quad[7]: return False
    if quad[4] != quad[6]: return False
    if quad[3] != quad[5]: return False
    return True

def quad_to_rect(quad):
    assert(len(quad) == 8)
    assert(quad_as_rect(quad))
    return (quad[0], quad[1], quad[4], quad[3])

def rect_to_quad(rect):
    assert(len(rect) == 4)
    return (rect[0], rect[1], rect[0], rect[3], rect[2], rect[3], rect[2], rect[1])

def shape_to_rect(shape):
    assert(len(shape) == 2)
    return (0, 0, shape[0], shape[1])

def griddify(rect, w_div, h_div):
    w = rect[2] - rect[0]
    h = rect[3] - rect[1]
    x_step = w / float(w_div)
    y_step = h / float(h_div)
    y = rect[1]
    grid_vertex_matrix = []
    for _ in range(h_div + 1):
        grid_vertex_matrix.append([])
        x = rect[0]
        for _ in range(w_div + 1):
            grid_vertex_matrix[-1].append([int(x), int(y)])
            x += x_step
        y += y_step
    grid = np.array(grid_vertex_matrix)
    return grid

def distort_grid(org_grid, max_shift):
    new_grid = np.copy(org_grid)
    x_min = np.min(new_grid[:, :, 0])
    y_min = np.min(new_grid[:, :, 1])
    x_max = np.max(new_grid[:, :, 0])
    y_max = np.max(new_grid[:, :, 1])
    new_grid += np.random.randint(- max_shift, max_shift + 1, new_grid.shape)
    new_grid[:, :, 0] = np.maximum(x_min, new_grid[:, :, 0])
    new_grid[:, :, 1] = np.maximum(y_min, new_grid[:, :, 1])
    new_grid[:, :, 0] = np.minimum(x_max, new_grid[:, :, 0])
    new_grid[:, :, 1] = np.minimum(y_max, new_grid[:, :, 1])
    return new_grid

def grid_to_mesh(src_grid, dst_grid):
    assert(src_grid.shape == dst_grid.shape)
    mesh = []
    for i in range(src_grid.shape[0] - 1):
        for j in range(src_grid.shape[1] - 1):
            src_quad = [src_grid[i    , j    , 0], src_grid[i    , j    , 1],
                        src_grid[i + 1, j    , 0], src_grid[i + 1, j    , 1],
                        src_grid[i + 1, j + 1, 0], src_grid[i + 1, j + 1, 1],
                        src_grid[i    , j + 1, 0], src_grid[i    , j + 1, 1]]
            dst_quad = [dst_grid[i    , j    , 0], dst_grid[i    , j    , 1],
                        dst_grid[i + 1, j    , 0], dst_grid[i + 1, j    , 1],
                        dst_grid[i + 1, j + 1, 0], dst_grid[i + 1, j + 1, 1],
                        dst_grid[i    , j + 1, 0], dst_grid[i    , j + 1, 1]]
            dst_rect = quad_to_rect(dst_quad)
            mesh.append([dst_rect, src_quad])
    return mesh

im = Image.open('./old_driver/data/train/c0/img_292.jpg')
dst_grid = griddify(shape_to_rect(im.size), 4, 4)
src_grid = distort_grid(dst_grid, 50)
mesh = grid_to_mesh(src_grid, dst_grid)
im = im.transform(im.size, Image.MESH, mesh)
im.show()

在: enter image description here 后: enter image description here

我建议在iPython中执行上面的代码然后打印出mesh以了解im.transform需要什么样的输入。对我来说输出是:

In [1]: mesh
Out[1]:
[[(0, 0, 160, 120), [0, 29, 29, 102, 186, 120, 146, 0]],
 [(160, 0, 320, 120), [146, 0, 186, 120, 327, 127, 298, 48]],
 [(320, 0, 480, 120), [298, 48, 327, 127, 463, 77, 492, 26]],
 [(480, 0, 640, 120), [492, 26, 463, 77, 640, 80, 605, 0]],
 [(0, 120, 160, 240), [29, 102, 9, 241, 162, 245, 186, 120]],
 [(160, 120, 320, 240), [186, 120, 162, 245, 339, 214, 327, 127]],
 [(320, 120, 480, 240), [327, 127, 339, 214, 513, 284, 463, 77]],
 [(480, 120, 640, 240), [463, 77, 513, 284, 607, 194, 640, 80]],
 [(0, 240, 160, 360), [9, 241, 27, 364, 202, 365, 162, 245]],
 [(160, 240, 320, 360), [162, 245, 202, 365, 363, 315, 339, 214]],
 [(320, 240, 480, 360), [339, 214, 363, 315, 453, 373, 513, 284]],
 [(480, 240, 640, 360), [513, 284, 453, 373, 640, 319, 607, 194]],
 [(0, 360, 160, 480), [27, 364, 33, 478, 133, 480, 202, 365]],
 [(160, 360, 320, 480), [202, 365, 133, 480, 275, 480, 363, 315]],
 [(320, 360, 480, 480), [363, 315, 275, 480, 434, 469, 453, 373]],
 [(480, 360, 640, 480), [453, 373, 434, 469, 640, 462, 640, 319]]]

答案 1 :(得分:7)

在类似的说明中,您可以使用ImageMagick的Python API执行Shepards's Distortion

koala ears koala ears pull

答案 2 :(得分:5)

是的,有。它有点低级,但PIL(Python Imaging Library)具有执行此类转换的功能。我从来没有真正为它工作(因为我的问题有点简单),但你可以玩它。

这是PIL转换的一个很好的资源(你想看 MESH ):http://effbot.org/tag/PIL.Image.Image.transform


来自文档:

  
    

与QUAD类似,但数据是目标矩形和相应的源四边形的列表。

  
im.transform(size, MESH, data)

数据是矩形的元组:

data = [((a, b, c, d), (e, f, g, h)), 
        ((i, j, k, l), (m, n, o, p))]

它将第一个矩形转换为第二个矩形。