Извлечь произвольный прямоугольный участок из изображения с заданными 4 точечными координатами - PullRequest
0 голосов
/ 16 апреля 2019

Учитывая координаты четырех произвольных точек на изображении (которые гарантированно образуют прямоугольник), я хочу извлечь патч, который они представляют, и получить их векторизованное (плоское) представление. Как я могу это сделать?

Я видел ответ на этот вопрос и, используя его, я смог добраться до нужного мне патча. Например, учитывая координаты изображения 4 углов зеленого прямоугольника на этом изображении:

Example test image

Я могу добраться до патча и получить что-то вроде:

patch extracted

используя следующий код:

p1 = (334,128)
p2 = (438,189)
p3 = (396,261)
p4 = (292,200)
pts = np.array([p1, p2, p3, p4])

mask = np.zeros((img.shape[0], img.shape[1]))

cv2.fillConvexPoly(mask, pts, 1)
mask = mask.astype(np.bool)

out = np.zeros_like(img)
out[mask] = img[mask]
patch = img[mask]

cv2.imwrite(img_name, out)

Однако проблема в том, что полученная мною переменная patch представляет собой просто массив всех пикселей изображения, которые принадлежат заплатке, когда изображение читается в виде матрицы в главном порядке строк.

Я хочу, чтобы переменная patch содержала пиксели в том порядке, в котором они могут сформировать подлинное изображение, чтобы я мог выполнять над ним операции. Есть ли функция opencv, о которой я должен знать, которая помогла бы мне в этом?

Спасибо!

1 Ответ

0 голосов
/ 16 апреля 2019

Вот как это можно реализовать:

Код:

    # create a subimage with the outer limits of the points
    subimg = out[128:261,292:438]

    # calculate the angle between the 2 'lowest' points, the 'bottom' line
    myradians = math.atan2(p3[0]-p4[0], p3[1]-p4[1])
    # convert to degrees 
    mydegrees = 90-math.degrees(myradians)

    # create rotationmatrix
    h,w = subimg.shape[:2]
    center = (h/2,w/2)
    M = cv2.getRotationMatrix2D(center, mydegrees, 1)
    # rotate subimage
    rotatedImg = cv2.warpAffine(subimg, M, (h, w))

Результат:
enter image description here

Далее,черные области на изображении можно легко обрезать, удалив все строки / столбцы, которые на 100% черные.
Окончательный результат:
enter image description here
Код:

    # converto image to grayscale
    img = cv2.cvtColor(rotatedImg, cv2.COLOR_BGR2GRAY)

    # sum each row and each volumn of the image
    sumOfCols = np.sum(img, axis=0)
    sumOfRows = np.sum(img, axis=1)

    # Find the first and last row / column that has a sum value greater than zero, 
    # which means its not all black. Store the found values in variables
    for i in range(len(sumOfCols)):
            if sumOfCols[i] > 0:
                    x1 = i
                    print('First col: ' + str(i))
                    break

    for i in range(len(sumOfCols)-1,-1,-1):
            if sumOfCols[i] > 0:
                    x2 = i
                    print('Last col: ' + str(i))
                    break

    for i in range(len(sumOfRows)):
            if sumOfRows[i] > 0:
                    y1 = i
                    print('First row: ' + str(i))
                    break

    for i in range(len(sumOfRows)-1,-1,-1):
            if sumOfRows[i] > 0:
                    y2 = i
                    print('Last row: ' + str(i))
                    break

    # create a new image based on the found values
    finalImage = rotatedImg[y1:y2,x1:x2]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...