Reading In Videofluoroscopy (VFS) AVIs, Converting to DICOM Series?

Hello Everyone.

I have a bunch of Videofluoroscopy (VFS) studies exported off the scanner in .avi format…

I’m not surprised to see itk.imread('movi_xyz.avi') in Python to tell me:

RuntimeError: Could not create IO object for reading file movi_xyz.avi

I’m wondering, what’s the shortest path from .avi to DICOM series — I’m going to have to script this is Python.

Kind regards,
Constantine

Use OpenCV to read in the AVI file. Convert it to a Numpy array. Then use SimpleITK to convert it to a series of SimpleITK images and write out that DICOM.

1 Like

Thank you, @dchen. Sounds easy enough.

As my advisor once said to me “It’s a simple matter of code.” I wanted to kill him at that point.

1 Like

Yup, and now that I’m writing the code…

Would you tell me, I still have to do this frame-by-frame, when using OpenCV, right?

And then, frame-by-frame (converted to numpy array) use SimpleITK to write as DICOM?

Maybe you can link me to an example, please?

OK, I asked Google’s AI to write the code for me. Here’s the result:


import cv2
import SimpleITK as sitk

# Define the video file path
video_path = "video_1_75ff58251edb441e99ebbcba22c2641c.mp4"

# Create a video capture object
cap = cv2.VideoCapture(video_path)

# Check if the video capture object is opened successfully
if not cap.isOpened():
    print("Error opening video stream or file")
    exit()

# List to store the numpy arrays of the video frames
frames = []

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()

    # If the frame is read correctly retrieve frame as a numpy array
    if ret:
        frames.append(frame)

        # Press 'q' to quit
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    # Break the loop if there is an error in reading
    else:
        break

# Release the video capture object
cap.release()

# Print the total number of frames in the video
print(f"Total number of frames in video: {len(frames)}")


# You can now access each frame as a numpy array using the 'frames' list
#
for f in frames:
    print()
    print(type(f))
    print(f.shape)

    img = sitk.GetImageFromArray(f)
    print(type(img))
    print(img.GetSize())

I only wrote the loop at the end. And the code worked. We’ll all be out of jobs soon.

And if you want to see how to write a DICOM series from a 3d image, here’s SimpleITK’s example:
https://simpleitk.readthedocs.io/en/master/link_DicomSeriesReadModifyWrite_docs.html

2 Likes

@dchen Dave — thank you very much for being so forthcoming with the answers and tips! And yes, it is important to know how to ask Google AI nicely…

I’ve never played with SimpleITK, but some things may be… well, simple enough in it, like the sitk.GetImageFromArray (static?) method.

Is there an equivalent in the (plain) ITK — or, given a (numpy) array/buffer, is there a way to set image data from a buffer in a regular ITK image, like in itk::ImportImageContainer::SetImportPointer(…)?

It was from a while back — I remember that ITK offers itk::VideoFileReader and it was my (now seems unjustified) assumption that Python ITK wrapping may expose the class.

What is the easy way to discover what is and what isn’t Python-wrapped in ITK?

Now I’m faced with a choice of giving up on ITK Python wrapping and going back to C++, to be able to access full feature set and documentation. I find lack of Python ITK wrapped documentation a big gap and stumbling block, where I need to feel my way in the dark. Or else, I’d be very glad to find that I’m doing something wrong is this process.

Yes, ITK has a similar function, itk.image_from_array.

1 Like

Ah, Dave (@dchen) — thank you! Yes, in this case it does look like I’ve fallen short in the RTFM department — I can see this itk.image_from_array mentioned on the ITK Python Quick Start guide page, about ⅓ of the way through. Shame on me. :face_with_open_eyes_and_hand_over_mouth:

Although, now it is aliased to itk::GetImageFromArray.

I’m still wondering though how to discover ITK Python API in the absence of full reference/full-text-search.

For now I’ve built my own full-text-search:

import re, itk
print(', '.join([s for s in dir(itk) if 'imagefromarray' in re.sub(r'[\W_]+', '', s.lower())]))

To return this sort of thing:

GetImageFromArray, image_from_array

Probably should turn this into a function to be loaded on start-up…