Как найти верхний левый угол моего контурного ограничивающего прямоугольника в Python OpenCV

Чем я занимаюсь: у меня есть роботизированная рука, и я хочу найти координаты x, y объектов на листе бумаги.

Я могу найти контур листа бумаги и получить его размеры (h, w). Мне нужны координаты моего верхнего левого угла, поэтому, когда я помещаю объекты на свой лист бумаги, я могу получить координаты изображения относительно этой точки. Оттуда я конвертирую эти пиксельные координаты в сантиметры, и я смогу вернуть координаты x, y моей роботизированной руке.

Проблема: я нашел центр своего контура и подумал, что левый верхний угол будет тогда ...

координата центра x - (ширина / 2), координата центра y - (высота / 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)

person NoviceCoder    schedule 16.03.2018    source источник
comment
Предполагая, что c - это контур листа бумаги, cv2.boundingRect (c) должен вернуть [intX, intY, intWidth, intHeight], где (intX, intY) - ваш верхний левый угол. Однако не проверено. Скажите, работает ли у вас!   -  person Yohboy    schedule 16.03.2018
comment
Спасибо, я попробую это решение сегодня позже и доложу, когда у меня будет доступ к лаборатории!   -  person NoviceCoder    schedule 16.03.2018


Ответы (1)


Находит повернутый прямоугольник минимальной площади, охватывающий входной набор 2D точек.

От: OpenCV docs

Итак, причина вашей проблемы очевидна, ваш контур имеет небольшой наклон, поэтому минимальный прямоугольник, охватывающий весь контур, будет вне границ на нижней стороне.

С

contours

просто содержит вектор точек (здесь речь идет об интерфейсе C ++), должно быть легко найти верхний левый угол путем поиска точки с наименьшим значением x и наибольшим значением y в наибольшем контуре.

person s1hofmann    schedule 16.03.2018
comment
Хорошо, спасибо, что имеет смысл. Я попробую это, когда у меня будет доступ к лаборатории, и скажу вам, работает ли это. - person NoviceCoder; 16.03.2018
comment
Да, спасибо, я смог запустить этот код, следуя вашей идее, и большую часть времени он находит верхний левый угол! self.extLeft = кортеж (c [c [:,:, 0] .argmin ()] [0]) - person NoviceCoder; 17.03.2018
comment
self.extLeft = кортеж (c [c [:,:, 0] .argmin ()] [0]) - person NoviceCoder; 17.03.2018