2017-02-17 5 views
0

私は以下のコードを使って、open cv 3でC++を使って以下の画像をスケルトン化しています。入力画像は以下の通りです。 enter image description hereopen cvで画像をスケルトン化する方法

#include "stdafx.h" 
#include <opencv2/opencv.hpp> 

#include <iostream> 
#include <vector> 
#include <opencv2/opencv.hpp> 
#include <opencv/cvaux.h> 
#include <opencv2/core/core.hpp> 
#include "opencv2/imgproc/imgproc.hpp" 
#include <opencv2/highgui/highgui.hpp> 


using namespace cv; 
using namespace std; 

/** 
* Perform one thinning iteration. 
* Normally you wouldn't call this function directly from your code. 
* 
* Parameters: 
*  im Binary image with range = [0,1] 
*  iter 0=even, 1=odd 
*/ 
void thinningIteration(cv::Mat& img, int iter) 
{ 
    CV_Assert(img.channels() == 1); 
    CV_Assert(img.depth() != sizeof(uchar)); 
    CV_Assert(img.rows > 3 && img.cols > 3); 

    cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1); 

    int nRows = img.rows; 
    int nCols = img.cols; 

    if (img.isContinuous()) { 
     nCols *= nRows; 
     nRows = 1; 
    } 

    int x, y; 
    uchar *pAbove; 
    uchar *pCurr; 
    uchar *pBelow; 
    uchar *nw, *no, *ne; // north (pAbove) 
    uchar *we, *me, *ea; 
    uchar *sw, *so, *se; // south (pBelow) 

    uchar *pDst; 

    // initialize row pointers 
    pAbove = NULL; 
    pCurr = img.ptr<uchar>(0); 
    pBelow = img.ptr<uchar>(1); 

    for (y = 1; y < img.rows - 1; ++y) { 
     // shift the rows up by one 
     pAbove = pCurr; 
     pCurr = pBelow; 
     pBelow = img.ptr<uchar>(y + 1); 

     pDst = marker.ptr<uchar>(y); 

     // initialize col pointers 
     no = &(pAbove[0]); 
     ne = &(pAbove[1]); 
     me = &(pCurr[0]); 
     ea = &(pCurr[1]); 
     so = &(pBelow[0]); 
     se = &(pBelow[1]); 

     for (x = 1; x < img.cols - 1; ++x) { 
      // shift col pointers left by one (scan left to right) 
      nw = no; 
      no = ne; 
      ne = &(pAbove[x + 1]); 
      we = me; 
      me = ea; 
      ea = &(pCurr[x + 1]); 
      sw = so; 
      so = se; 
      se = &(pBelow[x + 1]); 

      int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) + 
       (*ea == 0 && *se == 1) + (*se == 0 && *so == 1) + 
       (*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) + 
       (*we == 0 && *nw == 1) + (*nw == 0 && *no == 1); 
      int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw; 
      int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we); 
      int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we); 

      if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0) 
       pDst[x] = 1; 
     } 
    } 

    img &= ~marker; 
} 

/** 
* Function for thinning the given binary image 
* 
* Parameters: 
*  src The source image, binary with range = [0,255] 
*  dst The destination image 
*/ 
void thinning(const cv::Mat& src, cv::Mat& dst) 
{ 
    dst = src.clone(); 
    dst /= 255;   // convert to binary image 

    cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1); 
    cv::Mat diff; 

    do { 
     thinningIteration(dst, 0); 
     thinningIteration(dst, 1); 
     cv::absdiff(dst, prev, diff); 
     dst.copyTo(prev); 
    } while (cv::countNonZero(diff) > 0); 

    dst *= 255; 
} 



/** 
* This is an example on how to call the thinning funciton above 
*/ 





int main() 
{ 
    cv::Mat src = cv::imread("G:\\realimage9.jpg"); 
    /*Mat image = imread("G:\\realimage.jpg", CV_LOAD_IMAGE_UNCHANGED);*/ 
    if (!src.data) 
     return -1; 


    cv::Mat bw; 
    cv::cvtColor(src, bw, CV_BGR2GRAY); 







    // /*dilate(bw, bw, Mat(), Point(-1, -1), 4); 
    // erode(bw, bw, Mat(), Point(-1, -1), 2);*/ 
    GaussianBlur(bw, bw, cv::Size(9, 9), 2, 2); 

    cv::imshow("blur", bw); 

    cv::threshold(bw, bw, 10, 255, CV_THRESH_BINARY_INV); 
    cv::imshow("convert", bw); 




    thinning(bw, bw); 
    cv::imshow("src", src); 
    cv::imshow("dst", bw); 
    cv::waitKey(); 
    return 0; 



} 

私が手出力が十分に滑らかではありませんenter image description here

です。ここではzhang-suen-thinningアルゴリズムを使用しています。私はインターネットからこのコードを手に入れました。私はcvとC++を開くのが新しいです。私はここにくっついている。私の次のステップは、エンドポイント、穴などのような特徴を抽出することです。そのため、より滑らかなスケルトン画像を得るために役立つかもしれません。

答えて

3

これは未解決の問題です。

これは、Web上にある紙の上に、あなたが望むものを多かれ少なかれ実行する、Javaのプログラムです。しかしそれはまだ実験的なものと考えるべきです。あなたがあなたの研究/ソフトウェアに便利this codeを見つけた場合

enter image description here

、以下の出版物を引用考慮してください。

アンドレス・ソリスモンテーロとヨッヘン・ラング。 Skeleton pruning by contour approximation and the integer medial axis transform。 コンピュータ&グラフィックス、エルゼビア、2012年

寄与
  1. Andrés Solís Montero
  2. Jochen Lang
  3. デビッドLareau
  4. アナ・ローラ・ペレス
  5. コリー・エドマンズ
+0

ですコードを取得する方法があります。 –

+0

githubのリンクにアクセスしてください:https://github.com/asolis/skeletonPruning –

+0

ありがとうございました。私はこれを試し、あなたに知らせるでしょう。 :) –

関連する問題