Home>

Using Python, OpenCV, etc., I am processing a video using the interframe difference method, dividing the video into images, and then trimming and saving the image. The process of trimming is complete, but the following error message occurred when saving the next image.

Applicable source code
import cv2
import numpy as np
from PIL import Image
import os
import shutil
def video_2_frames (video_file, image_dir, image_file):
        # Delete the entire directory tree if it exists.
        if os.path.exists (image_dir):
            shutil.rmtree (image_dir)
        # Make the directory if it doesn't exist.
        if not os.path.exists (image_dir):
            os.makedirs (image_dir)
        # Video to frames
        global i
        global j
        global count
        i = 0
        j = 0
        count = 0
        cap = cv2.VideoCapture (video_file)
        fgbg = cv2.bgsegm.createBackgroundSubtractorMOG ()
        while (cap.isOpened ()):
            flag, frame = cap.read () # Capture frame-by-frame
            if flag == False: # Is a frame left?
                break
            if i == 30:
                fgmask = fgbg.apply (frame)
                cv2.imwrite (image_dir + image_file% str (j), fgmask) # Save a frame
                print ('Save', image_dir + image_file% str (j))
                i = 0
                j + = 1
            i + = 1
        cap.release () # When everything done, release the capture
video_2_frames ('./ movie.mp4', './image_dir /', 'img_% s.jpg')
def nparray_to_rgb (nparry: np.array):
    return (int (nparry [0]), int (bg_color [1]), int (bg_color [2]))
def find_edge (img_path: str):
    img = cv2.imread (img_path, 0)
    blur = cv2.blur (img, (5,5))
    print ('blur')
    print (blur)
    edges = cv2.Canny (blur, 100,200)
    print ('edges')
    print (edges)
    return edges
def find_target (edges):
    results = np.where (edges == 255)
    print ('results')
    print (results)
    top = np.min (results [0])
    bottom = np.max (results [0])-1
    left = np.min (results [1])
    right = np.max (results [1])-1
    return (left, top, right, bottom)

def to_RGB (image: Image):
    if image.mode! = 'RGBA': return image
    background = Image.new ("RGB", image.size, (255, 255, 255))
    print ('image.mode =' + image.mode)
    background.paste (image, mask = image.split () [3]) # 3 is the alpha channel
    background.format = image.format
    return background
def get_crop_img (img_path: str):
    edges = find_edge (img_path)
    left, top, right, bottom = find_target (edges)
    rgb_img = to_RGB (Image.open (img_path))
    trim_img = rgb_img.crop ((left, top, right, bottom))
    cv2.imwrite ('./ image_dir/img _' + str (count) + '_ trim.jpg', trim_img)
    print ('crop_img')
for count_img in range (1, j):
    print ('crop _' + str (count_img))
    get_crop_img ('./ image_dir/img _' + str (count_img) + '. jpg')
    count_img + = 1
    count + = 1
Error message
line 78, in get_crop_img
    cv2.imwrite ('./ image_dir/img _' + str (count) + '_ trim.jpg', trim_img)
TypeError: Expected Ptr<cv :: UMat>for argument '% s'


Why did this error occur?
What should I do about it?
I would appreciate it if you could tell me.

Supplemental information (FW/tool version etc.)

Development environment (IDE): Spyder (Python3.7)

  • Answer # 1

    trim_img is PIL data. If you just want to save it, you should use PIL.save.

    cv2.imwrite ('./ image_dir/img _' + str (count) + '_ trim.jpg', trim_img)
    Not
    trim_img.save ('./ image_dir/img _' + str (count) + '_ trim.jpg')

    Is it necessary to convert PIL data to a data format handled by OpenCV if you really want to save it with imwrite?
    In that case, the following may be helpful.
    https://qiita.com/derodero24/items/f22c22b22451609908ee