【问题标题】:Bounding box of blob in image图像中 blob 的边界框
【发布时间】:2021-03-31 08:42:07
【问题描述】:

我有一张黑色背景的灰度图像,上面有一些非黑色的物体,如下所示:

现在我想找到每个对象的最小(矩形)边界框。如果有帮助,我可以在每个对象内提供一个起点。

由于没有花哨的阈值或任何东西,我想避免像 Canny 这样的东西来寻找轮廓。如果一个像素不为 0,则它在 blob 中。

【问题讨论】:

  • 寻找边缘追踪算法。如果您不知道有多少斑点,请先读取图像中的水平线和垂直线,寻找有斑点的东西。一旦你找到一个,找到一个边缘并追踪它。然后继续寻找模糊的东西,消除你已经找到的东西。你知道的关于 blob 的规则越多(最小大小、blob 的数量等),它运行的速度就越快。我刚刚重新阅读,您在博客中有一个起点。从那里往下看,找到一个边缘,然后走。

标签: c# opencv bounding-box


【解决方案1】:

为了在图像中不完全黑色的任何地方绘制矩形,您可以执行以下操作:

imagefile = '/path/to/your/image'
img = cv2.imread(imagefile)

# Convert you image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# Threshold the image to extract only objects that are not black
# You need to use a one channel image, that's why the slice to get the first layer
tv, thresh = cv2.threshold(gray[:,:,0], 1, 255, cv2.THRESH_BINARY)

# Get the contours from your thresholded image
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]

# Create a copy of the original image to display the output rectangles
output = img.copy()

# Loop through your contours calculating the bounding rectangles and plotting them
for c in contours:
    x, y, w, h = cv2.boundingRect(c)
    cv2.rectangle(output, (x,y), (x+w, y+h), (0, 0, 255), 2)
# Display the output image
plt.imshow(cv2.cvtColor(output, cv2.COLOR_BGR2RGB))

【讨论】:

    【解决方案2】:

    不管你使用什么,你仍然需要遍历所有像素。虽然Bitmap.GetPixel(x,y) 经常被使用,但是速度很慢。但如果你锁定内存中的位并遍历字节数组,它会快数百倍。

    请查看document 以了解内存中图像的锁定位。

    【讨论】:

    • 自己实现一些循环不会是问题,我也熟悉位锁定。我只是在想这样一个简单的目标可能可以用一些现有的库函数来完成,而不是自己重新发明轮子。该库也可能会遍历所有像素,是的,很清楚。但是,为什么要重新发明轮子。
    • 我不确定这样的库是否存在。但是,如果您已经开始发明轮子,那么您现在就拥有了。
    • 否则我仍然会调试一些奇怪的边缘情况。 @Carlos Melus 版本效果很好,所以有一个库函数。这不像我花时间等待答案涂鸦,但在此期间我做了其他事情。所以总的来说,这仍然是最快且最干净的解决方案。
    猜你喜欢
    • 2021-08-29
    • 1970-01-01
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 2022-08-16
    • 2019-04-05
    • 2014-12-06
    相关资源
    最近更新 更多