TypeError: an integer is required (got type StreamingMedia)

What I’m trying to do:
I’m taking a video as a file and sending it to my google colab for prediction. Before the predicting can begin I’m converting the video into frames that I can predict on. This is where I’m getting the TypeError.

What I’ve tried and what’s not working:
It’s saying:

TypeError: an integer is required (got type StreamingMedia)

This error is occurring at the following line:

# Read the video from specified path 
  cam = cv2.VideoCapture(name) 

Code Sample:
Here is my file loader function


  def file_loader_1_change(self, file, **event_args):
    """This method is called when a new file is loaded into this FileLoader"""
   
    result , score = anvil.server.call('pred',file)
    if result == 0:
        self.l1.text = "Poor shot , your shot is %0.2f% effective"%(score)
      
    elif result == 1:
        self.l1.text = "Good shot , your shot is %0.2f% effective"%(score)
    
    else:
        self.l1.text = "No shot detected"
   
    pass



Here is my pred() function:

import cv2
import os
import numpy as np
from google.colab import files
from keras.preprocessing import image
@anvil.server.callable
def pred(name):

# Read the video from specified path 
  cam = cv2.VideoCapture(name) 

  try: 

    # creating a folder named data 
    if not os.path.exists('data'): 
        os.makedirs('data') 

# if not created then raise error 
  except OSError: 
    print ('Error: Creating directory of data') 

# frame 
  currentframe = 0

  while(True): 

    # reading from frame 
    ret,frame = cam.read() 

    if ret: 
        # if video is still left continue creating images 
        name = './data/frame' + str(currentframe) + '.jpg'
        print ('Creating...' + name) 

        # writing the extracted images 
        cv2.imwrite(name, frame) 

        # increasing counter so that it will 
        # show how many frames are created 
        currentframe += 1
    else: 
        break

# Release all space and windows once done 
  cam.release() 
  cv2.destroyAllWindows() 
  
  p = [0]*3
  for i in os.listdir('/content/data/'):
    path = '/content/data/' + i
    img = image.load_img(path, target_size=(640, 360))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x /= 255.0
    images = np.vstack([x])
    t=model.predict(images,batch_size=32)
    p[t.argmax()] += 1
  if p[0] > 5 or p[1] > 5:
    if p[0] >= p[1]:
      return 0 , 60 - p[0]%60
    else:
      return 1 , 60 + p[1]%40 
  else:
    return 2 , 0

Clone link:
https://anvil.works/build#clone:ENUQGLIASUO55S4J=K2VXQ6UEPODG42P33BANV2T3

Is it possible that you have more than one callable named pred?

No I have only one pred , the problem is how can I pass a media file object as a video.

Well, you’ve listed two separate functions, from two separate files, both entirely without line numbers, and not told us which line 10 in which file, so I had to make a reasonable guess: that it was line 10 of the function you mentioned first. That would make if result == 0: a reasonable guess for being line 10. The pred you listed was returning two numbers, so it looked like a different pred was responsible.

Let’s not guess anymore. Which line is line 10 from the error message?

I’m sorry for the confusion , it’s line 10 in the second file i.e. pred(name). To be exact ,

# Read the video from specified path 
  cam = cv2.VideoCapture(name) 

Is where the error is happening. I’ve reflected the changes in the question.

You’ll want to check out the docs for opencv.
https://docs.opencv.org/master/d8/dfe/classcv_1_1VideoCapture.html

The constructor needs a filename rather than a file.

So you’ll probably want to look through the anvil docs on how to work with media objects on disk

Anvil Docs | Files on Disk

2 Likes

Ok , I’m converting the file into its temporary file:

import cv2
import os
import numpy as np
from google.colab import files
from keras.preprocessing import image
import anvil.media
@anvil.server.callable
def pred(name):
  with anvil.media.TempFile(name) as file_name:

# Read the video from specified path 
    cam = cv2.VideoCapture(file_name) 

    try: 

    # creating a folder named data 
      if not os.path.exists('data'): 
          os.makedirs('data') 

# if not created then raise error 
    except OSError: 
      print ('Error: Creating directory of data') 

# frame 
    currentframe = 0

    while(True): 

    # reading from frame 
      ret,frame = cam.read() 

      if ret: 
        # if video is still left continue creating images 
        name = './data/frame' + str(currentframe) + '.jpg'
        print ('Creating...' + name) 

        # writing the extracted images 
        cv2.imwrite(name, frame) 

        # increasing counter so that it will 
        # show how many frames are created 
        currentframe += 1
      else: 
        break

# Release all space and windows once done 
    cam.release() 
    cv2.destroyAllWindows() 

But , I’m getting the following error:

AttributeError: 'str' object has no attribute 'get_bytes'
at /usr/local/lib/python3.7/dist-packages/anvil/media.py, line 18
  called from <ipython-input-13-a4e91cf898ca>, line 9
  called from Form1, line 71

The error message gives a hint at what’s going on here. It looks like name is not a file but a str. From the code snippets it looked like name was the file. I presume you’ve changed it somewhere along the way to str.

Adding print statements to your code will helps to determine the types you have in your program.

1 Like

Solved it , I was passing the url before which was a string , now I’m passing a file.

def file_loader_1_change(self, file, **event_args):
    """This method is called when a new file is loaded into this FileLoader"""
  
    blob = Blob([file.get_bytes()], {'type': file.content_type})
    url = URL.createObjectURL(blob)
    self.video_1.src = ""
    self.video_1.src = url
   
   
    result , score = anvil.server.call('pred',file)

Thanks @stucork !!!
Currently my app takes around 30 secs to give a prediction , any idea on how to reduce this?