Рассчитать преобразование на основе привязки в изображении opencv2 / py - PullRequest
0 голосов
/ 29 апреля 2020

Я хотел бы рассчитать матрицу преобразования (вращение, масштабирование и перемещение) в соответствии с привязкой на изображении.

Мое изображение - это изображение метки, которая всегда будет содержать матрицу данных. Я использую стороннюю библиотеку для обнаружения матрицы данных. Затем я получаю его размер, ориентацию (используя результат cv2.minAreaRect(dm_contour)) и положение. Я строю то, что я называю своим «якорем» с этими параметрами.

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

С помощью этих нескольких шагов я могу правильно разместить свои ROI в соответствии с новым контекстом метки, если он имеет только перевод (смещен влево, вправо, сверху, снизу).

Но как как только я пытаюсь заменить ОИ на повернутой этикетке, это не сработает.

Если я думаю, что моя проблема связана с моей матрицей ротации и целым процессом "перевести в исходное положение и вернуться в положение". Но я не могу понять, что я делаю неправильно ...

Мой код для преобразования позиции ROI выглядит так:

def process_job(anchor, img, job, file_path):
    """
    Process job file on current picture
    @param anchor = Current scene anchor
    @param img = Current picture
    @param job = Job object
    @param file_path = Job file path
    """
    print("Processing job " + file_path)
    """ Unpack detected anchor """
    a_x, a_y = (anchor[0], anchor[1])
    rotation = anchor[2]
    anchor_size = int(anchor[3])

    for item_i in job:
        item = job[item_i]
        if 'anchor' in item:
            """ Apply size rate """
            size_rate = anchor_size / int(item['anchor']['size'])
            """" Item anchor pos """
            i_a_x, i_a_y = int(item['anchor']['x']), int(item['anchor']['y'])
            """ Calculate transformation """
            """ Scaling """
            S = np.array([
                            [size_rate, 0, 0],
                            [ 0, size_rate, 0],
                            [ 0, 0, 1]
                        ])

            """ Rotation """
            angle = rotation - int(item['anchor']['o'])
            theta = np.radians(angle)
            c, s = np.cos(theta), np.sin(theta)

            R = np.array((
                        (c, s, 0),
                        (-s, c, 0),
                        (0, 0, 1)
                        ))

            """ Translation """
            x_scale = a_x - i_a_x
            y_scale = a_y - i_a_y

            T = np.array([
                            [1, 0, x_scale],
                            [0,  1, y_scale],
                            [0, 0, 1]
                        ])

            """ Shear """
            shx_factor = 0
            Shx = np.array([
                            [1, shx_factor, 0],
                            [0, 1, 0],
                            [0, 0, 1]
                        ])

            shy_factor = 0
            Shy = np.array([
                            [1,0, 0],
                            [shy_factor, 1, 0],
                            [0, 0, 1]
                        ])

            print("Scaling: " + str(size_rate) + " Rotation:" + str(angle) + " Translation:" + str((x_scale, y_scale)))
            if 'rect' in item:
                """ Unpack rectangle """
                """ (r_x1, r_y1) top-left corner """
                """ (r_x2, r_y2) bottom right corner """
                r_x1, r_y1, r_x2, r_y2 = (int(item['rect']['x1']), int(item['rect']['y1']), int(item['rect']['x2']), int(item['rect']['y2']))

                """ As np arrays """
                rect_1 = np.array([r_x1, r_y1, 1])
                rect_2 = np.array([r_x2, r_y2, 1])

                """ Translate to origen """
                T_c_1 = np.array([
                                [1, 0, -r_x1],
                                [0,  1, -r_y1],
                                [0, 0, 1]
                            ])
                """ Translate to origen """
                T_c_2 = np.array([
                                [1, 0, -r_x2],
                                [0,  1, -r_y2],
                                [0, 0, 1]
                            ])

                """ Back to postion """
                T_r1 = np.array([
                                [1, 0, r_x1],
                                [0,  1, r_y1],
                                [0, 0, 1]
                            ])

                """ Back to postion """
                T_r2 = np.array([
                                [1, 0, r_x2],
                                [0,  1, r_y2],
                                [0, 0, 1]
                            ])
                """ Apply transformations """
                final_1 =  T @ T_r1 @ R @ T_c_1 @ S @ rect_1
                final_2 =  T @ T_r2 @ R @ T_c_2 @ S @ rect_2
                x1, y1, x2, y2 = final_1[0], final_1[1], final_2[0], final_2[1]

                print("From " + str((r_x1, r_y1, r_x2, r_y2)))
                print("To " + str((int(x1), int(y1), int(x2), int(y2))))

                cv2.line(img, (int(x1), int(y1)), (int(x2), int(y2)), \
                            (0,0,0), 2)

    cv2.imwrite('./output/job.png', img)

А вот пример моих изображений:

Original, user defined ROI

First sample, shifted, correct detection

Second sample, rotated, misplaced ROI (out of picture)

Спасибо заранее за вашу помощь,

1 Ответ

0 голосов
/ 07 мая 2020

Итак,

Я даже не знаю, нашел ли кто-то время, чтобы прочитать мой вопрос, но если это может помочь, вот что я сделал.


В моей первой версии кода я пытался вычислить следующую матрицу преобразования:

  • Матрица перевода 'T'
  • Вращение 'R'
  • Масштабирование 'S'

Но не хватало двух из них:

  • Полное X 'ShX'
  • Полное Y 'ShY'

Моя первая вторая версия выглядела как roi_pos = ShX @ ShY @ S @ T @ T_to_pos @ R @ T_to_origin @ item_roi

Результаты были очень неуклюжими, и ROI, который я определял с моей моделью, не был правильно расположен на моих тестовых образцах. Но ротация была правильной, и каким-то образом рентабельность инвестиций упала бы до ожидаемых результатов.

Затем я подумал об оптимизации своего обнаружения Datamatrix, поэтому я приложил все усилия, чтобы реализовать свою собственную версию обнаружения DM на python / numpy / openCV алгоритм. Обнаружение острого DM помогло мне лучше оценить параметры ориентации и масштаба, но ROI все еще были отключены.

Итак, я обнаружил гомографию, которая в точности соответствует тому, что я хочу. Это берет пункты в известном плане и те же самые пункты в плане пункта назначения. Затем он вычисляет преобразование, которое произошло между двумя планами.

С этой матрицей 'H', я знаю, можно сделать roi_pos = H @ item_roi, что гораздо точнее.

Вот и все, надеюсь, это поможет

...