IOError:[Errno 22]无效模式('rb')或文件名:'\ x89PNG \ n'

时间:2016-06-22 10:35:46

标签: python image ioerror

我刚开始编程(使用Python),因为我需要开发一种允许我执行直径分布的可执行文件。我设法找到了有用的东西(下面的代码):

# Put here all modules you would need in order to represent your data

import matplotlib.pylab as plt 
import numpy as np
import collections as c
from collections import Counter
from PIL import Image
import matplotlib.mlab as mlab
from scipy.optimize import curve_fit
import Tkinter as tk
from tkFileDialog import askopenfilename

# This prints the plot containing the diameter distribution of our sample

root = tk.Tk() ; root.withdraw()
filename = askopenfilename(parent=root)
f = open(filename)

with f as input: #Change the Results.txt file for your own .txt file
    a = zip(*(line.strip().split('\t') for i,line in enumerate(input) if i != 0))

areas = a[1]

diam = []
for area in areas:
    diam.append(round((np.sqrt(float(area)/ np.pi) * 2), 3)) # The number 3 tells us how many decimals will be shown
hist, bins = np.histogram(diam, 50)
diam.sort()

counts = c.Counter(diam)

'''This prints the table which includes all diameter values 
and how many of them we can find on our sample# '''

table = sorted(counts.items()) 
col_labels = ['Diameter (nm)', 'Counts'] # In Diameter column you can add the units inside the empty parenthesis
table_vals = table

q = diam

mu = sum(q)/float(len(q))
variance = np.var(q)
sigma = np.sqrt(variance)

# In the plt.suptitle part --> change the default name to your sample name

plt.subplot(121)
plt.bar(counts.keys(), counts.values(), 0.01, color="black")
plt.tick_params(direction = 'out', labeltop='off', labelright='off')
plt.xlabel('Diameter (nm)', fontsize=16, fontweight='bold')
plt.ylabel('Count (a.u.)', fontsize=16, fontweight='bold')
plt.title(r'$\mathregular{Diameter \ distribution\ of \ the\ sample:}\ \mu=%.3f,\ \sigma=%.3f$' % (mu, sigma), fontsize=18, fontweight='bold')
plt.suptitle('Silicon nanopillars grown epitaxially', fontsize=22, fontweight='bold')
plt.autoscale(enable=True, axis='x', tight=None)

the_table = plt.table(cellText = table_vals, colLabels = col_labels, loc = 'bottom', cellLoc = 'center', bbox = [0.67, 0.18, 0.30, 0.8])
the_table.auto_set_font_size(False)
the_table.set_fontsize(12)

# This adds a gaussian fit to our histogram

plt.plot()

x = diam

yhist, xhist = np.histogram(x, bins=np.arange(4096))

xh = np.where(yhist > 0)[0]
yh = yhist[xh]

def gaussian(x, a, mu, sigma):
return a * np.exp(-((x - mu)**2 / (2 * sigma**2)))

popt, pcov = curve_fit(gaussian, xh, yh, [1, mu, sigma]) 

i = np.linspace(min(diam)-20, max(diam), 1000) 
plt.plot(i, gaussian(i, *popt), lw=3, ls=':', c='r')
plt.xlim(min(diam)-10, max(diam)+10)

# This adds the image from where the data is extracted (always use .png images otherwise this won't work)

im = Image.open('Dosi05.png') # Put here the original image
im2 = Image.open('Dosi05_Analyzed.png') # Put here the thresholded and analysed image

plt.subplot(222)
plt.imshow(im, cmap='gray')
plt.axis('off')
plt.title('Original Image', fontsize=14, fontweight='bold') 

plt.subplot(224)
plt.imshow(im2, cmap='gray')
plt.axis('off')
plt.title('Processed Image', fontsize=14, fontweight='bold')


plt.show()

但我被要求做与.txt文件相同的操作,但使用plt.subplot(222)和plt.subplot(224)绘制图像,以避免触及代码。

我尝试使用Tkinter做类似的事情(见下面的代码):

# Put here all modules you would need in order to represent your data

import matplotlib.pylab as plt 
import numpy as np
import collections as c
from collections import Counter
from PIL import Image
import matplotlib.mlab as mlab
from scipy.optimize import curve_fit
import Tkinter as tk
from tkFileDialog import askopenfilename, askopenfile
from skimage import data

# This prints the plot containing the diameter distribution of our sample

root = tk.Tk() ; root.withdraw()
filename = askopenfilename(parent=root)
f = open(filename)

with f as input: #Change the Results.txt file for your own .txt file
    a = zip(*(line.strip().split('\t') for i,line in enumerate(input) if i != 0))

