FrontPage | changes | 一覧 | 新規 | 検索 | 設定

floodFillでラベリング

最終更新: 2014年12月19日()23:40; Revision: 1.5; by momma
編集 | コピー | 変更点 | 履歴 | raw
  1. 概要
    1. 利点
    2. 欠点
  2. ソース
    1. C
    2. C++ I/F
  3. テスト用画像
    1. とりあえずテスト
    2. 256以上のBlob
    3. 4or8近傍

floodFill関数を用いてラベリング処理

任意の色で塗り潰しが可能なfloodFill関数を使ったラベリング処理

[編集]

概要

  1. 0 or 255の8bit画像を32bit画像へ変換し,255を0.5にする
  2. 画像をスキャンして0.5だったら1から始まるラベル番号++で塗る
  3. ヒストグラムを取得
  4. 背景のカウントを0
  5. std::sortまたはqsortを使ってサイズ順に並べ替え
  6. おしまい
[編集]

利点

[編集]

欠点

[編集]

ソース

[編集]

C

  /*
   * CfloodFill_Labeling.cpp
   *
   *  Created on: 2011/02/11
   *      Author: Eiichiro Momma
   */
  #include <opencv2/core/core_c.h>
  #include <opencv2/imgproc/imgproc_c.h>
  #include <opencv2/highgui/highgui_c.h>
  #include <stdio.h>
  #include <stdlib.h>
  
  //compat.hppから拝借
  #define cvGetHistValue_1D( hist, idx0 ) \
      ((float*)cvPtr1D( (hist)->bins, (idx0), 0))
  
  enum{
    nNeighbors = 8,
    isVisible = 1,
    vDelay = 10
  };
  
  //並び替え用
  typedef struct {
    int idx;
    float val;
  }histo_dat;
  
  int comp(const void *d1, const void *d2)
  {
    histo_dat left = *(histo_dat *)d1;
    histo_dat right = *(histo_dat *)d2;
    return right.val - left.val;
  }
  
  
  int main(void)
  {
    IplImage *fsrc;
    //0 or 255の2値画像
    IplImage *src = cvLoadImage("test3.png", CV_LOAD_IMAGE_GRAYSCALE);
    if (src==NULL)
      {
        return 1;
      }
    //255個以上のBlobへ対応するためCV_32Fへ
    fsrc = cvCreateImage(cvGetSize(src), IPL_DEPTH_32F, 1);
    cvConvertScale(src, fsrc, 1, 0);
  
    // 0~255 -> 0~0.5
    cvThreshold(fsrc, fsrc, 128, 0.5, CV_THRESH_BINARY);
    int nL=1;
    if(isVisible)
      {
        cvNamedWindow("src",CV_WINDOW_AUTOSIZE);
        cvShowImage("src",fsrc);
        cvWaitKey(0);
      }
  
    for (int y=0; y< fsrc->height; y++)
      {
        for (int x=0; x<fsrc->width; x++)
          {
            //floodFillでラベル=濃度の塗り潰し
            if (cvGetReal2D(fsrc, y, x) > 0.25 && cvGetReal2D(fsrc, y, x) < 0.75)
              {
                cvFloodFill(fsrc, cvPoint(x,y), cvScalar(nL), cvScalar(0.25), cvScalar(0.25), NULL, nNeighbors);
                if (isVisible)
                  {
                    cvShowImage("src",fsrc);
                    cvWaitKey(vDelay);
                  }
                nL++;
              }
          }
      }
    //BlobのサイズをcalcHistで求める
    int size[] = {nL};
    float range[]={0,nL};
    float* ranges[]={range};
    IplImage *imgs[]={fsrc};
    CvHistogram *h = cvCreateHist(1, size, CV_HIST_ARRAY, ranges, 1);
    cvCalcHist(imgs, h);
    float *fval;
    histo_dat hd;
    histo_dat *vhd = (histo_dat*)malloc(sizeof(hd)*nL);
    for (int i=0; i<nL; i++)
      {
        hd.idx = i;
        fval=cvGetHistValue_1D(h,i);
        hd.val = *fval;
        vhd[i] = hd;
      }
    //ignore background
    vhd[0].val = 0.0;
    cvSetReal1D(h->bins, 0, 0.0);
  
    qsort(vhd, nL, sizeof(hd), comp);
    for (int i=0; i<nL; i++)
      {
        printf("%d: %f\n", vhd[i].idx, vhd[i].val);
      }
  
    float maxVal;
    int mI;
    cvGetMinMaxHistValue(h, NULL, &maxVal, NULL, &mI);
    printf("max: %d, %f\n", mI, maxVal);
    if (isVisible)
      {
        cvConvertScale(fsrc, fsrc, 1.0/nL, 0);
        cvShowImage("src",fsrc);
        cvWaitKey(0);
      }
    free(vhd);
    return 0;
  }
