# -*- coding: utf-8 -*-
"""Ball Finder

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1kd61VAWbSYBUXLSrT-RS10UgR5dL6V2o
"""

from google.colab import drive
drive.mount('/content/drive')

# Commented out IPython magic to ensure Python compatibility.
# %cd drive/My\ Drive/420\ Project
!dir
!pwd

from __future__ import division
import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow as tf
import zipfile
import math
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image
sys.path.append("..")
import cv2

# %cd "drive/My Drive/420 Project"
# !pwd

# !dir

modelPath =  'frozen_inference_graph.pb'

tfDetectionGraph = tf.Graph()



with tfDetectionGraph.as_default():
    graph = tf.GraphDef()
    with tf.gfile.GFile(modelPath,'rb') as temp:
        graphModel = temp.read()
        graph.ParseFromString(graphModel)
        tf.import_graph_def(graph,name='')

def loss(patchLeft,patchRight):
    if patchLeft.shape!=patchRight.shape:
        print("loss error")
        return float('inf')
    # one = patchLeft - patchLeft.mean()
    # two = patchRight - patchRight.mean()
    # product = np.mean(one*two)
    # std = patchLeft.std() * patchRight.std()
    patch = patchLeft-patchRight
    patch = patch*patch
    return np.sum(patch)

    if std == 0:
        return 0
    return product/std

def calcBallScore(imageSeg, comp):
    height,width,_ = comp.shape
    height2,width2,_ = imageSeg.shape
    bestLoss = float("-inf")
    bestCoord = (0,0)
    if height2< height or width2<width:
        return bestLoss,bestCoord
    for y in range(0, height2 - height):
        for x in range(0, width2-width):
            patch = imageSeg[y:y+height, x:x+width]
            score = loss(patch,comp)
            if (score>bestLoss):
                bestLoss = score
                bestCoord = (x,y)
    return score,bestCoord



def findBall(image_np, boxInfo,previousMatch):
    comp = cv2.imread("comparison.jpg")
    image = np.copy(image_np)
    h,w,_ = comp.shape
    pm = previousMatch
    bestScore = float('-inf')
    bestCoord = [0,0,0,0]
    bestCoord2 =[0,0,0,0]
    newBox = False
    for n in boxInfo:
        score = n["score"]
        coord = n["coord"]
        xmin = coord[0][0]
        ymin = coord[0][1]
        xmax = coord[1][0]
        ymax = coord[1][1]

        imageSeg = image[ymin-10:ymax+10,xmin-10:xmax+10]
        # ballScore,coord = calcBallScore(imageSeg, comp)
        if (imageSeg.shape[0]<h or imageSeg.shape[1]<w):
            print("size wrongggg")
            continue
        ballScore,coord =matchTemplate(imageSeg,comp, previousMatch)

        if ballScore>bestScore:
            bestScore = ballScore
            bestCoord = [xmin,ymin,xmax,ymax]
            bestCoord2 = [xmin+coord[0]-5,ymin+coord[1]-5,xmin+coord[2]-5,ymin+coord[3]-5]    
        # if ballScore>bestScore:

        #     if pm ==[0,0,0,0]:
        #         bestScore = ballScore
        #         bestCoord = [xmin,ymin,xmax,ymax]
        #         bestCoord2 = [xmin+coord[0],ymin+coord[1],xmin+coord[2],ymin+coord[3]]
                
        #     elif overlap([xmin+coord[0],ymin+coord[1],xmin+coord[2],ymin+coord[3]],pm):   
        #         bestScore = ballScore
        #         bestCoord = [xmin,ymin,xmax,ymax]
        #         bestCoord2 = [xmin+coord[0],ymin+coord[1],xmin+coord[2],ymin+coord[3]]

                
        
    return bestCoord,bestCoord2
def overlap(coord1,coord2): 
     
    if(coord1[0]>coord2[2] or coord1[1]>coord2[3]): 
        return False
  
    if(coord2[0] > coord1[2] or coord1[1] > coord2[3]): 
        return False
  
    return True
