Skip to content

Commit 6246fad

Browse files
committed
Update ximgproc.hpp
1 parent 6965db1 commit 6246fad

File tree

3 files changed

+46
-68
lines changed

3 files changed

+46
-68
lines changed

modules/ximgproc/include/opencv2/ximgproc.hpp

+18-43
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,6 @@
1-
/*
2-
* By downloading, copying, installing or using the software you agree to this license.
3-
* If you do not agree to this license, do not download, install,
4-
* copy or use the software.
5-
*
6-
*
7-
* License Agreement
8-
* For Open Source Computer Vision Library
9-
* (3 - clause BSD License)
10-
*
11-
* Redistribution and use in source and binary forms, with or without modification,
12-
* are permitted provided that the following conditions are met :
13-
*
14-
* * Redistributions of source code must retain the above copyright notice,
15-
* this list of conditions and the following disclaimer.
16-
*
17-
* * Redistributions in binary form must reproduce the above copyright notice,
18-
* this list of conditions and the following disclaimer in the documentation
19-
* and / or other materials provided with the distribution.
20-
*
21-
* * Neither the names of the copyright holders nor the names of the contributors
22-
* may be used to endorse or promote products derived from this software
23-
* without specific prior written permission.
24-
*
25-
* This software is provided by the copyright holders and contributors "as is" and
26-
* any express or implied warranties, including, but not limited to, the implied
27-
* warranties of merchantability and fitness for a particular purpose are disclaimed.
28-
* In no event shall copyright holders or contributors be liable for any direct,
29-
* indirect, incidental, special, exemplary, or consequential damages
30-
* (including, but not limited to, procurement of substitute goods or services;
31-
* loss of use, data, or profits; or business interruption) however caused
32-
* and on any theory of liability, whether in contract, strict liability,
33-
* or tort(including negligence or otherwise) arising in any way out of
34-
* the use of this software, even if advised of the possibility of such damage.
35-
*/
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
364

375
#ifndef __OPENCV_XIMGPROC_HPP__
386
#define __OPENCV_XIMGPROC_HPP__
@@ -68,6 +36,8 @@
6836
/**
6937
@defgroup ximgproc Extended Image Processing
7038
@{
39+
@defgroup ximgproc_binarization Binarization
40+
7141
@defgroup ximgproc_edge Structured forests for fast edge detection
7242
7343
This module contains implementations of modern structured edge detection algorithms,
@@ -124,7 +94,7 @@ namespace cv
12494
namespace ximgproc
12595
{
12696

127-
//! @addtogroup ximgproc
97+
//! @addtogroup ximgproc_binarization
12898
//! @{
12999

130100
enum ThinningTypes{
@@ -179,15 +149,20 @@ CV_EXPORTS_W void niBlackThreshold( InputArray _src, OutputArray _dst,
179149
int blockSize, double k, int binarizationMethod = BINARIZATION_NIBLACK,
180150
double r = 128 );
181151

182-
/** @brief Applies a binary blob thinning operation, to achieve a skeletization of the input image.
152+
/** @brief Performs binary image thinning to obtain a skeletonized representation of the input image.
183153
184-
The function transforms a binary blob image into a skeletized form using the technique of Zhang-Suen.
154+
This function applies a thinning algorithm, reducing the binary blobs in the input image to a skeletal form.
155+
By default, it uses the Zhang-Suen technique, which iteratively removes pixels from the boundaries of the blobs
156+
while preserving the overall structure and connectivity of the objects.
157+
158+
@param src Source image: an 8-bit, single-channel binary image where the blobs are represented by pixels with a value of 255 (white),
159+
and the background is 0 (black).
160+
@param dst Destination image of the same size and type as src, where the result of the thinning operation will be stored.
161+
This operation can be performed in-place, meaning `src` and `dst` can be the same.
162+
@param thinningType The thinning algorithm to apply. By default, the Zhang-Suen algorithm is used. See cv::ximgproc::ThinningTypes for other options.
163+
*/
164+
CV_EXPORTS_W void thinning(InputArray src, OutputArray dst, int thinningType = THINNING_ZHANGSUEN);
185165

186-
@param src Source 8-bit single-channel image, containing binary blobs, with blobs having 255 pixel values.
187-
@param dst Destination image of the same size and the same type as src. The function can work in-place.
188-
@param thinningType Value that defines which thinning algorithm should be used. See cv::ximgproc::ThinningTypes
189-
*/
190-
CV_EXPORTS_W void thinning( InputArray src, OutputArray dst, int thinningType = THINNING_ZHANGSUEN);
191166

