gpt4 book ai didi

python - 如何在 OpenCV 中找到二进制骨架图像的端点?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:55:03 27 4
gpt4 key购买 nike

我有一个骨架作为二进制像素,例如:

Example binary skeleton image

我想找到这个骨架的端点坐标(在本例中有四个),如果适用,可以使用 Open CV。

效率很重要,因为我要实时分析视频源中的许多内容,并且需要同时做很多其他事情。

(请注意,很抱歉上面的屏幕截图有调整大小的人工制品,但它是我正在使用的 8-connected 骨架。)

最佳答案

根据您个人资料中问题和答案的标签,我假设您需要 C++ 实现。骨架化对象时,对象的厚度应为 1 像素。因此,我可以建议的一件事是找到图像中非零的像素,然后在该像素周围的 8 连通邻域中搜索并计算那些非零的像素。如果计数仅为 2,则这是骨架端点的候选者。请注意,我还将忽略边界,这样我们就不会越界。如果计数为 1,则它是一个嘈杂的孤立像素,因此我们应该忽略它。如果它是 3 或更多,那么这意味着您正在检查骨架中某个点的骨架的一部分,或者您正在检查多条线连接在一起的点,因此这也不应该是端点。

老实说,除了根据这个标准检查所有骨架像素之外,我想不出任何算法....所以复杂度将是 O(mn),其中 mn 是图像的行和列。对于图像中的每个像素,8 像素邻域检查需要恒定时间,这对于您检查的所有骨架像素都是相同的。但是,这肯定是次线性的,因为图像中的大部分像素将为 0,因此大多数时候不会进行 8 像素邻域检查。

因此,这是我会尝试的,假设您的图像存储在名为 imcv::Mat 结构中,它是单个 channel (灰度)图像,类型为 uchar。我还将以 std::vector 类型存储骨架端点所在位置的坐标。每次我们检测到一个骨架点时,我们都会一次将两个整数添加到 vector 中 - 我们检测到结束骨架点的行和列。

// Declare variable to count neighbourhood pixels
int count;

// To store a pixel intensity
uchar pix;

// To store the ending co-ordinates
std::vector<int> coords;

// For each pixel in our image...
for (int i = 1; i < im.rows-1; i++) {
for (int j = 1; j < im.cols-1; j++) {

// See what the pixel is at this location
pix = im.at<uchar>(i,j);

// If not a skeleton point, skip
if (pix == 0)
continue;

// Reset counter
count = 0;

// For each pixel in the neighbourhood
// centered at this skeleton location...
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {

// Get the pixel in the neighbourhood
pix = im.at<uchar>(i+y,j+x);

// Count if non-zero
if (pix != 0)
count++;
}
}

// If count is exactly 2, add co-ordinates to vector
if (count == 2) {
coords.push_back(i);
coords.push_back(j);
}
}
}

如果你想在完成后显示坐标,只需检查这个 vector 中的每一对元素:

for (int i = 0; i < coords.size() / 2; i++)
cout << "(" << coords.at(2*i) << "," coords.at(2*i+1) << ")\n";

为了完整起见,这里还有一个 Python 实现。我正在使用一些 numpy 的函数来让我自己更轻松地完成这项工作。假设你的图片存储在img中,也是一张灰度图,导入OpenCV库和numpy(即import cv2import numpy as np), 这是等效的代码:

# Find row and column locations that are non-zero
(rows,cols) = np.nonzero(img)

# Initialize empty list of co-ordinates
skel_coords = []

# For each non-zero pixel...
for (r,c) in zip(rows,cols):

# Extract an 8-connected neighbourhood
(col_neigh,row_neigh) = np.meshgrid(np.array([c-1,c,c+1]), np.array([r-1,r,r+1]))

# Cast to int to index into image
col_neigh = col_neigh.astype('int')
row_neigh = row_neigh.astype('int')

# Convert into a single 1D array and check for non-zero locations
pix_neighbourhood = img[row_neigh,col_neigh].ravel() != 0

# If the number of non-zero locations equals 2, add this to
# our list of co-ordinates
if np.sum(pix_neighbourhood) == 2:
skel_coords.append((r,c))

要显示终点的坐标,您可以这样做:

print "".join(["(" + str(r) + "," + str(c) + ")\n" for (r,c) in skel_coords])

小注:此代码未经测试。我没有在这台机器上安装 C++ OpenCV,所以希望我写的能起作用。如果它不能编译,您当然可以将我所做的翻译成正确的语法。祝你好运!

关于python - 如何在 OpenCV 中找到二进制骨架图像的端点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26537313/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com