areas = a[1]

diam = []
for area in areas:
    diam.append(round((np.sqrt(float(area)/ np.pi) * 2), 3)) # The number 3 tells us how many decimals will be shown
hist, bins = np.histogram(diam, 50)
diam.sort()

counts = c.Counter(diam)

'''This prints the table which includes all diameter values 
and how many of them we can find on our sample# '''

table = sorted(counts.items()) 
col_labels = ['Diameter (nm)', 'Counts'] # In Diameter column you can add the units inside the empty parenthesis
table_vals = table

q = diam

mu = sum(q)/float(len(q))
variance = np.var(q)
sigma = np.sqrt(variance)

# In the plt.suptitle part --> change the default name to your sample name

plt.subplot(121)
plt.bar(counts.keys(), counts.values(), 0.01, color="black")
plt.tick_params(direction = 'out', labeltop='off', labelright='off')
plt.xlabel('Diameter (nm)', fontsize=16, fontweight='bold')
plt.ylabel('Count (a.u.)', fontsize=16, fontweight='bold')
plt.title(r'$\mathregular{Diameter \ distribution\ of \ the\ sample:}\ \mu=%.3f,\ \sigma=%.3f$' % (mu, sigma), fontsize=18, fontweight='bold')
plt.suptitle('Silicon nanopillars grown epitaxially', fontsize=22, fontweight='bold')
plt.autoscale(enable=True, axis='x', tight=None)

the_table = plt.table(cellText = table_vals, colLabels = col_labels, loc = 'bottom', cellLoc = 'center', bbox = [0.67, 0.18, 0.30, 0.8])
the_table.auto_set_font_size(False)
the_table.set_fontsize(12)

# This adds a gaussian fit to our histogram

plt.plot()

x = diam

yhist, xhist = np.histogram(x, bins=np.arange(4096))

xh = np.where(yhist > 0)[0]
yh = yhist[xh]

def gaussian(x, a, mu, sigma):
    return a * np.exp(-((x - mu)**2 / (2 * sigma**2)))

popt, pcov = curve_fit(gaussian, xh, yh, [1, mu, sigma]) 

i = np.linspace(min(diam)-20, max(diam), 1000) 
plt.plot(i, gaussian(i, *popt), lw=3, ls=':', c='r')
plt.xlim(min(diam)-10, max(diam)+10)

# This adds the image from where the data is extracted (always use .png images otherwise this won't work)

image_formats = [('PNG','*.png')]
file_path_list = askopenfilename(filetypes=image_formats, initialdir='/', title='Please select a picture to analyze')

for file_path in file_path_list:
     image = data.imread(file_path) 
     image2 = data.imread(file_path) 

plt.subplot(222)
plt.imshow(image, cmap='gray')
plt.axis('off')
plt.title('Original Image', fontsize=14, fontweight='bold') 

plt.subplot(224)
plt.imshow(image2, cmap='gray')
plt.axis('off')
plt.title('Processed Image', fontsize=14, fontweight='bold')

plt.show()

但是在选择第一个图像文件之后,Python会抛出以下内容:

[IOError:[Errno 22]无效模式('rb')或文件名:'\ x89PNG \ n'1

有人可以告诉我我可以做些什么来解决这个问题,或者是否有其他方法可以通过从文件浏览器中选择而不是在代码本身中更改它们来显示图像?

希望问题足够明确,谢谢你的帮助!

ý

1 个答案:

答案 0 :(得分:-1)

askopenfilename的retrun值是一个字符串。当你遍历一个字符串(Probabily像C:\Somepath\someimage.png这样的路径)时,你得到以下错误。

  

Errno2:没有这样的文件或目录:u' C'

您需要使用askopenfilenames模块来获取多个文件。

image_formats = [('PNG','*.png')]
file_path_list = askopenfilenames(filetypes=image_formats, initialdir='/', title='Please select a picture to analyze')
for file_path in file_path_list:
    file_path = os.path.normpath(file_path)  # To normalize path 
    image = data.imread(file_path) 
    image2 = data.imread(file_path) 

for file_path in file_path_list.split()用于python< 2.7.7,因为返回值为string instead of tuple

https://docs.python.org/2/library/os.path.html#os.path.normpath

原始问题

Op已使用askopenfile代替askopenfilename

粘贴代码 如果未指定r,则

tkFileDialog.askopenfile会返回以mode模式打开的所选文件。

def askopenfile(mode = "r", **options):
    "Ask for a filename to open, and returned the opened file"

    filename = Open(**options).show()
    if filename:
        return open(filename, mode)
    return None

imread的输入是图像文件路径。 您需要使用askopenfilenames返回所选文件路径。