Python 需要使用轮廓检测图像的第二个极值点
我正在尝试使用轮廓检测图像的第二个极值点 我试着做下面的事情Python 需要使用轮廓检测图像的第二个极值点,python,image,opencv,image-processing,Python,Image,Opencv,Image Processing,我正在尝试使用轮廓检测图像的第二个极值点 我试着做下面的事情 我正在寻找图像的所有轮廓 对等高线NumPy数组进行排序 删除NUMPY数组中的最后一个元素以去除外部轮廓,以免在极值点检测中考虑。李> 选择极值点 代码如下: import imutils import cv2 import numpy as np image = cv2.imread(r"SimpleBoxTest.png") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) gray
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
回溯(最近一次呼叫最后一次):
文件“C:/TestCode/DocumentLayoutDetection/extreamPoints.py”,第41行,在
extLeft=tuple(c[c[:,:,0].argmin()][0])
索引器:数组的索引太多
下面的图片只是一个参考图片,我会尝试其他图片也
图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])
您不需要删除最后一个元素,您可以从末尾获取第二个元素
不是一个NumPy数组,而是一个列表c=sorted(cnts,key=cv2.contourArea)的结果
您可以使用
检查类型,结果是type(c)
您可以使用
:del
删除最后一个元素,但不必这样做李>delc[-1]
- 使用:
提取列表的最后一个元素。c=c[-2]
现在
是类型(c)
李> - 使用
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循环的解决方案:
- 您可以使用
连接列表中的NumPy数组。np.vstack(c)
然后找到连接数组中的极值点
# 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()
结果:
谢谢你的回答。我在其他图像上尝试了相同的代码,当有一个充满文本的页面时,获取极值点是主要目的。这段代码在这种情况下没有帮助。我将为同一个问题添加一个参考图像。是啊!我今天把它理解为列表。您可以绘制所有轮廓:
cv2。绘制轮廓(图像,CNT,-1,(0,0,255),厚度=5)
。结果看起来像。绿色框位于第二大轮廓周围。“图像的第二个极端点”是什么?我更新了我的帖子。我希望这就是你的意思。我喜欢你用优化代码解决问题的方式。事实上,我在当天晚些时候以一种非常复杂的方式解决了这个问题。但这是最好的解决办法。是的!这是一个列表,但是,当我们喜欢上面的代码时,我们将无法找到极值点,因为它将有最后一个列表的极值点。