[編集]

C++ I/F

  /*
   * floodFill_Labeling.cpp
   *
   *  Created on: 2011/02/01
   *      Author: Eiichiro Momma
   */
  #include <opencv2/core/core.hpp>
  #include <opencv2/imgproc/imgproc.hpp>
  #include <opencv2/highgui/highgui.hpp>
  #include <iostream>
  #include <vector>
  #include <algorithm>
  #include <functional>
  
  using namespace cv;
  enum{
    nNeighbors = 8, // 4 or 8 近傍
    isVisible = 1,  // 処理の過程,結果を表示
    vDelay = 10 // isVisibleでの遅延時間[ms]
  };
  
  //並び替え用
  struct histo_dat{
    int idx;
    float val;
  };
  bool operator<(const histo_dat& left, const histo_dat& right)
  {
    return left.val < right.val;
  }
  bool operator>(const histo_dat& left, const histo_dat& right)
  {
    return left.val > right.val;
  }
  
  int main(void)
  {
    Mat fsrc;
    //0 or 255の2値画像
    Mat src = imread("test3.png", CV_LOAD_IMAGE_GRAYSCALE);
    if (src.empty())
      {
        return 1;
      }
    //255個以上のBlobへ対応するためCV_32Fへ
    src.convertTo(fsrc, CV_32FC1, 1, 0);
    // 0~255 -> 0~0.5
    threshold(fsrc, fsrc, 128, 0.5, CV_THRESH_BINARY);
    int nL=1;
    if(isVisible)
      {
        namedWindow("src",CV_WINDOW_AUTOSIZE);
        imshow("src",fsrc);
        waitKey(0);
      }
    for (int y=0; y<fsrc.rows; y++)
      {
        for (int x=0; x<fsrc.cols; x++)
          {
            //floodFillでラベル=濃度の塗り潰し
            if (fsrc.at<float>(y,x) > 0.25 && fsrc.at<float>(y,x)< 0.75)
              {
                floodFill(fsrc, Point(x,y), Scalar(nL), NULL, Scalar(0.25), Scalar(0.25), nNeighbors);
                if (isVisible)
                  {
                    imshow("src",fsrc);
                    waitKey(vDelay);
                  }
                nL++;
              }
  
          }
      }
    //BlobのサイズをcalcHistで求める
    Mat histo;
    float range[]={0,nL};
    const float* ranges[]={range};
    calcHist(&fsrc, 1, 0, Mat(), histo, 1,&nL ,ranges, true, false);
  
    //std::sortで並び替え
    std::vector<histo_dat> vhd;
    histo_dat hd;
    for (int i=0; i<nL; i++)
      {
        hd.idx = i;
        hd.val = histo.at<float>(i);
        vhd.push_back(hd);
      }
    //ignore background
    vhd[0].val = 0.0;
    std::sort(vhd.begin(), vhd.end(), std::greater<histo_dat>());
    for (int i=0; i<nL; i++)
      {
        std::cout << vhd[i].idx << ": " << vhd[i].val << " pixel\n";
      }
  
    double maxVal;
    Point mP;
    minMaxLoc(histo, 0, &maxVal, 0, &mP, Mat());
    std::cout << "max idx is " << mP.y << ":" << maxVal << std::endl;
    if (isVisible)
      {
        fsrc.convertTo(fsrc, CV_32FC1, 1.0/nL , 0);
        imshow("src",fsrc);
        waitKey(0);
      }
    return 0;
  }
[編集]

テスト用画像

[編集]

とりあえずテスト

http://www.eml.ele.cst.nihon-u.ac.jp/~momma/img/floodFill_test1.png

[編集]

256以上のBlob

http://www.eml.ele.cst.nihon-u.ac.jp/~momma/img/floodFill_test2.png

[編集]

4or8近傍

http://www.eml.ele.cst.nihon-u.ac.jp/~momma/img/floodFill_test3.png

[編集]

Momma's wikiはgithub内へ引っ越す予定です

Powered by WiKicker

日本大学理工学部へ 電気工学科へ 門馬研究室へ