Python与OpenCV:第二大物体
我正在开发一个Python脚本,目的是从图像中找出颜色匹配的最大和第二大物体。我已经成功找到了最大的物体,并在它周围画了一个轮廓和一个框。不过,我现在遇到了难题,想找到第二大的物体。我希望第二大的物体能够被单独检测出来。
import numpy as np
import cv2
font = cv2.FONT_HERSHEY_SIMPLEX
lineType = cv2.LINE_AA
im = cv2.imread('Photos/test.jpg')
im_ycrcb = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
ball_ycrcb_mint = np.array([0, 90, 100],np.uint8)
ball_ycrcb_maxt = np.array([25, 255, 255],np.uint8)
ball_ycrcb = cv2.inRange(im_ycrcb, ball_ycrcb_mint, ball_ycrcb_maxt)
#cv2.imwrite('Photos/output2.jpg', ball_ycrcb) # Second image
areaArray = []
count = 1
_, contours, _ = cv2.findContours(ball_ycrcb, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for i, c in enumerate(contours):
area = cv2.contourArea(c)
areaArray.append(area)
areaLargest = np.argmax(areaArray)
areaLargestMax = max(areaArray)
areaLargestCnt = contours[areaLargest]
x, y, w, h = cv2.boundingRect(areaLargestCnt)
if area == areaLargestMax and area > 10000:
cv2.drawContours(im, contours, i, (255, 0, 0), 2)
cv2.rectangle(im, (x, y), (x+w, y+h), (0,255,0), 2)
cv2.imwrite('Photos/output3.jpg', im)
我正在使用以下图像进行测试:球的图片
任何帮助都非常感谢!
3 个回答
2
image, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = sorted(cnts, key=cv2.contourArea)
cnt会给你一个按面积从小到大排列的轮廓列表。
你可以通过索引来找到某个轮廓的面积:
area = cv2.contourArea(cnt[index])
索引可以是1, 2, 3……一直到len(cnts)的长度。
如果你想访问面积最大的轮廓:
cnt[reverse_index]
把reverse_index设为-1,这样你就能得到面积最大的轮廓。
如果想要第二大面积的轮廓,就把reverse_index设为-2,以此类推。
5
你可以使用 sorted(contours, key=cv2.contourArea, reverse=True)
这个代码来得到一个按面积从大到小排列的轮廓列表。
4
首先,先创建一个轮廓和轮廓面积的数组,这样找到第n大轮廓会简单一些。
import numpy as np
import cv2
im = cv2.imread('Photos/test.jpg')
im_ycrcb = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
ball_ycrcb_mint = np.array([0, 90, 100],np.uint8)
ball_ycrcb_maxt = np.array([25, 255, 255],np.uint8)
ball_ycrcb = cv2.inRange(im_ycrcb, ball_ycrcb_mint, ball_ycrcb_maxt)
#cv2.imwrite('Photos/output2.jpg', ball_ycrcb) # Second image
areaArray = []
count = 1
contours, _ = cv2.findContours(ball_ycrcb, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for i, c in enumerate(contours):
area = cv2.contourArea(c)
areaArray.append(area)
#first sort the array by area
sorteddata = sorted(zip(areaArray, contours), key=lambda x: x[0], reverse=True)
#find the nth largest contour [n-1][1], in this case 2
secondlargestcontour = sorteddata[1][1]
#draw it
x, y, w, h = cv2.boundingRect(secondlargestcontour)
cv2.drawContours(im, secondlargestcontour, -1, (255, 0, 0), 2)
cv2.rectangle(im, (x, y), (x+w, y+h), (0,255,0), 2)
cv2.imwrite('Photos/output3.jpg', im)
这个代码基本上可以满足你的需求。我把一些会导致我使用的opencv版本崩溃的多余代码去掉了。