Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

Python OpenCV 365 day learning plan, enter the graphics realm with eraser. This blog is the 44th in the series.

Foundation of basic knowledge

Today to review the last blog to write binary operation, the content is still immature, sure enough, the first time to learn just to master a little fur, there are a lot of details of knowledge points need to supplement.

Binary learning iteration

First of all, the cv2. Theshold function for learning, function prototype and parameters of the basic part, read the previous blog can, focus on the following content. Function prototype or first reference:

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

The main argument is type, so let’s review the basic use of the basic function code, after all, there is code to review the content:

import cv2 as cv
import numpy as np
src = cv.imread("./test.png")
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

retval, dst = cv.threshold(gray, 127.255, cv.THRESH_BINARY)

image = np.hstack((gray, dst))
cv.imshow("image", image)
cv.waitKey()
Copy the code

The running results are as follows:

The last type parameter is the key knowledge reviewed, and its value affects the result of the final binary graph. The common values of type are as follows, which can also be divided into three groups, respectively

  1. THRESH_BINARYTHRESH_BINARY_INV;
  2. THRESH_TRUNC;
  3. THRESH_TOZEROTHRESH_TOZERO_INV.

The two values in the first group and the two values in the third group have the same meaning and are opposite, so you can just look at one parameter value.

THRESH_BINARY is most commonly used to indicate that when the pixel value is greater than the threshold thresh, the color set by maxval is taken. Thresh is set to 127 and maxval to 255. THRESH_BINARY sets all values greater than 127 to 255. Note here that the binarization operation is grayscale image, although the transfer of color image also plays a role, but when doing binarization, it is necessary to convert the color image into a binary image in advance.

THRESH_TOZERO does not change the number of pixels above the threshold, and the number of pixels below the threshold is set to 0.

import cv2 as cv
import numpy as np

cv.namedWindow("image",cv.WINDOW_FREERATIO)

src = cv.imread("./test.png")
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

retval1, dst1 = cv.threshold(gray, 127.255, cv.THRESH_BINARY)
retval2, dst2 = cv.threshold(gray, 127.255, cv.THRESH_TOZERO)
image = np.hstack((dst1,dst2))
cv.imshow("image", image)
cv.waitKey()
Copy the code

Using this method, it is obvious that there are places where the grayscale is worth preserving. Note that THRESH_TOZERO is set to zero for pixels above the threshold. THRESH_BINARY comparison shows that if you’re black, you’re black, and if you’re white, you’re whiter. So when using THRESH_TOZERO, it’s okay to write it like this.

retval2, dst2 = cv.threshold(gray, 127.0, cv.THRESH_TOZERO)
Copy the code

THRESH_TRUNC truncates the threshold. If the value is greater than the threshold, set it to the threshold. Otherwise, the test code is as follows:

retval1, dst1 = cv.threshold(gray, 127.255, cv.THRESH_BINARY)
retval2, dst2 = cv.threshold(gray, 127.0, cv.THRESH_TOZERO)
retval3, dst3 = cv.threshold(gray, 127.0, cv.THRESH_TRUNC)
image = np.hstack((dst1,dst2,dst3))
Copy the code

After comparison, it is immediately clear that THRESH_TRUNC sets the upper limit of the image’s gray level to a specific value, such as 127 in this case.

Image smoothing learning iteration

Smoothing, or convolution, has been covered before and after this blog, and we’ll supplement it when we look at it again.

To deal with the noise in the image, you can use the median filter, it is a simple average convolution operation, after about convolution in mathematics related, put in slightly after 10 days, in the supplement, because then the content of the many places will have convolution, learn some more about the application layer, to analyse the mathematical foundation, will get twice the result with half the effort.

Although it does not involve mathematical principles, we still need to carry out a basic cognition of the underlying implementation. In order to facilitate the implementation, I use a manually generated grayscale map to demonstrate.

Generate a grayscale map code:

import cv2 as cv
import numpy as np
Generate a 10*10 grayscale image
src = np.random.randint(256,size=(10.10),dtype=np.uint8)
print(src)

cv.imshow("src",src)
Copy the code

Because it is generated randomly, the output code looks like this:

[[90 134 192 243 116 2 172 143 22 218] [192 145 171 125 175 138 64 232 90 160] [61 20 231 37 77 27 141 182 71 194] [136 86 10 239 196 137 192 243 47 40] [220 167 3 50 227 70 135 227 225 218] [207 10 213 134 249 157 179 112 58 78] [107 33 68 143 124 215 175 167 108 195] [32 227 43 249 61 168 230 180 82 47] [89 211 253 141 199 140 34 185 179 32] [18 98 109 92 37 13 200 102 97 218]]Copy the code

The mean filter will choose one by default3x3And then do the convolution from left to right, top to bottom.The 137 in red in the figure above is the result of mean filtering, adding up the nine numbers around the central number 145 and dividing by 9 to get 137, replacing 145. But the problem with this operation is that the edges don’t fit the convolution kernel3x3Eraser, here also refer to the relevant data, the explanation is edge filling, namely a few blog before learning content, but I try later, found that the result is not ideal, time or want to consult the OpenCV source code, check what is calculated, but the core idea is more clear, The mean is just calculating the average.

Since it is the average value of the nine values of the convolution kernel instead of the intermediate pixel value, the final effect is smooth. When applied to a specific image, the effect is shown as follows.

import cv2 as cv
import numpy as np

cv.namedWindow("image",cv.WINDOW_FREERATIO)

src = cv.imread("./t1.jpg")
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

dst = cv.blur(gray,(3.3))
image = np.hstack((gray,dst))
cv.imshow("image", image)
cv.waitKey()
Copy the code

The convolution kernel size can be set to any size, but it is recommended to set to3x3,5x5These odd numbers.

Box filtering

It seems that the content of box filtering was not involved in the previous blog. Here is a supplement, which is basically consistent with the usage of mean filtering. The function prototype is as follows:

dst = cv2.boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]])
Copy the code

You can choose whether to normalize or not, and the code can run the following:

# normalization
dst = cv.boxFilter(gray,-1, (3.3),normalize=True)
# Do not normalize
dst = cv.boxFilter(gray,-1, (3.3),normalize=False)
Copy the code

To put it simply, without normalization operation, after using 3×3 convolution kernel for calculation, without dividing by 9, pixels will be out of bounds, and 255 will be retained by default.

Gaussian filtering is to increase the knowledge related to Gaussian distribution, or to increase the concept of spatial distance correlation, namely, the pixel weight around the pixel is different. Compared with mean filtering, Gaussian filtering has better smoothing effect.

Median filtering is to sort the matrix covered by the convolution kernel from small to large, and then take the median as the pixel value of the target image.

Eraser section

I hope you learned something from today’s hour, and I’ll see you in the next blog