[英]How to obtain (x,y) coordinates of a shape found using mask in OpenCV, Python?
I am trying to locate certain items on an image.我正在尝试在图像上找到某些项目。 The image in simplified form looks like this:简化形式的图像如下所示:
I would like to obtain the (x,y) coordinates of the bold black text on top of the second rectangle, as well as of the three colored rectangles.我想获得第二个矩形顶部的粗体黑色文本以及三个彩色矩形的 (x,y) 坐标。
I have the masks ready, except for the mask of the black text that I wasn't able to figure out.我已经准备好了面具,除了我无法弄清楚的黑色文字的面具。 However, the text is always on top of the rectangle so if I'd be able to figure out the position of the bottom large rectangle, I would have the position of the text too.但是,文本总是在矩形的顶部,所以如果我能够找出底部大矩形的 position,我也会得到文本的 position。
These are the outputs I got:这些是我得到的输出:
I tried using the ConnectedComponents function based on this comment but apart from coloring and grouping the various objects, I didn't manage to move forward, so I didn't include that snippet below to make things as clear as possible.我尝试根据此评论使用 ConnectedComponents function,但除了对各种对象进行着色和分组之外,我没有设法继续前进,因此我没有在下面包含该片段以使事情尽可能清晰。
Here is my code so far:到目前为止,这是我的代码:
import cv2
import numpy as np
import imutils
PATH = "stackoverflow.png"
img = cv2.imread(PATH)
imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
mask_border = cv2.inRange(imgHSV,np.array([0,0,170]),np.array([0,0,175]))
mask_green = cv2.inRange(imgHSV,np.array([76,221,167]),np.array([76,221,167]))
mask_pink = cv2.inRange(imgHSV,np.array([168,41,245]),np.array([172,41,252]))
mask_red = cv2.inRange(imgHSV,np.array([4,207,251]),np.array([4,207,251]))
#mask_black = ???
all_masks = cv2.bitwise_or(mask_border, mask_green)
all_masks = cv2.bitwise_or(all_masks, mask_pink)
all_masks = cv2.bitwise_or(all_masks, mask_red)
cv2.imshow("Masks", all_masks)
imgResult = cv2.bitwise_and(img,img,mask=all_masks)
cv2.imshow("Output", imgResult)
cv2.waitKey(0)
You can binarise image and then apply some morphological operations to get the proper connected components.您可以对图像进行二值化,然后应用一些形态学操作来获得正确的连接组件。 Here is an approach.这是一种方法。 You can fine-tune this to get proper output.您可以对其进行微调以获得正确的 output。
import numpy as np
import cv2
import os
image=cv2.imread('path/to/image.jpg')
###binarising
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret2,th2 = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
###applying morphological operations to dilate the image
kernel=np.ones((3,3),np.uint8)
dilated=cv2.dilate(th2,kernel,iterations=3)
### finding contours, can use connectedcomponents aswell
_,contours,_ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
### converting to bounding boxes from polygon
contours=[cv2.boundingRect(cnt) for cnt in contours]
### drawing rectangle for each contour for visualising
for cnt in contours:
x,y,w,h=cnt
cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
Normal binary image正常二值图像
Dilated image放大图像
Try out this example: simple blob detector .试试这个例子: 简单的斑点检测器。 I would run it on your actual mask, rather than the rgb image since it will work pretty well on a binarized image like your mask.我会在你的实际蒙版上运行它,而不是 rgb 图像,因为它在像你的蒙版这样的二值化图像上效果很好。 Then pulling the pt and size attributes from the keypoints returned will give you the center and radius of your blobs.然后从返回的关键点中提取 pt 和 size 属性将为您提供 blob 的中心和半径。 (tbh not sure if it will be average or max radius without testing it). (不确定它是平均半径还是最大半径而不进行测试)。 I probably wouldn't even use the radius for your use case though, From the center point of each blob, I would search iteratively in the -x and -y axis (separately), out from that point.不过,我什至可能不会将半径用于您的用例,从每个 blob 的中心点,我将在 -x 和 -y 轴(分别)上迭代搜索,从该点开始。 At each step I would check if it was a black or white pixel and I would wait until I saw some adjustable variable number of black pixels in a row (basically to avoid triggering on text, but trying to trigger on exit of box and entrance to background).在每个步骤中,我都会检查它是黑色像素还是白色像素,然后我会等到在一行中看到一些可调节的可变数量的黑色像素(基本上是为了避免触发文本,但尝试在退出框和进入时触发背景)。 Those coords for x and y will be the upper left hand corner of your box. x 和 y 的坐标将位于框的左上角。 If you want you can do it in the positive x and y direction too in order to get the full bounding box.如果您愿意,您也可以在正 x 和 y 方向上进行操作,以获得完整的边界框。
I think the easiest method is to apply cv2.ConnectedComponentsWithStats
to your mask images.我认为最简单的方法是将cv2.ConnectedComponentsWithStats
应用于您的蒙版图像。 Included in the results are the Centroids, being the center coordinates of each "cluster".结果中包括质心,即每个“集群”的中心坐标。
See here: https://stackoverflow.com/a/35854198/221166见这里: https://stackoverflow.com/a/35854198/221166
You might want to apply Dilation beforehand, to connect inner islands (eg in b, d, g characters) with the surrounding rectangle.您可能希望事先应用 Dilation,将内岛(例如 b、d、g 字符)与周围的矩形连接起来。
,contours, = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) does not generate the x,y cordinates of every pixel ,contours, = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 不会生成每个像素的 x,y 坐标
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.