読者です 読者をやめる 読者になる 読者になる

のどあめ

ググってもなかなか出てこなかった情報を垂れ流すブログ。

OpenCV 3.0 で cvSegmentFGMask

OpenCV 3.0.0 では,IplImage,legacy関数などの1.x系のサポートがなくなっています.
つまりcvHogehogeみたいな関数は使えません.
たいていの機能はcv::Hogehogeみたいな関数が実装されているのですが,一部の関数は代替関数がなくて残念なことになる場合があります.

私の環境でも,一部のプログラムで使っていたcvSegmentFGMaskが使えなくなり,困っていました.
cvSegmentFGMaskは,ノイズっぽいmask画像をいい感じにまとめてくれる関数です.

この度cvSegmentFGMaskをOpenCV 3.0で使えるように1.x系のソースを参考にして2.x系で実装しました.

cvSegmentFGMaskの2.0系実装

cvSegmentFGMask.cpp

#include <opencv2/opencv.hpp>

namespace cv {
  void SegmentFGMask(InputArray src, OutputArray dst, bool poly1Hull0, float perimScale, Point offset=Point(0,0))
  {
    Mat mask = src.getMat().clone();
    if(mask.type() != CV_8UC1) throw std::runtime_error("src.type() != CV_8UC1");

    Mat new_mask = Mat::zeros(mask.size(), mask.type());

    std::vector<std::vector<Point>> contours;
    findContours(mask, contours,RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, offset);

    const Scalar white(255);
    for (int i = 0; i < contours.size(); i++){
      double len = cv::arcLength(contours[i], true);
      double q = (mask.rows + mask.cols) / perimScale; 

      if (len >= q){
        std::vector<std::vector<Point>> tmp_contours(1);
        if (poly1Hull0){
          cv::approxPolyDP(contours[i], tmp_contours[0], 2.0, true);
        } else{
          tmp_contours[0] = contours[i];
        }
        drawContours(new_mask, tmp_contours, 0, white, -1, 8,cv::noArray(),-1,Point(-offset.x,-offset.y));
      }
    }
    new_mask.copyTo(dst);
  }
}

int main(){
  cv::VideoCapture video("./WalkByShop1cor.mpg");
  cv::BackgroundSubtractorMOG bgs;

  while(1){
    cv::Mat image;
    video >> image;

    if(image.empty()) break;
    cv::Mat mask;
    bgs(image,mask);
    cv::Mat segmented_mask;
    cv::SegmentFGMask(mask,segmented_mask,true,16.0f);
    {
      cv::Mat tmp;
      cv::hconcat(mask,segmented_mask,tmp);
      cv::imshow("mask",tmp);
      char k = cv::waitKey(1);
      if(k == 'q') break;
    }
  }
  return 0;
}

結果

左が普通の背景差分.右がcv::SegmentFGMaskをかけたものです.
f:id:ykicisk:20150203000821p:plain

今回のまとめ

必要がなければOpenCV 2.x 系に戻しましょう.