我正在做一个大学项目,我尝试使用openCV在Android应用程序的屏幕截图上检测UI元素。我不希望这种UI元素检测具有100%的准确性。
这是我的以下代码。我将图像转换为灰度,应用高斯模糊,然后使用自适应阈值将图像转换为二进制。之后,我使用查找轮廓方法。
ap = argparse.ArgumentParser()
ap.add_argument("-i","--image", help = "path to an image", required =
True)
args = vars(ap.parse_args())
image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray",gray)
cv2.waitKey(0)
blurred = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.adaptiveThreshold(blurred, 255,
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 11, 4)
cv2.imshow("thresh",thresh)
cv2.waitKey(0)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cv2.drawContours(image, cnts, -1, (0,255,0), 1)
cv2.imshow("contours", image)
cv2.waitKey(0)
for c in cnts:
area = cv2.contourArea(c)
print(area)
if area > 50:
M = cv2.moments(c)
cX = int(M['m10'] / M['m00'])
cY = int(M['m01'] / M['m00'])
#cv2.drawContours(image, [c], -1, (0,255,0), 2) # draw contours on image
(x,y,w,h) = cv2.boundingRect(c) # for each contour get a
bounding rectangle
mask = np.zeros(image.shape[:2], dtype = "uint8") # find
shape of the image dimensions and set up a mask
mask[y: y + h, x: x + w] = 255 # convert region of
interest into white
to_display = cv2.bitwise_and(image,image, mask = mask) # carry
out bitwise and
#cv2.putText(image, 'center', (c))
cv2.imshow("Image", to_display)
cv2.waitKey(0)
这是我运行代码的屏幕截图。
最左边的屏幕快照表示在对其应用阈值后的图像。
中间图像表示绘制轮廓后得到的图像。
最后一张图片显示了当我检查每个单独的轮廓时。轮廓线覆盖了直线,但不封装矩形。
我有几个问题。
1)是否可以筛出白色矩形的轮廓。为了实现此目的,我必须对代码进行哪些更改?
2)我正在尝试筛除不重要的轮廓,例如。的话,我在想是否可以使用getArea()函数来帮助我。我的想法是,我将设置最小轮廓大小以过滤掉占单词较小的轮廓。
这是我试图在此屏幕快照中识别“对象”的另一张图像。
我在这里遇到相同的问题,无法识别白色矩形。我只是识别矩形的边框。
感谢任何形式的帮助,因为我还是openCv的新手
处理前的原始图像:
答案 0 :(得分:1)
没有必要模糊。实际上,这使我变得更加困难。简单的阈值最适合硬过渡。第二张图片最简单。在灰色背景上有白色物品。通过仅选择非常白色的值,就可以选择项目。
结果:
代码:
# load image
img = cv2.imread("app.png")
# convert to gray
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# crate a mask that hold only white values (above 250)
ret,thresh1 = cv2.threshold(img2,250,255,cv2.THRESH_BINARY)
# find contours in mask
im2, contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# select large contours (menu items only)
for cnt in contours:
print(cv2.contourArea(cnt))
if cv2.contourArea(cnt) > 5000:
# draw a rectangle around the items
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0),3)
#cv2.drawContours(img, [cnt], 0, (0,255,0), 3) #also works, but has issues with letters at the last item
#show image
cv2.imshow("img", img)
#cv2.imshow("mask", thresh) # shows mask
cv2.waitKey(0)
cv2.destroyAllWindows()
第一个图像更复杂,因为它被一条非常细的红线分开。在HSV色彩空间中选择颜色更加容易。接下来的红色值用于创建蒙版,去除一些噪点,然后检测轮廓。
结果:
# load image
img = cv2.imread("app2.png")
# convert to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# set lower and upper color limits
lower_val = np.array([0,0,0])
upper_val = np.array([20,50,255])
# Threshold the HSV image
mask = cv2.inRange(hsv, lower_val, upper_val)
# remove noise
kernel = np.ones((1,2),np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
kernel = np.ones((1,5),np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# find contours in mask
im2, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# select large contours (menu items only)
for cnt in contours:
print(cv2.contourArea(cnt))
if cv2.contourArea(cnt) > 1000:
# draw a rectangle around the items
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0),3)
#show image
cv2.imshow("img", img)
cv2.imshow("mask", mask)
cv2.waitKey(0)
cv2.destroyAllWindows()