2017-02-17 3 views
0

Ich benutze den folgenden Code, um das folgende Bild in open cv 3 mit C++ zu skelettieren. Das Eingabebild ist wie folgt. enter image description hereWie man ein Bild in open cv C++ skelettiert

#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; 



} 

Der Ausgang ich erhalte, ist enter image description here

, die nicht glatt genug ist. Ich habe hier den Zhang-Suen-Verdünnungsalgorithmus benutzt. Ich habe diesen Code aus dem Internet bekommen. Ich bin neu, um cv und C++ zu öffnen. Ich stecke hier fest. Mein nächster Schritt besteht darin, Features wie Endpunkte, Löcher usw. zu extrahieren. Daher könnte mir jemand helfen, ein besseres, glattes skelettiertes Bild zu erhalten.

Antwort

3

Es ist ein offenes Problem.

Dies ist ein Papier und ein funktionierendes Java-Programm im Web, das mehr oder weniger was Sie wollen. Aber es sollte immer noch als experimentell betrachtet werden.

enter image description here

Wenn Sie this code nützlich bei Ihrer Recherche/Software finden, beachten Sie bitte die folgenden Publikation zitiert:

Andrés Solís Montero und Jochen Lang. Skeleton pruning by contour approximation and the integer medial axis transform. Computer & Graphics, Elsevier, 2012.

Mitwirkende
  1. Andrés Solís Montero
  2. Jochen Lang
  3. David Lareau
  4. Ana Laura Perez
  5. Corey Edmunds
+0

Ist es gibt eine Möglichkeit, den Code zu bekommen. –

+0

Gehen Sie zum GitHub-Link: https://Github.com/Asolis/SkeletonPruning –

+0

Vielen Dank für Ihre freundliche Beratung. Ich werde es versuchen und dich wissen lassen. :) –

Verwandte Themen