【问题标题】:Python and OpenCV Image Target Detection and DifferentiationPython 和 OpenCV 图像目标检测和区分
【发布时间】:2017-02-10 00:01:37
【问题描述】:

我的任务是编写一个程序,为我的火箭俱乐部从高度检测和区分三个“目标”。这些目标是 3 个大型防水布,我有 RGB 值。

当我开始这个项目时,我使用防水布的确切 RGB 值覆盖了具有 3 个矩形的 GoogleEarth 图像,并且我的代码完美运行。但是,当我真正收到防水布并开始在地面上拍照时,我的代码无法识别具有我规定的 RGB 颜色边界的防水布。

我尝试将图像转换为 HSV 色彩空间,但无法正常工作。我还考虑过使用轮廓 - 试图让程序识别绑定每个目标的 4 条直线。问题是这些图像将在户外拍摄,因此我无法控制环境照明条件。

有没有人知道什么色彩空间或计算机视觉方法可以让我识别和区分这些目标,而不管室外照明如何?

处理后的原图
待识别的实际防水布

代码如下:

import cv2
import numpy as np

image = cv2.imread('2000 ft.png', 1)
#hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)


#cv2.waitKey(0)
cv2.destroyAllWindows()

# define target strings
targ = ['Target 1 - Blue', 'Target 2 - Yellow', 'Target 3 - Red']
i = 0

# BGR boundaries of colors
boundaries = [
# 0, 32, 91
    ([40, 10, 0], [160, 60, 20]),
# 255, 209, 0
    ([0, 180, 220], [20, 230, 255]),
# 166, 9, 61
    ([40, 0, 150], [80, 30, 185]),
]

# colors for rectangle outlines 
colors = [
          ([91, 32, 0]), ([0, 209, 255]), ([61, 9, 166])
]

# # loop over the boundaries
for (lower, upper) in boundaries:

     # create NumPy arrays from the boundaries
    lower = np.array(lower, dtype = "uint16")
    upper = np.array(upper, dtype = "uint16")

     # find the colors within the specified boundaries and apply
     # the mask
    mask = cv2.inRange(image, lower, upper)
    output = cv2.bitwise_and(image, image, mask = mask)
    # frame threshold
    frame_threshed = cv2.inRange(image, lower, upper)
    imgray = frame_threshed

    # iteratively view masks 
    cv2.imshow('imgray',imgray)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    ret,thresh = cv2.threshold(frame_threshed,127,255,0)
    contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

     # Find the index of the largest contour
    areas = [cv2.contourArea(c) for c in contours]
    max_index = np.argmax(areas)
    cont=contours[max_index]

    # putting text and outline rectangles on image
    x,y,w,h = cv2.boundingRect(cont)
    cv2.rectangle(image,(x,y),(x+w,y+h),colors[i],2)
    cv2.putText(image, targ[i], (x-50, y-10), cv2.FONT_HERSHEY_PLAIN, 0.85, (0, 255, 0))
     # cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),4)
    cv2.imshow("Show",image)
    cv2.waitKey()
    cv2.destroyAllWindows()
    i += 1

cv2.destroyAllWindows()

我正在使用我没有太多经验的 OpenCV 库用 Python 编写这段代码,我在这方面经验丰富。任何帮助将不胜感激!

