পিক্সেলগুলিতে সঠিক আকারের সাথে একটি চিত্র নির্দিষ্ট করা এবং সংরক্ষণ করা


152

বলুন আমার কাছে আকারের 3841 x 7195 পিক্সেলের চিত্র রয়েছে। আমি চিত্রটির বিষয়বস্তু ডিস্কে সংরক্ষণ করতে চাই, ফলস্বরূপ পিক্সেলগুলিতে নির্দিষ্ট করা সঠিক আকারের একটি চিত্র ।

অক্ষ নেই, শিরোনাম নেই। শুধু চিত্র। আমি ব্যক্তিগতভাবে ডিপিআইগুলির বিষয়ে চিন্তা করি না, কারণ আমি পিক্সেলের ডিস্কে চিত্রটি পর্দায় যে আকার নেয় তা নির্দিষ্ট করতে চাই ।

আমি অন্যান্য থ্রেড পড়েছি এবং তারা সকলেই ইঞ্চিতে রূপান্তরগুলি করতে বলে মনে হচ্ছে এবং তারপরে চিত্রটির মাত্রা ইঞ্চিগুলিতে নির্দিষ্ট করে এবং কোনওভাবে ডিপিআইকে সামঞ্জস্য করবে। আমি পিক্সেল থেকে ইঞ্চি রূপান্তর থেকে ফলস্বরূপ নির্ভুলতার সম্ভাব্য ক্ষতির সাথে মোকাবিলা করতে এড়াতে চাই।

আমি চেষ্টা করেছি:

w = 7195
h = 3841
fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(im_np, aspect='normal')
fig.savefig(some_path, dpi=1)

কোনও ভাগ্য ছাড়াই (পাইথন অভিযোগ করে যে প্রস্থ এবং উচ্চতা প্রতিটি অবশ্যই 32768 (?) এর নীচে হওয়া উচিত)

সবকিছু আমি দেখেছি থেকে, matplotlibপ্রয়োজন চিত্রে আকার নির্দিষ্ট করা inchesএবং dpi, কিন্তু আমি শুধুমাত্র আগ্রহী পিক্সেল চিত্রে ডিস্ক লাগে। কিভাবে আমি এটি করতে পারব?

স্পষ্ট করার জন্য: আমি এটি করার জন্য একটি উপায় খুঁজছি matplotlib, এবং অন্যান্য চিত্র-সংরক্ষণ গ্রন্থাগারগুলির সাথে নয়।


ম্যাটপ্ল্লিটিবের সাহায্যে চিত্রের আকারটি সরাসরি ইঞ্চিতে সেট করা সম্ভব নয়।
tiago

উত্তর:


175

ম্যাটপ্লটলিব সরাসরি পিক্সেল নিয়ে কাজ করে না, বরং শারীরিক আকার এবং ডিপিআই দিয়ে থাকে। আপনি যদি একটি নির্দিষ্ট পিক্সেল আকারের একটি চিত্র প্রদর্শন করতে চান তবে আপনাকে আপনার মনিটরের ডিপিআই জানতে হবে। উদাহরণস্বরূপ এই লিঙ্কটি এটি আপনার জন্য সনাক্ত করবে।

আপনার যদি 3841x7195 পিক্সেলের একটি চিত্র থাকে তবে আপনি এটি নিরীক্ষণ করেননি যে এটি বড় unlikely এটি খুব বড় এটি পর্দার আকারে সঙ্কুচিত হবে)। আসুন কল্পনা করুন যে আপনি একটি উদাহরণের জন্য 800x800 পিক্সেল চিত্র চান। আমার মনিটরে 800x800 পিক্সেল চিত্রটি কীভাবে প্রদর্শিত হবে তা এখানে my_dpi=96:

plt.figure(figsize=(800/my_dpi, 800/my_dpi), dpi=my_dpi)

সুতরাং আপনি মূলত আপনার ডিপিআই দ্বারা মাত্রাগুলি ইঞ্চিতে ভাগ করুন divide

