2016-06-22 2 views
0

Я только начал программировать (с Python), потому что мне нужно было разработать своего рода исполняемый файл, который позволяет мне выполнять распределение диаметров , Мне удалось получить что-то, что работает (код ниже):IOError: [Errno 22] недействительный режим ('rb') или имя файла: ' x89PNG n'

# 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

Может кто-нибудь сказать мне, что я могу сделать, чтобы решить эту проблему, или если есть другие способы отображения изображений, выбрав из браузера файлов вместо того, чтобы менять их в самом коде?

Надеюсь, что вопрос достаточно ясен, спасибо за вашу помощь заранее!

У

+0

Вы могли бы предоставить весь трассу здесь! – praba230890

+0

@ praba230890 traceback находится на картинке, если вы нажмете 1 рядом с описанием IOError, вы получите к нему – Yandrakus

ответ

-1

Значение Retrun из askopenfilename является строкой. Когда вы проходили по строке (Вероятно, путь, как C:\Somepath\someimage.png), вы получили следующую ошибку.

Errno2: No such file or directory: 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() для питона < 2.7.7, так как возвращаемое значение было string instead of tuple.

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


Orignal Вопрос

Op расклеивали код с askopenfile вместо askopenfilename

tkFileDialog.askopenfile возвращает выбранный файл открыт в режиме r если 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, который возвращает выбранный путь к файлам.

+0

Прежде всего спасибо за ваш ответ, похоже, что я вставлял здесь неправильный код. Я использовал 'askopenfilename', и эта проблема снова возникает. Также я не уверен, как связана ваша первая часть ответа на мой вопрос, извините, если это очевидно, но, как я уже сказал, я недавно начал программировать (2 недели назад), и для меня это довольно сложно понять. – Yandrakus

+0

Использование 'askopenfilename' предоставит вам путь, но я вижу, что вы просматриваете строку при использовании' для файла_папки в файле_path_list'. Вы можете попробовать с помощью 'askopenfilenames' с изменениями, которые я предложил, или вставить выходные данные' print file_path_list' для большей ясности. Первая часть моего ответа - это реализация 'askopenfile'. Я упомянул об этом, чтобы показать, что возвращаемое значение является файловым дескриптором. В любом случае, как вы упомянули, что здесь вы вводите неправильный код, так что это не имеет значения. – thegreenogre

+0

Я изменил то, что вы мне сказали, и теперь ошибка изменилась на Errno2: нет такого файла или каталога: u'C ' (довольно сложно сделать снимок экрана об ошибке, потому что окно программирования закрывается так быстро, как оно появляется) , – Yandrakus