Python to VFS to MovieFileIn Top Issue

I was hoping you guys could help me with one little last piece I can’t seem to get working. I am generating an image in python. I am storing the image using VFS. It seems to be storing, but isn’t showing in the VFS palette tool or in the MovieFileIn top. In fact the MovieFileIn has a warning: Failed to open file. The path resolves correctly in the MovieFileIn from op(‘/project1/base1’).vfs[‘image.png’] but I get that warning. Also, the image will store to disc so it is being created properly. I have a Base, base1, next to the MovieFileIn. I am at a loss. My current code is below. What am I missing?? Thanks!

Part of my code:

#Note: image is created in code above this line
imgBytes = cv.imencode('.png', image)
dataEncode=np.array(imgBytes)
strEncode = dataEncode.tostring()
image = bytearray(strEncode)

if not op('base1').vfs.find(pattern='image.png'):
    op('base1').vfs.addByteArray(image, 'image.png')

print(op('base1').vfs.find(pattern='image.png'))

Going to try to figure out what’s going on this coming week. Would you mind posting your whole file or at least the entire script? If it’s private, you can send to ivan@derivative.ca.

Sure. Here is my test file. I’ve tried it several ways but this is the last iteration. It does use the ArUco library for opencv. Thanks for looking.

Aruco.3.toe (8.0 KB)

Thanks for the report, we’ll take a look. It does look like the issue is specifically with virtual files added via addByteArray, so as a workaround for the time being you could instead add them with addFile.

EDIT: My mistake – I made a test case with TOP.saveByteArray() but forgot to provide the correct extension, so it defaulted to ‘.tiff’. I changed it to TOP.saveByteArray(‘.png’) and it worked.

Hi @bradfichter,

imencode returns 2 values: retVal (bool) and the actual array. So in your code you have to access the second part of what imencode returns ( cv.imencode('.png', image)[1] ):

imgBytes = cv.imencode('.png', image)[1]
dataEncode=np.array(imgBytes)
strEncode = dataEncode.tostring()
image = bytearray(strEncode)

if not op('base1').vfs.find(pattern='image.png'):
    op('base1').vfs.addByteArray(image, 'image.png')
else:
    op('base1').vfs['image.png'].byteArray = image
print(op('base1').vfs.find(pattern='image.png'))

cheers
Markus

Thanks Eric. I tried addFile and an error popped up saying td.VFSFile object has no attribute “addFile”. So I looked it up and realized this is reading from disc which is what I am trying to avoid. It seems like the addByteArray path has worked for others. Can’t completely verify that though.

Thanks for pointing that out. I tried that and still no luck. Just curious if you are you able to get that to work using the toe I uploaded?

Hi @bradfichter,

yup - works for me. The other change i made was adding the else statement for writing to the vfs file in case it already existed:

else:
    op('base1').vfs['image.png'].byteArray = image

Aruco.4.toe (8.6 KB)

Best
Markus

Eric, something IS writing. When I print

print(op('base1').vfs.find(pattern='image.png'))

I get

type:VFSFile name:image.png owner:/project1/base1 originalFilePath: size:2048 date:2020-08-10

Also, if I try to rewrite without checking, it errors saying it exists.

Using snaut’s correction, I modified the code to:

import cv2 as cv
from cv2 import aruco
import numpy as np

dictionary = cv.aruco.Dictionary_get(cv.aruco.DICT_6X6_250)
 
image = np.zeros((200, 200), dtype=np.uint8)
image = cv.aruco.drawMarker(dictionary, 34, 200, image, 1);

cv.imwrite("marker33.png", image)

imgBytes = cv.imencode('.png', image)[1]

strEncode = imgBytes.tostring()
image = bytearray(strEncode)

if not op('base1').vfs.find(pattern='image.png'):
    op('base1').vfs.addByteArray(image, 'image.png')
else:
    op('base1').vfs['image.png'].byteArray = image
    
print(op('base1').vfs.find(pattern='image.png'))

Still no luck.

Looks like you’re missing the following line from Markus’s original code snippet:

dataEncode=np.array(imgBytes)

I modified it seeing that printed results are the same. So it works without it. Believe it or not, after looking at the new top posted and seeing it actually working, I deleted my MovieInTop and added a new one inputting the path and it works. Weird. However, it is still not showing in the VFS palette tool.

Actually testing a few times, any time you get an error, you have to delete and add the MovieFileIn top. Which now I see was part of my problem debugging this.

Thanks for looking into it!

Now on to figuring out what my opencv camera calibration is spitting out the wrong tvec vector (I think).