8

I have two PIL images and two sets of corresponding 2D points that make a triangle.

For example:

image1:
100x100 pixels
points = [(10,10), (20,20), (10,20)]

image2:
250x250 pixels
points = [(35,30), (75,19), (50,90)]

I want to copy the triangular region from image1 and transform it to fit into the corresponding triangular region of image2. Is there any way to do this with PIL without having to copy pixel by pixel and calculate the transformation myself?

4

2 に答える 2

6

アフィン変換でこれを行うことができました(この質問のおかげです)。アフィン変換後、目的の三角形がマスクに描画され、目的の画像に貼り付けられます。これが私が思いついたものです:

import Image
import ImageDraw
import numpy

def transformblit(src_tri, dst_tri, src_img, dst_img):
    ((x11,x12), (x21,x22), (x31,x32)) = src_tri
    ((y11,y12), (y21,y22), (y31,y32)) = dst_tri

    M = numpy.array([
                     [y11, y12, 1, 0, 0, 0],
                     [y21, y22, 1, 0, 0, 0],
                     [y31, y32, 1, 0, 0, 0],
                     [0, 0, 0, y11, y12, 1],
                     [0, 0, 0, y21, y22, 1],
                     [0, 0, 0, y31, y32, 1]
                ])

    y = numpy.array([x11, x21, x31, x12, x22, x32])

    A = numpy.linalg.solve(M, y)

    src_copy = src_img.copy()
    srcdraw = ImageDraw.Draw(src_copy)
    srcdraw.polygon(src_tri)
    src_copy.show()
    transformed = src_img.transform(dst_img.size, Image.AFFINE, A)

    mask = Image.new('1', dst_img.size)
    maskdraw = ImageDraw.Draw(mask)
    maskdraw.polygon(dst_tri, fill=255)

    dstdraw = ImageDraw.Draw(dst_img)
    dstdraw.polygon(dst_tri, fill=(255,255,255))
    dst_img.show()
    dst_img.paste(transformed, mask=mask)
    dst_img.show()


im100 = Image.open('test100.jpg')
im250 = Image.open('test250.jpg')

tri1 = [(10,10), (20,20), (10,20)]
tri2 = [(35,30), (75,19), (50,90)]

transformblit(tri1, tri2, im100, im250)

ソースの 100x100 画像は次のようになります (白で覆われた三角形)。

src_before

宛先の 250x250 画像は次のようになります (白で塗りつぶされた三角形の領域)。

dst_before

そして、変換と貼り付けの後、目的の画像は次のようになります。

dst_after

于 2011-08-05T15:53:38.537 に答える
0

編集済み

この戦略にはまだピクセル操作が含まれますが、API をある程度活用できます。

  1. ソース画像を RGBA に変換します。
  2. 三角形を囲む最小の四角形を見つけます。
  3. 三角形の一部ではなく、長方形内のすべてのピクセルを手動で完全に透明に設定します。(x/y 値のセットと を使用すると、それほど問題なくこれを実行できる場合がmapありpartialます。)
  4. ターゲット イメージ内の三角形を囲む最小の四角形を見つけます。
  5. ソースを囲む四角形をターゲット サイズにスケーリングして、四角形をターゲット イメージにコピーします。
于 2011-08-04T22:07:56.923 に答える