用于径向失真的OpenCV 3 Python 3校准摄像机会产生错误

时间:2017-02-13 12:10:55

标签: python opencv

在使用OpenCV 3在Python 3中运行函数时出现问题,我想校准带有校准数据.npz的视频,并在重映射矩阵行时产生错误消息。

校准的视频输出很棒,但它附带了一条错误信息,可以防止任何进一步的执行。我怎么能让脚本忽略错误并继续?

任何答案都将不胜感激。

这是代码:

import cv2, time, sys
import numpy as np
import matplotlib.pyplot as plt

filename = 'vtest3.mp4'
filename_2 = 'vtest3_undistort.mp4'
crop = 0.5

#FIRST FUNCTION (UNDISTORTION)
def undistortion(filename):
print('Loading data files')

npz_calib_file = np.load('calibration_data.npz')

distCoeff = npz_calib_file['distCoeff']
intrinsic_matrix = npz_calib_file['intrinsic_matrix']

npz_calib_file.close()

print('Finished loading files')
print(' ')
print('Starting to undistort the video....')

# Opens the video import and sets parameters
video = cv2.VideoCapture(filename)
# Checks to see if a the video was properly imported
status = video.isOpened()

if status == True:
    FPS = video.get(cv2.CAP_PROP_FPS)
    width = video.get(cv2.CAP_PROP_FRAME_WIDTH)
    height = video.get(cv2.CAP_PROP_FRAME_HEIGHT)
    size = (int(width), int(height))
    total_frames = video.get(cv2.CAP_PROP_FRAME_COUNT)
    frame_lapse = (1 / FPS) * 1000

    # Initializes the export video file
    codec = cv2.VideoWriter_fourcc(*'DIVX')
    video_out = cv2.VideoWriter(str(filename[:-4]) + '_undistort.mp4', codec, FPS, size, 1)

    # Initializes the frame counter
    current_frame = 0

    newMat, ROI = cv2.getOptimalNewCameraMatrix(intrinsic_matrix, distCoeff, size, alpha=crop,
                                                centerPrincipalPoint=1)
    mapx, mapy = cv2.initUndistortRectifyMap(intrinsic_matrix, distCoeff, None, newMat, size, m1type=cv2.CV_32FC1)

    while current_frame < total_frames:
        success, image = video.read()
        current_frame = video.get(cv2.CAP_PROP_POS_FRAMES)

        dst = cv2.remap(image, mapx, mapy, cv2.INTER_LINEAR)
        # dst = cv2.undistort(image, intrinsic_matrix, distCoeff, None)

        video_out.write(dst)

    video.release()
    video_out.release()

else:
    print('Error: Could not load video')
    sys.exit()

#SECOND FUNCTION
def hauptprogramm(filename_2):
# Create an empty List for x- and y-Positions that will be filled in for-loop
# with the .append function
xposition = []  # Empty list for x-Positions
yposition = []  # Empty list for y-Positions

# Open the Video with die VideoCapture function
# Name the video that is opened cap
cap = cv2.VideoCapture(filename_2)

# set the framenumber to the last frame just to take a picture
cap.set(1, cap.get(cv2.CAP_PROP_FRAME_COUNT));  # Where frame_no is the frame you want
ret, frame = cap.read()  # Read the frame
cv2.imwrite('kurve.jpg', frame)

# set the framenumber to 1, which is the first frame of the video
# from here we begin to analyse the video
cap.set(1, 1);
# cv2.imshow('window_name', frame) # show frame on window
# pos_frame = cap.get(cv2.CAP_PROP_POS_FRAMES)

