如何在 Python OpenCV 中找到轮廓边界框的最左上角
How to find upper left most corner of my Contour Bounding Box in Python OpenCV
我在做什么:我有一个机械臂,我想在一张纸上找到物体的 x,y 坐标。
我能够找到一张 sheet 纸的轮廓并得到它的尺寸 (h,w)。我想要左上角的坐标,这样当我将对象放在我的纸上时,我可以获得相对于该点的图像坐标。从那里我会将这些像素坐标转换为 cm,然后我将能够 return x,y 坐标到我的机械臂。
问题:我找到轮廓的中心,我认为左上角将是...
中心x坐标-(width/2),中心y坐标-(height/2)
我得到的轮廓框的图片。
*带框的轮廓图 应该在轮廓的左上角附近
但是,我得到的坐标超出了我的纸张范围。有没有更简单的方法来找到我的左上角坐标?
代码
class Boundary(object):
def __init__(self, image):
self.frame = image
self.DefineBounds()
def DefineBounds(self):
# convert the image to grayscale, blur it, and detect edges
# other options are four point detection, white color detection to search for the board?
gray = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(gray, 35, 125)
# find the contours in the edged image and keep the largest one;
# we'll assume that this is our piece of paper in the image
# (cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
th, contours, hierarchy = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
c = max(contours, key=cv2.contourArea)
# compute the bounding box of the of the paper region and return it
cv2.drawContours(self.frame, c, -1, (0, 255, 0), 3)
cv2.imshow("B and W", edged)
cv2.imshow("capture", self.frame)
cv2.waitKey(0)
# minAreaRect returns (center (x,y), (width, height), angle of rotation )
# width = approx 338 (x-direction
# height = 288.6 (y-direction)
self.CenterBoundBox = cv2.minAreaRect(c)[0]
print("Center location of bounding box is {}".format(self.CenterBoundBox))
CxBBox = cv2.minAreaRect(c)[0][1]
CyBBox = cv2.minAreaRect(c)[0][0]
# prints picture resolution
self.OGImageHeight, self.OGImageWidth = self.frame.shape[:2]
#print("OG width {} and height {}".format(self.OGImageWidth, self.OGImageHeight))
print(cv2.minAreaRect(c))
BboxWidth = cv2.minAreaRect(c)[1][1]
BboxHeight = cv2.minAreaRect(c)[1][0]
self.Px2CmWidth = BboxWidth / 21.5 # 1cm = x many pixels
self.Px2CmHeight = BboxHeight / 18 # 1cm = x many pixels
print("Bbox diemensions {} x {}".format(BboxHeight, BboxWidth))
print("Conversion values Px2Cm width {}, Px2Cm height {}".format(self.Px2CmWidth, self.Px2CmHeight))
self.TopLeftCoords = (abs(CxBBox - BboxWidth/2), abs(CyBBox - BboxHeight/2))
x = int(round(self.TopLeftCoords[0]))
y = int(round(self.TopLeftCoords[1]))
print("X AND Y COORDINATES")
print(x)
print(y)
cv2.rectangle(self.frame, (x, y), (x+10, y+10), (0, 255, 0), 3)
print(self.TopLeftCoords)
cv2.imshow("BOX",self.frame)
cv2.waitKey(0)
Finds a rotated rectangle of the minimum area enclosing the input 2D point set.
发件人:OpenCV docs
所以你的问题原因很明显,你的轮廓有点倾斜,所以包围整个轮廓的最小矩形会在下边出界。
自
contours
只是保存了一个点的向量(这里说的是C++接口),在最大的等高线中搜索x最小y最大的点应该很容易找到左上角
我在做什么:我有一个机械臂,我想在一张纸上找到物体的 x,y 坐标。
我能够找到一张 sheet 纸的轮廓并得到它的尺寸 (h,w)。我想要左上角的坐标,这样当我将对象放在我的纸上时,我可以获得相对于该点的图像坐标。从那里我会将这些像素坐标转换为 cm,然后我将能够 return x,y 坐标到我的机械臂。
问题:我找到轮廓的中心,我认为左上角将是...
中心x坐标-(width/2),中心y坐标-(height/2)
我得到的轮廓框的图片。
*带框的轮廓图 应该在轮廓的左上角附近
但是,我得到的坐标超出了我的纸张范围。有没有更简单的方法来找到我的左上角坐标?
代码
class Boundary(object):
def __init__(self, image):
self.frame = image
self.DefineBounds()
def DefineBounds(self):
# convert the image to grayscale, blur it, and detect edges
# other options are four point detection, white color detection to search for the board?
gray = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(gray, 35, 125)
# find the contours in the edged image and keep the largest one;
# we'll assume that this is our piece of paper in the image
# (cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
th, contours, hierarchy = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
c = max(contours, key=cv2.contourArea)
# compute the bounding box of the of the paper region and return it
cv2.drawContours(self.frame, c, -1, (0, 255, 0), 3)
cv2.imshow("B and W", edged)
cv2.imshow("capture", self.frame)
cv2.waitKey(0)
# minAreaRect returns (center (x,y), (width, height), angle of rotation )
# width = approx 338 (x-direction
# height = 288.6 (y-direction)
self.CenterBoundBox = cv2.minAreaRect(c)[0]
print("Center location of bounding box is {}".format(self.CenterBoundBox))
CxBBox = cv2.minAreaRect(c)[0][1]
CyBBox = cv2.minAreaRect(c)[0][0]
# prints picture resolution
self.OGImageHeight, self.OGImageWidth = self.frame.shape[:2]
#print("OG width {} and height {}".format(self.OGImageWidth, self.OGImageHeight))
print(cv2.minAreaRect(c))
BboxWidth = cv2.minAreaRect(c)[1][1]
BboxHeight = cv2.minAreaRect(c)[1][0]
self.Px2CmWidth = BboxWidth / 21.5 # 1cm = x many pixels
self.Px2CmHeight = BboxHeight / 18 # 1cm = x many pixels
print("Bbox diemensions {} x {}".format(BboxHeight, BboxWidth))
print("Conversion values Px2Cm width {}, Px2Cm height {}".format(self.Px2CmWidth, self.Px2CmHeight))
self.TopLeftCoords = (abs(CxBBox - BboxWidth/2), abs(CyBBox - BboxHeight/2))
x = int(round(self.TopLeftCoords[0]))
y = int(round(self.TopLeftCoords[1]))
print("X AND Y COORDINATES")
print(x)
print(y)
cv2.rectangle(self.frame, (x, y), (x+10, y+10), (0, 255, 0), 3)
print(self.TopLeftCoords)
cv2.imshow("BOX",self.frame)
cv2.waitKey(0)
Finds a rotated rectangle of the minimum area enclosing the input 2D point set.
发件人:OpenCV docs
所以你的问题原因很明显,你的轮廓有点倾斜,所以包围整个轮廓的最小矩形会在下边出界。
自
contours
只是保存了一个点的向量(这里说的是C++接口),在最大的等高线中搜索x最小y最大的点应该很容易找到左上角