Handling Animated Image Files#
Goal#
In this tutorial, you will learn how to:
Use
cv::imreadanimationto load frames from animated image files.Understand the structure and parameters of the
cv::Animationstructure.Display individual frames from an animation.
Use
cv::imwriteanimationto writecv::Animationto a file.
Source Code#
Downloadable code: Click here
Code at a glance:
#include <opencv2/highgui.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv; int main( int argc, const char** argv ) { std::string filename = argc > 1 ? argv[1] : "animated_image.webp"; if (argc == 1) { Animation animation_to_save; Mat image(128, 256, CV_8UC4, Scalar(150, 150, 150, 255)); int duration = 200; for (int i = 0; i < 10; ++i) { animation_to_save.frames.push_back(image.clone()); putText(animation_to_save.frames[i], format("Frame %d", i), Point(30, 80), FONT_HERSHEY_SIMPLEX, 1.5, Scalar(255, 100, 0, 255), 2); animation_to_save.durations.push_back(duration); } imwriteanimation("animated_image.webp", animation_to_save, { IMWRITE_WEBP_QUALITY, 100 }); } Animation animation; bool success = imreadanimation(filename, animation); if (!success) { std::cerr << "Failed to load animation frames\n"; return -1; } while (true) for (size_t i = 0; i < animation.frames.size(); ++i) { imshow("Animation", animation.frames[i]); int key_code = waitKey(animation.durations[i]); // Delay between frames if (key_code == 27) exit(0); } return 0; }
Downloadable code: Click here
Code at a glance:
import cv2 as cv import numpy as np def main(filename): if filename == "animated_image.webp": # Create an Animation instance to save animation_to_save = cv.Animation() # Generate a base image with a specific color image = np.full((128, 256, 4), (150, 150, 150, 255), dtype=np.uint8) duration = 200 frames = [] durations = [] # Populate frames and durations in the Animation object for i in range(10): frame = image.copy() cv.putText(frame, f"Frame {i}", (30, 80), cv.FONT_HERSHEY_SIMPLEX, 1.5, (255, 100, 0, 255), 2) frames.append(frame) durations.append(duration) animation_to_save.frames = frames animation_to_save.durations = durations # Write the animation to file cv.imwriteanimation(filename, animation_to_save, [cv.IMWRITE_WEBP_QUALITY, 100]) animation = cv.Animation() success, animation = cv.imreadanimation(filename) if not success: print("Failed to load animation frames") return while True: for i, frame in enumerate(animation.frames): cv.imshow("Animation", frame) key_code = cv.waitKey(animation.durations[i]) if key_code == 27: # Exit if 'Esc' key is pressed return if __name__ == "__main__": import sys main(sys.argv[1] if len(sys.argv) > 1 else "animated_image.webp")
Explanation#
Initializing the Animation Structure#
Initialize a cv::Animation structure to hold the frames from the animated image file.
Loading Frames#
Use cv::imreadanimation to load frames from the specified file. Here, we load all frames from an animated WebP image.
bool success = imreadanimation(filename, animation);
if (!success) {
std::cerr << "Failed to load animation frames\n";
return -1;
}
success, animation = cv.imreadanimation(filename)
if not success:
print("Failed to load animation frames")
return
Displaying Frames#
Each frame in the animation.frames vector can be displayed as a standalone image. This loop iterates through each frame, displaying it in a window with a short delay to simulate the animation.
Note: Frame durations in
cv::Animationare expressed in milliseconds. When displaying frames manually usingcv::waitKey, make sure to use the corresponding duration value to preserve the original animation timing.
Saving Animation#
if (argc == 1)
{
Animation animation_to_save;
Mat image(128, 256, CV_8UC4, Scalar(150, 150, 150, 255));
int duration = 200;
for (int i = 0; i < 10; ++i) {
animation_to_save.frames.push_back(image.clone());
putText(animation_to_save.frames[i], format("Frame %d", i), Point(30, 80), FONT_HERSHEY_SIMPLEX, 1.5, Scalar(255, 100, 0, 255), 2);
animation_to_save.durations.push_back(duration);
}
imwriteanimation("animated_image.webp", animation_to_save, { IMWRITE_WEBP_QUALITY, 100 });
}
if filename == "animated_image.webp":
# Create an Animation instance to save
animation_to_save = cv.Animation()
# Generate a base image with a specific color
image = np.full((128, 256, 4), (150, 150, 150, 255), dtype=np.uint8)
duration = 200
frames = []
durations = []
# Populate frames and durations in the Animation object
for i in range(10):
frame = image.copy()
cv.putText(frame, f"Frame {i}", (30, 80), cv.FONT_HERSHEY_SIMPLEX, 1.5, (255, 100, 0, 255), 2)
frames.append(frame)
durations.append(duration)
animation_to_save.frames = frames
animation_to_save.durations = durations
# Write the animation to file
cv.imwriteanimation(filename, animation_to_save, [cv.IMWRITE_WEBP_QUALITY, 100])
Summary#
The cv::imreadanimation and cv::imwriteanimation functions make it easy to work with animated image files by loading frames into a cv::Animation structure, allowing frame-by-frame processing.
With these functions, you can load, process, and save frames from animated image files like GIF, AVIF, APNG, and WebP.