Гомография Opencv не дает требуемой трансформации

Я пытаюсь преобразовать изображение по краю объекта (здесь объект — книга). Используя хитроумное обнаружение краев, я обнаруживаю края и из матрицы оценок, основываясь на значении пикселя, я выбираю 4 случайные координаты, лежащие на краю, для преобразования. Но трансформация не такая, как она думала. В чем проблема/где я что-то упускаю?

Сначала я вырезал часть изображения. Затем применил хитрое обнаружение края и случайным образом выбрал 4 точки координат края, исходя из моего собственного состояния, как: Мое исходное изображение:

Гомография Opencv не дает требуемой трансформации

Для эксперимента я вырезал в соответствии с моими потребностями:

Гомография Opencv не дает требуемой трансформации

Размер этого изображения (61 160)

Теперь мне нужно преобразовать изображение выше, чтобы край книги был параллелен горизонтальной оси.

img = cv2.imread('download1.jpg',0)
edges = cv2.Canny(img,100,200)
print(img.shape)
plt.show()
plt.imshow(img,cmap='gray')

l=[]
y_list=[]
k=1
for i in range (0,img.shape[0]):
  for j in range (0,img.shape[1]):
    if (edges[i][j]==255) and k<=4 and i>31 and j not in y_list:
      l.append([j,i])
      y_list.append(j)
      k+=1
      break

Изображение обнаружения края получается как:

Гомография Opencv не дает требуемой трансформации

Содержимое списка l

[[49 32]
 [44 33]
 [40 34]
 [36 35]]

Затем установите точки назначения, указанные в списке lt, как:

[[49 61]
 [44 60]
 [40 61]
 [36 60]]

Затем обнаружил матрицу гомографии и использовал ее для определения перспективы деформации:

h, status = cv2.findHomography(l,lt)
im_out = cv2.warpPerspective(img, h, (img.shape[1],img.shape[0]))

Но это не дает нужного результата! Результирующее выходное изображение получается как:

Гомография Opencv не дает требуемой трансформации

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
366
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

  1. читать изображение
  2. краевой детектор
  3. линия, чтобы получить все линии (с наклоном внутри определенного интервала)

    lines = cv.HoughLinesP(img, 1, np.pi/180, 100, minLineLength=100, maxLineGap=10)
    
  4. получить средний наклон линий, потому что в моем случае у меня было много параллельных линий, которые можно было использовать в качестве ссылки, и таким образом я смог получить лучший результат

     for line in lines:
         x1,y1,x2,y2 = line[0]
         if (x2-x1) != 0:
             angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
         else:
             angle = 90
         #you can skip this test if you have no info about the lines you re looking for
         #in this case offset_angle is = 0
         if min_angle_threshold <= angle <= max_angle_threshold:
            tot_angle = tot_angle + angle
            cnt = cnt + 1
     average_angle = (tot_angle / cnt) - offset_angle 
    
  5. применить встречное вращение

      center = your rotation center - probably the center of the image
      rotation_matrix = cv.getRotationMatrix2D(center, angle, 1.0)
      height, width = img.shape
      rotated_image = cv.warpAffine(img, rotation_matrix, (width, height))
    
     #do whatever you want, then rotate image back
     counter_rotation_matrix = cv.getRotationMatrix2D(center, -angle, 1.0)
     original_image = cv.warpAffine( rotated_image, counter_rotation_matrix, (width, height))
    

Обновлено: см. полный пример здесь:

    import math
    import cv2 as cv

    img = cv.imread('C:\\temp\\test_3.jpg',0)
    edges = cv.Canny(img,100,200)
    lines = cv.HoughLinesP(edges[0:50,:], 1, np.pi/180, 50, minLineLength=10, maxLineGap=10)
    tot_angle = 0
    cnt = 0
    for line in lines:
        x1,y1,x2,y2 = line[0]
        if (x2-x1) != 0:
            angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
        else:
            angle = 90

        if -30 <= angle <= 30:
            tot_angle = tot_angle + angle
            cnt = cnt + 1
    average_angle = (tot_angle / cnt)
    h,w = img.shape[:2]
    center = w/2, h/2
    rotation_matrix = cv.getRotationMatrix2D(center, average_angle, 1.0)
    height, width = img.shape
    rotated_image = cv.warpAffine(img, rotation_matrix, (width, height))
    cv.imshow("roto", rotated_image)
    #do all your stuff here, add text and whatever
    #...
    #...
    counter_rotation_matrix = cv.getRotationMatrix2D(center, -average_angle, 1.0)
    original_image = cv.warpAffine( rotated_image, counter_rotation_matrix, (width, height))
    cv.imshow("orig", original_image)

повернутый

![rotated]1

counter_rotated

![counter_rotated]2

Обновлено:

если вы хотите применить гомографию (отличную от простого поворота, потому что она также применяет преобразование перспективы), под кодом, чтобы заставить его работать:

#very basic example, similar to your code with fixed terms
l  = np.array([(11,32),(43,215),(142,1),(205,174)])
lt = np.array([(43,32),(43,215),(205,32),(205,215)])
h, status = cv.findHomography(l,lt)
im_out = cv.warpPerspective(img, h, (img.shape[1],img.shape[0]))

Чтобы сделать это программно - для «l»: просто используйте хиглайны и найдите 4 угла, затем добавьте их

  • для «lt»: найдите «пункт назначения» для всех 4 точек, например, используйте нижние углы в качестве ориентира.

    lines = cv.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=150, maxLineGap=5)
    l = []
    for line in lines:
        x1,y1,x2,y2 = line[0]
    
        if (x2-x1) != 0:
            angle = math.atan((float(y2-y1))/float((x2-x1))) * 180 / math.pi
        else:
            angle = 90
        # consider only vertical edges
        if 60 <= angle:
            l.append((x1,y1))
            l.append((x2,y2))
            x_values.append(max(x1,x2)) 
            if len(y_values) == 0:
                y_values.append(y1)
                y_values.append(y2)
    l  = np.array(l)
    lt = np.array([(x_values[0],y_values[0]),(x_values[0],y_values[1]),(x_values[1],y_values[0]),(x_values[1],y_values[1])])
    

затем вызовите findhomography, как это было сделано выше Надеюсь, это достаточно ясно!

3

На самом деле я хочу вставить текст, а затем повернуть его, как это сделать?

Hamsa 13.06.2019 13:45

Я могу вставить текст, но как его повернуть, чтобы получить предыдущее изображение?

Hamsa 13.06.2019 13:45

Я думаю, вы можете просто добавить текст к повернутому изображению, а затем повернуть его обратно (угол *-1)

Mauro Dorni 13.06.2019 14:08

Я вижу, что центр определяет, как изображение будет вращаться, как сделать, чтобы изображение вращалось по определенному краю? Как определить центр вращения

Hamsa 13.06.2019 14:19

Я хочу сделать ребро параллельно горизонтальной оси, как это сделать?

Hamsa 13.06.2019 14:21

Зависит от результата, который вы хотите: я думаю, вы можете просто поместить центр изображения или использовать нижний левый угол книги (проверьте края линий и найдите точку с младшим x и основным y)

Mauro Dorni 13.06.2019 14:21

да, я пытался изменить строку x1,y1,x2,y2 = line[0] на x1,y1,x2,y2 = line[1] , но она показывает ошибку как index 1 is out of bounds for axis 0 with size 1, почему это так?

Hamsa 13.06.2019 14:28

Давайте продолжить обсуждение в чате.

Mauro Dorni 13.06.2019 14:40

Другие вопросы по теме