pytorch object too deep for array when saving image - python

I am trying to run the code from the following github rep:
https://github.com/iamkrut/image_inpainting_resnet_unet
I havent changed anything in the code and it is causing a ValueError, that the object is too deep, when the code tries to save the image. The error seems to come from these two lines.
images = img_tensor.cpu().detach().permute(0,2,3,1)
plt.imsave(join(data_dir, 'samples', image), images[index,:,:,:3])
Here is the error statement
File "train.py", line 205, in <module>
data_dir=args.data_dir)
File "train.py", line 94, in train_net
plt.imsave(join(data_dir, 'samples', image), images[index,:,:,:]);
File "C:\ProgramData\Anaconda3\envs\torch2\lib\site-packages\matplotlib\pyplot.py", line 2140, in imsave
return matplotlib.image.imsave(fname, arr, **kwargs)
File "C:\ProgramData\Anaconda3\envs\torch2\lib\site-packages\matplotlib\image.py", line 1498, in imsave
_png.write_png(rgba, fname, dpi=dpi)
ValueError: object too deep for desired array
Anyone know what could be causing this or how to fix it?
Thank you

matplotlib package does not understand the pytorch datatype (tensor). you should convert tensor array to numpy array and then use matplotlib functions.
a = torch.rand(10, 3, 20, 20)
plt.imsave("test.jpg", a.cpu().detach().permute(0, 2, 3, 1)[0, ...]) # Error
plt.imsave("test.jpg", a.cpu().detach().permute(0, 2, 3, 1).numpy()[0, ...])

I managed to fix the code by changing the lines to
images=img_tensor.cpu().numpy()[0]
images = np.transpose(images, (1,2,0))
plt.imsave(join(data_dir, 'samples', image), images)
Still not sure what was wrong with the previous version. So if anyone knows please tell me.

Related

How to get seams of a color image in OpenCV2 in Python?

I am writing a bit of code to allow me to remove seams from an image. Currently, my code allows me to find, highlight, and remove seams from a greyscale image. I am needing to remove seams from colored images and my code will not allow me to do that. Can anyone help me modify my code to allow me to do this?
My code:
import numpy as np
import cv2
import math
import time
def getEdgeImage(img,margin=10):
kernel=np.float64([[-1,0,1]])
Ix=cv2.filter2D(img,cv2.CV_64F,kernel)
Iy=cv2.filter2D(img,cv2.CV_64F,kernel)
I=np.hypot(Ix,Iy)
m=I.max()
I[:,:margin]=m
I[:,-margin:]=m
return I
def getEnergyMap(img,repulseMask=None,attractMask=None):
edges=getEdgeImage(img)
if attractMask is not None:
edges[attractMask==1]=-10
if repulseMask is not None:
edges[repulseMask==1]=235
kernel=np.ones(3,np.float64)
for i in range(1,len(edges)):
minAbove=cv2.erode(edges[i-1],kernel).T[0]
edges[i]+=minAbove
return edges
def getSeam(img,repulseMask=None,attractMask=None):
energyMap=getEnergyMap(img,repulseMask,attractMask)
y=len(energyMap)-1
x=np.argmin(energyMap[y])
seam=[(x,y)]
while len(seam)<len(energyMap):
x,y=seam[-1]
newY=y-1
newX=x+np.argmin(energyMap[newY,x-1:x+2])-1
seam.append((newX,newY))
return seam
img1=cv2.imread("image.jpg") #[::2,::2]
# attractMask=img1*0
# repulseMask=img1*0
seam=getSeam(img1)
The attract and repulse masks are unimportant to the code currently, they are just used so I can manually plug in pixel coordinates to increase or decrease the amount of seams going in that coordinate plane.
The error I get when I run this code:
Traceback (most recent call last):
File "Program.py", line 110, in <module>
seam=getSeam(img1)
File "Program.py", line 62, in getSeam
energyMap=getEnergyMap(img,repulseMask,attractMask)
File "Program.py", line 58, in getEnergyMap
edges[i]+=minAbove
ValueError: operands could not be broadcast together with shapes (960,3) (960,) (960,3)
Is there anyway that I can get this to work with my code? I'll modify the functions if that is what I need to do.
Then try this, these are separate channels given to functions individually.
r=img1[:,:,0]
seam_r=getSeam(r)
g=img1[:,:,1]
seam_g=getSeam(g)
b=img1[:,:,2]
seam_b=getSeam(b)
After this, pass the results to your post function individually.