আপনি যদি কোনও নির্দিষ্ট আকারের একটি চিত্র সংরক্ষণ করতে চান তবে এটি আলাদা বিষয়। স্ক্রিন ডিপিআই এখন আর তেমন গুরুত্বপূর্ণ নয় (যদি না আপনি এমন চিত্র জিজ্ঞাসা করেন যা স্ক্রিনে ফিট না হয়)। 800x800 পিক্সেলের চিত্রের একই উদাহরণ ব্যবহার করে আমরা এর dpiকীওয়ার্ডটি ব্যবহার করে এটি বিভিন্ন রেজোলিউশনে সংরক্ষণ করতে পারি savefig। স্ক্রিনের মতো একই রেজোলিউশনে এটি সংরক্ষণ করতে কেবল একই ডিপিআই ব্যবহার করুন:

plt.savefig('my_fig.png', dpi=my_dpi)

এটি 8000x8000 পিক্সেল চিত্র হিসাবে সংরক্ষণ করতে, 10 গুণ বড় ডিপিআই ব্যবহার করুন:

plt.savefig('my_fig.png', dpi=my_dpi * 10)

মনে রাখবেন যে ডিপিআইয়ের সেটিংটি সমস্ত ব্যাকেন্ডের দ্বারা সমর্থিত নয়। এখানে, পিএনজি ব্যাকএন্ড ব্যবহৃত হয়, তবে পিডিএফ এবং পিএস ব্যাকেন্ডগুলি আকারটি আলাদাভাবে প্রয়োগ করবে। এছাড়াও, ডিপিআই এবং আকারগুলি পরিবর্তন করা ফন্টসাইজের মতো জিনিসগুলিকেও প্রভাবিত করবে। একটি বৃহত্তর ডিপিআই হ'ল ফন্ট এবং উপাদানগুলির আকারের তুলনামূলক আকারে রাখবে, তবে আপনি যদি বড় আকারের জন্য ছোট ফন্টগুলি চান তবে আপনাকে ডিপিআইয়ের পরিবর্তে শারীরিক আকার বাড়িয়ে তুলতে হবে।

আপনার উদাহরণটিতে ফিরে আসা, আপনি যদি 3841 x 7195 পিক্সেল সহ কোনও চিত্র সংরক্ষণ করতে চান তবে আপনি নিম্নলিখিতটি করতে পারেন:

plt.figure(figsize=(3.841, 7.195), dpi=100)
( your code ...)
plt.savefig('myfig.png', dpi=1000)

নোট করুন যে আমি বেশিরভাগ স্ক্রিনে ফিট করার জন্য 100 এর চিত্র dpi ব্যবহার করেছি তবে dpi=1000প্রয়োজনীয় রেজোলিউশন অর্জনের জন্য সংরক্ষণ করেছি । আমার সিস্টেমে এটি 3840x7190 পিক্সেল সহ একটি পিএনজি উত্পাদন করে - দেখে মনে হয় যে ডিপিআই সংরক্ষিত সর্বদা নির্বাচিত মানের থেকে 0.02 পিক্সেল / ইঞ্চি ছোট থাকে, এটি বৃহত্তর চিত্রের আকারগুলিতে (ছোট) প্রভাব ফেলবে। এখানে আরও কিছু আলোচনা ।


5
এটা মনে রাখা সহজ যে মনিটরের মাপগুলি (এবং সেইজন্য স্ট্যান্ডার্ড ব্রাউজার এবং ইউআই উইন্ডো মাপ) সাধারণত 96 ডিপিআই - 96 এর গুণাবলী অনুসারে হয় S হঠাৎ 1440 পিক্সেলের মতো সংখ্যাগুলি অর্থবহ (15 ইঞ্চি) হয় যখন এটির মতো চিন্তা করা হয়।
ড্যানি স্ট্যাপল

এটি পাস figsizeকরার কাজটি পেতে পারেনি plt.figure। সমাধানটি অন্যান্য উত্তরগুলির পরামর্শ অনুসারে করা হয়েছিল এবং এটিকে কল ছাড়াই figsize কল করার পরে কল করুনfig.set_size_inches(w,h)
ত্রিনিদাদ

এর জন্য দস্তাবেজ figureএবং savefig
হ্যান্ডেল করুন

লিঙ্কটি অ্যাপল থান্ডারবোল্ট প্রদর্শনের জন্য সঠিক মানটি দেখায় না।
দিমিত্রি

