【问题标题】:Shape detection with opencv/python使用 opencv/python 进行形状检测
【发布时间】:2019-02-25 23:42:41
【问题描述】:

我正在尝试教我的测试自动化框架使用 opencv 检测应用程序中的选定项目(该框架从被测设备中抓取帧/屏幕截图)。选定的项目总是有一定的大小,总是有蓝色边框,这有帮助,但它们包含不同的缩略图。请参阅提供的示例图片。

我已经对该主题进行了很多谷歌搜索和阅读,并且我已经接近让它在示例图像中的图像 C 的一个场景中正常工作。 example image 这是选中项目上有播放符号的地方。

我的理论是 OpenCV 在这种情况下会感到困惑,因为播放符号基本上是圆形的,里面有一个三角形,我要求它找到一个矩形。

我发现这很有帮助:https://www.learnopencv.com/blob-detection-using-opencv-python-c/

我的代码如下所示:

import cv2
import numpy as np

img = "testimg.png"

values = {"min threshold": {"large": 10, "small": 1},
          "max threshold": {"large": 200, "small": 800},
          "min area": {"large": 75000, "small": 100},
          "max area": {"large": 80000, "small": 1000},
          "min circularity": {"large": 0.7, "small": 0.60},
          "max circularity": {"large": 0.82, "small": 63},
          "min convexity": {"large": 0.87, "small": 0.87},
          "min inertia ratio": {"large": 0.01, "small": 0.01}}
size = "large"

# Read image
im = cv2.imread(img, cv2.IMREAD_GRAYSCALE)

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = values["min threshold"][size]
params.maxThreshold = values["max threshold"][size]

# Filter by Area.
params.filterByArea = True
params.minArea = values["min area"][size]
params.maxArea = values["max area"][size]

# Filter by Circularity
params.filterByCircularity = True
params.minCircularity = values["min circularity"][size]
params.maxCircularity = values["max circularity"][size]


# Filter by Convexity
params.filterByConvexity = False
params.minConvexity = values["min convexity"][size]

# Filter by Inertia
params.filterByInertia = False
params.minInertiaRatio = values["min inertia ratio"][size]

# Create a detector with the parameters
detector = cv2.SimpleBlobDetector(params)

# Detect blobs.
keypoints = detector.detect(im)

for k in keypoints:
    print k.pt
    print k.size

# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
# the size of the circle corresponds to the size of blob   
im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0, 0, 255),
                                      cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# Show blobs
cv2.imshow("Keypoints", im_with_keypoints)
cv2.waitKey(0)

如何让 OpenCV 只查看由蓝色边框定义的外部形状而忽略内部形状(播放符号,当然还有缩略图)?我敢肯定它一定是可行的。

【问题讨论】:

  • 我还有一个问题。如果图像周围没有边框怎么办?有什么方法可以检测白色背景下略带圆角的缩略图?

标签: python python-2.7 opencv image-processing computer-vision


【解决方案1】:

有许多不同的技术可以完成这项工作。我不太确定 BlobDetector 是如何工作的,所以我采取了另一种方法。此外,我不确定您需要什么,但您可以根据需要修改此解决方案。

import cv2
import numpy as np
from matplotlib.pyplot import figure
import matplotlib.pyplot as plt

img_name = "CbclA.png" #Image you have provided

min_color = 150 #Color you are interested in (from green channel)
max_color = 170

min_size = 4000 #Size of border you are interested in (number of pixels)
max_size = 30000


img_rgb = cv2.imread(img_name)
img = img_rgb[:,:,1] #Extract green channel
img_filtered = np.bitwise_and(img>min_color, img < max_color) #Get only colors of your border


nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(img_filtered.astype(np.uint8))

good_area_index = np.where(np.logical_and(stats[:,4] > min_size,stats[:,4] < max_size)) #Filter only areas we are interested in

for area in stats[good_area_index] : #Draw it
    cv2.rectangle(img_rgb, (area[0],area[1]), (area[0] + area[2],area[1] + area[3]), (0,0,255), 2)

cv2.imwrite('result.png',img_rgb)

查看connectedComponentsWithStats的文档

注意:我使用的是 Python 3

编辑:添加结果图片

【讨论】:

    【解决方案2】:

    如果我猜对了,你会想要一个矩形来包围带有弯曲边缘的蓝色框。如果是这种情况,那就很容易了。 应用这个 -

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    edged = cv2.Canny(gray, 75, 200) # You'll have to tune these
    
    # Find contours
    
    (_, contour, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 
    # This should return only one contour in 'contour' in your case
    

    这应该可以,但如果你仍然得到一个带有弯曲边缘的轮廓(边界框),请应用这个 -

    rect = cv2.approxPolyDP(contour, 0.02 * cv2.arcLength(contour, True), True) 
    # Play with the second parameter, appropriate range would be from 1% to 5%
    

    【讨论】:

      【解决方案3】:

      在阅读了您的建议后,我对此进行了更多尝试,发现斑点检测不是可行的方法。然而,如上所述,使用颜色识别来查找轮廓解决了这个问题。再次感谢!

      我的解决方案如下所示:

      frame = cv2.imread("image.png")
      color = ((200, 145, 0), (255, 200, 50))
      lower_color = numpy.array(color[0], dtype="uint8")
      upper_color = numpy.array(color[1], dtype="uint8")
      
      # Look for the color in the frame and identify contours
      color = cv2.GaussianBlur(cv2.inRange(frame, lower_color, upper_color), (3, 3), 0)
      contours, _ = cv2.findContours(color.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      
      if contours:
      
          for c in contours:
              rectangle = numpy.int32(cv2.cv.BoxPoints(cv2.minAreaRect(c)))
      
              # Draw a rectangular frame around the detected object
              cv2.drawContours(frame, [rectangle], -1, (0, 0, 255), 4)
      
          cv2.imshow("frame", frame)
          cv2.waitKey(0)
          cv2.destroyAllWindows()
      

      【讨论】:

        猜你喜欢
        • 2014-03-28
        • 1970-01-01
        • 2014-07-25
        • 1970-01-01
        • 2011-09-13
        • 1970-01-01
        • 1970-01-01
        • 2018-02-28
        • 2016-06-01
        相关资源
        最近更新 更多