# start an infinite while loop by setting while True
# the loop will go on until we break it
while True:

    # read a frame of the video and name it frame0
    # read the next frame of the video and name it frame1
    # set both frames retangle by writing ret,frame

    ret, frame0 = cap.read()
    ret, frame1 = cap.read()
    ret, frame2 = cap.read()
    # the program will lateron compare every pixel from frame0 to frame1 and
    # locate the areas where many pixels have changed
    # we only are interested in the area where the missile is flying
    # the moving of the catapult itself for exemple would cause trouble
    # so we paint lines over the areas we are not interested in these lines
    # will be painted every loop over frame1
    cv2.line(frame1, (0, 0), (0, 511), (255, 0, 0), 200)
    cv2.line(frame1, (0, 500), (1000, 500), (255, 0, 0), 350)
    cv2.line(frame1, (0, 350), (150, 350), (255, 0, 0), 400)

    # the same lines will be painted over frame2
    cv2.line(frame2, (0, 0), (0, 511), (255, 0, 0), 200)
    cv2.line(frame2, (0, 500), (1000, 500), (255, 0, 0), 350)
    cv2.line(frame2, (0, 350), (150, 350), (255, 0, 0), 400)

    # for the function that will compare frame1 and frame2 both frames have
    # to be in black and white
    # the next function will be used to convert frame1 and frame2 to black and
    # white and will name them gray1 and gray2
    gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)

    # the absdiff function will compare the gray1 and gray2 images and returns
    # an image named diffimage
    diffimage = cv2.absdiff(gray1, gray2)

    # the result of that function returns a black and white image
    # to get clear results the image will be converted to a binary image
    # the new image called diffimage only has pixels that are white or black
    ret, threshold = cv2.threshold(diffimage, 30, 255, cv2.THRESH_BINARY)

    # to reduce the image noise we will make the threshold image blurry by using
    # the blur function
    threshold = cv2.blur(threshold, (25, 25))

    # when converting the blurry image into a threshold image for a secound
    # time the small noisy pixels of the image will be gone and the areas where
    # a lot of pixels have changed in will be clearer and bigger
    ret, threshold = cv2.threshold(threshold, 30, 255, cv2.THRESH_BINARY)

    # ========================find the white areas ==================
    # now we want to find the white areas in the picture that show
    # our flying missile
    # !exakte funktion noch nicht verstanden
    image, contours, hierarchy = cv2.findContours(threshold.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # !exakte funktion noch nicht verstanden
    for cnt in contours:
        area = cv2.contourArea(cnt)

        # to reduce the chance of tracking background noise that might be left
        # even after reducing it with the blur and threshold functions
        # we only track the position of if the white area is bigger than x=10
        if area > 10:
            # we are looking for the bounding rectangle that is around our area
            # x and y equal the pixelposition of the  top right point of the rectangle
            # w and h equal the width and height of the rectangle
            x, y, w, h = cv2.boundingRect(cnt)

            # we are interested in the center of the rectangle so we add w/2 to x
            # and h/2 to y
            # because the x- and y-positions have to be integer we round the values
            # and declare them as such
            xpos = int(round(x + w / 2))
            ypos = int(round(y + h / 2))

            # to see if everything works fine wile running the program the positions
            # can be printed in the console by removing the hashtag
            # print("x= ", xpos)
            # print("y= ", ypos)

            # now the list of x- and y-positions will be extended by every loop
            # with these list of positions we can work later on for the
            # post-processing of the curve the object is flying
            xposition.append(xpos)
            yposition.append(ypos)

            # not necessary to post-process but a nice visualisation and checking
            # if everything works as it is supposed to
            # a small circle will be painted on the x- and y-position
            # therefore we take the "empty" frame0 that does not have the colored
            # lines painted into
            cv2.circle(frame0, (xpos, ypos), 5, (0, 255, 0), -1)

            # a rectangle will be surrounding the center just to keep track of the
            # moving object
            cv2.rectangle(frame0, (x, y), (x + w, y + h), (255, 0, 0), 3)

            # write the x- and y- position in each frame
            cv2.putText(frame0, 'x = ' + str(xpos), (xpos - 20, ypos - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                        (0, 0, 255), 2, cv2.LINE_AA)
            cv2.putText(frame0, 'y = ' + str(ypos), (xpos - 20, ypos + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                        (0, 0, 255), 2, cv2.LINE_AA)

            # x-Positionen in Konsole mitschreiben
            # print(xposition)

    # ========================= Open Windows ====================
    # the imshow functions open a window and show the selected frame each
    # while loop (play the video)
    # by removing the hashtag the selected video will open when running the
    # program

    # 1. Show the original frames and paint the previous visulisation
    cv2.imshow('Orginal mit Verfolgung', frame0)

    # 2. Show the threshold frames
    cv2.imshow('threshold frames', threshold)

    # 3. Show the painted lines in frame1 and frame2 (same parameters)
    cv2.imshow('mit Balken', frame1)

    # if we press the ESC button the loop will break
    if cv2.waitKey(10) == 27:  # mit ESC verlassen
        break

    # if we reach the total number of frames the loop will break
    if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):
        # If the number of captured frames is equal to the total number of frames,
        # we stop

        break

# after we break the loop we release the cap and force all windows to close
cap.release()
cv2.destroyAllWindows()

# does not make sense, just a way to fix a bug in opencv
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(100)

# =================== Spielerei ====================
# cap2 = cv2.VideoCapture("vtest3.m4v")
# while True:
#    cap2.set(1,cv2.CAP_PROP_FRAME_COUNT)
#    ret, frame = cap.read()
#    cv2.imshow('window_name', frame)
#
#    if cv2.waitKey(10) == 27: # mit ESC verlassen
#        break
#
# cap.release()
# cv2.destroyAllWindows()
# cv2.waitKey(1)
# cv2.waitKey(1)
# cv2.waitKey(1)
# cv2.waitKey(1)
# cv2.waitKey(1)
# cv2.waitKey(1)
# cv2.waitKey(1)


# ========== Plot öffnen und speichern ===================
plt.plot(np.asarray(xposition), np.asarray(yposition), 'g^')
plt.axis('equal')
plt.savefig('positionen.png')

# ============== Image lesen und auswerten ===============
image = cv2.imread('kurve.jpg')

for i in range(0, len(xposition)):
    cv2.circle(image, (xposition[i], yposition[i]), 5, (0, 255, 0), -1)

cv2.imwrite('positionen2.png', image)

undistortion(filename)

hauptprogramm(filename_2)

0 个答案:

没有答案