0

I am trying to import certain variables from a separate python code to my main code. The separate code is this:

import cv2
import numpy as np
import os
import glob

# Defining the dimensions of checkerboard
CHECKERBOARD = (7, 9)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# Creating vector to store vectors of 3D points for each checkerboard image
objpoints = []
# Creating vector to store vectors of 2D points for each checkerboard image
imgpoints = []

# Defining the world coordinates for 3D points
objp = np.zeros((1, CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32)
objp[0, :, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
prev_img_shape = None

# Extracting path of individual image stored in a given directory
images = glob.glob('./images/*.jpg')
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # Find the chess board corners
    # If desired number of corners are found in the image then ret = true
    ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD,
                                             cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)

    """
    If desired number of corner are detected,
    we refine the pixel coordinates and display 
    them on the images of checker board
    """
    if ret == True:
        objpoints.append(objp)
        # refining pixel coordinates for given 2d points.
        corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)

        imgpoints.append(corners2)

        # Draw and display the corners
        img = cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret)

    cv2.imshow('img', img)
    cv2.waitKey(0)

cv2.destroyAllWindows()

h, w = img.shape[:2]

"""
Performing camera calibration by 
passing the value of known 3D points (objpoints)
and corresponding pixel coordinates of the 
detected corners (imgpoints)
"""
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

print("Camera matrix : \n")
print(mtx)
print("dist : \n")
print(dist)
print("rvecs : \n")
print(rvecs)
print("tvecs : \n")
print(tvecs)

At the end of the code there are variables that I need to import into my main code (mtx, dist, rvecs and tvecs). When I try to import like this

from Calibration import *

or like this

from Calibration import mtx, tvecs, rvecs, dist

I get this error:

NameError: name 'img' is not defined

How can I do this correctly?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 1
    use `if __name__ == '__main__':` and put all the variables under it which u wanted to use in other file – Ghost Ops Sep 20 '21 at 14:16
  • Are you sure your issue is with the import and it is not, instead, the fact that when you invoke img = cv2.imread(fname) that that function is not working appropriately and, hence, img is not being defined? In other words, your issue is with the cv2.imread function? – Rasputin Sep 20 '21 at 14:29
  • @Rasputin I suspect the issue is even simpler: per my answer I think the glob isn't matching, so img is unset later on. In any case that's a lot of code to run just to import a variable. – 2e0byo Sep 20 '21 at 14:31

2 Answers2

1

You want to put everything except the variables under

if __name__ == "__main__":
    do_stuff

What's happening is that your import is evaluating everything in the imported code and trying to run it, which isn't what you want.

However best practice is to put the action of your code inside a function called main, and then run that in the if __name__ == "__main__" block. So your code would look like this:

my_var = x

def my_fn():
    pass

def my_other_fn():
    pass

def main():
    my_fn()
    my_other_fn()

if __name__ == "__main__":
    main()

This way:

  • you can import variables and functions from your script without running anything (good!)
  • you can import the main() function and run it from somewhere else (good! think of making e.g. a CLI)
  • you can run the script itself (good!)

We call main() the entrypoint function (and name it main by convention).

__name__ is a special variable which is equal to __main__ iff the script is run. See this question for more detail. So the condition __name__ == "__main__" is only true when you run the script, and you don't try to run the code contained in it when you import your variables.

P.S. your specific error is occurring because there are no images ./images/ when you import the script, and so the for block never runs, and thus img is undefined when python gets to h, w = img.shape[:2]. But you don't want to be running that code at all.

2e0byo
  • 5,305
  • 1
  • 6
  • 26
1

Following on @GostOps and @2e0byo

Bring your code under a function and return the variable that you want to import from another file.

# Calibration.py

def calibration():
    ...
    ...
    ...

    cv2.destroyAllWindows()

    h, w = img.shape[:2] 

    """
    Performing camera calibration by 
    passing the value of known 3D points (objpoints)
    and corresponding pixel coordinates of the 
    detected corners (imgpoints)
    """

    return cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) 


if __name__ == "__main__":
    calibration()

then you can import from another file and assign it to the desired variable there

from Calibration import calibration

ret, mtx, dist, rvecs, tvecs = calibration()
Parthi
  • 76
  • 5