There is a code that, in principle, works:

from PIL import Image, ImageOps, ImageDraw im = Image.open('image.png') size = (200, 200) # размер итогового портрета # маска mask = Image.new('L', size, 0) draw = ImageDraw.Draw(mask) draw.ellipse((0, 0) + size, fill=255) im = im.resize(size) output = ImageOps.fit(im, mask.size, centering=(0.5, 0.5)) output.putalpha(mask) output.thumbnail(size, Image.ANTIALIAS) output.save('image_output.png') 

The result is enter image description here

As you can see, a round image is obtained, but the proportions are distorted. How to get a round portrait based on the original image, but with normal proportions?

  • Maybe use im.crop instead of im.resize ? - Surfin Bird
  • The problem is that crop, for example (100, 100) on one image will give a circle, and the image of a different size will cut only the corners. - Xyanight

1 answer 1

I meant something like this:

 from PIL import Image, ImageDraw # Подготавливает маску, рисуя её в <antialias> раз больше и # затем уменьшая, чтобы получилось сглаженно. def prepare_mask(size, antialias = 2): mask = Image.new('L', (size[0] * antialias, size[1] * antialias), 0) ImageDraw.Draw(mask).ellipse((0, 0) + mask.size, fill=255) return mask.resize(size, Image.ANTIALIAS) # Обрезает и масштабирует изображение под заданный размер. # Вообще, немногим отличается от .thumbnail, но по крайней мере # у меня результат получается куда лучше. def crop(im, s): w, h = im.size k = w / s[0] - h / s[1] if k > 0: im = im.crop(((w - h) / 2, 0, (w + h) / 2, h)) elif k < 0: im = im.crop((0, (h - w) / 2, w, (h + w) / 2)) return im.resize(s, Image.ANTIALIAS) size = (200, 200) im = Image.open('image.png') im = crop(im, size) im.putalpha(prepare_mask(size, 4)) im.save('image_output.png') 

Result ( original , with .thumbnail instead of crop ):

Result

  • This is the same. Proportions are distorted. As I understand it, here you need to put a mask with a finished alpha-frame on the original image so that everything that is behind the round frame of the mask is in the alpha channel. - Xyanight
  • Where are they distorted, then? I, at least, everything is clear . - Surfin Bird
  • You have everything clearly because you have the same height and width of the image. That is, you have it square. Take for example an image of 600x300 and see the result. - Xyanight
  • I specifically made it clearer, look at image_grid.png in the screenshot. The size is 481 × 261. In the cropped version, the squares remain squares. And the cat is not square (for comparison, here is your code , do you really not see the difference?). And in general, just look at the contents of crop() , you can see how the proportions are preserved. :) - Surfin Bird
  • Here is the result of your example - habrastorage.org/files/fb5/8da/55a/… - Xyanight