简体   繁体   中英

Errors in using cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

In an attempt to compute the number of white pixels in each frame of my animation(white circle moving on black frame), I came across this OpenCV function :

cap = cv2.VideoCapture('control_random.mp4')

total_white_pixels_in_video_sequence = 0

while(cap.isOpened()):

    # Take each frame of the video.
    _, frame = cap.read()


    #print(frame)

    # Convert BGR to gray
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    print ("No. of pixels : ", gray.shape[0] * gray.shape[1])

    # Counting the number of pixels with given value: define range of gray color in HSV
    total_white_pixels_in_video_sequence += np.count_nonzero(gray == 255)

    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

print ("total_white_pixels_in_video_sequence : ", total_white_pixels_in_video_sequence)

I got the first error:

error: OpenCV(4.1.0) /io/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed)._src.empty() in function 'cvtColor'

I found here two possible solutions to this error:

  1. I tried gray = cv2.cvtColor(np.float32(frame), cv2.COLOR_BGR2GRAY) , but I still got an error:

TypeError: Expected cv::UMat for argument 'src'

  1. Then I tried gray = cv2.cvtColor(cv2.UMat(frame), cv2.COLOR_BGR2GRAY) , and got the error:

AttributeError: 'cv2.UMat' object has no attribute 'shape'

When I print frame, I get an array of zeros: [[[0 0 0] [0 0 0] [0 0 0]...

I checked the path, and it is in the same directory of this code. So the path shouldn't be a problem?

I checked the integrity of my video file, following this link recommendations, and I tried this command in my Linux terminal: ffmpeg -v error -i control_random.mp4 -f null - 2>error.log but it is not printing anything.

My question: is it worth it to debug this, or is there another way to compute the number of white pixels per frame. I can also do it while I am creating the animation, and before generating the video.

This piece of my code create my animation:

for Nframes in range(8):

    with shader:  

        transformations['view_matrix'] = get_view_matrix(z=scrDist)
        transformations.send()


        for sphere in spheres:

            # Update Spheres Positions
            sphere.position.x += sphere.dx
            sphere.position.y += sphere.dy
            sphere.position.z += sphere.dz

            # Draw the spheres
            sphere.draw()

    # Get the back buffer frames
    win.getMovieFrame(buffer='back')

    win.flip()

Your help is highly appreciated and desperately needed. Thanks very much in advance!

My guess is that you had this error at different time points and that's what's confusing here. The original error probably happen in the end of the video.

At least we can say for sure that in the end of the video this code will output an error because _, frame = cap.read() will return frame=None in the end.

Therefore to avoid your problem you have to read the returned value "_" and break if it's False (indicating that no frame have been acquired).

Maybe you used the while loop because the number of frames is kind of weird to get, you have to use:

number_of_frames = video_capture.get(cv2.CAP_PROP_FRAME_COUNT)

This allows to use a regular for loop and keep this boolean for error cases. Here is the updated code, it works with one of my mp4.

cap = cv2.VideoCapture('control_random.mp4')
total_white_pixels_in_video_sequence = 0

if cap.isOpened():

    number_of_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    for frame_number in range(number_of_frames):
        # Take each frame of the video.
        success, frame = cap.read()

        if not success:
            raise Exception('Failed to read the frame number: {}'.format(frame_number))

        print('{} / {}'.format(frame_number, number_of_frames))

        # Convert BGR to gray
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        print("No. of pixels : ", gray.shape[0] * gray.shape[1])

        # Counting the number of pixels with given value: define range of gray color in HSV
        total_white_pixels_in_video_sequence += np.count_nonzero(gray == 255)

        cv2.imshow('frame', gray)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

cap.release()
cv2.destroyAllWindows()

print("total_white_pixels_in_video_sequence : ", total_white_pixels_in_video_sequence)

Also note that you can test separately the conversion of fully black images:

gray = cv2.cvtColor(np.zeros((256,256,3), dtype=np.ubyte), cv2.COLOR_BGR2GRAY)

I think that your trial 1. fails because BGR images are 8u images, so it doesn't accept floats. For your trial 2, note that opencv usually works with numpy arrays (as in zeros example above).

Hope this helps!

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