This is the 29th day of my participation in the August Wenwen Challenge.More challenges in August

preface

Image processing is a very high science and very interesting. To master image processing requires a lot of knowledge, but as entertainment, the requirements for this knowledge are much lower. In Python image processing, we usually use the Pillow library, which provides a number of operations, such as grayscale conversion, Gaussian blur, and color channel separation. In addition, OpenCV also provides some image processing methods. You can combine the two to create effective image processing.

Introduction to PIL

PIL stands for Python Imaging Library. In fact, PIL only supports Python 2.7. Most of us now use Python 3.x. There is a compatible version of the Pillow module in 3.x, which has the basic operations of PIL, but also adds some new operations.

1.1 installation

We use PIP installation:

pip install pillow
Copy the code

After the installation is complete, we can use it. Although Pillow is used when the installation is ours, in actual use, we import PIL:

from PIL import Image
Copy the code

The Image class is the one we use most often. After importing the module, let’s look at the simplest operation:

from PIL import Image

# Open image
img = Image.open('0_img/q.jpg')

# display images
img.show()
Copy the code

So we’re done reading and displaying images. Of course, after we get the object of the image, we can get its corresponding properties:

from PIL import Image

# Open image
img = Image.open('0_img/q.jpg')

print('Image format:', img.format)
print('Image size:',img.size)
print('Image width:', img.width)
print('Image height:', img.height)

# display images
img.show()
Copy the code

The output is as follows:

Image format: JPEG Image size: (1280.720) Image width:1280Image height:720
Copy the code

Second, use PIL to process images

Usually processing images requires us to master a lot of knowledge related to images, but we can use modules to achieve image processing very simply. We don’t need to know the underlying implementation, just what these processes do.

2.1 Image Array

We use PIL reads the images, it is the return value of a PIL, JpegImagePlugin. JpegImageFile object, and we in the use of OpenCV processing, processing is ndarray object. We can convert it to an Ndarray object using the following statement:

from PIL import Image
import numpy as np
# fetch image
img = Image.open('0_img/q.jpg')
Convert it to an NDARray object using NP
img_array = np.array(img)
Copy the code

The transformed NDARray object has RGB three color channels, each pixel of the image has three values, the size of the value is (0~255).

2.2 Gray conversion

Gray transformation refers to a method to change the gray value of each pixel in the source image point by point according to certain target conditions according to certain transformation relations. Gray transformation can improve image quality. We usually say that black and white photos are grayscale photos, and the pixel values in the real sense of black and white images are only 0 and 255, and PIL to achieve grayscale conversion is very simple:

from PIL import Image
# fetch image
img = Image.open('0_img/q.jpg')
# Grayscale conversion
grey_img = img.convert('L')
# Save image
grey_img.save('0_img/grey.jpg')
Copy the code

The comparison between the original image and the grayscale image is as follows:

2.3 Image Mixing

Image blending is to mix two images together, we can create a monochrome image, and then mix again:

from PIL import Image 
# fetch image
img1 = Image.open('0_img/q.jpg')
# Create an image
img2 = Image.new('RGB', img1.size, (255.0.0))
# Blending images
Image.blend(img1, img2, 0.5).show()
Copy the code

We use image.new to create an Image. This method passes in three parameters. The first is that the mode of the Image usually has “RGB”, “L” (gray scale), etc. The second parameter is the image size, and the third parameter is the color value. We can pass color characters “red”, “blue”, and so on directly.

The method for blending images is image.blend, which takes three parameters, the first and second of which are the Image objects, and the third is the transparency of IMG2. After mixing, the effect is as follows:

2.4 Image scaling

Image scaling means to enlarge or shrink an image according to its size. Usually we can use this method to generate a thumbnail image of the image. Image scaling uses the thumbnail method, which receives a tuple of two elements, width and height:

