我有一个大的二进制图像(4k x 7k pix),我想从中提取整个黄色部分作为一个矩形。我尝试了二元腐蚀以平衡黄色区域内的特征。然后我使用了 的bbox
方法,skimage.regionprops
但对于带有一个大 bbox 的大图像,它似乎不够快。你有什么建议吗?
问问题
960 次
2 回答
2
由于您提供的图像包含分散注意力的轴,并且颜色错误且太小,因此我在终端中使用ImageMagick创建了尽可能逼真的版本:
convert bbox.png -alpha off -crop 120x215+40+13 -colorspace gray -normalize -threshold 50% -scale 4200x7200\! bbox.png
全尺寸版本为 4200x7200。
然后我写了一个numpy
基于 - 的版本bbox
如下
#!/usr/local/bin/python3
import numpy as np
from PIL import Image
def bbox(image):
"""Find bounding box of image"""
# Project all columns into row same width as image
proj=np.any(image,axis=0)
# Find first non-zero value from Left
L=np.argmax(proj)
# And right
R=image.shape[1]-np.argmax(np.flipud(proj))-1
# Project all rows into column same height as image
proj=np.any(image,axis=1)
# Find first non-zero value from Top
T=np.argmax(proj)
# And Bottom
B=image.shape[0]-np.argmax(np.flipud(proj))-1
return T,L,B,R
image=np.array(Image.open("a.png").convert("L"))
print(bbox(image))
在我的 Mac 上运行 5.3 毫秒。只是为了好玩,我对它进行了线程化,并在单独的并行线程上运行了水平投影和垂直投影,它下降到 3.6 毫秒,结果相同。
#!/usr/local/bin/python3
import numpy as np
from PIL import Image
import threading
import queue
def DoOneDim(image,axis,q):
"""Find bounding box of image"""
proj=np.any(image,axis=axis)
# Find first non-zero value
A=np.argmax(proj)
# And and last
B=image.shape[1-axis]-np.argmax(np.flipud(proj))-1
q.put({axis:(A,B)})
def bboxTh(image):
"""Threaded version of bbox() that does vertical and horizontal on their own theads"""
q = queue.Queue()
Hthread=threading.Thread(target=DoOneDim, args=(image,0,q))
Vthread=threading.Thread(target=DoOneDim, args=(image,1,q))
Hthread.start()
Vthread.start()
Hthread.join()
Vthread.join()
results=dict()
while not q.empty():
results.update(q.get())
return results
image=np.array(Image.open("a.png").convert("L"))
print(bboxTh(image))
标识的框如下所示:
于 2018-07-23T13:09:41.927 回答
0
因为您正在寻找单个边界框,所以不要使用regionprops
或任何每个对象的功能。这也使得您无需尝试从所有黄点中制作单个对象。
这里最简单的解决方案是遍历图像,并为每个像素确定它是否“足够黄”(无论这对您的应用程序意味着什么)。如果是这样,请将像素的坐标添加到正在运行的边界框计算中。
边界框计算非常简单:
top_left = [1e9, 1e9]
bottom_right = [0, 0]
for ...:
# within your loop over the pixels, [x, y] are the current coordinates
top_left = [min(top_left[0], x), min(top_left[1], y)];
bottom_right = [max(bottom_right[0], x), max(bottom_right[1], y)];
skimage 可能有一种方法可以在没有循环的情况下执行此操作,但我根本不知道那个包。
于 2018-07-22T06:44:38.400 回答