How to iteratively load read_pixel and write to envi file; python3

I want to load hyperspectral data per pixel into an array and write this pixel out again using Python 3.5. I want to calculate something with the spectral information of this Pixel.
I have tried two different ways and both don't work the way I want.
First of all I have updated spectral package since the last version was stated not to work with iteratively envi.save_image but still my approach does not work.
Second my approaches both are not very good with my double for loop - I know -
If anyone could please help me on my problem.
1st:
myfile=open_image('input.hdr')
for i in range(0,myfile.shape[0]):
for j in range(0,myfile.shape[1]):
mypixel = (myfile.read_pixel(i,j))
envi.save_image('output.hdr', mypixel, dtype=np.int16)
1st example does not save the image rather gives me the error code
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.5/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 699, in runfile
execfile(filename, namespace)
File "/usr/local/lib/python3.5/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 88, in execfile
exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)
File "/dtc/Python/Masking.py", line 132, in <module>
envi.save_image('test.hdr', mypixel, dtype=np.int16)#, metadata=myfile.metadata)
File "/usr/local/lib/python3.5/site-packages/spectral/io/envi.py", line 415, in save_image
data, metadata = _prepared_data_and_metadata(hdr_file, image, **kwargs)
File "/usr/local/lib/python3.5/site-packages/spectral/io/envi.py", line 568, in _prepared_data_and_metadata
add_image_info_to_metadata(image, metadata)
File "/usr/local/lib/python3.5/site-packages/spectral/io/envi.py", line 613, in add_image_info_to_metadata
metadata['samples'] = image.shape[1]
IndexError: tuple index out of range
2nd:
myfile=open_image('input.hdr')
envi.create_image('test.hdr',ext='.bip', interleave='bip',dtype='h',force=True,metadata=myfile.metadata)
open('test.bip', 'w').close() # empties the created file
file = open('test.bip', 'ab')#ab #opens the created file for appending the new bands
for i in range(0,myfile.shape[0]):
for j in range(0,myfile.shape[1]):
mypixel = (myfile.read_pixel(i,j))
file.write(mypixel)
file.close()
myfile.close()
The second example saves the image but stores the Pixel in a different order and messes up my image.
So this is the very short, fast and easy solution thanks to a colleague.
myfile=envi.open('input.hdr') #opens image for calculating with it
imageArray = 10000*myfile[:,:,:] #do some math with it;
#10000* is needed because input data are thresholded between {0;10000}
#and during processing get thresholded between {0;1}.
#For preventing 0 in the output with datatype int the thresholding to {0;10000} is necessary again
envi.save_image('test.hdr',imageArray,dtype=np.int16,metadata=myfile.metadata,force=True)
I have to say in advance that I am not familiar with the spectral package and envi and therefore unfortunately cannot offer a ready-to-use solution. Besides, I am not sure if I correctly understood what you are trying to do with your image.
But just some thoughts: Could the write/save function inside the for loop cause your problem, because every pixel is treated in the exact same way and it gets overwritten? I can not relate to the IndexError though.
Maybe you need a function where you can rather write a certain pixel to an empty image passing also i and j. A second option could be to save each pixel in an array and save it to an image at once after the for loop.

Python code for basic fft of grid image

