【发布时间】:2018-08-20 09:38:44
【问题描述】:
我使用徽标和其他简单图形,其中没有渐变或复杂图案。我的任务是从带有字母和其他元素的标志片段中提取出来。
为此,我定义了背景颜色,然后遍历图片以分割图像。这是我的代码以供更多理解:
MAXIMUM_COLOR_TRANSITION_DELTA = 100 # 0 - 765
def expand_segment_recursive(image, unexplored_foreground, segment, point, color):
height, width, _ = image.shape
# Unpack coordinates from point
py, px = point
# Create list of pixels to check
neighbourhood_pixels = [(py, px + 1), (py, px - 1), (py + 1, px), (py - 1, px)]
allowed_zone = unexplored_foreground & np.invert(segment)
for y, x in neighbourhood_pixels:
# Add pixel to segment if its coordinates within the image shape and its color differs from segment color no
# more than MAXIMUM_COLOR_TRANSITION_DELTA
if y in range(height) and x in range(width) and allowed_zone[y, x]:
color_delta = np.sum(np.abs(image[y, x].astype(np.int) - color.astype(np.int)))
print(color_delta)
if color_delta <= MAXIMUM_COLOR_TRANSITION_DELTA:
segment[y, x] = True
segment = expand_segment_recursive(image, unexplored_foreground, segment, (y, x), color)
allowed_zone = unexplored_foreground & np.invert(segment)
return segment
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Pass image as the argument to use the tool")
exit(-1)
IMAGE_FILENAME = sys.argv[1]
print(IMAGE_FILENAME)
image = cv.imread(IMAGE_FILENAME)
height, width, _ = image.shape
# To filter the background I use median value of the image, as background in most cases takes > 50% of image area.
background_color = np.median(image, axis=(0, 1))
print("Background color: ", background_color)
# Create foreground mask to find segments in it (TODO: Optimize this part)
foreground = np.zeros(shape=(height, width, 1), dtype=np.bool)
for y in range(height):
for x in range(width):
if not np.array_equal(image[y, x], background_color):
foreground[y, x] = True
unexplored_foreground = foreground
for y in range(height):
for x in range(width):
if unexplored_foreground[y, x]:
segment = np.zeros(foreground.shape, foreground.dtype)
segment[y, x] = True
segment = expand_segment_recursive(image, unexplored_foreground, segment, (y, x), image[y, x])
cv.imshow("segment", segment.astype(np.uint8) * 255)
while cv.waitKey(0) != 27:
continue
在运行时结束时,我预计会提取 13 个分离的片段(对于这个特定的图像)。但相反,我得到了 RecursionError: maximum recursion depth exceeded,这并不奇怪,因为可以为图像的每个像素调用 expand_segment_recursive()。而且,即使使用 600x500 的小图像分辨率,我也能接到最多 300K 次调用。
我的问题是如何在这种情况下摆脱递归,并可能使用 Numpy 或 OpenCV 算法优化算法?
【问题讨论】:
-
也许您可以提供另一个样本,另外,请提供您希望获得的“结果”?
-
哇,循环/递归看起来是个坏主意。您可以尝试进行二值化(阈值),然后连接组件?或者如果它像这个标志可能会转换为 HSV 颜色空间并执行 inRange 以选择蓝色部分?在这种特定情况下,您甚至可以只做一个阈值来获取“蓝色”部分的掩码
-
@api55 关键是我们有几个颜色相同的段。如果我对图像应用阈值,我将获得该颜色的所有片段。不合适,在这种情况下必须将段分开。连接的组件看起来很相关,你有使用它的好例子吗?
-
ahhhh 好的,现在它是有道理的,但是做阈值然后连接组件可能会成功。给我一分钟,我把它写下来作为答案
-
这个问题也可能有用:使用
cv::inRange(OpenCV) stackoverflow.com/questions/10948589/… 选择正确的 HSV 上下边界进行颜色检测
标签: python numpy opencv image-processing