This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

Threshold processing

1. Threshold processing

Threshold processing is the process of setting a certain threshold and processing the pixels larger than the threshold or smaller than the threshold uniformly. Take this simple image:

Each cell represents a pixel, and the number in the cell represents the pixel value of the image. If the threshold is set to 8, we can divide the picture into two regions, as shown below:

And then we do the same thing for the green area or the blue area, and that’s the threshold processing.

Our usual operation is to treat the pixel value above a certain threshold as 255, or the pixel value below a certain threshold as 0. Or both. When we do both at the same time, we can binary the operation, because the image is only pure black and pure white.

2. Use NUMPY to realize threshold processing

In numpy’s Ndarray array, Boolean index operations are provided. Boolean indexes allow you to quickly and easily implement threshold processing without having to write a lot of for loops.

Boolean index operations are based on Boolean matrices, so we need to know about Boolean matrices.

(1) Boolean matrix

A Boolean matrix is just a matrix with a Boolean element type, and with a Boolean matrix we can perform Boolean index operations on real matrices.

We generate a Boolean matrix using the following code:

import numpy as np
m = np.array([False.True.False.False], dtype=np.bool_)
print(m)
Copy the code

The output is as follows:

[False  True False False]
Copy the code

But this matrix doesn’t seem to work. The above code is written just to let you know that a Boolean matrix is just an NdarRay array of Boolean type.

In addition to creating our own Boolean matrix manually, we can also generate a Boolean matrix for an array by using the comparison operator. Such as:

import numpy as np
# Generate a two-dimensional matrix
x = np.array([
    [10.13.90],
    [80.21.34],
    [1.4.6]], dtype=np.uint8
)
# Generate Boolean matrix by comparison
bool_x = x > 8
print(bool_x)

Copy the code

In the code, we create a two-dimensional matrix. We then generate a Boolean matrix with x > 8. Here is the output:

[[ True  True  True]
 [ True  True  True]
 [False False False]]
Copy the code

As you can see, bool_X and X have the same shape, and there is a one-to-one correspondence between Boolean and two-dimensional matrix elements. If the element value is greater than 8, it is True in the Boolean matrix and False otherwise. The picture is as follows:

(2) Boolean index

So with a Boolean matrix, we can do a Boolean index. Boolean indexes operate only on the True portion of the matrix. For example, the following code:

import numpy as np
x = np.array([
    [10.13.90],
    [80.21.34],
    [1.4.6]], dtype=np.uint8
)
bool_x = x > 8
# Assign 255 to elements greater than 8
x[bool_x] = 255
print(x)
Copy the code

The output is as follows:

[[255 255 255]
 [255 255 255]
 [  1   4   6]]
Copy the code

Just to be clear, we’re dealing with a real matrix. The Boolean matrix is just a guide, telling the program what elements we need to operate on.

As you can see from the result, all elements greater than 8 are assigned 255, and the rest are unchanged.

3. Opencv implements threshold processing

(1) Threshold processing function

Opencv provides a function for threshold processing, whose function is defined as:

thresh, dst = cv2.threshold(src, thresh, maxval, type)
Copy the code

The meanings of parameters are as follows:

The two values returned are the threshold and the processed resulting image.

The following are optional parameters for the threshold type:

The maxval parameter only comes into play when our threshold processing type is binary processing.

(3) Differences in threshold processing

Let’s talk about the differences between the various threshold treatments. The details are as follows:

Let’s do this in code:

import cv2
# Read image
img = cv2.imread('beautiful.JPG'.0)
# Binarization threshold processing
_, result = cv2.threshold(img, 127.255, cv2.THRESH_BINARY)
# Display images
cv2.imshow('result', result)
cv2.waitKey()
cv2.destroyAllWindows()
Copy the code

Here is the comparison between the effect and the original:

As you can see, the original was darker. However, our threshold is set to 127, resulting in a less effective binary image, which will be addressed later.

Let’s try the cut-off threshold again:

import cv2
img = cv2.imread('beautiful.JPG')
_, result = cv2.threshold(img, 100.255, cv2.THRESH_TRUNC)
cv2.imshow('result', result)
cv2.waitKey()
cv2.destroyAllWindows()
Copy the code

This time we did not read the image in grayscale, so the final result is also a color image. Here is the effect:

Because some of the high pixel values were suppressed, the image was darker and the contrast was significantly reduced.

The rest of you can try it yourself.

4. Otsu processing

In all of the examples above, we need to set the threshold manually. And different images set different threshold effect will be very different, and Otsu algorithm is an automatic threshold algorithm. We can do this directly with the cv2.threshold function, using the following:

import cv2
import numpy as np
img = cv2.imread('beautiful.JPG'.0)
_, result1 = cv2.threshold(img, 127.255, cv2.THRESH_BINARY)
Use the Otsu algorithm
thresh, result2 = cv2.threshold(img, 0.255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
Stitch the two images horizontally
result = np.hstack((result1, result2))
# Output the threshold obtained by the Ostu algorithm
print(thresh)
cv2.imshow('result', result)
cv2.waitKey()
cv2.destroyAllWindows()
Copy the code

We used ordinary binarization and Otsu algorithm respectively, and the renderings are as follows:

This time the background is much clearer.

The output threshold is as follows:

99.0
Copy the code

You can experiment with a few different images.

More content can follow my public number “new folder X”.