Use OpenCV Gaussian in Python to blur my ugly face

@Author: Runsen

No one can deny that good-looking people are more attractive and pleasing to the eye. Everyone likes them. Good-looking people must be more dominant no matter in the workplace or in love.

However, this “face value” is not the other “face value”. When it comes to "face value," most of them think of faces.

Therefore, for me, I want to blur the faces of images and videos. In this blog, you will learn how to use the OpenCV library in Python to blur faces in images and videos.

In order to blur the faces displayed in the image, first detect these faces and their positions in the image. In this regard, check the previous tutorial on face detection , where the source code of face detection is used.

We use SSD-based face detection. The specific source code is shown below.

import cv2
import numpy as np
# 下载链接:https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt
prototxt_path = "weights/deploy.prototxt.txt"
# 下载链接:https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel 
model_path = "weights/res10_300x300_ssd_iter_140000_fp16.caffemodel"
model = cv2.dnn.readNetFromCaffe(prototxt_path, model_path)
image = cv2.imread("beauty.jpg")
h, w = image.shape[:2]
blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300),(104.0, 177.0, 123.0))
model.setInput(blob)
output = np.squeeze(model.forward())
font_scale = 1.0
for i in range(0, output.shape[0]):
    confidence = output[i, 2]
    if confidence > 0.5:
        box = output[i, 3:7] * np.array([w, h, w, h])
        start_x, start_y, end_x, end_y = box.astype(np.int)
        cv2.rectangle(image, (start_x, start_y), (end_x, end_y), color=(255, 0, 0), thickness=2)
        cv2.putText(image, f"{confidence*100:.2f}%", (start_x, start_y-5), cv2.FONT_HERSHEY_SIMPLEX, font_scale, (255, 0, 0), 2)
cv2.imshow("image", image)
cv2.waitKey(0)
cv2.imwrite("beauty_detected.jpg", image)

Gaussian Blur

There are many blur algorithms, one of which is called Gaussian Blur, which uses normal distribution for image processing.

Since the name is Gaussian filter, it has a certain relationship with Gaussian distribution (normal distribution).

The one-dimensional form of the "Gaussian function" is

f ( x ) = 1 σ 2 π e − ( x − μ ) 2 2 σ 2 f(x)=\frac{1}{ \sigma\sqrt{2\pi} }e^{-\frac{(x-μ)^2}{2{\sigma^2}}} f ( x )=σ2 π                                                          ​1​e−2 σ2( x − μ )2​

according to μ = 0 μ=0 μ=0The one-dimensional Gaussian function of can be derived to obtain the two-dimensional Gaussian function:

h ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 h(x,y)=\frac{1}{2\pi\sigma^2}e^{-\frac{x^2+y^2}{2{\sigma^2}}} h ( x ,y )=2 π σ21​e−2 σ2x2+ y2​

The so-called "blur" can be understood as taking the average value of surrounding pixels for each pixel.


In the above figure, 2 is the middle point, and the peripheral points are all 1.

"Intermediate point" takes the average value of "peripheral points" and it becomes 1. Numerically, this is a kind of "smoothing". In graphics, it is equivalent to producing a "blur" effect, and the "middle point" loses details.

Generally, Gaussian blur has a corresponding weight matrix.

Assuming that the coordinates of the center point are (0,0), then the coordinates of the 8 nearest points are as follows:

In order to calculate the weight matrix, the value of σ needs to be set. Suppose σ=1.5, the 1weight matrix of blur radius is as follows:

The sum of the weights of these 9 points is equal to 0.4787147. If only the weighted average of these 9 points is calculated, the sum of their weights must be equal to 1, so the above 9 values ​​have to be divided by 0.4787147 respectively to obtain the final weight matrix.

With the weight matrix, the value of Gaussian blur can be calculated. Assuming there are 9 pixels, the gray value (0-255) is as follows:

Each point is multiplied by its own weight value:

