簡體   English   中英

使用 opencv/python 進行形狀檢測

[英]Shape detection with opencv/python

我正在嘗試教我的測試自動化框架使用 opencv 檢測應用程序中的選定項目(該框架從被測設備中抓取幀/屏幕截圖)。 所選項目始終具有特定大小,並且始終具有藍色邊框,這有助於但它們包含不同的縮略圖圖像。 請參閱提供的示例圖像。

我已經對這個主題進行了大量的谷歌搜索和閱讀,並且我已經接近讓它在示例圖像中的圖像 C 的情況下正常工作。 示例圖像這是所選項目上有播放符號的地方。

我的理論是 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 只查看由藍色邊框定義的外部形狀而忽略內部形狀(播放符號,當然還有縮略圖)? 我敢肯定它必須以某種方式可行。

有許多不同的技術可以完成這項工作。 我不太確定 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

result - red rectangles around detected areas

編輯:添加了結果圖像

如果我猜對了,您需要一個矩形,該矩形邊界帶有彎曲邊緣的藍色框。 如果是這種情況,那就很容易了。 應用這個 -

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%

在閱讀了您的建議后,我對此進行了更多的嘗試,並發現 blob 檢測不是可行的方法。 使用顏色識別來找到輪廓解決了這個問題,但是正如上面所建議的。 再次感謝!

我的解決方案如下所示:

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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM