[英]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
編輯:添加了結果圖像
如果我猜對了,您需要一個矩形,該矩形邊界帶有彎曲邊緣的藍色框。 如果是這種情況,那就很容易了。 應用這個 -
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.