আমি এই সমাধানটি পছন্দ করি তবে আমার একটি সতর্কতা রয়েছে। লেখার আকার DPI যেমন ব্যস্ত আইশ। (আমার সিস্টেমটি ম্যাকবুক প্রো, ওএস এক্স), তাই ইন্টারেক্টিভ প্রিন্টিংয়ের জন্য ডিপিআই তৈরির ক্ষেত্রে বড় আকারের (10 * মাই_ডিপিআই এর মতো) পাঠটিকে নিকটবর্তী অদৃশ্যে সঙ্কুচিত করে।
অধ্যাপক হস্টার

16

এটি আপনার কোডের উপর ভিত্তি করে রঙের শব্দ এবং পছন্দসই মাত্রাগুলি সহ একটি 93Mb পিএনজি চিত্র উত্পন্ন করার জন্য কাজ করেছিল:

import matplotlib.pyplot as plt
import numpy

w = 7195
h = 3841

im_np = numpy.random.rand(h, w)

fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(im_np, aspect='normal')
fig.savefig('figure.png', dpi=1)

আমি লিনাক্স মিন্ট 13 এ পাইথন ২.7 লাইব্রেরির শেষ পিআইপি সংস্করণগুলি ব্যবহার করছি।

আশা করি এইটি কাজ করবে!


4
খুব কম ডিপিআই সেট করার অর্থ হ'ল ফন্টগুলি খুব কমই দৃশ্যমান হবে, যদি না খুব বড় ফন্টের আকারগুলি সুস্পষ্টভাবে ব্যবহার করা হয়।
টিয়াগো

1
উচ্চতর ডিপিআই সেট করা এবং আপনার ইঞ্চির আকার (যা স্বেচ্ছাসেবী হয়) সেই ডিপিআই দিয়ে ভাগ করা ভাল। তার বাইরে, আপনার সেটআপ পিক্সেল পুনরুত্পাদন জন্য একটি সঠিক পিক্সেল উত্পাদন করে, ধন্যবাদ!
ফরাসীখেল্ডার

আমি এর প্লট উপাদানগুলির সাথে চেনাশোনাগুলি সংরক্ষণ করার আগে এটি ব্যবহার করার চেষ্টা করছি (চেনাশোনা, লাইন, ...)। এটি লাইন প্রস্থকে বিরক্ত করে, যাতে উপাদানগুলি সবেच দৃশ্যমান হয়।
গৌথির

5

টিয়াগো দ্বারা গৃহীত প্রতিক্রিয়ার ভিত্তিতে, এখানে একটি ছোট জেনেরিক ফাংশন রয়েছে যা অ্যারের মতো একই রেজোলিউশন সম্পন্ন একটি চিত্রকে একটি আঙ্কুল অ্যারে রফতানি করে:

import matplotlib.pyplot as plt
import numpy as np

def export_figure_matplotlib(arr, f_name, dpi=200, resize_fact=1, plt_show=False):
    """
    Export array as figure in original resolution
    :param arr: array of image to save in original resolution
    :param f_name: name of file where to save figure
    :param resize_fact: resize facter wrt shape of arr, in (0, np.infty)
    :param dpi: dpi of your screen
    :param plt_show: show plot or not
    """
    fig = plt.figure(frameon=False)
    fig.set_size_inches(arr.shape[1]/dpi, arr.shape[0]/dpi)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)
    ax.imshow(arr)
    plt.savefig(f_name, dpi=(dpi * resize_fact))
    if plt_show:
        plt.show()
    else:
        plt.close()

টিয়াগো দ্বারা পূর্ববর্তী উত্তরে যেমন বলা হয়েছিল, স্ক্রিন ডিপিআই প্রথমে খুঁজে পাওয়া দরকার যা উদাহরণস্বরূপ এখানে করা যেতে পারে: http://dpi.lv

আমি resize_factফাংশনে একটি অতিরিক্ত যুক্তি যুক্ত করেছি যা আপনি চিত্রটি মূল রেজোলিউশনের 50% (0.5) তে রফতানি করতে পারবেন, উদাহরণস্বরূপ।


2

ওপি 1: 1 পিক্সেল ডেটা সংরক্ষণ করতে চায়। বিজ্ঞান চিত্রগুলির সাথে কাজ করা একজন জ্যোতির্বিদ হিসাবে আমি চিত্রের ডেটা কোনও প্রকারের অনুমতি দিতে পারি না কারণ এটি অজানা এবং অবিশ্বাস্য শব্দ বা ত্রুটিগুলির পরিচয় দেয়। উদাহরণস্বরূপ, এখানে 480x480 চিত্রের একটি স্নিপেট রয়েছে পাইপ্লট.সেসফিগ () এর মাধ্যমে সংরক্ষণ করা হয়েছে: ম্যাটপ্ল্লোলিব প্রায় 2x2 আকারে পুনর্নির্মাণ করা পিক্সেলের বিশদ, তবে 1x2 পিক্সেলের কলামটি লক্ষ্য করুন

