【问题标题】:OpenCV contour minimum dimension location in pythonpython中的OpenCV轮廓最小尺寸位置
【发布时间】:2015-12-01 14:04:19
【问题描述】:

我正在使用背景减法来分析户外场景的移动物体。当太阳出来时,我遇到了阴影问题。我正在使用轮廓来隔离对象。目前我只是分析轮廓的上半部分,因为阴影通常在下半部分。

想象一个橡皮鸭的轮廓,我想做的是找到鸭子脖子的 y 位置,即轮廓处于其最小水平尺寸的位置。 有人可以为我指出如何找到“鸭脖子”的正确方向吗?

代码中binary是运动物体的阈值图像,HIGHTWIDTH是图像的高度和宽度,lab是LAB色彩空间中的同一张图像。

我想用一个函数来替换half = int(h/2) 线,以找到一条水平线的 y 位置以切断“鸭脖”。

_,contours,_ = cv2.findContours(binary.copy(), cv2.RETR_EXTERNAL,
                            cv2.CHAIN_APPROX_SIMPLE)

# loop over the contours
for i, cnt in enumerate(contours):

   # compute the bounding box for the contour
   (x, y, w, h) = cv2.boundingRect(cnt)

   # reject contours outside size range
   if w > 250 or w < 30 or h > 250 or h < 30 :
          continue

   # make sure the box is inside the frame
   if x <= 0 or y <= 0 or x+w >= (WIDTH -1) or y+h >= (HIGHT -1):
          continue

   # isolate feature
   half = int(h/2)
   roi = lab[y:y+half, x:x+w]
   mask = binary[y:y+half, x:x+w]

   # calculate the mean of the colour
   mean = cv2.mean(roi, mask = mask)
   # note: mean is L a b
   L = int(mean[0])
   a = int(mean[1])
   b = int(mean[2])
   print L,a,b

我正在使用 opencv 3 和 python 2.7

附:我已经尝试过背景减法器 MOG2,据说它可以识别阴影,但它对我的使用来说是一种嘈杂的方式,而且不可行。

【问题讨论】:

  • 向您的问题添加一些具有实际和预期结果的图像。点击标签下的编辑链接。您没有足够的声誉来添加图片,但您可以发布来自 imgur 或类似网站的公共链接
  • 嗨,Miki,我添加了一个草图,应该有助于澄清,请随时问其他问题。我想到了 3 种可能的解决方案,1)以某种方式使用矩,2)遍历轮廓列表以找到转折点,3)水平求和行以获得轮廓,然后找到轮廓的转折点。前两个我不知道所以关于如何使用时刻或如何访问和解释轮廓列表的一些帮助会很有帮助。或者任何其他建议将不胜感激。
  • 抱歉,当您尝试按照要求执行操作时会感到痛苦,但请尽可能避免使用 Dropbox/其他临时链接 - 我们希望这些问题能够帮助人们多年,如果您删除了 Dropbox将来提交文件,这会使这个问题变得不那么有价值。因此,与 imgur 进行安排,以确保所有图像都在此期间。在这种情况下,我已经为您完成了。希望你能找到答案!
  • 我不是 OpenCV 专家,但我不相信这种方法会完全准确,因为我无法区分阳光下的球和“真正的”橡皮鸭没有影子。更复杂的是真正的鸭子,阴影=三个夹点。您是否有任何其他意见表明应该/不应该有阴影?
  • 嗨,Basic,你是对的,但它不一定是 100%,因为我稍后在代码中构建了一个特征向量并使用聚类方法来识别对象的类型。我的问题仅限于我的代码中的这一步,以便我可以使用更多的实际对象来计算我的特征向量,而不是在没有太阳时松散一半的对象。

标签: python opencv image-processing opencv3.0


【解决方案1】:

您可以定义一个遮罩来侵蚀图像,这样您就可以从山谷中破坏顶部和底部的斑点。您可以将其应用于您的代码,如下所示:

# loop over the contours
for i, cnt in enumerate(contours):

   # compute the bounding box for the contour
   (x, y, w, h) = cv2.boundingRect(cnt)

   # reject contours outside size range
   if w > 250 or w < 30 or h > 250 or h < 30 :
          continue

   # make sure the box is inside the frame
   if x <= 0 or y <= 0 or x+w >= (WIDTH -1) or y+h >= (HIGHT -1):
          continue

   # ---------------
   # create a mask for erosion, you can play with the mask size/shape
   mask = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
   # erode the original image
   eroded_img = cv2.erode(binary,mask,iterations = 1)
   cv2.imshow("Eroded image",eroded_img)
   # find the middle of the two new contours
   _,new_contours,_ = cv2.findContours(eroded_img, cv2.RETR_EXTERNAL,
                      cv2.CHAIN_APPROX_SIMPLE)
   (_, y_t, _, h_t) = cv2.boundingRect(new_contours[0])
   (_, y_b, _, h_b) = cv2.boundingRect(new_contours[1])
   bottom_top_y = max(y_t, y_b) # highest y of bottom part
   top_bottom_y = min(y_t+h_t, y_b+h_b) # lowest y of top part
   half = top_bottom_y + (bottom_top_y - top_bottom_y)/2
   # ------------

   # isolate feature
   roi = lab[y:y+half, x:x+w]
   mask = binary[y:y+half, x:x+w]

   # calculate the mean of the colour
   mean = cv2.mean(roi, mask = mask)
   # note: mean is L a b
   L = int(mean[0])
   a = int(mean[1])
   b = int(mean[2])
   print L,a,b

希望对您有所帮助!更多二值图像形态学操作示例,可以查看here

【讨论】:

  • 艾克,非常感谢您的意见。这绝对是一种方法。我已经使用 erode 来减小掩码大小,以便对象的边缘不包括在我的识别计算中。也许我会循环腐蚀直到有 2 个轮廓,然后将顶部轮廓恢复到接近原始大小。干杯:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 2015-12-22
  • 1970-01-01
  • 2018-09-09
相关资源
最近更新 更多