OpenCV provides the cv2.gaussianblur() function to apply Gaussian smoothing to the input source image. The following is the syntax of the GaussianBlur() function:

dst = cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType=BORDER_DEFAULT]]] )
parameterdescription
srcInput image
dstOutput image
ksizeGaussian kernel size (depending on height and width). height and width should be odd numbers and can have different values. If ksize is set to [0 0], ksize is calculated based on the sigma value.
sigmaXsigma The standard deviation of the kernel along the X axis (horizontal direction).
sigmaYsigma The standard deviation of the kernel along the Y axis (horizontal direction).
borderTypeThe border type specifies the image boundary when the kernel is applied to the image boundary. The possible values ​​are: cv.BORDER_CONSTANT cv.BORDER_REPLICATE cv.BORDER_REFLECT cv.BORDER_WRAP cv.BORDER_REFLECT_101 cv.BORDER_TRANSPARENT cv.BORDER_REFLECT101 cv.BORDER_DEFAULT ISOLA.

The specific code of using OpenCV to implement Gaussian blur in Python

import cv2
import numpy as np
import sys

# https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt
prototxt_path = "weights/deploy.prototxt.txt"
# https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel 
model_path = "weights/res10_300x300_ssd_iter_140000_fp16.caffemodel"

# 加载Caffe模型
model = cv2.dnn.readNetFromCaffe(prototxt_path, model_path)
image_file = "image.jpg"
# 读取所需图像
image = cv2.imread(image_file)
# 获取图像的宽度和高度
h, w = image.shape[:2]
# 高斯模糊核的大小取决于原始图像的宽度和高度
kernel_width = (w // 7) | 1
kernel_height = (h // 7) | 1
# 预处理图像:调整大小并执行平均减法
blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300), (104.0, 177.0, 123.0))
# 将图像输入神经网络
model.setInput(blob)
# 进行推理并得到结果
output = np.squeeze(model.forward())
# output 是一个 numpy 数组,它检测了所有的人脸,让我们迭代这个数组,只模糊我们确信它是人脸的部分:
for i in range(0, output.shape[0]):
    confidence = output[i, 2]
    # get the confidence
    # 如果置信度高于40%,则模糊边界框(面)
    if confidence > 0.4:
        # 得到周围的盒子cordinate和升级到原来的形象
        box = output[i, 3:7] * np.array([w, h, w, h])
        # 转换为整数
        start_x, start_y, end_x, end_y = box.astype(np.int)
        # 获取人脸图像
        face = image[start_y: end_y, start_x: end_x]
        # 对这张脸应用高斯模糊
        face = cv2.GaussianBlur(face, (kernel_width, kernel_height), 0)
        # 将模糊的人脸放入原始图像中
        image[start_y: end_y, start_x: end_x] = face
cv2.imshow("image", image)
cv2.waitKey(0)
cv2.imwrite("image_blurred.jpg", image)

Here, we are unlike the previous face detection tutorial where we draw a bounding box for each detected face. Instead, here we take the box coordinates and apply Gaussian blur to them.

Code analysis

The cv2.GaussianBlur() method uses a Gaussian filter to blur the image, applying the median value to the center pixel within the kernel size. It accepts the input image as the first parameter, the Gaussian kernel size as the tuple in the second parameter, and the sigma parameter as the third parameter.

We calculated the Gaussian kernel size from the original image, it must be an odd number and a positive integer, I divided the original image by 7, so it depends on the image shape, and perform bitwise OR to ensure that the resulting value is odd, of course you can set the kernel size yourself , The bigger the blur.

Original Picture
Gaussian Blur Image

The following is combined with the camera to blur my ugly face, the specific code is shown below.

import cv2
import numpy as np
import time

