I. Preface
If you've ever printed something yourself, you should have experienced this. If you use a picture you've taken, it still feels visible on your phone, but as soon as you print it out it's pitch black. For example, these two pictures below:
Because the image on the left has large shadows, all the printouts are unpleasant to look at (since it costs 30 cents to print, the second image is just a simulation of the effect I used the program to simulate).
So is there any way to fix it? The answer is yes, and today we're going to explore a few ways to remove shadows.
Second, how to remove the shadow?
First of all, in order to facilitate the process, we usually do a grayscale conversion (i.e., convert the image to a gray image with only one layer).
Then we analyze that there are three main colors in the image above, the font color (black), the paper color (off-white), and the shadow color (gray). Once we know that, we're good to go. We just need to treat the gray and white parts as white.
So what do I have to do to know the white and gray areas? For an 8-bit grayscale image, the black part of the image is roughly around 0-30 pixels. The white and gray should be around 31-255 (this range is just a rough estimate, you need to look at the picture for the actual situation). As shown in the picture:
On the left is the original image and on the right is the processed image. We processed the gray and near-white parts to white.
So let's get down to business below.
Third, numpy's ndarray array
Some readers may not have had access to numpy, so here is a brief description.
numpy is a third-party module with which we can easily work with multidimensional arrays (ndarray arrays). Images are stored in OpenCV as ndarray arrays, so our operations on arrays are operations on images.
We need to install the OpenCV module before we can use it:
pip install opencv-python
numpy is automatically installed when OpenCV is installed.
Here we mainly look at the operation of Boolean indexes, first look at the following code:
import numpy as np # Create an ndarray array with elements 1, 0, 1, 1 arr = ([1, 0, 1, 1]) # Determine if there are any zeros in the array res = arr == 0 # Assign elements of the array that are 0 to 10 arr[res] = 10
If you have not been exposed to numpy will not quite understand the above syntax. Let's talk about it in detail:
Creating an ndarray array: We can replace an existing list with an ndarray object, which is easy to understand.
To determine whether there is 0 in the array: we can directly use the ndarray object to determine, for example: arr == 0, he will return an element structure and the number of the same ndarray object. But the return of the object of the original type bool, let's look at the output of res:
[False True False False]
As you can see from the results, our comparison arr==0 is a comparison of each element in the array and returns the boolean value of the comparison.
Assign the element of the array that is 0 to 10: And the most difficult to understand operation arr[res]. It actually gets the view that is True in res, for example, the result above is that the second is True then only the view of the second element will be returned. We execute the following code:
arr[res] = 10
It is to assign the part of arr that corresponds to a res of True to 10, that is, to assign the part of arr that has a value of 0 to 10.
Here is the final result of arr:
[ 1 10 1 1]
You can see that the original 0 is processed as a 1.
IV. Removing shadows
Now that we know the boolean index, we can process the image. We just need to read the image and process the parts with pixel values greater than 30 to white. Here is our code:
import cv2 # Read the picture img = ('', 0) # Change pixel values greater than 30 to 255 (white) img[img > 30] = 255 # Save the modified image ('', img)
The above code is very simple, we use the function to read the picture, the first parameter is the path of the picture, the second parameter indicates that the reading is a grayscale map. Let's take a look at the effect image:
You can see that the shadows are well removed. Some words are more blurred, we can adjust it by adjusting the range of gray and white ground. For example:
img[img > 40] = 255
The exact value will depend on the image to be processed.
V. Improvements
For the above processing, there can be a small improvement. We can make the paper color not so white, let's see the improved code:
import cv2 import numpy as np img = ('', 0) # Calculate the mean value of the grayed-out portion of the pixels pixel = int((img[img > 140])) # Change the off-white part to a color close to the background img[img > 30] = pixel ('', img)
Instead of setting the gray part to 255 in the code above, we have calculated a value beforehand.
pixel = int((img[img > 140]))
Guessing that the color value of the shaded portion is less than 140, we first index out the portion of the image that is greater than 140. Then the average value, so that we calculated roughly is the background color of the original image, and then the part of the image is not the text is processed as the background color, is the final result. The following is our results:
You can see that the results are much better this time. But since the background is all one color, it still looks a little different.
One thing to note, though, is that the above operation only applies to simpler images, such as test papers for example.
To this article on OpenCV how to remove shadows in the picture of the realization of the article is introduced to this, more related to OpenCV to remove shadows in the picture content, please search for my previous articles or continue to browse the following related articles I hope you will support me in the future!