2

Here is what I have now.

The imported libraries:

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import numpy as np
import cv2
import time

For instance(this part of code is from internet example), I draw a plot with a "text" on it.

fig = plt.figure(figsize=(6,6.5))
canvas = FigureCanvas(fig)
ax = fig.gca()
ax.text(0.0,0.0,"Test", fontsize=45)
ax.axis('off')

Then, I save it to, well, "1.png".

plt.savefig("1.png")

Finally, I create a video writer and write the png into the video.

size = (600,650)
fps = 2
fourcc = cv2.VideoWriter_fourcc('I', '4', '2', '0')
video = cv2.VideoWriter("1.avi", fourcc, fps, size)
image = cv2.imread('1.png')
video.write(image)
video.release()

Here is the question: I need to save the picture and then read it as the numpy array that opencv can read, is there any way that I can directly transform the fig object to the image object(numpy array)?

Thank you guys very much!

Zizheng Yang
  • 141
  • 1
  • 12
  • I think this is doing what you want: https://stackoverflow.com/questions/42603161/convert-an-image-shown-in-python-into-an-opencv-image – Ian Chu Feb 04 '21 at 17:38
  • I have tried the method, I there are some bug at what is did on slicing. But yeah, that's what I wanna to ask. – Zizheng Yang Feb 04 '21 at 20:05

1 Answers1

1

Let's analyze step-by-step:

  1. size = (600,650)
    

Does the size of the image is 600, 650?

If I were you, I would initialize as

image = cv2.imread('1.png')
(height, width) = image.shape[:2]
size = (width, height)

or if you want the output as (600, 650), then resize the image:

image = cv2.imread('1.png')
image = cv2.resize(image, (600, 650))
  1. fps = 2
    

Why? you set frame-per-second to 2, why not 10?, 15? source

  1. fourcc = cv2.VideoWriter_fourcc('I', '4', '2', '0')
    

Why I420? You want to create .avi file, then set to MJPG source

If I were you, I would initialize as:

fourcc = cv2.VideoWriter_fourcc(*'MJPG')
  1. video = cv2.VideoWriter("1.avi", fourcc, fps, size)
    

What type of images are you working with? color, gray?. You need to initialize as a parameter in the VideoWriter

For color image:

video = cv2.VideoWriter("1.avi", fourcc, fps, size, isColor=True)

For gray images:

video = cv2.VideoWriter("1.avi", fourcc, fps, size, isColor=False)

An example code:


import cv2

img = cv2.imread("1.png")
(h, w) = img.shape[:2]
size = (w, h)
fps = 20
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
video = cv2.VideoWriter("1.avi", fourcc, fps, size, isColor=True)
video.write(img)
video.release()

Also know that cv2.imread reads the image in BGR fashion. If you want your images as RGB you need to convert it like:

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
Ahmet
  • 7,527
  • 3
  • 23
  • 47
  • You addressed everything except the question asked, which was how to go from figure to video frame without a PNG file in-between. – Ben Voigt Aug 01 '23 at 18:13
  • "frame without a PNG file in-between" then how do you show a frame? – Ahmet Aug 02 '23 at 08:39
  • You get an image of the matplotlib figure in-memory, uncompressed. For example with `figure.canvas.buffer_rgba()`. The video encoder wants uncompressed input data anyway. If you save to a PNG first, you're wasting time on PNG compression, disk I/O, and decompression. – Ben Voigt Aug 02 '23 at 14:29