SoFunction
Updated on 2024-10-28

Making music posters with Python

preamble

Some time ago in a friend then get the inspiration to think can be used as a music play page as a poster image. In fact, the next to talk about and the poster is still a gap, and the specific realization is just a simple picture paste, but the effect is still good. The effect is as follows, I hope you like:

The left side is the original image, the right side is the figure that needs to be added to the center and the main character of the figure. In fact, if the direct use of ps to achieve the above figure is very simple, on the contrary, with the code to achieve a little twisted, but the realization process is still very interesting, I hope this blog can be can let you learn knowledge.

Creating Circular Charts with Pillow

In the above image, the center is a round image, and Pillow itself does not provide a method to generate a round image (or maybe I didn't find it), so you need to implement it yourself. Before we do that, let's install the Pillow module:

pip install pillow

To create a circular image, we first create a transparency in RGBA mode based on the size of the original image:

# The method is passed three parameters, the first is the mode, the second is a tuple of sizes, and the third is a color
im = ('RGBA', (300, 300), (255, 255, 255, 0))

The above code is creating a fully transparent 300*300 image on which we draw a maximum circle:

# Get the drawer
drawer = (im)
# Draw a yellow circle, the ellipse method passes three parameters, the first is the area of the smallest square that contains the circle, the second is the color, and the third is the width of the sides
((0, 0, 300, 300), fill=(255, 255, 0), width=0)

Generate the image below:

We prepare a 300*300 square image and iterate through each pixel of the image, if the pixel value of A==0 (i.e., the pixel is not transparent) then we set the pixel value of that area of the image to be transparent.

The code is as follows:

# Open the image to be converted into a circle, we crop the image beforehand
pic = (img_path).convert('RGBA')
# Iterate over each pixel of the image
for i in range(300):
  for j in range(300):
    # Get the pixels of this pixel point
     r, g, b, a = ((i, j))
    # When the rgb value is not yellow, i.e. when the pixel value is transparent
    if (r, g, b) != (255, 255, 0):
      # Set the pixel values of the original image to transparent
      ((i, j), (255, 255, 255, 0))

Our pic is the round image, the full code is as follows:

# Diameter of the circle in the background image
radius = 533
# Size of the picture
circle_size = (radius, radius)
def generate_circle_image(img_path):
  # Create a transparent square
  im = ('RGBA', circle_size, (255, 255, 255, 0))
  # Get the painter
  drawer = (im)
  # Draw a yellow circle on a transparent square #
  ((0, 0, circle_size[0], circle_size[1]), fill=(255, 255, 0), width=0)
  # Open the image to be converted into a circle, we crop the image beforehand
  pic = (img_path).convert('RGBA')
  # Modify the image size so that the image is the same size as the circle
  re_pic = (circle_size, )
  # Iterate over each pixel of the image
  for i in range(circle_size[0]):
    for j in range(circle_size[1]):
      r, g, b, a = ((i, j))
      if (r, g, b) != (255, 255, 0):
        re_pic.putpixel((i, j), (255, 255, 255, 0))
  return re_pic

In the above method, we have improved the code a bit, before we need to use the specified size of the image as the material, now it only needs to be a square image.

Generate Poster

Originally I thought I could just paste the circular image directly onto the background image, but after trying it, I realized that the effect was not quite what I thought it would be, anyway, it just didn't work, and the effect is as follows:

It's pasted on yes, and the image is transparent, but from this effect it looks like the paste is just a pixel replacement, not an image overlay. So I came up with the idea of traversing the pixels again.

I got the pixels from the left side of the square above, and the pixels from the top side by special means (actually looked at them with ps). I tried graphical detection and pixel determination to automatically identify the position of the middle circle, but it didn't work well (it just failed anyway), so I had to shamelessly look at the pixels with ps.

Back to the point, we don't need to traverse the whole image with the traversing pixels approach, we just need to start from (left, top) pixels and traverse to the (left+radius, top+radius) area, which means traversing the square area (left, top and radius are all what I got via ps).

We first make a copy of the background image and paste it on the copy. Then traverse the pasted image, if the pixel value is transparent, we replace the pixel at that position of the original image to the copy, the realization principle is the same as above, the code is as follows:

def generate_music_post(circle_im, bg_im):
   """
     Generate a music poster by passing in a circular image and a background image
     circle_im: circle image
     bg_im: background image
     return: the generated image
   """
  # Copy copy
  bg_copy = bg_im.copy()
  # Paste the circular image onto the copy
  bg_copy.paste(circle_im, (left, top))
  # Iterate over the pixel square region
  for i in range(left, left+radius):
    for j in range(top, top+radius):
      # Get pixel values
      color = bg_copy.getpixel((i, j))
      # If the pixel is transparent. color has the value (r,g,b,a), color[3] is the value of a, the transparent value
      if color[3] == 0:
        # Replace the original pixel with a copy of the transparency
        bg_copy.putpixel((i, j), bg_im.getpixel((i, j)))
  # Return the composited image
  return bg_copy

This completes it. The complete code is below:

from PIL import Image, ImageDraw

left = 273      # Distance of the circle from the left
top = 573      # Distance of the circle from the upper edge
radius = 533    # Diameter of the circle
circle_size = (radius, radius)    # The size of the outer square of a circle

def generate_circle_image(img_path):
  # Create a transparent square
  im = ('RGBA', circle_size, (255, 255, 255, 0))
  # Get the painter
  drawer = (im)
  # Draw a yellow circle on a transparent square #
  ((0, 0, circle_size[0], circle_size[1]), fill=(255, 255, 0), width=0)
  # Open the image to be converted into a circle, we crop the image beforehand
  pic = (img_path).convert('RGBA')
  re_pic = (circle_size, )

  # Iterate over each pixel of the image
  for i in range(circle_size[0]):
    for j in range(circle_size[1]):
      r, g, b, a = ((i, j))
      if (r, g, b) != (255, 255, 0):
        re_pic.putpixel((i, j), (255, 255, 255, 0))

  return re_pic

def generate_music_post(circle_im, bg_im):
   """
     Generate a music poster by passing in a circular image and a background image
     circle_im: circle image
     bg_im: background image
     return: the generated image
   """
  # Copy copy
  bg_copy = bg_im.copy()
  # Paste the circular image onto the copy
  bg_copy.paste(circle_im, (left, top))
  # Iterate over the pixel square region
  for i in range(left, left+radius):
    for j in range(top, top+radius):
      # Get pixel values
      color = bg_copy.getpixel((i, j))
      # If the pixel is transparent. color has the value (r,g,b,a), color[3] is the value of a, the transparent value
      if color[3] == 0:
        # Replace the original pixel with a copy of the transparency
        bg_copy.putpixel((i, j), bg_im.getpixel((i, j)))
  # Return the composited image
  return bg_copy

# Generate circular images
pic = generate_circle_image('')
# Read background image in RGBA mode
bg_im = ('').convert('RGBA')
# Generate music posters
music_post = generate_music_post(pic, bg_im)
music_post.show()

Also, this example could be smarter. We could use OpenCV to recognize the face of the subject image, and then compute a more suitable square region based on the face region, so that we don't have to pass in the square (though there are still issues such as the accuracy of face recognition to consider).

The code has been uploaded to the GitHub address below:/IronSpiderMan/MusicPost

Material images are also in there.

Above is the details of making music posters with Python, for more information about making music posters with python, please follow my other related articles!