简体   繁体   English

OpenCv不接受一个函数中的多个绘制指令(在Python中)

[英]OpenCv doesn't accept multiple draw instructions in a function (in Python)

I am following this opencv tutorial about pose estimation and "augmented reality" , and modifying it to work in real time with a webcam. 我正在关注有关姿势估计和“增强现实”的opencv教程 ,并对其进行修改以使用网络摄像头实时工作。 All works well but I found this strange fact. 一切正常,但我发现了这个奇怪的事实。

I have to show some code first. 我必须先显示一些代码。 The tutorial tells me to define an external draw function like 本教程告诉我定义一个外部绘制函数,例如

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

to draw the 3 axes on my chessboard, then display it in my video with 在棋盘上绘制3个轴,然后将其显示在我的视频中

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

In this way, the script draws only the blue (X) line. 这样,脚本仅绘制蓝色(X)线。 But if I define 3 different functions like 但是如果我定义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

leaving uncommented every time a different line, then draw the lines in sequence on the same image like this 每次留下不同的线条时都无需注释,然后像这样在同一张图像上依次绘制线条

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

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

I obtain the goal of the tutorial, exactly like this , plus the fact I obtained a script to work in real time. 我获得了本教程的目标, 就像这样 ,并获得了可以实时工作的脚本。

This is a workaround, but it works. 这是一种解决方法,但是可以。 My question is: why openCV does not draw the three lines in the same function? 我的问题是: 为什么openCV不在同一函数中绘制三行? It depends on my openCV version (2.4.8)? 这取决于我的openCV版本(2.4.8)? It depends on my python version (2.7)? 这取决于我的python版本(2.7)?

UPDATE1 UPDATE1

After Micka's request (I hope to undertand it well) I modified my original draw function as 在Micka的要求下(我希望能很好地理解它),我将原始绘图功能修改为

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

And the result (one set of points as example) is 结果(以一组点为例)为

[[[ 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]]]

printing them in another way 用另一种方式打印

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

gives something like 给像

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

UPDATE 2 In the comments they suggest to print 3 "simple" lines in a function. 更新2在注释中,他们建议在函数中打印3条“简单”行。 I wrote 我写

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

and surprisingly this time all the 3 lines were printed. 令人惊讶的是,这次打印了所有3行。

Simplest code that reproduces this problem and matches what you've got there is as follows. 重现此问题并与您所拥有的内容相匹配的最简单的代码如下。

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)

Lines 1: 第1行:

结果不好

Lines 2: 第2行:

好结果

Function draw_1 here corresponds to your original draw function, and draw_2 corresponds to what you had in UPDATE 2. 这里的draw_1函数对应于原始的draw函数,而draw_2对应于UPDATE 2中的函数。

Notice that in draw_1 , you assign the result of cv2.line back to img . 请注意,在draw_1 ,分配的结果cv2.lineimg This is a problem, since according to the documentation cv2.line returns None . 这是一个问题,因为根据文档 cv2.line返回None

Hence, your first call will turn your image to None , and the remaining two line are drawn to "Nothing". 因此,您的第一个调用会将您的图像变为None ,其余两行被绘制为“ Nothing”。

As Dan Masek pointed out in his solution the original code from the tutorial 正如Dan Masek在其解决方案中指出的那样,本教程中的原始代码

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

has simply to be changed into 只需更改为

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

or without any specifications 或没有任何规格

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

and all works. 和所有作品。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM