使用opencv/opencv4nodejs/Node.js对图像进行人脸检测并进行遮罩处理
动机
我想要创建一个工具,可以对使用前置摄像头拍摄的带有人物或带有脸部照片的证件照片进行脸部遮罩。
选择语言
在应用画像处理库opencv时,支持的语言有C/C++、Java和Python。根据这次的动机,我认为Python是最适合的选择。Python有大量的示例代码可供参考。但是,我对Python的知识了解较少,担心会花费较长时间。然而,我找到了一个可以在Node.js环境下使用opencv的库opencv4nodejs,所以决定试试看。
坑洞
opencv4nodejs 是一个使用 JavaScript 编写的 OpenCV 绑定库,它与原始的 OpenCV 相比,不仅在类型和方法上有所差异,而且还与 JavaScript 的语言规范相一致,包括参数等方面也有所不同。因此,无法简单地将 Python 代码直接替换为 opencv4nodejs 的使用方式。我之前对这一点考虑得有些太过简单,导致遇到了一些问题。
环境设立
Windows10(64位)上安装了Nodist(0.9.1) Node.js 11.13.0,并且安装了opencv4nodejs(5.5.0)。
这个公式的步骤请看这里。
事前提醒
-
- スペースを含むパスにインストールしない → node-gyp でパスが読めない
- 日本語を含むパスにインストールしない → opencvでパスが読めない
安装 CMake
在安装 opencv4nodejs 时会提示要求安装,如果没有安装会出错无法继续进行。
-
- 安装 CMake
- 将路径添加到包含可执行文件的文件夹 例如:G:\Program Files\CMake\bin
git
设置git允许长文件名(用于opencv4nodejs内的C++编译)
git config –system core.longpaths true
npm:一种用于JavaScript包管理的工具。
-
- 以下是这些命令的中文翻译:
安装 node-gyp
npm install –global node-gyp
安装 windows-build-tools
npm install –global windows-build-tools
※可能需要一些时间
安装 opencv4nodejs
npm install opencv4nodejs
※可能需要很长时间
实施
我用TypeScript来写的。
人脸检测
我直接使用了示例代码。在opencv4nodejs中,有许多丰富的示例源代码可供使用。
import * as cv from 'opencv4nodejs';
export const feceMaskBlur = (imagePath:string) => {
// 対象画像読込
const image = cv.imread(imagePath);
if (!image) {
throw new Error(`No file ${imagePath}`);
}
const classifier = new cv.CascadeClassifier(cv.HAAR_FRONTALFACE_ALT2);
// detect faces
const { objects, numDetections } = classifier.detectMultiScale(image.bgrToGray());
if (!objects.length) {
throw new Error(`No faces detected! ${imagePath}`);
}
console.log('顔検出した領域:', objects);
console.log('確度:', numDetections);
// draw detection
let blurImage:cv.Mat;
blurImage = image.copy();
objects.forEach((rect, i) => {
// 顔検出した部分に対してマスクを実施
blurImage = drawBlurRect(blurImage, rect, numDetections[i]);
});
// file 保存
cv.imwrite(imagePath, blurImage);
}
可以通过以下坐标和大小获取检测到的区域。
顔検出した領域: [ Rect { height: 525, width: 525, y: 1188, x: 1923 },
Rect { height: 262, width: 262, y: 3214, x: 2298 },
Rect { height: 584, width: 584, y: 878, x: 2714 } ]
確度: [ 8, 4, 11 ]
覆盖部分的图片
针对上述获取的区域,我们会应用掩码。在Python中,图像数据以二维数组的形式加载,因此可以通过指定坐标位置进行赋值。但是在opencv4nodejs中,由于格式不同,让我有些困惑。
def mosaic_area(src, x, y, width, height, ratio=0.1):
dst = src.copy()
dst[y:y + height, x:x + width] = mosaic(dst[y:y + height, x:x + width], ratio)
return dst
dst_area = mosaic_area(src, 100, 50, 100, 150)
cv2.imwrite('data/dst/opencv_mosaic_area.jpg', dst_area)
使用Python和OpenCV对图像进行马赛克处理(全图、局部、人脸等)。
我在搜索中找到了这个问题。
// 対象のRectを塗りつぶし
const drawBlurRect = (image: cv.Mat, rect: cv.Rect, numDetection: number):cv.Mat => {
// 領域の切り出し
const srcRoi:cv.Mat = image.getRegion(rect);
// 切り出した部分にマスクをかける
const masked = cv.blur(srcRoi, new cv.Size(rect.width,rect.height));
// 切り出した部分を元画像に合成
masked.copyTo(image.getRegion(rect));
return image;
}
执行
总结和觉察
如果要从图像中识别出某物,可以使用识别器,OpenCV中已经准备了用于此识别的预训练文件。
这次我们使用了Haar Cascade识别器的haarcascade_frontalface_alt2.xml(在代码中被称为cv.HAAR_FRONTALFACE_ALT2)(如示例所示)。
考虑到本次主要使用前置摄像头拍摄正面照片,因此面部识别匹配成功,但是需要注意的是侧脸的识别较困难。
请提供更多上下文。
-
- 【入門者向け解説】openCV顔検出の仕組と実践(detectMultiScale)
- OpenCV-CookBook 画像処理