Polygon crop/clip using Python / PIL

前端 未结 3 1050
南方客
南方客 2020-12-15 13:34

The polygon points along with the uncut, original image are sent by client to the server.

Is there a way that I can clip (crop) the original image along these point

相关标签:
3条回答
  • 2020-12-15 13:53

    I did this code to clip an area of an image defined by a polygon.

    from PIL import Image, ImageDraw
    
    original = Image.open("original.jpg")
    xy = [(100,100),(1000,100),(1000,800),(100,800)]
    mask = Image.new("L", original.size, 0)
    draw = ImageDraw.Draw(mask)
    draw.polygon(xy, fill=255, outline=None)
    black =  Image.new("L", original.size, 0)
    result = Image.composite(original, black, mask)
    result.save("result.jpg")
    
    0 讨论(0)
  • 2020-12-15 13:55

    Another solution based on @user2667409 's answer,
    it uses 1 bit per element to represent the mask, and exports the final result into JPEG format.

    import numpy
    from PIL import Image, ImageDraw
    
    # read image as RGB (without alpha)
    img = Image.open("crop.jpg").convert("RGB")
    
    # convert to numpy (for convenience)
    img_array = numpy.asarray(img)
    
    # create mask
    polygon = [(444,203),(623,243),(691,177),(581,26),(482,42)]
    
    # create new image ("1-bit pixels, black and white", (width, height), "default color")
    mask_img = Image.new('1', (img_array.shape[1], img_array.shape[0]), 0)
    
    ImageDraw.Draw(mask_img).polygon(polygon, outline=1, fill=1)
    mask = numpy.array(mask_img)
    
    # assemble new image (uint8: 0-255)
    new_img_array = numpy.empty(img_array.shape, dtype='uint8')
    
    # copy color values (RGB)
    new_img_array[:,:,:3] = img_array[:,:,:3]
    
    # filtering image by mask
    new_img_array[:,:,0] = new_img_array[:,:,0] * mask
    new_img_array[:,:,1] = new_img_array[:,:,1] * mask
    new_img_array[:,:,2] = new_img_array[:,:,2] * mask
    
    # back to Image from numpy
    newIm = Image.fromarray(new_img_array, "RGB")
    newIm.save("out.jpg")
    
    0 讨论(0)
  • 2020-12-15 14:09

    I found a solution using numpy and PIL- so thought I will share:

    import numpy
    from PIL import Image, ImageDraw
    
    # read image as RGB and add alpha (transparency)
    im = Image.open("crop.jpg").convert("RGBA")
    
    # convert to numpy (for convenience)
    imArray = numpy.asarray(im)
    
    # create mask
    polygon = [(444,203),(623,243),(691,177),(581,26),(482,42)]
    maskIm = Image.new('L', (imArray.shape[1], imArray.shape[0]), 0)
    ImageDraw.Draw(maskIm).polygon(polygon, outline=1, fill=1)
    mask = numpy.array(maskIm)
    
    # assemble new image (uint8: 0-255)
    newImArray = numpy.empty(imArray.shape,dtype='uint8')
    
    # colors (three first columns, RGB)
    newImArray[:,:,:3] = imArray[:,:,:3]
    
    # transparency (4th column)
    newImArray[:,:,3] = mask*255
    
    # back to Image from numpy
    newIm = Image.fromarray(newImArray, "RGBA")
    newIm.save("out.png")
    
    0 讨论(0)
提交回复
热议问题