আপনি দেখতে পাচ্ছেন যে বেশিরভাগ পিক্সেল কেবল দ্বিগুণ হয়ে গিয়েছিল (সুতরাং 1x1 পিক্সেল 2x2 হয়ে যায়) তবে কিছু কলাম এবং সারি পিক্সেল 1x2 বা 2x1 এ পরিণত হয়েছে যার অর্থ আসল বিজ্ঞানের ডেটা পরিবর্তন করা হয়েছে।

আলকার ইঙ্গিত অনুসারে, plt.imsave () যা ওপি যা চাইবে তা অর্জন করবে। বলুন যে আপনার কাছে চিত্রের অ্যারে im এ চিত্রের ডেটা সঞ্চিত আছে, তখন কেউ এর মতো কিছু করতে পারে

plt.imsave(fname='my_image.png', arr=im, cmap='gray_r', format='png')

এই উদাহরণে যেখানে ফাইলের নামটির "png" এক্সটেনশন রয়েছে (তবে আপনার এখনও অবশ্যই আমি বলতে পারি বিন্যাস = 'পিএনজি' দিয়ে ফর্ম্যাটটি নির্দিষ্ট করতে হবে), চিত্রের অ্যারেটি আরআর, এবং আমরা উল্টো গ্রেস্কেল "ধূসর_আর" বেছে নিয়েছি কালারম্যাপ হিসাবে। আমি সাধারণত গতিশীল পরিসীমা নির্দিষ্ট করতে vmin এবং vmax যুক্ত করি তবে এগুলি alচ্ছিক।

শেষ ফলাফলটি ইম অ্যারের মতো ঠিক একই পিক্সেল মাত্রার একটি পিএনজি ফাইল।

দ্রষ্টব্য: ওপি কোনও অক্ষর ইত্যাদি নির্দিষ্ট করে না যা এই সমাধানটি ঠিক কী করে। যদি কেউ অক্ষ, টিকস ইত্যাদি যোগ করতে চায় তবে আমার পছন্দসই পদ্ধতিটি স্বতন্ত্র = ট্রু (পিএনজি বা পিডিএফ) দিয়ে সংরক্ষণ করে একটি পৃথক প্লটের জন্য তা করা ইমেজটির উপরের অংশটি আবৃত করুন। এটি গ্যারান্টি দেয় যে আপনি মূল পিক্সেল অক্ষত রেখেছেন।


ধন্যবাদ। আমি এই প্রশ্নটি জিজ্ঞাসা করার কয়েক বছর হয়ে গেছে, তবে যা আমি মনে করি এবং আপনার উত্তরে যা দেখেছি তা থেকে, আপনি যখন একটি চিত্র হিসাবে একটি অ্যারের ডেটা সংরক্ষণ করার চেষ্টা করছেন তখন এটি ভাল কাজ করবে, তবে আপনি যদি সংরক্ষণ করতে চান তবে একটি সত্য নিজেই চিত্র (এর বিষয়বস্তু নির্বিশেষে) এবং এখনও ফলাফল চিত্রের পিক্সেল মাত্রা ঠিক নিয়ন্ত্রণ করে?
আমিলিও ওয়াজকেজ-রেইনা

-1

plt.imsave আমার জন্য কাজ করেছে। আপনি এখানে ডকুমেন্টেশনগুলি খুঁজে পেতে পারেন: https://matplotlib.org/3.2.1/api/_as_gen/matplotlib.pyplot.imsave.html

#file_path = directory address where the image will be stored along with file name and extension
#array = variable where the image is stored. I think for the original post this variable is im_np
plt.imsave(file_path, array)

আসল পোস্টের ব্যবহারের ক্ষেত্রে আপনি কোন পরামিতিটি সেট করছেন এবং প্রস্তাবিত মানগুলি ঠিক তা দেখিয়ে নমুনা কোড যুক্ত করুন।
সারা মেসার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.