2016-11-19 2 views
1

Я следую this opencv tutorial about pose estimation and "augmented reality" и изменяю его для работы в реальном времени с помощью веб-камеры. Все работает хорошо, но я нашел этот странный факт.OpenCv не принимает несколько команд рисования в функции (в Python)

Сначала я должен показать код. Учебник рассказывает мне, чтобы определить внешнюю функцию отрисовки как

def draw(img, corners, imgpts): 
    corner = tuple(corners[0].ravel()) 
    img = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5) 
    img = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5) 
    img = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5) 
    return img 

нарисовать 3 оси на моей шахматной доске, а затем отобразить его в моем видео

imgpts, jac = cv2.projectPoints(axis, rvecs, tvecs, mtx, dist) 
    img = draw(img,corners,imgpts) 
# Draw and display the corners 
cv2.imshow('REALITY',img) 

В этом случае сценарий рисует только синяя (X) линия. Но если я определяю 3 различных функций, таких как

def drawx(img, corners, imgpts): 
    corner = tuple(corners[0].ravel()) 
    img = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5) 
    #img = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5) 
    #img = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5) 
    return img 

оставляя раскомментирована каждый раз другую линию, а затем нарисуйте линии последовательно на том же изображении, как этот

imgx = drawx(img,corners,imgpts) 
    imgy = drawy(img,corners,imgpts) 
    imgz = drawz(img,corners,imgpts) 

# Draw and display the corners 
cv2.imshow('REALITY',img) 

я получить цель урока , exactly like this, а также тот факт, что я получил скрипт для работы в режиме реального времени.

Это обходной путь, но он работает. Мой вопрос: Почему openCV не рисует три линии в одной и той же функции? Это зависит от моей версии openCV (2.4.8)? Это зависит от моей версии python (2.7)?

Update1

После запроса Micka в (я надеюсь на undertand это хорошо) я изменил свою первоначальную функцию отрисовки в

def draw(img, corners, imgpts): 
    corner = tuple(corners[0].ravel()) 
    img = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5) 
    img = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5) 
    img = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5) 
    print imgpts 
    return img 

И результат (один набор точек, как, например) является

[[[ 323.7434082 162.16279602]] 

[[ 329.28009033 350.18307495]] 

[[ 513.23809814 349.89364624]] 

[[ 512.85174561 161.18948364]] 

[[ 281.99362183 157.28944397]] 

[[ 290.17071533 384.95501709]] 

[[ 512.66680908 384.78421021]] 

[[ 512.18347168 156.10710144]]] 

их печать по-другому

print tuple(imgpts[0].ravel()) 
print tuple(imgpts[1].ravel()) 
print tuple(imgpts[2].ravel()) 

дает что-то вроде

(351.51596, 55.176319) 
(352.62543, 254.72102) 
(542.78979, 256.04565) 

UPDATE 2 В комментариях они предлагают напечатать 3 "простых" строк в функции. Я написал

def draw_test(img): 
    cv2.line(img, (0,0), (200,10), (255,0,0), 5) 
    cv2.line(img, (0,0), (200,200), (0,255,0), 5) 
    cv2.line(img, (0,0), (10,200), (0,0,255), 5) 
    return img 

и, на удивление, на этот раз все 3 строки были напечатаны.

+0

можете ли вы напечатать все координаты точки в вашей первой функции розыгрыша? – Micka

+0

@Micka Я обновляю вопрос с помощью 1 набора точечных координат, найденных в качестве входных данных функции рисования. И я обнаружил, что также, если я помещаю cv2.line в цикл FOR в определенную функцию, также выводится только первая строка. – marcoresk

+0

thx. но лучше печатать каждый отдельно: tuple (imgpts [0] .ravel()) tuple (imgpts [1] .ravel()) tuple (imgpts [2] .ravel()) для визуализации фактического ввода. Следующим шагом будет жесткое программирование 3 разных строк в одной функции для тестирования. – Micka

ответ

1

Простой код, который воспроизводит эту проблему и соответствует тому, что у вас есть, заключается в следующем.

import cv2 
import numpy as np 


img1 = np.zeros((300,300,3), np.uint8) 
img2 = np.zeros((300,300,3), np.uint8) 

def draw_1(img): 
    img = cv2.line(img, (0,0), (200,10), (255,0,0), 5) 
    img = cv2.line(img, (0,0), (200,200), (0,255,0), 5) 
    img = cv2.line(img, (0,0), (10,200), (0,0,255), 5) 
    return img 

def draw_2(img): 
    cv2.line(img, (0,0), (200,10), (255,0,0), 5) 
    cv2.line(img, (0,0), (200,200), (0,255,0), 5) 
    cv2.line(img, (0,0), (10,200), (0,0,255), 5) 
    return img 

draw_1(img1) 
draw_2(img2) 

cv2.imwrite("lines_1.png", img1) 
cv2.imwrite("lines_2.png", img2) 

Линия 1:

Bad result

Lines 2:

Good result

Функция draw_1 здесь соответствует исходной draw функции и draw_2 соответствует тому, что вы имели в UPDATE 2.

Обратите внимание, что в draw_1 вы назначаете результат от cv2.line до img. Это проблема, поскольку в соответствии с documentationcv2.line возвращается None.

Следовательно, ваш первый звонок превратит ваше изображение в None, а оставшиеся две линии нарисованы на «Nothing».

1

Как Dan Masek pointed out in his solution исходный код из учебника

def draw(img, corners, imgpts): 
    corner = tuple(corners[0].ravel()) 
    img = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5) 
    img = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5) 
    img = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5) 
    return img 

просто быть изменен в

def draw(img, corners, imgpts): 
    corner = tuple(corners[0].ravel()) 
    img_x = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5) 
    img_y = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5) 
    img_z = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5) 
    return img_x, img_y, img_z 

или без каких-либо спецификаций

def draw(img, corners, imgpts): 

corner = tuple(corners[0].ravel()) 
cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5) 
cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5) 
cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5) 
return img 

и все работает.