python - 是否有用于带有受控点的 python 图像变形/图像变形的库?

标签 python image-processing image-manipulation

<分区>

您会拍摄图像并标记特定点(例如,标记人的眼睛、 Nose 、嘴巴等周围的区域),然后将它们转换为标记到另一幅图像中的点。像这样的东西:

transform(original_image, marked_points_in_the_original, marked_points_in_the_reference)

我似乎找不到描述它的算法,也找不到任何库。我也愿意自己做,只要我能找到好的/易于理解的 Material 即可。我知道这是可能的,因为我在谷歌上看到了一些不完整的(没有真正解释如何去做).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) 是屏幕最左上角的部分。如果我做的一切都正确,那么这个方法并不能真正满足我的需要。

最佳答案

Blender 提供的示例代码对我不起作用。此外,im.transform 的 PIL 文档含糊不清。所以我深入研究了PIL源代码,终于弄清楚了接口(interface)的使用方法。这是我的完整用法:

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]]]

关于python - 是否有用于带有受控点的 python 图像变形/图像变形的库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5071063/

相关文章:

node.js - 在 Nodejs 中使用 gm 调整大小并合成两个或多个图像

python - Python OpenCV-如何删除窗口边框和标题

python - 为什么将 import 语句放在函数内部并不常见?

android - 我如何根据十六进制颜色代码给出颜色名称?

image-processing - 棕褐色调是如何产生的?

javascript - 简单的基于网络的图标编辑器

python - 在 value_counts pandas 分类数据中包含零

python - 所有行都期望第 0 行

matlab - 如何在 Matlab 中以堆栈样式绘制多个 2D 图像?

PHP Imagick setImageOpacity 破坏透明度什么都不做