找到轮廓属性
Find the Contour Properties
我正在使用 Visual Studio 2012 和 OpenCV。我想找到具有以下规格的 two-point 坐标。
第一个点:最高最左边的点
第二点:最高最右点
就像你在图片中看到的那样。
首先我想指出这个答案是写在 Python 中的,它的目的是给出一个关于如何解决这个问题的想法。
其次,定义最高点和最左点(与最高点和最右点相同)是一个问题,因为轮廓的形状变化很大。这意味着左右的最极端值并不总是与最高值互补。以下图为例:
右上角的红点是北向最高的但不是最右的(它是所有 4 个点中最左边的)而下红点是最右的点但不是最高的(它实际上是北向最低的!)。还有另外2点介于两者之间,可以符合上述标准。
也就是说,我已经在 Python 中为您的图片中描述的最相似的解决方案制作了一个脚本,以展示我将如何尝试处理该问题。它可能不是您想要的,并且可能有更好的解决方案,但这可能会给您一个想法或弄清楚您实际需要什么。
我冒昧地下载了您的示例图片并对其进行了一些编辑,以便我可以举个例子。这是我的 "originals":
我提取了图像的轮廓和 select 最大的轮廓 - returns 一组点。然后我提取了 X 坐标中的最大值(最右边的点)和最低的 Y 坐标(最北点)。因为轮廓没有直线,所以我已经为最极端点的显着点可以变化多少设置了一个阈值(在你的情况下,数字可能不同 - 我的情况是 +- 3)。然后我在一个列表中附加了阈值中所有最正确的点,在另一个列表中附加了所有最北点。然后对于最左边的 select 列表中 X 坐标最低的点和另一个列表中 Y 坐标最低的点作为最右边的点。
结果如下:
希望对您有所帮助。干杯!
Python中的示例:
import cv2
import numpy as np
img = cv2.imread('uplupr.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, threshold = cv2.threshold(gray,170,255,cv2.THRESH_BINARY)
im, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
mask = np.zeros(img.shape, dtype="uint8")
cnt = max(contours, key=cv2.contourArea)
cv2.drawContours(mask, [cnt], -1, (255,255,255), 1)
top_right_append = 0
top_up_append = 1000
point_up = []
point_right = []
for i in cnt:
top_up = int(i[:,1])
top_right = int(i[:, 0])
if top_right > top_right_append:
top_right_append = int(top_right)
if top_up < top_up_append:
top_up_append = int(top_up)
for i in cnt:
if int(i[:,1]) < top_up_append+3:
up = (int(i[:,0]), int(i[:,1]))
point_up.append(up)
for i in cnt:
if int(i[:,0]) > top_right_append-3:
right = (int(i[:,0]), int(i[:,1]))
point_right.append(right)
point_up.sort(key=lambda tup: tup[0])
point_right.sort(key=lambda tup: tup[1])
cv2.circle(mask,(point_up[0]), 4, (0,0,255), -1)
cv2.circle(mask,(point_right[0]), 4, (0,0,255), -1)
cv2.imshow('image', mask)
我正在使用 Visual Studio 2012 和 OpenCV。我想找到具有以下规格的 two-point 坐标。
第一个点:最高最左边的点
第二点:最高最右点
就像你在图片中看到的那样。
首先我想指出这个答案是写在 Python 中的,它的目的是给出一个关于如何解决这个问题的想法。
其次,定义最高点和最左点(与最高点和最右点相同)是一个问题,因为轮廓的形状变化很大。这意味着左右的最极端值并不总是与最高值互补。以下图为例:
右上角的红点是北向最高的但不是最右的(它是所有 4 个点中最左边的)而下红点是最右的点但不是最高的(它实际上是北向最低的!)。还有另外2点介于两者之间,可以符合上述标准。
也就是说,我已经在 Python 中为您的图片中描述的最相似的解决方案制作了一个脚本,以展示我将如何尝试处理该问题。它可能不是您想要的,并且可能有更好的解决方案,但这可能会给您一个想法或弄清楚您实际需要什么。
我冒昧地下载了您的示例图片并对其进行了一些编辑,以便我可以举个例子。这是我的 "originals":
我提取了图像的轮廓和 select 最大的轮廓 - returns 一组点。然后我提取了 X 坐标中的最大值(最右边的点)和最低的 Y 坐标(最北点)。因为轮廓没有直线,所以我已经为最极端点的显着点可以变化多少设置了一个阈值(在你的情况下,数字可能不同 - 我的情况是 +- 3)。然后我在一个列表中附加了阈值中所有最正确的点,在另一个列表中附加了所有最北点。然后对于最左边的 select 列表中 X 坐标最低的点和另一个列表中 Y 坐标最低的点作为最右边的点。
结果如下:
希望对您有所帮助。干杯!
Python中的示例:
import cv2
import numpy as np
img = cv2.imread('uplupr.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, threshold = cv2.threshold(gray,170,255,cv2.THRESH_BINARY)
im, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
mask = np.zeros(img.shape, dtype="uint8")
cnt = max(contours, key=cv2.contourArea)
cv2.drawContours(mask, [cnt], -1, (255,255,255), 1)
top_right_append = 0
top_up_append = 1000
point_up = []
point_right = []
for i in cnt:
top_up = int(i[:,1])
top_right = int(i[:, 0])
if top_right > top_right_append:
top_right_append = int(top_right)
if top_up < top_up_append:
top_up_append = int(top_up)
for i in cnt:
if int(i[:,1]) < top_up_append+3:
up = (int(i[:,0]), int(i[:,1]))
point_up.append(up)
for i in cnt:
if int(i[:,0]) > top_right_append-3:
right = (int(i[:,0]), int(i[:,1]))
point_right.append(right)
point_up.sort(key=lambda tup: tup[0])
point_right.sort(key=lambda tup: tup[1])
cv2.circle(mask,(point_up[0]), 4, (0,0,255), -1)
cv2.circle(mask,(point_right[0]), 4, (0,0,255), -1)
cv2.imshow('image', mask)