【问题讨论】:

    标签: python image opencv color-detection


    【解决方案1】:

    相机(实际上是火箭)的颜色将取决于环境光,而且不太可能

    # colors for rectangle outlines 
    colors = [
              ([91, 32, 0]), ([0, 209, 255]), ([61, 9, 166])
    ]
    

    您可以通过计算图像的像素坐标来检查这一点,并进行打印验证。

    如果您仍然可以更改标记,我会使用对比度更大的标记,而不是单一颜色(例如带有白色边框的蓝色正方形等),这将有助于 canny > findContour 和随后的 approxpoly 找到正方形。

    如果更改标记是不行的,那么最好的办法是分离 R、G 和 B 通道,然后执行 canny > findcontour。我怀疑红色和蓝色方块会很好,但黄色方块会很差,因为它融入了景观。

    【讨论】:

      【解决方案2】:

      我已经把代码移到了python3/OpenCV3,否则是基于你的代码

      @pandamakes 的说法是正确的。您需要寻找接近目标值的像素,但不能假设您会得到非常接近该值的像素。

      我添加了一个忽略边界的遮罩(您会在周围看到很多伪影),并且我修改了目标值,因为在现实生活中您不太可能获得零值的像素(尤其是在您有大气反射的航拍图像中) )

      基本上我正在寻找一个值接近目标值的区域,并使用洪水填充来定位实际目标边界

      EDIT  从 RGB 色彩空间转移到 CIELab 并仅使用 ab 色通道以增加对照明条件的鲁棒性

      import cv2
      import numpy as np
      
      image = cv2.imread('tarpsB.jpg', 1)
      #convert to CIELab
      cielab = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)
      
      # define target strings
      targ = ['Target 1 - Blue', 'Target 2 - Yellow', 'Target 3 - Red']
      i = 0
      
      # colors = [
      #           ([91, 40, 40]), ([40, 209, 255]), ([81, 60, 166])
      # ]
      # rough conversion of BGR target values to CIELab 
      cielab_colors = [
                ([20, 20, -40]), ([80, 0, 90]), ([40, 70, 30])
      ]
      
      # # loop over the boundaries
      height = image.shape[0]
      width = image.shape[1]
      mask = np.ones(image.shape[0:2])
      
      cv2.circle( mask, (int(width/2), int(height/2)), int(height/2), 0, -1 );
      mask = 1-mask
      mask = mask.astype('uint8')
      
      #for color in colors:
      for cielab_color in cielab_colors:
          diff_img = cielab.astype(float)
          # find the colors within the specified boundaries and apply
          # the mask
      
          diff_img[:, :, 0] = np.absolute( diff_img[:, :, 0] - 255 * cielab_color[0] / 100 )
          diff_img[:, :, 1] = np.absolute( diff_img[:, :, 1] - (cielab_color[1] + 128) )
          diff_img[:, :, 2] = np.absolute( diff_img[:, :, 2] - (cielab_color[2] + 128) )
      
      
          diff_img = ( diff_img[:, :, 1] + diff_img[:, :, 2]) / 2
          diff_img = cv2.GaussianBlur(diff_img, (19, 19), 0)
          minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(diff_img, mask)
          min_img = np.array(diff_img/255)
      
          ff_mask = np.zeros( (height + 2, width + 2), np.uint8)
          cv2.floodFill(image, ff_mask, minLoc, 255, (12, 12, 12), (12, 12, 12), cv2.FLOODFILL_MASK_ONLY );
          ff_mask = ff_mask[1:-1, 1:-1]
          im2, contours, hierarchy = cv2.findContours(ff_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
      
          # Find the index of the largest contour
          areas = [cv2.contourArea(c) for c in contours]
          max_index = np.argmax(areas)
          cont=contours[max_index]
          print('target color = {}'.format(image[minLoc[1], minLoc[0], :]))
          # putting text and outline rectangles on image
          x,y,w,h = cv2.boundingRect(cont)
          cv2.rectangle(image,(x,y),(x+w,y+h),colors[i],2)
          cv2.putText(image, targ[i], (x-50, y-10), cv2.FONT_HERSHEY_PLAIN, 0.85, (0, 255, 0))
      
          cv2.imshow('diff1D',diff_img/255)
          cv2.imshow('ff_mask',ff_mask*255)
          cv2.waitKey(0)
          i += 1
      
      cv2.imshow("Show",image)
      cv2.waitKey(0)
      
      cv2.destroyAllWindows()
      

      编辑添加输出图像

      【讨论】:

      • 嗨,罗莎,我使用了这段代码,它与我最初发布的图像配合得很好。但是,我今天拍摄了更多样本图像,红色和蓝色目标没有被识别。不同的颜色边界是否有助于识别这些目标?这是我尝试分析的其中一张图片:jpeg-optimizer.com/uploaded_images_final/…
      • 理想情况下,您应该学习目标颜色,但我认为,如果您从几个(非连续)帧中对颜色进行采样并将目标颜色设置为样本,则意味着您将获得合理的结果
      • 无论如何,我更新了代码以使用 CIELab 而不是 RGB,它应该会更好
      猜你喜欢
      • 2016-10-12
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 2021-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多