OpenCV Python actual combat (part outside) - OpenCV realizes image cartoon

Keywords: Python OpenCV Deep Learning image processing

preface

In blog Opencv Python practice (4) -- common OpenCV image processing technologies( ❤️ 10000 word long text, including a large number of examples ❤️)> As described in, you can apply CV2. Bilaterfilter () To reduce noise while retaining sharp edges. However, this filter will produce ladder effect and false edges in the filtered image. Although this defect can be reduced by improving bilateral filtering, this effect can be used to create cool cartoon images. In this article, let's explore how to realize cartoon images in OpenCV.

Cartoon image

To realize the cartoon of the image, we first need to construct the sketch of the image according to the edge of the image.
The sketch_image() function is used to construct the sketch of the image. Firstly, the color image is transformed into a gray image, and then the image is smoothed by cv2.medianBlur() median filter to reduce noise:

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray = cv2.medianBlur(img_gray, 5)

Next, the Laplacian operator cv2.Laplacian() is used as the edge detector:

edges = cv2.Laplacian(img_gray, cv2.CV_8U, ksize=5)

Next, create a sketch of the image by using the edge of the image, and threshold process the generated image by applying cv2.threshold() (the threshold technology will be specifically introduced later. Here, we only need to know that this function provides us with a binary image from a given gray image as the output of the sketch_image() function) . different thresholds can be used to control the number of black pixels (i.e. detected edges) appearing in the result image. If the threshold is very small (e.g. 10), many black pixels will appear. On the contrary, if the value is large (e.g. 200), few black pixels will be obtained. You can obtain your own satisfactory results through this value:

ret, threshold = cv2.threshold(edges, 145, 255, cv2.THRESH_BINARY_INV)

Next, we can write the cartonize_image() function to realize the function of cartoon image.
In order to obtain cartoon effect, first call cv2.bilaterfilter() function with a larger value, for example:

cv2.bilateralFilter(img, 10, 250, 250) 

The second and final step is to use the cv2.bitwise_and() function (bitwise operation) to combine the sketch image with the output of bilateral filtering. The sketch image is used as a mask to ensure the output of these values. If necessary, the output can also be converted to gray image:

cartoonized = cv2.bitwise_and(filtered, filtered, mask=threshold)

if gray_mode:
    return cv2.cvtColor(cartoonized, cv2.COLOR_BGR2GRAY)

In addition to the above custom functions to realize image cartoon, OpenCV also provides similar built-in functions. The following filters can be used to realize the same functions:

  1. CV2. Pencil sketch(): this filter generates pencil sketch line diagrams (similar to the custom sketch_image() function)
  2. cv2.stylization(): this filter can be used to produce various non photorealistic effects. You can apply cv2.stylization() to obtain cartoon effects (similar to the custom cartonize_image() function)

The code running results are shown in the following figure:

Complete code

The complete code is as follows:

import cv2
import matplotlib.pyplot as plt

def show_with_matplotlib(color_img, title, pos):
    img_RGB = color_img[:, :, ::-1]

    ax = plt.subplot(2, 4, pos)
    plt.imshow(img_RGB)
    plt.title(title, fontsize=10)
    plt.axis('off')

def sketch_image(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    img_gray = cv2.medianBlur(img_gray, 5)

    edges = cv2.Laplacian(img_gray, cv2.CV_8U, ksize=5)

    ret, threshold = cv2.threshold(edges, 145, 255, cv2.THRESH_BINARY_INV)

    return threshold

# Cartoon realization of user-defined functions
def cartonize_image(img, gray_mode=False):
    # Extracting edges in an image
    threshold = sketch_image(img)
    # Bilateral filtering
    filtered = cv2.bilateralFilter(img, 10, 250, 250)
    # Cartoon
    cartoonized = cv2.bitwise_and(filtered, filtered, mask=threshold)

    if gray_mode:
        return cv2.cvtColor(cartoonized, cv2.COLOR_BGR2GRAY)
    
    return cartoonized

plt.figure(figsize=(14, 6))
plt.suptitle("Cartoonizing images", fontsize=14, fontweight='bold')

image = cv2.imread('sigonghuiye.jpeg')

custom_sketch_image = sketch_image(image)
custom_cartonized_image = cartonize_image(image)
custom_cartonized_image_gray = cartonize_image(image, True)

# Cartoon using OpenCV function
sketch_gray, sketch_color = cv2.pencilSketch(image, sigma_s=20, sigma_r=0.1, shade_factor=0.1)
stylizated_image = cv2.stylization(image, sigma_s=60, sigma_r=0.07)

show_with_matplotlib(image, "image", 1)
show_with_matplotlib(cv2.cvtColor(custom_sketch_image, cv2.COLOR_GRAY2BGR), 'custom sketch', 2)
show_with_matplotlib(cv2.cvtColor(sketch_gray, cv2.COLOR_GRAY2BGR), 'sketch gray cv2.pencilSketch()', 3)
show_with_matplotlib(sketch_color, 'sketch color cv2.pencilSketch()', 4)
show_with_matplotlib(stylizated_image, 'cartoonized cv2.stylization()', 5)
show_with_matplotlib(custom_cartonized_image, 'custom cartoonized', 6)
show_with_matplotlib(cv2.cvtColor(custom_cartonized_image_gray, cv2.COLOR_GRAY2BGR), 'custom cartoonized gray', 7)

# img_RGB = custom_cartonized_image[:, :, ::-1]
# plt.imshow(img_RGB)
# plt.title('custom cartoonized')
# plt.axis('off')
plt.show()

More cartoon effect display

We can obtain satisfactory cartoon effect by modifying the source image or function parameters:



Let's do it.

Related links

Opencv Python practice (4) -- common OpenCV image processing technologies( ❤️ 10000 word long text, including a large number of examples ❤️)>

Posted by robin_percy on Sat, 20 Nov 2021 03:15:34 -0800