Ich benutze den folgenden Code, um das folgende Bild in open cv 3 mit C++ zu skelettieren. Das Eingabebild ist wie folgt. Wie 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;
}
, 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.
Ist es gibt eine Möglichkeit, den Code zu bekommen. –
Gehen Sie zum GitHub-Link: https://Github.com/Asolis/SkeletonPruning –
Vielen Dank für Ihre freundliche Beratung. Ich werde es versuchen und dich wissen lassen. :) –