이미지에 대해 얼굴 검출을 수행하고 마스크합니다 (opencv/opencv4nodejs/Node.js)

동기



인카메라로 인물이나 얼굴 사진들이 증명서를 촬영한 에비던스 화상에 대해서, 얼굴 부분의 마스크를 실시하는 툴을 작성하고 싶었다.

언어선정



이미지 처리 라이브러리 opencv의 해당 언어는 C/C++ Java Python입니다.
이번 동기인 툴적으로 사용한다면 Python이 적합하다고 생각합니다. 샘플 코드도 많이 있습니다. 그러나 자신이 파이썬에 대한 지식이 적고 시간이 걸릴 것 같아서 순회했습니다.
그러나 opencv를 Node.js 환경에서 사용할 수있는 라이브러리 opencv4nodejs을 찾았으므로 시도하기로 결정했습니다.

함정



opencv4nodejs는 opencv의 타입이나 메소드와 완전히 같은 명칭이 아니고, JavaScript의 언어 사양에 맞추어 인수등도 다릅니다. → Contribution Guide
따라서 파이썬 코드를 그대로 바꾸면 OK! 같은 형태로 구현할 수 없습니다.
자신은 여기를 안이하게 생각하고 있어 약간 빠졌습니다…

환경 구축



Windows10(64bit)
Nodist(0.9.1) Node.js 11.13.0 이상
opencv4nodejs(5.5.0) 설치

공식 절차는 여기

사전주의


  • 공백이있는 경로에 설치하지 마십시오. → node-gyp으로 경로를 읽을 수 없습니다.
  • 일본어가 포함 된 경로에 설치하지 않음 → opencv에서 경로를 읽을 수 없습니다

  • cmake 설치



    opencv4nodejs 설치 중에 요청되며, 그렇지 않으면 오류로 진행되지 않습니다.

  • cmake 설치
  • 실행 파일이 있는 폴더로 PATH를 통과시키는 예: G:\Program Files\CMake\bin

  • git



    git 긴 파일 이름 권한 설정 (opencv4nodejs 내에서 C++ 컴파일 용)git config --system core.longpaths true

    npm


  • 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 ]
    

    이미지의 일부 덮어쓰기



    위에서 얻은 영역에 마스크를 적용합니다.
    파이썬이라면 이미지의 데이터는 2차원 배열로 읽혀지기 때문에 좌표 위치를 지정하여 대입하는 형태로 기술할 수 있는 것입니다만, 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에서 이미지에 모자이크 처리 (전면, 부분, 얼굴 등) 보다 인용

    issue 을 검색하여 발견했습니다.
    
    // 対象の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 이미지 처리
  • 좋은 웹페이지 즐겨찾기