from PIL import Image
# fetch image
img1 = Image.open('0_img/q.jpg')
Print the size of the element's image
print(img1.size)
Reduce the width and height of img1 to 1/2 of their original size
img1.thumbnail((img1.size[0] / /2, img1.size[1] / /2))
Output the size after scaling
print(img1.size)
Copy the code

The following output is displayed:

(1280.720)
(640.360)
Copy the code

Note that the open, New, and blend methods mentioned above are static methods of the Image class, whereas thumbnail is a method that needs to be executed with an actual object.

2.5 Image clipping and pasting

Clipping and pasting are basic operations for images and are very simple to implement in PIL. Crop uses the Crop method, which passes in a tuple with four parameters (x in the upper left corner, Y in the upper left corner, X in the lower right corner, y in the lower right corner), clipping is done based on the original image. Paste is also done using the paste method, which passes in two parameters, the image object and the upper-left coordinate tuple. The code is as follows:

from PIL import Image
# fetch image
img = Image.open('0_img/q.jpg')
# copy image
img1 = img.copy()
img2 = img.copy()
# Crop the image,
crop_im = img1.crop((200.200.400.400))
# Paste image
img2.paste(crop_im, (0.0))
img2.show()
Copy the code

The renderings are as follows:

2.6 Channel separation and merger

Channel separation is achieved by simply calling the split method, which returns three grayscale Image objects. Merge the image.merge method for a color channel, which takes two parameters, the first is the Image mode and the second is the list of colors:

from PIL import Image
# fetch image
img1 = Image.open('0_img/q.jpg')
img2 = Image.open('0_img/s.jpg')
# Channel separation
r1, g1, b1 = img1.split()
r2, g2, b2 = img2.split()
# Channel merge
img3 = Image.merge('RGB', [r1, g2, b1])
img3.show()
Copy the code

The comparison between the effect picture and the original picture is as follows:

The left is S.jpg, the middle is Q.jpg, and the most right is the merged image.

2.7 Gaussian Blur

Gaussian blur is also known as Gaussian smooth, which intuitively makes the picture blurred, but its actual function is to reduce the noise of the picture. There are a number of processes that require gaussian blurring in advance, which is implemented in PIL by calling filter:

from PIL import Image,ImageFilter

# fetch image
img = Image.open('0_img/q.jpg')
# Gaussian blur
g_img = img.filter(ImageFilter.GaussianBlur)
g_img.show()
Copy the code

The filter method adds a filter to an image, and there are many preset filters available in the ImageFilter class.

2.8 Color brightness adjustment

There are a number of classes available in ImageEnhance to tweak images, as follows:

The name of the class Methods effect
ImageEnhance.Color Gets the color adjuster
ImageEnhance.Contrast Gets the contrast adjuster
ImageEnhance.Brightness Gets the brightness adjuster
ImageEnhance.Sharpness Get the sharpness adjuster

To adjust the image, we need to adjust the corresponding regulator, and then adjust, let’s use the color as an example:

from PIL import Image,ImageEnhance
# fetch image
img = Image.open('0_img/q.jpg')
Get the color modifier
color_enhance = ImageEnhance.Color(img)
Adjust the color. If the value is less than 1, it is attenuated. If the value is greater than 1, it is enhanced
enhance_img = color_enhance.enhance(0.5)
# display image
enhance_img.show()
Copy the code

The other properties are tuned the same way as colors.

Introduction to OpenCV

OpenCV, like PIL, can also do image processing. However, OpenCV reads images in NDARray form and in BGR mode. Let’s install OpenCV:

pip3 install opencv-python
Copy the code

Then we can start using it.

3.1 OpenCV reads the image

OpenCV reads images through the cv2.imread method, which returns an NDARRay object in mode BGR.

import cv2
# fetch image
img = cv2.imread('jt.jpg')
# display image, pass two arguments, the first is the window name, the second is the ndarray object
cv2.imshow('img', img)
# Wait for keyboard input
cv2.waitKey(0)
Destroy all Windows
cv2.destroyAllWindows()
Copy the code

