如何使用 openCV 和 HAAR Cascades 来模糊人脸?

Posted

技术标签:

【中文标题】如何使用 openCV 和 HAAR Cascades 来模糊人脸?【英文标题】:How to use openCV and HAAR Cascades to blur faces? 【发布时间】:2013-08-06 13:24:29 【问题描述】:

我想知道是否有一种方法可以对 haarcascade 人脸分类器自动识别的人脸进行模糊处理。

使用下面的代码,我可以检测人脸、裁剪这张人脸周围的图像或在其上绘制一个矩形。

image = cv2.imread(imagepath)

# Specify the trained cascade classifier
face_cascade_name = "./haarcascade_frontalface_alt.xml"

# Create a cascade classifier
face_cascade = cv2.CascadeClassifier()

# Load the specified classifier
face_cascade.load(face_cascade_name)

#Preprocess the image
grayimg = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)
grayimg = cv2.equalizeHist(grayimg)

#Run the classifiers
faces = face_cascade.detectMultiScale(grayimg, 1.1, 2, 0|cv2.cv.CV_HAAR_SCALE_IMAGE, (30, 30))

print "Faces detected"

if len(faces) != 0:            # If there are faces in the images
    for f in faces:         # For each face in the image

        # Get the origin co-ordinates and the length and width till where the face extends
        x, y, w, h = [ v for v in f ]

        # Draw rectangles around all the faces
        cv2.rectangle(image, (x,y), (x+w,y+h), (255,255,255))
        sub_face = image[y:y+h, x:x+w]
        for i in xrange(1,31,2):
            cv2.blur(sub_face, (i,i))
        face_file_name = "./face_" + str(y) + ".jpg"
        cv2.imwrite(face_file_name, sub_face)

但我想模糊人脸,使他们无法被识别。

你知道怎么做吗?

感谢您的帮助

阿尔诺

【问题讨论】:

使用these 函数之一并传入包含人脸的图像子区域 嗨,Hammer,我想过,但我不知道如何仅模糊检测到面部的图像部分。谢谢。 我终于成功地做我想做的事了。为此,请按照您的建议应用 gaussianblur:sub_face = cv2.GaussianBlur(sub_face,(23, 23), 30) 然后我将此模糊图像重叠到新图像上:result_image[y:y+sub_face.shape[0], x:x+sub_face.shape[1]] = sub_face 对不起,我应该更明确一点。很高兴你明白了:) @ArnaudGeotribu,请将您的解决方案放入答案并接受它,以便搜索相同问题的人可以使用它。 【参考方案1】:

注意:神经网络(如 Resnet)现在比 HAAR Cascade 更准确地检测人脸,并且它们现在也集成在 OpenCV 中。它可能比使用这个问题中提到的解决方案更好。

但是,模糊/像素化面部的代码仍然适用。


您还可以通过添加包含面部区域 RGB 值平均值的正方形来像素化面部区域。

执行此操作的函数可能是这样的:

def pixelate_image(image: np.ndarray, nb_blocks=5, in_place=False) -> np.ndarray:
    """Return a pixelated version of a picture (need to be fed with a face to pixelate)"""
    # To pixelate, we will split into a given number of blocks
    # For each block, we will compute the average of RGB values of the block
    # And then we can just replace with a rectangle of this color
    # divide the input image into NxN blocks
    if not in_place:
        image = np.copy(image)
    h, w = image.shape[:2]
    blocks = tuple(
        np.linspace(0, d, nb_blocks + 1, dtype="int") for d in (w, h)
    )

    for i, j in product(*[range(1, len(s)) for s in blocks]):
        # compute the starting and ending (x, y)-coordinates
        # for the current block
        start = blocks[0][i - 1], blocks[1][j - 1]
        end = blocks[0][i], blocks[1][j]
        # extract the ROI using NumPy array slicing, compute the
        # mean of the ROI, and then draw a rectangle with the
        # mean RGB values over the ROI in the original image
        roi = image[start[1]:end[1], start[0]:end[0]]
        bgr = [int(x) for x in cv2.mean(roi)[:3]]
        cv2.rectangle(image, start, end, bgr, -1)

    return image

然后你只需要在这样的函数中使用它(使用pathlib 更新到 Python 3 并输入提示):

from pathlib import Path
from typing import Union

import cv2
import numpy as np

PathLike = Union[Path, str]

face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml")

def pixelate_faces_haar(img_path: PathLike, dest: Path):
    """Pixelate faces of people with OpenCV and save to a destination file"""
    img = cv2.imread(str(img_path))
    # To use cascade, we need to use Grayscale images
    # We can then detect faces
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.1, 4)

    for (x, y, width, height) in faces:
        roi = img[y:y+height, x:x+width]
        pixelate_image(roi, 15, in_place=True)

    dest.parent.mkdir(parents=True, exist_ok=True)
    cv2.imwrite(str(dest), img)
    print(f"Saved pixelated version of img_path to dest")```

【讨论】:

【参考方案2】:

您的代码的整个结尾可以替换为:

img[startX:endX, startY:endY] = cv2.blur(img[startX:endX, startY:endY], (23, 23))

而不是:

    # Get the origin co-ordinates and the length and width till where the face extends
    x, y, w, h = [ v for v in f ]

    # get the rectangle img around all the faces
    cv2.rectangle(image, (x,y), (x+w,y+h), (255,255,0), 5)
    sub_face = image[y:y+h, x:x+w]
    # apply a gaussian blur on this new recangle image
    sub_face = cv2.GaussianBlur(sub_face,(23, 23), 30)
    # merge this blurry rectangle to our final image
    result_image[y:y+sub_face.shape[0], x:x+sub_face.shape[1]] = sub_face

特别是因为您不要求使用圆形掩码,所以(对我而言)更容易阅读。

PS:很抱歉没有发表评论,没有足够的声誉来做这件事。即使该帖子已有 5 年历史,我想这可能是值得的,因为为这个特定问题找到了它..

【讨论】:

【参考方案3】:

我终于成功地做了我想做的事。 要做到这一点,请按照 Hammer 的建议应用 gaussianblur。 代码是:

image = cv2.imread(imagepath)
result_image = image.copy()

# Specify the trained cascade classifier
face_cascade_name = "./haarcascade_frontalface_alt.xml"

# Create a cascade classifier
face_cascade = cv2.CascadeClassifier()

# Load the specified classifier
face_cascade.load(face_cascade_name)

#Preprocess the image
grayimg = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)
grayimg = cv2.equalizeHist(grayimg)

#Run the classifiers
faces = face_cascade.detectMultiScale(grayimg, 1.1, 2, 0|cv2.cv.CV_HAAR_SCALE_IMAGE, (30, 30))

print "Faces detected"

if len(faces) != 0:         # If there are faces in the images
    for f in faces:         # For each face in the image

        # Get the origin co-ordinates and the length and width till where the face extends
        x, y, w, h = [ v for v in f ]

        # get the rectangle img around all the faces
        cv2.rectangle(image, (x,y), (x+w,y+h), (255,255,0), 5)
        sub_face = image[y:y+h, x:x+w]
        # apply a gaussian blur on this new recangle image
        sub_face = cv2.GaussianBlur(sub_face,(23, 23), 30)
        # merge this blurry rectangle to our final image
        result_image[y:y+sub_face.shape[0], x:x+sub_face.shape[1]] = sub_face
        face_file_name = "./face_" + str(y) + ".jpg"
        cv2.imwrite(face_file_name, sub_face)

# cv2.imshow("Detected face", result_image)
cv2.imwrite("./result.png", result_image)

阿诺

【讨论】:

您不需要if len(faces) != 0,for 循环不会遍历空列表。也就是,在每个 for 循环的顶部都有一个有效的内置 if 语句。 x,y,w,h = f 更pythonic 嗨 Arnaud,我在上面遇到了一个错误,你能帮忙吗?谢谢。顺便说一句,cv2.cv.CV_BGR2GRAY应该换成cv2.COLOR_BGR2HSV

以上是关于如何使用 openCV 和 HAAR Cascades 来模糊人脸?的主要内容,如果未能解决你的问题,请参考以下文章

使用OpenCV,Haar级联检测器进行面部眼睛嘴部检测

如何使用 OpenCV 创建 Haar Cascade (xml) 以跟踪手或手指?

Pyhton,OpenCV对象检测之——Haar级联人脸及眼睛检测

使用Python,OpenCV和Haar级联进行人脸检测

haar 训练 OpenCV 断言失败

如何利用OpenCV自带的级联分类器训练程序训练分类器