Skip to content

Commit a0910e2

Browse files
committed
Esqueletizar una imagen binaria
Implementación del algoritmo de Zhang Suen y Guo Hall.
1 parent 615b918 commit a0910e2

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

opencv-esqueleto/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
cmake_minimum_required(VERSION 3.0)
2+
3+
project( Tutorial_OpenCV_Esqueleto )
4+
5+
find_package( OpenCV 3.0.0 REQUIRED )
6+
7+
file(COPY star.jpg DESTINATION data)
8+
9+
add_executable( ${PROJECT_NAME} source.cpp)
10+
target_link_libraries( ${PROJECT_NAME} ${OpenCV_LIBS} )

opencv-esqueleto/source.cpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#include <iostream>
2+
#include <opencv2/opencv.hpp>
3+
4+
using namespace cv;
5+
using namespace std;
6+
7+
#define THINNING_ZHANGSUEN 1
8+
#define THINNING_GUOHALL 2
9+
10+
// Applies a thinning iteration to a binary image
11+
static void thinningIteration(Mat img, int iter, int thinningType) {
12+
Mat marker = Mat::zeros(img.size(), CV_8UC1);
13+
14+
if (thinningType == THINNING_ZHANGSUEN) {
15+
for (int i = 1; i < img.rows - 1; i++)
16+
{
17+
for (int j = 1; j < img.cols - 1; j++)
18+
{
19+
uchar p2 = img.at<uchar>(i - 1, j);
20+
uchar p3 = img.at<uchar>(i - 1, j + 1);
21+
uchar p4 = img.at<uchar>(i, j + 1);
22+
uchar p5 = img.at<uchar>(i + 1, j + 1);
23+
uchar p6 = img.at<uchar>(i + 1, j);
24+
uchar p7 = img.at<uchar>(i + 1, j - 1);
25+
uchar p8 = img.at<uchar>(i, j - 1);
26+
uchar p9 = img.at<uchar>(i - 1, j - 1);
27+
28+
int A = (p2 == 0 && p3 == 1) + (p3 == 0 && p4 == 1) +
29+
(p4 == 0 && p5 == 1) + (p5 == 0 && p6 == 1) +
30+
(p6 == 0 && p7 == 1) + (p7 == 0 && p8 == 1) +
31+
(p8 == 0 && p9 == 1) + (p9 == 0 && p2 == 1);
32+
int B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
33+
int m1 = iter == 0 ? (p2 * p4 * p6) : (p2 * p4 * p8);
34+
int m2 = iter == 0 ? (p4 * p6 * p8) : (p2 * p6 * p8);
35+
36+
if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
37+
marker.at<uchar>(i, j) = 1;
38+
}
39+
}
40+
}
41+
42+
if (thinningType == THINNING_GUOHALL) {
43+
for (int i = 1; i < img.rows - 1; i++)
44+
{
45+
for (int j = 1; j < img.cols - 1; j++)
46+
{
47+
uchar p2 = img.at<uchar>(i - 1, j);
48+
uchar p3 = img.at<uchar>(i - 1, j + 1);
49+
uchar p4 = img.at<uchar>(i, j + 1);
50+
uchar p5 = img.at<uchar>(i + 1, j + 1);
51+
uchar p6 = img.at<uchar>(i + 1, j);
52+
uchar p7 = img.at<uchar>(i + 1, j - 1);
53+
uchar p8 = img.at<uchar>(i, j - 1);
54+
uchar p9 = img.at<uchar>(i - 1, j - 1);
55+
56+
int C = ((!p2) & (p3 | p4)) + ((!p4) & (p5 | p6)) + ((!p6) & (p7 | p8)) + ((!p8) & (p9 | p2));
57+
int N1 = (p9 | p2) + (p3 | p4) + (p5 | p6) + (p7 | p8);
58+
int N2 = (p2 | p3) + (p4 | p5) + (p6 | p7) + (p8 | p9);
59+
int N = N1 < N2 ? N1 : N2;
60+
int m = iter == 0 ? ((p6 | p7 | (!p9)) & p8) : ((p2 | p3 | (!p5)) & p4);
61+
62+
if ((C == 1) && ((N >= 2) && ((N <= 3)) & (m == 0)))
63+
marker.at<uchar>(i, j) = 1;
64+
}
65+
}
66+
}
67+
68+
img &= ~marker;
69+
}
70+
71+
// Apply the thinning procedure to a given image
72+
void thinning(InputArray input, OutputArray output, int thinningType) {
73+
Mat processed = input.getMat().clone();
74+
// Enforce the range of the input image to be in between 0 - 255
75+
processed /= 255;
76+
77+
Mat prev = Mat::zeros(processed.size(), CV_8UC1);
78+
Mat diff, temp;
79+
80+
do {
81+
thinningIteration(processed, 0, thinningType);
82+
thinningIteration(processed, 1, thinningType);
83+
absdiff(processed, prev, diff);
84+
processed.copyTo(prev);
85+
86+
//// muestra la animacion en cada iteracion del algoritmo
87+
//temp = processed * 255;
88+
//imshow("test", temp);
89+
//waitKey(10);
90+
//// end animacion
91+
92+
} while (countNonZero(diff) > 0);
93+
94+
processed *= 255;
95+
96+
output.assign(processed);
97+
}
98+
99+
100+
int main(int argc, char** argv)
101+
{
102+
Mat image = imread("data/star.jpg", CV_LOAD_IMAGE_GRAYSCALE);
103+
104+
if (image.empty())
105+
{
106+
printf("No image data \n");
107+
return -1;
108+
}
109+
110+
Mat src = image.clone();
111+
thinning(src, src, 2);
112+
113+
// 1. dibujar el esqueleto a color verde sobre la imagen original
114+
cvtColor(image, image, CV_GRAY2BGR);
115+
116+
for (int i = 0; i < image.cols; i++)
117+
{
118+
for (int j = 0; j < image.rows; j++)
119+
{
120+
Scalar intensity = src.at<uchar>(j, i);
121+
if (intensity.val[0] == 255) {
122+
image.at<Vec3b>(j, i) = Vec3b(0, 255, 0);
123+
}
124+
}
125+
}
126+
// end 1
127+
128+
imshow("OpenCV Skeleton Final", src);
129+
imshow("Original Skeleton Final", image);
130+
waitKey(0);
131+
132+
return 0;
133+
}

opencv-esqueleto/star.jpg

24.9 KB
Loading

0 commit comments

Comments
 (0)