def matchTemplate(image_np,comp,previousMatch):
    if comp is None:
        comp = cv2.imread("comparison.jpg")
    h,w,_ = comp.shape

    image = np.copy(image_np)
    res = cv2.matchTemplate(image,comp,cv2.TM_CCOEFF_NORMED)

    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(np.copy(res))
    
    pt = (max_loc[0],max_loc[1])

    # return max_val,[pt[0], pt[1], pt[0] + w, pt[1] + h]

    # cv2.rectangle(image_np, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
    if (previousMatch==[0,0,0,0]):
        return max_val,[pt[0], pt[1], pt[0] + w, pt[1] + h]
    elif overlap([pt[0], pt[1], pt[0] + w, pt[1] + h],previousMatch):
        return max_val,[pt[0], pt[1], pt[0] + w, pt[1] + h]
    else:
        res2 = np.reshape(res, res.shape[0]*res.shape[1])
        sort = np.argsort(res2)
        # (y1, x1) = np.unravel_index(sort[0], res.shape)
        for i in range(min(len(sort),20)):
            x,y = np.unravel_index(sort[i], res.shape)
            pt =(x,y)
            if overlap([pt[0], pt[1], pt[0] + w, pt[1] + h],previousMatch):
                return max_val,[pt[0], pt[1], pt[0] + w, pt[1] + h]
    pt = (max_loc[0],max_loc[1])
    
    return 0,[pt[0], pt[1], pt[0] + w, pt[1] + h]
    return matchTemplate(image_np, cv2.resize(comp, (comp.shape[0]+6,comp.shape[1]+6),previousMatch))
    threshold = 0.5
    loc = np.where( res >= threshold)



    for pt in zip(*loc[::-1]):
        cv2.rectangle(image_np, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
        
    return image_np
    # cv2.imwrite("../../findSoccerball.jpg",image)


def MyCorrelation(I, h, mode):
    imgH, imgW = I.shape
    filterH, filterW = h.shape

    def _calcPixel(x,y,image):
        patch = image[y-filterH//2:y+filterH//2+1, x-filterW//2:x+filterW//2+1]
        multiplication = np.multiply(patch, h)

        return np.sum(multiplication)

    newImage = np.zeros((imgH+filterH*2-2,imgW+filterW*2-2))

    vPad = filterH//2
    hPad = filterW//2

    newImage[vPad*2:vPad*2+imgH,hPad*2:hPad*2+imgW] = np.copy(I)

    initX,initY = (filterW//2, filterH//2)
    # position = (filterW//2, filterH//2)
    # for x in range(len(newImage)):
    #     for y in range(len(newImage[0])):
    newImage_copy = np.copy(newImage)
    for x in range(imgW+hPad*2):
        for y in range(imgH+vPad*2):
            currX,currY = initX+x,initY+y
            newImage[currY, currX] = _calcPixel(currX,currY,newImage_copy)

    if (mode == "same"):
        return (newImage[vPad*2:vPad*2+imgH,hPad*2:hPad*2+imgW])
    elif(mode == "full"):
        return newImage
    elif(mode == "valid"):
        return (newImage[vPad*4:imgH,hPad*4:imgW])

    return newImage
    
def MyConvolution(I,h,mode):
    flippedFilter = np.flip(h)

    red = I[:,:,0]
    green = I[:,:,1]
    blue = I[:,:,2]

    blurR = MyCorrelation(red, flippedFilter, mode)
    blurG = MyCorrelation(green, flippedFilter, mode)
    blurB = MyCorrelation(blue, flippedFilter, mode)

    
    return (blurR,blurR,blurB)

v = 6

filename = 'videos/pen%dslow.mp4'%v

outputName = 'videos/pen%dslowFindTrial'%v + ".avi"

vid = cv2.VideoCapture(filename)

width = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = vid.get(5)
new_height = height
new_width = width

frameCount = vid.get(cv2.CAP_PROP_FRAME_COUNT)
vwriter = cv2.VideoWriter(outputName ,cv2.VideoWriter_fourcc(*'MJPG'),fps, (width, height)) 

with tfDetectionGraph.as_default():
    with tf.Session(graph=tfDetectionGraph) as detector:
        frameCounter = 0
        ballCoord = []
        ballInfo =outputName + '\n'
        ballCoord.append(outputName)
        # skip to specific frame (testing purposes only)
        # for i in range(15):
        #     success, image = vid.read()
        #     if not success:
        #         print("whoops")


        success, image_np = vid.read()
        height,width,_ = image_np.shape
        previousMatch = [0,0,0,0]
        while success:
            
            kernel = np.array([[-1,-1,-1,-1,-1],
                                [-1,2,2,2,-1],
                                [-1,2,8,2,-1],
                                [-2,2,2,2,-1],
                                [-1,-1,-1,-1,-1]])/8.0
            image_np = cv2.filter2D(image_np, -1, kernel)

            image_expanded = np.expand_dims(image_np,axis =0)
            image_tensor = tfDetectionGraph.get_tensor_by_name('image_tensor:0')
            boxes = tfDetectionGraph.get_tensor_by_name('detection_boxes:0')
            scores = tfDetectionGraph.get_tensor_by_name('detection_scores:0')
            classes = tfDetectionGraph.get_tensor_by_name('detection_classes:0')
            num_detections = tfDetectionGraph.get_tensor_by_name('num_detections:0')        

            boxes, scores, classes, num_detections = detector.run([boxes, scores, classes, num_detections], feed_dict = {image_tensor: image_expanded})
            orig_image = image_np
            origW, origH, _ = orig_image.shape
            
            boxes3 = np.squeeze(boxes)
            classes3 = np.squeeze(classes).astype(np.int32)
            scores3 = np.squeeze(scores)
                        
            boxes2=[]
            classes2=[]
            scores2=[]
            for i in range(len(boxes3)):
                if (classes3[i] == 2):
                    boxes2.append(boxes3[i])
                    classes2.append(classes3[i])
                    scores2.append(scores3[i])
            
            classes3 = np.array(classes2)
            boxes3 = np.array(boxes2)
            scores3 = np.array(scores2)
            boxInfo = []
            threshold =0.001

            for i in range(len(boxes3)):
                if scores3[i]>threshold:
                    ymin = int(boxes3[i][0] * new_height)
                    xmin = int(boxes3[i][1] * new_width)
                    ymax = int(boxes3[i][2] * new_height)
                    xmax = int(boxes3[i][3] * new_width)
                    boxcoord = ((xmin,ymin),(xmax,ymax))
                    score = scores3[i]
                    boxInfo.append({"coord": boxcoord, "score": score})

            res, coord = matchTemplate(image_np,None, previousMatch)

            
            

            finalBox,finalBox2 = findBall(image_np, boxInfo, previousMatch)
            previousMatch2 = finalBox2
            xmin,ymin,xmax,ymax = coord
            if res ==0:
                xmin,ymin,xmax,ymax = previousMatch
            else:
                previousMatch = coord
            
            cv2.rectangle(image_np, (xmin,ymin),(xmax,ymax),(0,0,0),2)
            xavg = (xmin+xmax)/2
            yavg = (ymin+ymax)/2
            ballInfo +=str(yavg) + " " +str(xavg)
            ballInfo += "\n"
        
            blurred = cv2.GaussianBlur(np.copy(image_np),(25,25),cv2.BORDER_DEFAULT)
            mask = np.ones(image_np.shape)
            rectSize = 100
            newXmin = max(0,xmin-rectSize)
            newYmin = max(0,ymin-rectSize)
            newXmax = min(image_np.shape[1],xmax+rectSize,)
            newYmax = min(image_np.shape[0],ymax+rectSize,)

            cv2.rectangle(mask, (newXmin,newYmin),(newXmax,newYmax),(0,0,0),-1)

            finalBlur = np.multiply(image_np, 1-mask) +np.multiply(blurred,mask)

            vwriter.write(finalBlur.astype(np.uint8))

            
            success, image_np = vid.read()
        file = open("ballInfo%d.txt"%v,'w')
        file.write(ballInfo)
        file.close()
        vid.release()
        vwriter.release()
        print("done")
8972a73304ff5100150c79ff94324899df38a71c
# -*- coding: utf-8 -*-
"""Ball Finder

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1kd61VAWbSYBUXLSrT-RS10UgR5dL6V2o
"""

from google.colab import drive
drive.mount('/content/drive')

# Commented out IPython magic to ensure Python compatibility.
# %cd drive/My\ Drive/420\ Project
!dir
!pwd

from __future__ import division
import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow as tf
import zipfile
import math
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image
sys.path.append("..")
import cv2

# %cd "drive/My Drive/420 Project"
# !pwd

# !dir

modelPath =  'frozen_inference_graph.pb'

tfDetectionGraph = tf.Graph()



with tfDetectionGraph.as_default():
    graph = tf.GraphDef()
    with tf.gfile.GFile(modelPath,'rb') as temp:
        graphModel = temp.read()
        graph.ParseFromString(graphModel)
        tf.import_graph_def(graph,name='')

def loss(patchLeft,patchRight):
    if patchLeft.shape!=patchRight.shape:
        print("loss error")
        return float('inf')
    # one = patchLeft - patchLeft.mean()
    # two = patchRight - patchRight.mean()
    # product = np.mean(one*two)
    # std = patchLeft.std() * patchRight.std()
    patch = patchLeft-patchRight
    patch = patch*patch
    return np.sum(patch)

    if std == 0:
        return 0
    return product/std

def calcBallScore(imageSeg, comp):
    height,width,_ = comp.shape
    height2,width2,_ = imageSeg.shape
    bestLoss = float("-inf")
    bestCoord = (0,0)
    if height2< height or width2<width:
        return bestLoss,bestCoord
    for y in range(0, height2 - height):
        for x in range(0, width2-width):
            patch = imageSeg[y:y+height, x:x+width]
            score = loss(patch,comp)
            if (score>bestLoss):
                bestLoss = score
                bestCoord = (x,y)
    return score,bestCoord



def findBall(image_np, boxInfo,previousMatch):
    comp = cv2.imread("comparison.jpg")
    image = np.copy(image_np)
    h,w,_ = comp.shape
    pm = previousMatch
    bestScore = float('-inf')
    bestCoord = [0,0,0,0]
    bestCoord2 =[0,0,0,0]
    newBox = False
    for n in boxInfo:
        score = n["score"]
        coord = n["coord"]
        xmin = coord[0][0]
        ymin = coord[0][1]
        xmax = coord[1][0]
        ymax = coord[1][1]

        imageSeg = image[ymin-10:ymax+10,xmin-10:xmax+10]
        # ballScore,coord = calcBallScore(imageSeg, comp)
        if (imageSeg.shape[0]<h or imageSeg.shape[1]<w):
            print("size wrongggg")
            continue
        ballScore,coord =matchTemplate(imageSeg,comp, previousMatch)

        if ballScore>bestScore:
            bestScore = ballScore
            bestCoord = [xmin,ymin,xmax,ymax]
            bestCoord2 = [xmin+coord[0]-5,ymin+coord[1]-5,xmin+coord[2]-5,ymin+coord[3]-5]    
        # if ballScore>bestScore:

        #     if pm ==[0,0,0,0]:
        #         bestScore = ballScore
        #         bestCoord = [xmin,ymin,xmax,ymax]
        #         bestCoord2 = [xmin+coord[0],ymin+coord[1],xmin+coord[2],ymin+coord[3]]
                
        #     elif overlap([xmin+coord[0],ymin+coord[1],xmin+coord[2],ymin+coord[3]],pm):   
        #         bestScore = ballScore
        #         bestCoord = [xmin,ymin,xmax,ymax]
        #         bestCoord2 = [xmin+coord[0],ymin+coord[1],xmin+coord[2],ymin+coord[3]]

                
        
    return bestCoord,bestCoord2
def overlap(coord1,coord2): 
     
    if(coord1[0]>coord2[2] or coord1[1]>coord2[3]): 
        return False
  
    if(coord2[0] > coord1[2] or coord1[1] > coord2[3]): 
        return False
  
    return True
def matchTemplate(image_np,comp,previousMatch):
    if comp is None:
        comp = cv2.imread("comparison.jpg")
    h,w,_ = comp.shape

    image = np.copy(image_np)
    res = cv2.matchTemplate(image,comp,cv2.TM_CCOEFF_NORMED)

    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(np.copy(res))
    
    pt = (max_loc[0],max_loc[1])

    # return max_val,[pt[0], pt[1], pt[0] + w, pt[1] + h]

    # cv2.rectangle(image_np, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
    if (previousMatch==[0,0,0,0]):
        return max_val,[pt[0], pt[1], pt[0] + w, pt[1] + h]
    elif overlap([pt[0], pt[1], pt[0] + w, pt[1] + h],previousMatch):
        return max_val,[pt[0], pt[1], pt[0] + w, pt[1] + h]
    else:
        res2 = np.reshape(res, res.shape[0]*res.shape[1])
        sort = np.argsort(res2)
        # (y1, x1) = np.unravel_index(sort[0], res.shape)
        for i in range(min(len(sort),20)):
            x,y = np.unravel_index(sort[i], res.shape)
            pt =(x,y)
            if overlap([pt[0], pt[1], pt[0] + w, pt[1] + h],previousMatch):
                return max_val,[pt[0], pt[1], pt[0] + w, pt[1] + h]
    pt = (max_loc[0],max_loc[1])
    
    return 0,[pt[0], pt[1], pt[0] + w, pt[1] + h]
    return matchTemplate(image_np, cv2.resize(comp, (comp.shape[0]+6,comp.shape[1]+6),previousMatch))
    threshold = 0.5
    loc = np.where( res >= threshold)



    for pt in zip(*loc[::-1]):
        cv2.rectangle(image_np, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
        
    return image_np
    # cv2.imwrite("../../findSoccerball.jpg",image)


def MyCorrelation(I, h, mode):
    imgH, imgW = I.shape
    filterH, filterW = h.shape

    def _calcPixel(x,y,image):
        patch = image[y-filterH//2:y+filterH//2+1, x-filterW//2:x+filterW//2+1]
        multiplication = np.multiply(patch, h)

        return np.sum(multiplication)

    newImage = np.zeros((imgH+filterH*2-2,imgW+filterW*2-2))

    vPad = filterH//2
    hPad = filterW//2

    newImage[vPad*2:vPad*2+imgH,hPad*2:hPad*2+imgW] = np.copy(I)

    initX,initY = (filterW//2, filterH//2)
    # position = (filterW//2, filterH//2)
    # for x in range(len(newImage)):
    #     for y in range(len(newImage[0])):
    newImage_copy = np.copy(newImage)
    for x in range(imgW+hPad*2):
        for y in range(imgH+vPad*2):
            currX,currY = initX+x,initY+y
            newImage[currY, currX] = _calcPixel(currX,currY,newImage_copy)

    if (mode == "same"):
        return (newImage[vPad*2:vPad*2+imgH,hPad*2:hPad*2+imgW])
    elif(mode == "full"):
        return newImage
    elif(mode == "valid"):
        return (newImage[vPad*4:imgH,hPad*4:imgW])

    return newImage
    
def MyConvolution(I,h,mode):
    flippedFilter = np.flip(h)

    red = I[:,:,0]
    green = I[:,:,1]
    blue = I[:,:,2]

    blurR = MyCorrelation(red, flippedFilter, mode)
    blurG = MyCorrelation(green, flippedFilter, mode)
    blurB = MyCorrelation(blue, flippedFilter, mode)

    
    return (blurR,blurR,blurB)

v = 6

filename = 'videos/pen%dslow.mp4'%v

outputName = 'videos/pen%dslowFindTrial'%v + ".avi"

vid = cv2.VideoCapture(filename)

width = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = vid.get(5)
new_height = height
new_width = width

frameCount = vid.get(cv2.CAP_PROP_FRAME_COUNT)
vwriter = cv2.VideoWriter(outputName ,cv2.VideoWriter_fourcc(*'MJPG'),fps, (width, height)) 

with tfDetectionGraph.as_default():
    with tf.Session(graph=tfDetectionGraph) as detector:
        frameCounter = 0
        ballCoord = []
        ballInfo =outputName + '\n'
        ballCoord.append(outputName)
        # skip to specific frame (testing purposes only)
        # for i in range(15):
        #     success, image = vid.read()
        #     if not success:
        #         print("whoops")


        success, image_np = vid.read()
        height,width,_ = image_np.shape
        previousMatch = [0,0,0,0]
        while success:
            
            kernel = np.array([[-1,-1,-1,-1,-1],
                                [-1,2,2,2,-1],
                                [-1,2,8,2,-1],
                                [-2,2,2,2,-1],
                                [-1,-1,-1,-1,-1]])/8.0
            image_np = cv2.filter2D(image_np, -1, kernel)

            image_expanded = np.expand_dims(image_np,axis =0)
            image_tensor = tfDetectionGraph.get_tensor_by_name('image_tensor:0')
            boxes = tfDetectionGraph.get_tensor_by_name('detection_boxes:0')
            scores = tfDetectionGraph.get_tensor_by_name('detection_scores:0')
            classes = tfDetectionGraph.get_tensor_by_name('detection_classes:0')
            num_detections = tfDetectionGraph.get_tensor_by_name('num_detections:0')        

            boxes, scores, classes, num_detections = detector.run([boxes, scores, classes, num_detections], feed_dict = {image_tensor: image_expanded})
            orig_image = image_np
            origW, origH, _ = orig_image.shape
            
            boxes3 = np.squeeze(boxes)
            classes3 = np.squeeze(classes).astype(np.int32)
            scores3 = np.squeeze(scores)
                        
            boxes2=[]
            classes2=[]
            scores2=[]
            for i in range(len(boxes3)):
                if (classes3[i] == 2):
                    boxes2.append(boxes3[i])
                    classes2.append(classes3[i])
                    scores2.append(scores3[i])
            
            classes3 = np.array(classes2)
            boxes3 = np.array(boxes2)
            scores3 = np.array(scores2)
            boxInfo = []
            threshold =0.001

            for i in range(len(boxes3)):
                if scores3[i]>threshold:
                    ymin = int(boxes3[i][0] * new_height)
                    xmin = int(boxes3[i][1] * new_width)
                    ymax = int(boxes3[i][2] * new_height)
                    xmax = int(boxes3[i][3] * new_width)
                    boxcoord = ((xmin,ymin),(xmax,ymax))
                    score = scores3[i]
                    boxInfo.append({"coord": boxcoord, "score": score})

            res, coord = matchTemplate(image_np,None, previousMatch)

            
            

            finalBox,finalBox2 = findBall(image_np, boxInfo, previousMatch)
            previousMatch2 = finalBox2
            xmin,ymin,xmax,ymax = coord
            if res ==0:
                xmin,ymin,xmax,ymax = previousMatch
            else:
                previousMatch = coord
            
            cv2.rectangle(image_np, (xmin,ymin),(xmax,ymax),(0,0,0),2)
            xavg = (xmin+xmax)/2
            yavg = (ymin+ymax)/2
            ballInfo +=str(yavg) + " " +str(xavg)
            ballInfo += "\n"
        
            blurred = cv2.GaussianBlur(np.copy(image_np),(25,25),cv2.BORDER_DEFAULT)
            mask = np.ones(image_np.shape)
            rectSize = 100
            newXmin = max(0,xmin-rectSize)
            newYmin = max(0,ymin-rectSize)
            newXmax = min(image_np.shape[1],xmax+rectSize,)
            newYmax = min(image_np.shape[0],ymax+rectSize,)

            cv2.rectangle(mask, (newXmin,newYmin),(newXmax,newYmax),(0,0,0),-1)

            finalBlur = np.multiply(image_np, 1-mask) +np.multiply(blurred,mask)

            vwriter.write(finalBlur.astype(np.uint8))

            
            success, image_np = vid.read()
        file = open("ballInfo%d.txt"%v,'w')
        file.write(ballInfo)
        file.close()
        vid.release()
        vwriter.release()
        print("done")