使用 cv2.findContours 输出作为 plt.contour 输入

Use cv2.findContours output as plt.contour input

我有如下图片

我使用

找到轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
contour = contours[0]

接下来,我确定轮廓的center

def find_center(contour: np.ndarray) -> tuple:
    M = cv2.moments(contour)
    x = int(M["m10"] / M["m00"])
    y = int(M["m01"] / M["m00"])

    return x, y

我想在网格中显示轮廓,其中 center 代表原点/(0,0) 点。所以,我减去 contour.

的每个 xy 点的 center

接下来,我想使用这些新坐标作为 plt.contour 的输入。 我需要创建一个 meshgrid

xs = new_contour[:,:,0].flatten()
ys = new_contour[:,:,1].flatten()

x = np.arange(int(min(xs)), int(max(xs)), 1) 
y = np.arange(int(min(ys)), int(max(ys)), 1) 
X, Y = np.meshgrid(x, y)

如何定义/处理 Z 输出开始看起来像这样:

编辑

按照建议,我尝试使用 patch.Polygon

p = Polygon(np.reshape(new_contour, (-1, 2)), facecolor = 'k', closed=True)

fig, ax = plt.subplots()

ax.add_patch(p)
ax.set_xlim([-250, 250])
ax.set_ylim([-250, 250])
plt.show()

输出如下所示:

它开始看起来像了,但它仍然在旋转。我不确定为什么。当我查看文档时,每个函数都使用 xy 坐标,所以不是这样。我做错了什么?

这是 plot 的最小示例。请记住opencv和matplotlib的y-coordinate有不同的方向:

import cv2
from matplotlib import pyplot as plt


im = cv2.imread("img.png", cv2.IMREAD_GRAYSCALE)
_, thresh = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
contour = contours[0]

M = cv2.moments(contour)
x = int(M["m10"] / M["m00"])
y = int(M["m01"] / M["m00"])

xs = [v[0][0] - x for v in contour]
ys = [-(v[0][1] - y) for v in contour]

plt.plot(xs, ys)
plt.grid()
plt.show()

这是另一个带有闭合多边形面片的示例:

import cv2
from matplotlib import pyplot as plt
from matplotlib.patches import Polygon


im = cv2.imread("img.png", cv2.IMREAD_GRAYSCALE)
_, thresh = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
contour = contours[0]

M = cv2.moments(contour)
x = int(M["m10"] / M["m00"])
y = int(M["m01"] / M["m00"])

p = Polygon([(v[0][0] - x, y - v[0][1]) for v in contour], closed=True)

fig, ax = plt.subplots()
ax.add_patch(p)
ax.set_xlim([-80, 80])
ax.set_ylim([-80, 80])
plt.grid()
plt.show()