# https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt
prototxt_path = "weights/deploy.prototxt.txt"
# https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel 
model_path = "weights/res10_300x300_ssd_iter_140000_fp16.caffemodel"
model = cv2.dnn.readNetFromCaffe(prototxt_path, model_path)
cap = cv2.VideoCapture(0)
while True:
    start = time.time()
    _, image = cap.read()
    h, w = image.shape[:2]
    # 高斯模糊核的大小取决于原始图像的宽度和高度
    kernel_width = (w // 7) | 1
    kernel_height = (h // 7) | 1
    # 预处理图像:调整大小并执行平均减法
    blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300), (104.0, 177.0, 123.0))
    # 将图像输入神经网络
    model.setInput(blob)
    # 进行推理并得到结果
    output = np.squeeze(model.forward())
    # output 是一个 numpy 数组,它检测了所有的人脸,让我们迭代这个数组,只模糊我们确信它是人脸的部分:
    for i in range(0, output.shape[0]):
        confidence = output[i, 2]
        # get the confidence
        # 如果置信度高于40%,则模糊边界框(面)
        if confidence > 0.4:
            # 得到周围的盒子cordinate和升级到原来的形象
            box = output[i, 3:7] * np.array([w, h, w, h])
            # 转换为整数
            start_x, start_y, end_x, end_y = box.astype(np.int)
            # 获取人脸图像
            face = image[start_y: end_y, start_x: end_x]
            # 对这张脸应用高斯模糊
            face = cv2.GaussianBlur(face, (kernel_width, kernel_height), 0)
            # 将模糊的人脸放入原始图像中
            image[start_y: end_y, start_x: end_x] = face
    cv2.imshow("image", image)
    if cv2.waitKey(1) == ord("q"):
        break
    time_elapsed = time.time() - start
    fps = 1 / time_elapsed
    print("FPS:", fps)

cv2.destroyAllWindows()
cap.release()

Of course, Opencv also supports video transmission, the following code is to realize the blur of the face when reading the video, as shown below.

import cv2
import numpy as np
import time
import sys

# https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt
prototxt_path = "weights/deploy.prototxt.txt"
# https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel 
model_path = "weights/res10_300x300_ssd_iter_140000_fp16.caffemodel"

model = cv2.dnn.readNetFromCaffe(prototxt_path, model_path)
video_file = "长的丑就是罪.mp4"
# 从视频捕获帧
cap = cv2.VideoCapture(video_file)
fourcc = cv2.VideoWriter_fourcc(*"XVID")
_, image = cap.read()
print(image.shape)
out = cv2.VideoWriter("output.avi", fourcc, 20.0, (image.shape[1], image.shape[0]))
while True:
    start = time.time()
    captured, image = cap.read()
    if not captured:
        break
    h, w = image.shape[:2]
    kernel_width = (w // 7) | 1
    kernel_height = (h // 7) | 1
    # 预处理图像:调整大小并执行平均减法
    blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300), (104.0, 177.0, 123.0))
    # 将图像输入神经网络
    model.setInput(blob)
    # 进行推理并得到结果
    output = np.squeeze(model.forward())
    # output 是一个 numpy 数组,它检测了所有的人脸,让我们迭代这个数组,只模糊我们确信它是人脸的部分:
    for i in range(0, output.shape[0]):
        confidence = output[i, 2]
        # get the confidence
        # 如果置信度高于40%,则模糊边界框(面)
        if confidence > 0.4:
            # 得到周围的盒子cordinate和升级到原来的形象
            box = output[i, 3:7] * np.array([w, h, w, h])
            # 转换为整数
            start_x, start_y, end_x, end_y = box.astype(np.int)
            # 获取人脸图像
            face = image[start_y: end_y, start_x: end_x]
            # 对这张脸应用高斯模糊
            face = cv2.GaussianBlur(face, (kernel_width, kernel_height), 0)
            # 将模糊的人脸放入原始图像中
            image[start_y: end_y, start_x: end_x] = face
    cv2.imshow("image", image)
    if cv2.waitKey(1) == ord("q"):
        break
    time_elapsed = time.time() - start
    fps = 1 / time_elapsed
    print("FPS:", fps)
    out.write(image)

cv2.destroyAllWindows()
cap.release()
out.release()

Original video:

Ugly is sin