192167
/** @brief Performs anisotropic diffusion on an image.
193168

modules/ximgproc/src/thinning.cpp

+24-23
Original file line numberDiff line numberDiff line change
@@ -95,34 +95,32 @@ static uint8_t lut_guo_iter1[] = {
9595
static void thinningIteration(Mat &img, Mat &marker, const uint8_t* const lut) {
9696
int rows = img.rows;
9797
int cols = img.cols;
98-
marker.col(0).setTo(1);
99-
marker.col(cols - 1).setTo(1);
100-
marker.row(0).setTo(1);
101-
marker.row(rows - 1).setTo(1);
10298

103-
marker.forEach<uchar>([=](uchar& value, const int position[]) {
104-
int i = position[0];
105-
int j = position[1];
106-
if (i == 0 || j == 0 || i == rows - 1 || j == cols - 1) { return; }
99+
// Parallelized iteration over pixels excluding the boundary
100+
parallel_for_(Range(1, rows - 1), [&](const Range& range) {
101+
for (int i = range.start; i < range.end; i++) {
102+
uchar* imgRow = img.ptr(i);
103+
uchar* markerRow = marker.ptr(i);
104+
for (int j = 1; j < cols - 1; j++) {
105+
if (imgRow[j]) {
106+
uchar p2 = imgRow[j - cols] != 0;
107+
uchar p3 = imgRow[j - cols + 1] != 0;
108+
uchar p4 = imgRow[j + 1] != 0;
109+
uchar p5 = imgRow[j + cols + 1] != 0;
110+
uchar p6 = imgRow[j + cols] != 0;
111+
uchar p7 = imgRow[j + cols - 1] != 0;
112+
uchar p8 = imgRow[j - 1] != 0;
113+
uchar p9 = imgRow[j - cols - 1] != 0;
107114

108-
auto ptr = img.ptr(i, j); // p1
109-
if (ptr[0]) {
110-
uchar p2 = ptr[-cols] != 0;
111-
uchar p3 = ptr[-cols + 1] != 0;
112-
uchar p4 = ptr[1] != 0;
113-
uchar p5 = ptr[cols + 1] != 0;
114-
uchar p6 = ptr[cols] != 0;
115-
uchar p7 = ptr[cols - 1] != 0;
116-
uchar p8 = ptr[-1] != 0;
117-
uchar p9 = ptr[-cols - 1] != 0;
118-
119-
int neighbors = p9 | (p2 << 1) | (p3 << 2) | (p4 << 3) | (p5 << 4) | (p6 << 5) | (p7 << 6) | (p8 << 7);
120-
value = lut[neighbors];
115+
int neighbors = p9 | (p2 << 1) | (p3 << 2) | (p4 << 3) | (p5 << 4) | (p6 << 5) | (p7 << 6) | (p8 << 7);
116+
markerRow[j] = lut[neighbors];
117+
}
118+
}
121119
}
122120
});
123121

122+
// Bitwise AND and reset marker for the next iteration
124123
img &= marker;
125-
marker.setTo(0);
126124
}
127125

128126
// Apply the thinning procedure to a given image
@@ -132,7 +130,10 @@ void thinning(InputArray input, OutputArray output, int thinningType){
132130
// Enforce the range of the input image to be in between 0 - 255
133131
processed /= 255;
134132
Mat prev = processed.clone();
135-
Mat marker = Mat::zeros(processed.size(), CV_8UC1);
133+
134+
Mat marker,marker_inner = processed(Rect(1, 1, processed.cols - 2, processed.rows - 2));
135+
copyMakeBorder(marker_inner, marker, 1, 1, 1, 1, BORDER_ISOLATED | BORDER_CONSTANT, Scalar(255));
136+
136137
const auto lutIter0 = (thinningType == THINNING_GUOHALL) ? lut_guo_iter0 : lut_zhang_iter0;
137138
const auto lutIter1 = (thinningType == THINNING_GUOHALL) ? lut_guo_iter1 : lut_zhang_iter1;
138139
do {

modules/ximgproc/test/test_thinning.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ TEST(ximgproc_Thinning, simple_ZHANGSUEN)
1717
check_img = imread(dir + "cv/ximgproc/results/Thinning_ZHANGSUEN.png", IMREAD_GRAYSCALE);
1818
EXPECT_EQ(0, cvtest::norm(check_img, dst, NORM_INF));
1919

20-
thinning(~src, dst, THINNING_ZHANGSUEN);
20+
dst = ~src;
21+
thinning(dst, dst, THINNING_ZHANGSUEN);
2122

2223
check_img = imread(dir + "cv/ximgproc/results/Thinning_inv_ZHANGSUEN.png", IMREAD_GRAYSCALE);
2324
EXPECT_EQ(0, cvtest::norm(check_img, dst, NORM_INF));
@@ -34,7 +35,8 @@ TEST(ximgproc_Thinning, simple_GUOHALL)
3435
check_img = imread(dir + "cv/ximgproc/results/Thinning_GUOHALL.png", IMREAD_GRAYSCALE);
3536
EXPECT_EQ(0, cvtest::norm(check_img, dst, NORM_INF));
3637

37-
thinning(~src, dst, THINNING_GUOHALL);
38+
dst = ~src;
39+
thinning(dst, dst, THINNING_GUOHALL);
3840

3941
check_img = imread(dir + "cv/ximgproc/results/Thinning_inv_GUOHALL.png", IMREAD_GRAYSCALE);
4042
EXPECT_EQ(0, cvtest::norm(check_img, dst, NORM_INF));

0 commit comments

Comments
 (0)