Reputation: 1219
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 points in Python server, and save the cropped image? I am currently using PIL, and would prefer a PIL or PIL extended solution.
Thanks in advance
Upvotes: 15
Views: 21516
Reputation: 1
This is how I did it:
def crop_region(filename):
im = open(filename, 'rb')
region = [(100,100),(1000,100),(1000,800),(100,800)]
arr = np.array(region)
(X, Y, W, H) = cv2.boundingRect(arr)
new_im = im.crop([X, Y, X + W,Y + H])
new_im.save("image.png", 'PNG') ````
Upvotes: 0
Reputation: 71
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")
Upvotes: 7
Reputation: 11
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")
Upvotes: 1
Reputation: 1219
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")
Upvotes: 32