2017-02-17 3 views
0

Я использую следующий код для скелеризации следующего изображения в open cv 3 с использованием C++. Входное изображение выглядит следующим образом. enter image description hereКак скелетонизировать изображение в открытом cv C++

#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

, которая не является достаточно гладкой. Здесь я использовал алгоритм прореживания чжан-суен. Я получил этот код из Интернета. Я новичок в открытии cv и C++. Я застрял здесь. Следующим шагом будет извлечение таких функций, как конечные точки, дыры и т. Д. Поэтому кто-то может помочь мне получить более гладкое скелетонированное изображение.

ответ

3

Это открытая проблема.

Это документ плюс рабочая программа Java в Интернете, которая делает более или менее то, что вы хотите. Но это все равно следует рассматривать как экспериментальное.

enter image description here

Если вы нашли this code полезной в ваших исследований/программного обеспечения, пожалуйста, рассмотрите со ссылкой на следующие публикации:

Андрес Солис Montero и Jochen Lang. Skeleton pruning by contour approximation and the integer medial axis transform. Компьютеры & Графика, Elsevier, 2012.

Авторы
  1. Andrés Solís Montero
  2. Jochen Lang
  3. Дэвид Lareau
  4. Ана Лаура Перес
  5. Corey Edmunds
+0

ли есть способ получить код. –

+0

Перейти к ссылке github: https://github.com/asolis/skeletonPruning –

+0

Большое вам спасибо за ваше внимание. Я попробую с этим и дам вам знать. :) –

Смежные вопросы