OpenCV segfault by writing video from panoramic picture

43 views Asked by At

I have a problem with openCV(4.6.0) and Python with linux 22.04.

I have a panoramic picture and try to create a video out of it that pans over the image. The first 100 pixel it works just fine but then a segfault exception is thrown by openCV. The image itself is more than 4000 pixel wide. I have no idea why the first frames work just fine. You can find the img here.

import numpy as np
import cv2

imgPath = './../pan/pan_01/pan_01_B_small.png'
width=1920
height=1080
chan=3
fps=30
seconds=10
numframes = fps*seconds

img = cv2.imread(imgPath, 1)
print("Image Size:", img.shape)
shiftPerFrame = (img.shape[1] - width) / numframes
print(img.shape[1])
print("Shift/Frame: ", shiftPerFrame)

# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, fps, (width,height))

for i in range(1,numframes):   # init frames
    x = int(i * shiftPerFrame)
    crop_img = img[0:height, x:x+width]
    print("Frame: ", i, " Position x:", x, " to ", x+width, "size: ", crop_img.shape)
    out.write(crop_img)
    #cv2.imwrite("data/img" + str(i) + ".jpg", crop_img)
    
out.release()

It isn't a problem to export the cropped image again as a new jpg.

I played a little with the shifting parameter. I found out that the problem is not the xth frame but somehow the pixel position. I also tried to import the image as a jpg or png. I also tryed several codecs. Each with the same error.

I am happy about any ideas and help.

1

There are 1 answers

0
Markus On

I can't explain why, but I could solve this issue in my environment by just copying the cropped image before writing. Please check:

import numpy as np
import cv2

imgPath = 'pan_01_B_small.jpg'
width = 1920
height = 1080
fps = 30
seconds = 10
numframes = fps * seconds

img = cv2.imread(imgPath)
print("Image Size:", img.shape)
shiftPerFrame = (img.shape[1] - width) / numframes
print("Shift/Frame: ", shiftPerFrame)

fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('video.avi', fourcc, fps, (width, height))

for i in range(1, numframes):
    x = int(i * shiftPerFrame)
    crop_img = np.array(img[0:height, x:x + width])  # <-- create a copy of the cropped image
    print("Frame: ", i, " Position x:", x, " to ", x + width, "size: ", crop_img.shape)
    out.write(crop_img)

out.release()

It looks VideoWriter.write() has issues with the internal representation of the numpy array right after slicing.

This way it works, too:

    crop_img = img[0:height, x:x + width].copy()

Edit: One more observation: If you add an empty row at the bottom of the input image, it works without the copy-step in the loop:

img = cv2.imread(imgPath)
img = cv2.copyMakeBorder(img, 0, 1, 0, 0, cv2.BORDER_CONSTANT, (0, 0, 0))