OpenCV跟踪轮廓将整个图像跟踪为最大轮廓?
Posted
技术标签:
【中文标题】OpenCV跟踪轮廓将整个图像跟踪为最大轮廓?【英文标题】:OpenCV trace contours tracing whole image as largest contour? 【发布时间】:2021-03-12 18:10:43 【问题描述】:我正在尝试生成用于训练神经网络的数据集,这需要我在视频的多个帧中围绕移动对象(蜗牛)进行裁剪。
我已将视频分割成帧并使用 OpenCV 通过使用 HSV 阈值和轮廓跟踪来裁剪对象,如下所示:
import cv2
import pandas as pd
import matplotlib
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt
img = cv2.imread("./pngs/04Feb21_1_crop/20000.png")
img_edit = cv2.imread("./pngs/04Feb21_1_crop/20000.png")
hsv_img = cv2.cvtColor(img_edit, cv2.COLOR_BGR2HSV)
plt.imshow(hsv_img) ## 1
low = np.array([99, 109, 77] )
high = np.array([115, 255, 255])
curr_mask = cv2.inRange(hsv_img, low, high)
hsv_img[curr_mask > 0] = ([84, 255, 200])
# converting the hsv image to gray in order to be able to apply
# contouring
RGB_again = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB)
gray = cv2.cvtColor(RGB_again, cv2.COLOR_RGB2GRAY)
ret, threshold = cv2.threshold(gray, 90, 255, 0)
plt.imshow(threshold, cmap="binary")
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
threshold = cv2.morphologyEx(threshold, cv2.MORPH_OPEN, kernel)
threshold = cv2.morphologyEx(threshold, cv2.MORPH_CLOSE, kernel)
contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
img_edit = cv2.drawContours(img_edit, contours, -1, (0,255,0), 3)
plt.imshow(img_edit)
正如您在此处看到的,底部的绿线表示存在包含照片底部边缘的轮廓。因此,当我选择最大的轮廓并围绕它进行裁剪时,如下所示:
# find largest contour
areaArray = []
count = 1
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
largestcontour = sorteddata[0][1]
x,y,w,h = cv2.boundingRect(largestcontour)
crop = img[y:y+h, x:x+w]
plt.imshow(crop)
整个图像被裁剪,因为最大轮廓的边界矩形本质上就是图像的大小。
我一直在通过选择第二大轮廓来规避这个问题,但它不适用于我的所有框架。例如,在这个框架中,选择第二大轮廓,如下所示:
secondlargestcontour = sorteddata[1][1]
像以前一样裁剪会产生这个灰色区域:
我在 HSV 阈值方面做错了吗?是不是因为物体本身与水的阴影/反射不够清晰?
非常感谢任何和所有帮助。我是 Python 和 OpenCV 的新手,如果我遗漏了一些非常明显的东西,我提前道歉。
用于所有代码的原始图像在这里:
【问题讨论】:
【参考方案1】:我认为改变 HSV 的上下边界可以解决你的问题。
我已将值更改为此
low = np.array([0, 35, 0])
high = np.array([253, 255, 255])
测试代码
import cv2
import numpy as np
image = cv2.imread("image.png")
HSV = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
low = np.array([0, 35, 0])
high = np.array([253, 255, 255])
mask = cv2.inRange(HSV, low, high)
cv2.imshow("mask", mask)
result = cv2.bitwise_and(image, image, mask=mask)
cv2.imshow("result", result)
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
sorted_contour = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)
largestcontour = sorted_contour[0]
x, y, w, h = cv2.boundingRect(largestcontour)
crop = image[y:y+h, x:x+w]
cv2.imshow("crop", crop)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出:
mask image | result image | crop image |
---|---|---|
【讨论】:
以上是关于OpenCV跟踪轮廓将整个图像跟踪为最大轮廓?的主要内容,如果未能解决你的问题,请参考以下文章