简体   繁体   中英

Python OpenCV: Conversion from float to int for using cv2.line()

I'm working on the optical flow tutorial of openCV using Python 2.7 with OpenCV 3.1.0 and have a question concerning the use of cv2.line(). Here is the original code with the highlighted part of interest:

import numpy as np
import cv2

cap = cv2.VideoCapture('slow.flv')

# params for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
                       qualityLevel = 0.3,
                       minDistance = 7,
                       blockSize = 7 )

# Parameters for lucas kanade optical flow
lk_params = dict( winSize  = (15,15),
                  maxLevel = 2,
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# Create some random colors
color = np.random.randint(0,255,(100,3))

# Take first frame and find corners in it
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)

# Create a mask image for drawing purposes
mask = np.zeros_like(old_frame)

while(1):
    ret,frame = cap.read()
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # calculate optical flow
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

    # Select good points
    good_new = p1[st==1]
    good_old = p0[st==1]

    ##################  IMPORTANT  ##################
    # draw the tracks
    for i,(new,old) in enumerate(zip(good_new,good_old)):
        a,b = new.ravel()
        c,d = old.ravel()
        mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)
        frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
    ##################  IMPORTANT  ##################

    ###########  START insert code below  ###########
    # Mean-vector of camera movement
    ############  END insert code below  ############

    img = cv2.add(frame,mask)

    cv2.imshow('frame',img)
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

    # Now update the previous frame and previous points
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1,1,2)

cv2.destroyAllWindows()
cap.release()

In my workspace the variables a, b, c and d are shown as array scalar float32 . So I would assume, that they need to be converted to tuples of int in order to execute cv2.line() or cv2.circle().

When I try to add code using cv2.line() I have to use a conversion to int (see below), otherwise I receive a very clear message: TypeError: integer argument expected, got float

    ###################### START added code
    ofvec = p1 - p0
    ofvec = np.mean(ofvec, 1) # Collapse the first dimension
    ofvec_cam = np.mean(ofvec,0) # mean of camera movement

    height, width = old_frame.shape[:2]
    x0 = np.int(width/2)
    y0 = np.int(height/2)
    pt_center = (x0, y0) 

    x = np.int( x0 - ofvec_cam[0].tolist() )
    y = np.int( y0 - ofvec_cam[1].tolist() )
    pt_ofvec_cam = (x, y)

    frame = cv2.line(frame, pt_center, pt_ofvec_cam, [0, 0, 255], 2)
    ###################### END added code

Can anyone explain this difference to me? Thanks in advance and have a nice day! AMTQ

It seems that cv2.line() treats differently two types of floats: "standard" Python floats and numpy floats. See the minimum working example using Python 2.7 with OpenCV 3.1.0:

import numpy as np, cv2
mask = np.zeros([10, 20, 3], dtype=np.uint8)
color = [0, 0, 0]

# Using Numpy
a = np.float32(12.34)
mask = cv2.line(mask, (a,a), (a,a), color)

# Using standard Python data type
b = 12.34
mask = cv2.line(mask, (b,b), (b,b), color)

In case a the command executes without a hitch, in case b we find the above mentioned error:

in <module> mask = cv2.line(mask, (b,b), (b,b), color)
TypeError: integer argument expected, got float`

Concerning the initial question I confirm that in the OpenCV tutorial the variables a, b, c and d are all numpy-floats whereas in the added code the variables x and y are standard Python floats before they are converted to numpy-ints by np.int().


Remarks

Both data types provide a method __int__() which returns the int-value of the float (see also difference between native int type and the numpy int types ).

The only reference to speak of that I have found is this note concerning the method fromarray in the documentation of OpenCV 2.4.13:

Note In the new Python wrappers (cv2 module) the function is not needed, since cv2 can process Numpy arrays (and this is the only supported array type).

In the docs of OpenCV 3.1.0 the method fromarray does not exist anymore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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