如何使用 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 Cascade (xml) 以跟踪手或手指?