Calling the imshow method only displays the image for a fraction of a second, so you need to call the WaitKey method, which receives the number of milliseconds to wait, or an infinite wait if 0 is passed. Since The bottom of OpenCV is C/C++, the window memory needs to be freed.

3.1 Images read by OpenCV and PIL are converted to each other

We already know how to convert Image object to NDARray object above, but because of the different Image mode, the display time is different, so we need to convert RGB to BGR or BRG to RGB.

RGB to BGR:

import cv2
import numpy as np
from PIL import Image

# Use PIL to read images
pil_img = Image.open('jt.jpg')
# Convert to an NDARray object with RGB mode
rgb = np.array(pil_img)
Convert RGB to BGR
bgr = rgb[...,::-1]
# Use OpencV to display images
cv2.imshow('pil_im', bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()
Copy the code

BGR to RGB:

import cv2
from PIL import Image
# fetch image
bgr = cv2.imread('jt.jpg')
# BGR RGB
rgb = bgr[...,::-1]
Convert an ndarray object to an Image object
cv_im = Image.fromarray(rgb)
cv_im.show()
Copy the code

After execution, it is found that the display effect is the same as the original picture.

Four, comprehensive operation

We have been talking about simple image processing, now let’s do some comprehensive operations.

4.1 Edge Detection

Many edge detection algorithms are provided in OpenCV, among which Canny is the current optimal algorithm, we can quickly achieve edge detection, the code is as follows:

import cv2
# fetch image
img = cv2.imread('jt.jpg')
# Grayscale conversion
grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Canny algorithm, the algorithm
canny_im = cv2.Canny(grey, 50.200)
# display images
cv2.imshow('canny', canny_im)
cv2.waitKey(0)
cv2.destroyAllWindows()
Copy the code

Let’s take a look at the original and renderings:

The general outline is there, but the light part is not recognized, so we think of color enhancement. The modified code is as follows:

import cv2
import numpy as np
from PIL import Image, ImageEnhance
# fetch image
img = Image.open('jt.jpg')
# Enhance color
color_enhance = ImageEnhance.Color(img)
en_im = color_enhance.enhance(5)
# Convert to an Ndarray object
img_array = np.array(en_im)
# Convert to BGR
bgr = img_array[...,::-1]
# Canny algorithm, this algorithm passes in three values, the first is the ndarray object, the second and third are the threshold
canny_im = cv2.Canny(bgr, 150.200)
cv2.imshow('canny', canny_im)
cv2.imwrite('canny.jpg', canny_im)
cv2.waitKey(0)
cv2.destroyAllWindows()
Copy the code

The renderings are as follows:

You can adjust it according to different pictures.

4.2 Combination effect of pictures and words

We will prepare a text picture, as small as possible, the text picture can be made with Windows built-in drawing tool. Then prepare another picture. The production idea is as follows:

  1. Prepare text images and background images
  2. We create a white image based on the size of the background image
  3. We pasted the text image from left to right and top to bottom onto the white image
  4. Blend the pasted problem image with the background image

The code is as follows:

from PIL import Image
# Read background image and text image
im = Image.open('zxz.jpg')
source = Image.open('zack.png')
Get the size of the background image and text image
im_size = im.size
source_size = source.size
# Calculate how many text images can fit on a line
width_num = im_size[0] // source_size[0]
# Calculate how many text images can fit in a column
height_num = im_size[1] // source_size[1]
# Create a white image of the same size as the background image
bg_im = Image.new('RGB', im_size, (255.255.255))
# loop variables
x, y = 0.0
# Loop, fill the text image with white image from left to right and top to bottom
for i in range(width_num+1):
    x = i * source_size[0]
    for j in range(height_num+1):
        y = j * source_size[1]
        bg_im.paste(source, (x, y))
# Blend the pasted text image with the background image
Image.blend(im, bg_im, 0.5).save('res.png')
Copy the code

The above code does the following:

You can make some interesting hybrid images based on what you’ve learned.