需要使用轮廓检测图像的第二个极值点

2024-03-29 11:21:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用轮廓检测图像的第二个极值点

我试着做下面的事情

  1. 我正在寻找图像的所有轮廓
  2. 对等高线NumPy数组进行排序
  3. 删除NUMPY数组中的最后一个元素以去除外部轮廓,以免在极值点检测中考虑。李>
  4. 选择极值点

代码如下:

import imutils
import cv2
import numpy as np

image = cv2.imread(r"SimpleBoxTest.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)

thresh = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.erode(thresh, None, iterations=2)
thresh = cv2.dilate(thresh, None, iterations=2)

cnts = cv2.findContours(thresh.copy(), cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

c=sorted(cnts, key=cv2.contourArea)
c = np.delete(c, (-1), axis=0) 

extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])

下面是错误

Traceback (most recent call last):
  File "C:/TestCode/DocumentLayoutDetection/extreamPoints.py", line 41, in <module>
    extLeft = tuple(c[c[:, :, 0].argmin()][0])
IndexError: too many indices for array

下面的图片只是一个参考图片,我会尝试其他图片也 Input image

图2 enter image description here


Tags: 图像imageimportnp图片数组cv2轮廓
2条回答

变量c是数组的列表,因此添加一个for循环来迭代它。 这解决了错误:

for d in c:
    extLeft = tuple(d[d[:, :, 0].argmin()][0])
    extRight = tuple(d[d[:, :, 0].argmax()][0])
    extTop = tuple(d[d[:, :, 1].argmin()][0])
    extBot = tuple(d[d[:, :, 1].argmax()][0])

您不需要删除最后一个元素,您可以从末尾获取第二个元素

  • c=sorted(cnts, key=cv2.contourArea)的结果不是一个NumPy数组,而是一个列表
    您可以使用type(c)检查类型,结果是<class 'list'>
    您可以使用del:del c[-1]删除最后一个元素,但不必这样做
  • 使用:c = c[-2]提取列表的最后一个元素。
    现在type(c)<class 'numpy.ndarray'>
  • 使用extLeft = c[:, :, 0].min()extRight = c[:, :, 0].max()查找最小值和最大值

代码如下:

import imutils
import cv2
import numpy as np

image = cv2.imread(r"SimpleBoxTest.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)

thresh = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.erode(thresh, None, iterations=2)
thresh = cv2.dilate(thresh, None, iterations=2)

cnts = cv2.findContours(thresh.copy(), cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

c=sorted(cnts, key=cv2.contourArea)

#c = np.delete(c, (-1), axis=0) 

# c is a list, and not a numpy array, so use del instead of np.delete
# But why?
# del c[-1]

# Get one element before the last element in the list
c = c[-2] # Now c is a numpy.ndarray

extLeft = c[:, :, 0].min()
extRight = c[:, :, 0].max()
extTop = c[:, :, 1].min()
extBot = c[:, :, 1].max()

# Draw rectangle for testing
cv2.rectangle(image, (extLeft, extTop), (extRight, extBot), (0, 255, 0))

cv2.imshow("image", image)
cv2.waitKey()
cv2.destroyAllWindows();

更新:

如果需要找到的所有等高线中的第二个极值点,可以在c中迭代等高线:

# Mark all contours with red:
cv2.drawContours(image, cnts, -1, (0, 0, 255), thickness=5)

# Delete last element of the list
del c[-1]

# Initialize:
extLeft, extRight, extTop, extBot = 1e9, -1e9, 1e9, -1e9

# Iterate list and find the extreme points
for cc in c:
    extLeft = min(cc[:, :, 0].min(), extLeft)
    extRight = max(cc[:, :, 0].max(), extRight)
    extTop = min(cc[:, :, 1].min(), extTop)
    extBot = max(cc[:, :, 1].max(), extBot)

# Draw rectangle for testing
cv2.rectangle(image, (extLeft, extTop), (extRight, extBot), (0, 255, 0), thickness=5)

不使用for循环的解决方案:

  • 您可以使用np.vstack(c)连接列表中的NumPy数组。
    然后找到连接数组中的极值点

代码:

# Delete last element of the list.
del c[-1]

# Concatenate arrays along vertical axis.
c = np.vstack(c)

# Find extreme points:
extLeft = c[:, :, 0].min()
extRight = c[:, :, 0].max()
extTop = c[:, :, 1].min()
extBot = c[:, :, 1].max()

结果:
enter image description here

相关问题 更多 >