As previously mentioned, cv2.bilateralFilter() can be applied to reduce noise while preserving the sharp edges. However, this filter can produce both intensity plateaus (the staircase effect) and false edges (gradient reversal) in the filtered image. While this can be taken into account in your filtered images (there are several improvements to the bilateral filter that deals with these artifacts), it can be very cool to create cartoonized images. The full code can be seen in cartoonizing.py , but in this section we will look at a brief description.
The process to cartoonize images is quite simple and it is performed in the cartonize_image(). function. First of all, the sketch of the image is constructed (see the sketch_image() function), which is based on the edges of the image. There are other edge detectors to use, but in this case, the Laplacian operator is used. Before calling the cv2.Laplacian() function, we reduce the noise by smoothing the image by means of the cv2.medianBlur() median filter. Once the edges have been obtained, the resulting image is thresholded by applying cv2.threshold(). We will look at thresholding techniques in the next chapter, but in this example this function gives us a binary image from the given grayscale image corresponding to the output of the sketch_image() function. You can play with the threshold value (in this case fixed to 70) in order to see how this value controls the number of black pixels (corresponding to the detected edges) appearing in the resulting image. If this value is small (for example, 10) many black border pixels will appear. If this value is big (for example, 200), few black border pixels will be outputted. To get a cartoonized effect, we call the cv2.bilateralFilter() function with big values (for example, cv2.bilateralFilter(img, 10, 250, 250)). The final step is to put together the sketch image and the output of the bilateral filter using cv2.bitwise_and() with the sketch image as the mask in order to set these values to the output. If desired, the output can also be converted to grayscale. Note that the cv2.bitwise_and() function is a bitwise operation, which we will see in the next section.
For the sake of completeness, OpenCV offers a similar functionality, and is also tested in this script. It works using the following filters:
- cv2.pencilSketch(): This filter produces a pencil sketch line drawing (similar to our sketch_image() function).
- cv2.stylization(): This filter can be applied to produce a wide variety of nonphotorealistic effects. In this case, we apply cv2.stylization() in order to get the cartoonized effect (similar to our cartonize_image() function).
The output corresponding to the cartoonizing.py script is shown in the following screenshot:
As you can see, the cartonize_image() function can also output a grayscale image calling cv2.cvtColor() to convert the image from BGR to grayscale.