john-guo/simply-view-image-for-python-opencv-debugging

Add TF 2 support

saeedizadi opened this issue · 1 comments

Hello,

Thank you so much for the great plugin. I think if you advertise it correctly, it will be helping many developers!

I wonder if you could add support for TF2 tensor arrays too. Currently, I have to manually convert tf tensors to numpy tensors with .numpy() to be able to visualize them.

Many thanks

Hi,
Thank you for your suggestion.

Due to I do not have any experience in TF2, I just made a little changes in the python eval expression:

(${vn}.numpy() * 255.0 if (hasattr(${vn}, 'dtype')) and (${vn}.dtype == np.float64 or ${vn}.dtype == np.float32) else ${vn}.numpy()) if callable(getattr(${vn}, 'numpy', None)) else (${vn} * 255.0 if (isinstance(${vn}, (np.ndarray)) and (${vn}.dtype == np.float64 or ${vn}.dtype == np.float32)) else ${vn})

As you noticed that I used "callable(getattr(${vn}, 'numpy', None))" to test if the variable is a tensor. So you must ensure Eager Execution is enabled in TF2 to use this extension. Then I found it's very lucky that tf.dtype is same as np.dtype, so I can directly use np.float32 instead of tf.float32 to test the type avoiding forced "import tensorflow".

Now this change bring a tiny trick to customize if your object cannot be a numpy array directly, just add a "numpy()" method and an additional "dtype" property supporting the normalized image to your object, even you can make a metaclass or decorator something else to take effect for convenience.

for example:

class DebugViewImageWrapper:

    def __init__(self, a):
        self.a = a
    
    def numpy(self):
        return self.a
  
    @property
    def dtype(self):
        return self.a.dtype

img = cv2.imread("test.jpg")
normalized_img = img.astype(np.float32) / 255.
wrapped_img = DebugViewImageWrapper(img)
wrapped_img = DebugViewImageWrapper(normalized_img)