This is the 30th day of my participation in the August Text Challenge.More challenges in August

preface

Some time ago in a friend so got the inspiration, thought can use music playing page as a poster picture. In fact, there is still a gap between what we want to talk about and posters, and the specific implementation is just a simple picture paste, but the effect is still good. The effect picture is as follows, I hope you like it:

On the left is the original image, and on the right is the image that needs to be added to the middle, which is also the main character of the image. In fact, it is very easy to implement the above image directly in PHOTOSHOP, but it is a little tortuous to implement in code, but the implementation process is still very interesting, I hope this blog can let you learn knowledge.

Use the Pillow to create a circle diagram

In the image above, there is a round image in the middle, and the Pillow itself does not provide a way to generate a round image (or MAYBE I did not find it), so I need to implement it myself. To implement this, we install the Pillow module:

pip install pillow
Copy the code

To create a circle image, we first create an RGBA transparent image based on the size of the original image:

This method takes in three parameters, the first is mode, the second is a tuple of size, and the third is color
im = Image.new('RGBA', (300.300), (255.255.255.0))
Copy the code

The above code creates a fully transparent 300 by 300 image on which we draw the largest circle:

# Get Carver
drawer = ImageDraw.Draw(im)
The ellipse method takes three parameters: the first is the area containing the smallest square of the circle, the second is the color, and the third is the edge width
drawer.ellipse((0.0.300.300), fill=(255.255.0), width=0)
Copy the code

The generated images are as follows:

We prepare A 300 by 300 square image and walk through every pixel of the image. If the pixel value is A==0 (i.e. the pixel is opaque) then we set the pixel value in that area of the image to transparent.

The code is as follows:

To convert the image into a circle, we crop the image beforehand
pic = Image.open(img_path).convert('RGBA')
Walk through every pixel of the image
for i in range(300) :for j in range(300) :Get the pixel of this pixel
     	r, g, b, a = im.getpixel((i, j))
        # When RGB value is not yellow, i.e., when pixel value is transparent
        if(r, g, b) ! = (255.255.0) :# Set the pixel value of the original image to transparent
        	pic.putpixel((i, j), (255.255.255.0))
Copy the code

Our PIC is a circular picture, the complete code is as follows:

# The diameter of the circle in the background
radius = 533
# Size of picture
circle_size = (radius, radius)
def generate_circle_image(img_path) :
    Create a transparent square
    im = Image.new('RGBA', circle_size, (255.255.255.0))
    # Get the painter
    drawer = ImageDraw.Draw(im)
    # Draw a yellow circle on the transparent square
    drawer.ellipse((0.0, circle_size[0], circle_size[1]), fill=(255.255.0), width=0)
    To convert the image into a circle, we crop the image beforehand
    pic = Image.open(img_path).convert('RGBA')
    # Resize the image so that it matches the size of the circle
    re_pic = pic.resize(circle_size, Image.ANTIALIAS)
    Walk through every pixel of the image
    for i in range(circle_size[0) :for j in range(circle_size[1]):
            r, g, b, a = im.getpixel((i, j))
            if(r, g, b) ! = (255.255.0):
                re_pic.putpixel((i, j), (255.255.255.0))
    return re_pic
Copy the code

In the above method, we have improved the code so that we need to use images of the specified size as materials, but now we only need to use square images.

Generate a poster

Originally I thought I could paste the round image directly onto the background image, but after trying it, I found that the effect is not quite what I expected. Anyway, it didn’t work, and the effect is as follows:

Yes, it is pasted in, and the image is also transparent, but from this effect, paste is only pixel replacement, not image overlay. So I came up with the idea of traversing pixels.

I used a special method to get the pixels from the top square to the left, and the pixels from the top. I tried image detection and pixel determination to automatically identify the position of the middle circle, but it didn’t work very well (it just failed anyway), so I shamelessly used Photoshop to look at the pixels.

To get back to the point, instead of traversing the entire image, we just need to start from the (left, top) pixel and traverse to the (left+ RADIUS, top+ RADIUS) region, i.e. traverse the square region (left, top and RADIUS are all obtained by photoshop).

We first copy the background picture and paste it on the copy. Then iterate over the pasted image. If the pixel value is transparent, we will replace the pixel at the position of the original image to the copy. The implementation principle is the same as above, the code is as follows:

def generate_music_post(circle_im, bg_im) :
 	Circle_im: circle picture bg_im: background picture return: generated picture """
	# copy copy
    bg_copy = bg_im.copy()
    # Paste the round picture onto the copy
    bg_copy.paste(circle_im, (left, top))
    # Walk through the pixel square area
    for i in range(left, left+radius):
        for j in range(top, top+radius):
            Get the pixel value
            color = bg_copy.getpixel((i, j))
            # If the pixel is transparent. The value of color is (r,g,b,a), and color[3] is the value of A, that is, the transparent value
            if color[3] = =0:
                # Replace the original pixel with the transparent part of the copy
                bg_copy.putpixel((i, j), bg_im.getpixel((i, j)))
	# Return the composited image
    return bg_copy
Copy the code

And you’re done. The complete code is as follows:

from PIL import Image, ImageDraw

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

def generate_circle_image(img_path) :
    Create a transparent square
    im = Image.new('RGBA', circle_size, (255.255.255.0))
    # Get the painter
    drawer = ImageDraw.Draw(im)
    # Draw a yellow circle on the transparent square
    drawer.ellipse((0.0, circle_size[0], circle_size[1]), fill=(255.255.0), width=0)
    To convert the image into a circle, we crop the image beforehand
    pic = Image.open(img_path).convert('RGBA')
    re_pic = pic.resize(circle_size, Image.ANTIALIAS)

    Walk through every pixel of the image
    for i in range(circle_size[0) :for j in range(circle_size[1]):
            r, g, b, a = im.getpixel((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) :
 	Circle_im: circle picture bg_im: background picture return: generated picture """
	# copy copy
    bg_copy = bg_im.copy()
    # Paste the round picture onto the copy
    bg_copy.paste(circle_im, (left, top))
    # Walk through the pixel square area
    for i in range(left, left+radius):
        for j in range(top, top+radius):
            Get the pixel value
            color = bg_copy.getpixel((i, j))
            # If the pixel is transparent. The value of color is (r,g,b,a), and color[3] is the value of A, that is, the transparent value
            if color[3] = =0:
                # Replace the original pixel with the transparent part of the copy
                bg_copy.putpixel((i, j), bg_im.getpixel((i, j)))
	# Return the composited image
    return bg_copy

# Generate a circular image
pic = generate_circle_image('girl.jpeg')
# Read background images in RGBA mode
bg_im = Image.open('music.jpg').convert('RGBA')
# Generate music posters
music_post = generate_music_post(pic, bg_im)
music_post.show()
Copy the code

Plus, this example could be even smarter. We can use OpenCV to recognize the face of the subject image, and then calculate a more suitable square area based on the face area, so we don’t have to pass in the square (but there are still issues such as accuracy of face recognition).

Code uploaded making address is as follows: https://github.com/IronSpiderMan/MusicPost

The source pictures are also in there.