simplecv | How to save generated frames to video

181 Views Asked by At

This is the function which generates a set of frames from an input video and stores them in a folder.

The full function:

def new_dewarp(self):        
    vidpath = self.iVidPath
    def isInROI(x, y, R1, R2, Cx, Cy):
        isInOuter = False
        isInInner = False
        xv = x-Cx
        yv = y-Cy
        rt = (xv*xv)+(yv*yv)
        if(rt < R2*R2):
            isInOuter = True
            if(rt < R1*R1):
                isInInner = True
        return isInOuter and not isInInner

    def buildMap(Ws, Hs, Wd, Hd, R1, R2, Cx, Cy):
        map_x = np.zeros((Hd,Wd),np.float32)
        map_y = np.zeros((Hd,Wd),np.float32)
        rMap = np.linspace(R1, R1 + (R2 - R1), Hd)
        thetaMap = np.linspace(0, 0 + float(Wd) * 2.0 * np.pi, Wd)
        sinMap = np.sin(thetaMap)
        cosMap = np.cos(thetaMap)

        for y in xrange(0, int(Hd-1)):
            map_x[y] = Cx + rMap[y] * sinMap
            map_y[y] = Cy + rMap[y] * cosMap

        return map_x, map_y

    # do the unwarping 
    def unwarp(img, xmap, ymap):
        output = cv2.remap(img.getNumpyCv2(), xmap, ymap, cv2.INTER_LINEAR)
        result = Image(output, cv2image=True)
        # return result
        return result

    #vidpath = 
    disp = Display((800, 600))
    #disp = Display((1296,972))
    vals = []
    last = (0, 0)
    # Load the video from the rpi
    vc = VirtualCamera(vidpath, "video")
    # Sometimes there is crud at the begining, buffer it out
    for i in range(0, 10):
        img = vc.getImage()
        img.save(disp)
    # Show the user a frame let them left click the center
    #    of the "donut" and the right inner and outer edge
    # in that order. Press esc to exit the display
    while not disp.isDone():
        test = disp.leftButtonDownPosition()
        if( test != last and test is not None):
            last = test
            print "[360fy]------- center = {0}\n".format(last)

            vals.append(test)




    # center of the "donut"    
    Cx = vals[0][0]
    Cy = vals[0][1]
    #print str(Cx) + " " + str(Cy)
    # Inner donut radius
    R1x = vals[1][0]
    R1y = vals[1][1]
    R1 = R1x-Cx
    #print str(R1)
    # outer donut radius
    R2x = vals[2][0]
    R2y = vals[2][1]
    R2 = R2x-Cx
    #print str(R2)
    # our input and output image siZes
    Wd = round(float(max(R1, R2)) * 2.0 * np.pi)
    #Wd = 2.0*((R2+R1)/2)*np.pi
    #Hd = (2.0*((R2+R1)/2)*np.pi) * (90/360)
    Hd = (R2-R1)
    Ws = img.width
    Hs = img.height
    # build the pixel map, this could be sped up
    print ("BUILDING MAP!")

    xmap,ymap = buildMap(Ws, Hs, Wd, Hd, R1, R2, Cx, Cy)
    print ("MAP DONE!")

    result = unwarp(img, xmap, ymap)

    result.save(disp)

    i = 0


    while img is not None:
        print "Frame Number: {0}".format(i)
        result = unwarp(img, xmap, ymap)
        result.save(disp)
        # Save to file
        fname = "vid_files/frames/FY{num:06d}.png".format(num=i)
        result.save(fname)

        img = vc.getImage()
        i = i + 1
    if img is None:
        self.statusText.setText(str( "Status: Done"))

The section in above code which does the saving of frames:

    while img is not None:
        print "Frame Number: {0}".format(i)
        result = unwarp(img, xmap, ymap)
        result.save(disp)
        # Save to file
        fname = "vid_files/frames/FY{num:06d}.png".format(num=i)
        result.save(fname)

        img = vc.getImage()
        i = i + 1
    if img is None:
        self.statusText.setText(str( "Status: Done"))

I want to know if there is anyway I can save the frames directly to a video( preferably mp4) with the frame rate and frame size of input video? I can fetch the frame size and frame rate using ffprobe if needed.

0

There are 0 best solutions below