I'm trying to take an fft of an image in python, alter the transformed image and take a reverse fft. Specifically, I have a picture of a grid that I'd like to transform, then black out all but a central, narrow vertical slit of the transform, then take a reverse fft.
The code I'm working with now, for no alteration to transform plane:
import os
os.chdir('/Users/terra/Desktop')
import Image, numpy
i = Image.open('grid.png')
i = i.convert('L') #convert to grayscale
a = numpy.asarray(i) # a is readonly
b = abs(numpy.fft.rfft2(a))
j = Image.fromarray(b)
j.save('grid2.png')
As of now, I'm getting an error message:
Traceback (most recent call last):
File "/Users/terra/Documents/pic2.py", line 11, in
j.save('grid2.png')
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PIL/Image.py", line 1439, in save
save_handler(self, fp, filename)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PIL/PngImagePlugin.py", line 506, in _save
raise IOError, "cannot write mode %s as PNG" % mode
IOError: cannot write mode F as PNG
I'm very new to programming and Fourier transforms, so most related threads I've found online are over my head. Very specific help is greatly appreciated. Thanks!
The main problem is that the array contains floats after the FFT, but for it to be useful for PNG output, you need to have uint8s.
The simplest thing is to convert it to uint8 directly:
b = abs(numpy.fft.rfft2(a)).astype(numpy.uint8)
This probably will not produce the image you want, so you'll have to normalize the values in the array somehow before converting them to integers.

ValueError: too many boolean indices

I am trying to visualize some data using matpolid, but i got this error
File "C:\Python27\lib\site-packages\matplotlib\mlab.py", line 2775, in griddata
tri = delaunay.Triangulation(x,y)
File "C:\Python27\lib\site-packages\matplotlib\delaunay\triangulate.py", line 98, in __init__
duplicates = self._get_duplicate_point_indices()
File "C:\Python27\lib\site-packages\matplotlib\delaunay\triangulate.py", line 137, in _get_duplicate_point_indices
return j_sorted[mask_duplicates]
ValueError: too many boolean indices
It happens when i call function
data=griddata(self.dataX,self.dataY,self.dataFreq,xi,yi)
Does anyone know why I got that error? I suppoes it it something with parameters, but I can figure out what
Might be worth updating your matplotlib. There has been a lot of work on the triangulation code that has made it into v1.3.0.
The what's new page for matplotlib v1.3.0 can be found at http://matplotlib.org/users/whats_new.html#triangular-grid-interpolation

Factors Analysis using MDP in Python

Excuse my ignorance, I'm very new to Python. I'm trying to perform factor analysis in Python using MDP (though I can use another library if there's a better solution).
I have an m by n matrix (called matrix) and I tried to do:
import mdp
mdp.nodes.FANode()(matrix)
but I get back an error. I'm guessing maybe my matrix isn't formed properly? My goal is find out how many components are in the data and find out which rows load onto which components.
Here is the traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "mdp/signal_node.py", line 630, in __call__
return self.execute(x, *args, **kwargs)
File "mdp/signal_node.py", line 611, in execute
self._pre_execution_checks(x)
File "mdp/signal_node.py", line 480, in _pre_execution_checks
self.train(x)
File "mdp/signal_node.py", line 571, in train
self._check_input(x)
File "mdp/signal_node.py", line 429, in _check_input
if not x.ndim == 2:
AttributeError: 'list' object has no attribute 'ndim'
Does anyone have any idea what's going on, and feel like explaining it to a Python newbie?
I have absolutely no experience with mdp, but it looks like it expects your matrices to be passed as a Numpy array instead of a list. Numpy is a package for high performance scientific computing. You can go to the Numpy home page and install it. After doing so, try altering your code to this:
import mdp, numpy
mdp.nodes.FANode()(numpy.array(matrix))
As Stephen said, the data must be a numpy array. More precisely it must be a 2D array, with the first index representing the different sampes and the second index representing the data dimensions (using the wrong order here can lead to the "singular matrix" error).
You should also take a look at the MDP documentation, which should answer all your questions. If that doesn't help there is the MDP user mailing list.

Categories