【问题标题】:Find the intersection line between two colors找到两种颜色之间的交线
【发布时间】:2021-03-16 20:53:37
【问题描述】:

我正在尝试在一组与此类似的图像中找到绿色和蓝色之间的交集:

所以我需要的是这样的东西:

因为在那之后我需要使用轮廓进行一些微积分,所以我想知道是否可以将曲线的点放在数组或其他东西中......但我不知道这是否可能。我试着做面具,但我不认为它会起作用......这是代码:

        lower_val = np.array([0, 0, 0])

        upper_val = np.array([150, 255, 150])

        mask = cv2.inRange(image, lower_val, upper_val)
        only_lumen = cv2.bitwise_and(image, image, mask=mask)
        gray = cv2.cvtColor(only_lumen, cv2.COLOR_BGR2GRAY)
        blur = cv2.GaussianBlur(gray, (3, 3), 0)
        thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
        thresh = 255 - thresh

这就是我试图显示点的方式:

    x, y = [i[0] for i in pts_list], [i[1] for i in pts_list]
    max_x, max_y = max(x), max(y)

    image = np.zeros((max_y + 1, max_x + 1))

    for i in range(len(pts_list)):
        image[max_y - y[i], x[i]] = 1

这是我获得的图像:

我不明白为什么这些点会在一个角落里相遇,为什么背景是紫色的......应该在中间的线条

【问题讨论】:

  • 这些是我认为您需要更好地指定以使您的问题更具体的事情:1)我们可以假设背景总是黑色的吗? 2)您是否只希望两种前景色(这里是蓝色和绿色)之间的交点而不是背景色? 3) 前景色是否只有 2 种? 4)只是你提到的那些还是会有所不同? 5)这里有两组交叉点,如果有很多这样的交叉点,您希望它们作为单独分组的点列表还是作为单个点列表?
  • 通过编辑帖子提供的信息越多,答案就越好。但是,是的,使用给定的信息,可以提取点集。我会根据我自己的假设(根据您提供的当前信息)写出答案。
  • 嗨!非常感谢您或您的回答:)我将再次回答您的观点,非常感谢! 1)是的,它总是会是黑色的。 2)我的想法只是在前景色之间(在这种情况下是蓝色和绿色)。 3)是的,它们只有两个 4)它们可以变化,所以我的想法是将它们作为参数。 5)我以前没有考虑过,但也许在两个列表中更好?之后我想做的是计算方向向量以查看表面是否规则。所以我的想法是将每个向量与前一个向量进行比较,看看它的方向是否相似(常规)
  • 或非常不同(将是不规则的)。谢谢!!!
  • 感谢您提供更多信息。如果您可以通过编辑将这些信息添加到您的问题中,那就太好了,以便查看该帖子的其他人可以更好地帮助您。在我编写代码和测试结果时给我一些时间。

标签: python image colors


【解决方案1】:

现在,我会给你一些你可以尝试的最简单的解决方案(可以改进很多):

边界像素(获取蒙版后)将彼此相邻,但如果您希望最小为 1 个像素宽度的边界,则必须选择一侧。对此的替代方法是设置搜索内核并使用形态学根据您的搜索内核扩展您的颜色蒙版。扩张蒙版中的共同点将是您可以通过简单地执行按位与来提取的邻域点。

# Define the color ranges for each color of interest for creating masks.
COLOR1_RANGE = [(30, 0, 0), (255, 50, 50)]  # Blue in BGR, [(low), (high)].
COLOR2_RANGE = [(0, 30, 0), (50, 255, 50)]  # Green in BGR, [(low), (high)].

# Create masks:
color1_mask = cv2.inRange(self.img, COLOR1_RANGE[0], COLOR1_RANGE[1])
color2_mask = cv2.inRange(self.img, COLOR2_RANGE[0], COLOR2_RANGE[1])

# Adjust according to your adjacency requirement.
kernel = np.ones((3, 3), dtype=np.uint8)

# Dilating masks to expand boundary.
color1_mask = cv2.dilate(color1_mask, kernel, iterations=1)
color2_mask = cv2.dilate(color2_mask, kernel, iterations=1)

# Required points now will have both color's mask val as 255.
common = cv2.bitwise_and(color1_mask, color2_mask)

# Common is binary np.uint8 image, min = 0, max = 255.
# SOME_THRESHOLD can be anything within the above range. (not needed though)
# Extract/Use it in whatever way you want it.
intersection_points = np.where(common > SOME_THRESHOLD)

# Say you want these points in a list form, then you can do this.
pts_list = [[r, c] for r, c in zip(*intersection_points)]
print(pts_list)

一些示例输出:

输入 01(简单):

输出 01(简单):

将点输出为列表(部分):

pts_list = [[99, 104], [99, 105], [100, 104], [100, 105], [100, 106], ...]

输入 02(复杂):

输出 02(复杂):

将点输出为列表(部分):

pts_list = [[127, 309], [127, 310], [127, 311], [127, 312], [127, 313], ...]

更新 1:
我对代码 cmets 做了一个小改动,使其更易于理解。

【讨论】:

  • 非常感谢!!!这正是我需要的:) 但我在显示点时遇到问题,我编辑了问题以附加图像。再次感谢
  • 因此,如果您想在计算机视觉领域重用这些点(例如使用 OpenCV、PIL、matplotlib 等),我建议使用 intersection_points 变量。 pts_list 是一种转换,使其以人类可读的形式打印(再次用于计算效率较低,但可能对调试有用)
  • 我假设您将灰度图像传递给 matplotlib.pyplot imshow() 而不更改其 cmap。
  • 请提供有关您如何尝试显示图像的详细信息。关于角落中的点,您将行点用作 x(行应该是 y),反之亦然。
  • 这是很多人都会犯的常见错误。直观地说,我们用 (x, y) 表示坐标,但图像等大多被认为是用 (row, col) 表示的矩阵,但这些在坐标意义上实际上是 (y, x)。
猜你喜欢
  • 2011-08-26
  • 2013-02-08
  • 2012-11-27
  • 2013-07-06
  • 2019-12-07
  • 1970-01-01
  • 2013-08-02
  • 2019-01-19
  • 2014-09-14
相关资源
最近更新 更多