For the graph created by matplotlib, it is explained as follows ** How to specify the size (width / height) of the plot area in pixels **.
In the case of Jupyter environment (Google Colab. Environment), ** by plt.show (...)
** PNG image displayed in the execution result cell ** and with plt.savefig (...)
** ** The size of the PNG image ** that is output as a file is different ** </ font>.
Specifically, the PNG image ** displayed in the execution result cell will be ** the surrounding margins are automatically cropped </ font> **. I will.
For example, if the following code is automated in the Google Colab. Environment, the image displayed in the output cell is $ 348 \ times 270 $ (px), while the image saved as test.png
is $ 400 \ times 300. It will be $ (px).
python
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,20,100) #Sample data for drawing
y = x ** 0.5 #Sample data for drawing
fig = plt.figure(dpi=100, figsize=(4,3))
plt.plot(x,y)
plt.savefig('test.png') #Output to file 400 x 300 px
plt.show() #348 x 270 px displayed in output cell
--figsize = (4,3)
specifies the "width" and "height" of the image in ** inch increments **.
--In dpi = 100
," Dot per Inch (= number of dots per inch (number of pixels) "is specified.
--The output image size is ** width ** is $ 4 , \ mathrm {inch} \ times 100 , \ mathrm {dpi} = 400 , \ mathrm {pixel} $, ** height ** is $ 3 \ , \ mathrm {inch} \ times 100 , \ mathrm {dpi} = 300 , \ mathrm {pixel} $ ... It should be, but it is displayed in the output cell The image will be a little smaller </ font> with the margins trimmed.
From now on, we will proceed to ** target images that are output as files ** with plt.savefig (...)
.
The image size (in pixels) could be calculated from the "size" and "DPI" of the figure
specified in inches, as described above. This can be calculated from an instance of figure
(fig
) as follows:
Calculate image size (in pixels)
fig_w_px = int(fig.get_figwidth() * fig.get_dpi())
fig_h_px = int(fig.get_figheight() * fig.get_dpi())
print(f'■ Fig size {fig_w_px} x {fig_h_px} [px]')
First, here, instead of the overall size of this image, the size of the (net) plot area surrounded by ** red frame ** </ font> ** as follows: ** Find out what the (pixel unit) looks like.
The size of the plot area (in pixels) can be calculated by getting the value from the Axes object (ʻax) as follows: In addition, since Japanese is used in the figure, in the Google Colab. Environment etc., please execute
! Pip install japanize-matplotlib` first to install the library.
Calculate plot area size (in pixels)
import numpy as np
import japanize_matplotlib
import matplotlib.pyplot as plt
x = np.linspace(0,20,100) #Sample data for drawing
y = x ** 0.5 #Sample data for drawing
fig = plt.figure(dpi=100, figsize=(4,3))
ax = plt.gca()
ax.plot(x,y)
ax.set_xlabel('input',fontsize=12)
ax.set_ylabel('output',fontsize=12)
plt.savefig('foo.png')
#Figure (whole image) size
fig_w_px = int(fig.get_figwidth() * fig.get_dpi())
fig_h_px = int(fig.get_figheight() * fig.get_dpi())
print(f'■ Fig size {fig_w_px} x {fig_h_px} [px]')
#Axis (plot area) size
ax_size_inch = ax.figure.get_size_inches()
ax_w_inch = ax_size_inch[0] * (ax.figure.subplotpars.right - ax.figure.subplotpars.left)
ax_h_inch = ax_size_inch[1] * (ax.figure.subplotpars.top - ax.figure.subplotpars.bottom)
ax_w_px = int( ax_w_inch * fig.get_dpi() )
ax_h_px = int( ax_h_inch * fig.get_dpi() )
print(f'■ Axis size {ax_w_px } x {ax_h_px } [px]')
The execution result is as follows. Also, if you open the file output foo.png with image editing software etc. and check the size of the plot area, it surely matches the following result.
Execution result
■ Fig size 400 x 300 [px]
■ Axis size 310 x 226 [px]
--ʻAx.figure.get_size_inches () `, the size of the area including the overall size of the Axes object (= ** scales and labels for each axis (characters such as" input "and" output ") ** ) Is obtained in inches.
--In ʻax.figure.subplotpars.left, it is a value ($ 0.0 $ to $ 1.0 $) that represents the ** left edge position ** of the plot area when the entire width of the Axes object is ** $ 1.0 $. Also, ʻax.figure.subplotpars.right
is a value that represents ** the rightmost position of the plot area **.
--Here, the difference between the two ʻax.figure.subplotpars.right --ax.figure.subplotpars.left` is the width of the plot area where the ** width of the Axes object is ** $ 1.0 $ It represents the ratio of **.
--In order to obtain the width of the plot area in ** inches **, the total width of the Axes object ʻax_size_inch [0] (in inches) and the width (ratio) of the plot area ʻax.figure.subplotpars.right - Multiply by ax.figure.subplotpars.left
and store in ʻax_w_inch`.
--In order to convert inches to pixels, ʻax_w_inch is multiplied by the resolution
fig.get_dpi () and stored in ʻax_w_px
.
I was able to ** find the size of the plot area in pixels **.
This time, on the contrary, ** specify the size of the plot area in pixels ** and draw a graph. The following code is a sample that draws a graph so that the size of the plot area is $ 400 \ times 300 $ (px).
--Reference: Demo Fixed Size Axes @ matplotlib.org
The cause is unknown, but at the end of the program, when the size of the plot area is recalculated and output, it becomes ʻAxis size 387 x 302 [px] `. However, when I measure the size of the plot area for the actually output image (foo.png), it is correctly $ 400 \ times 300 $ (px).
Graph output by specifying the size of the plot area in pixels
import numpy as np
import japanize_matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import Divider, Size #add to
from mpl_toolkits.axes_grid1.mpl_axes import Axes #add to
x = np.linspace(0,20,100) #Sample data for drawing
y = x ** 0.5 #Sample data for drawing
ax_w_px = 400 #Specify the width of the plot area in pixels
ax_h_px = 300 #Specify the height of the plot area in pixels
#Processing for size specification ↓ ↓ From here ↓ ↓
fig_dpi = 100
ax_w_inch = ax_w_px / fig_dpi
ax_h_inch = ax_h_px / fig_dpi
ax_margin_inch = (0.5, 0.5, 0.5, 0.5) # Left,Top,Right,Bottom [inch]
fig_w_inch = ax_w_inch + ax_margin_inch[0] + ax_margin_inch[2]
fig_h_inch = ax_h_inch + ax_margin_inch[1] + ax_margin_inch[3]
fig = plt.figure( dpi=fig_dpi, figsize=(fig_w_inch, fig_h_inch))
ax_p_w = [Size.Fixed(ax_margin_inch[0]),Size.Fixed(ax_w_inch)]
ax_p_h = [Size.Fixed(ax_margin_inch[1]),Size.Fixed(ax_h_inch)]
divider = Divider(fig, (0.0, 0.0, 1.0, 1.0), ax_p_w, ax_p_h, aspect=False)
ax = Axes(fig, divider.get_position())
ax.set_axes_locator(divider.new_locator(nx=1,ny=1))
fig.add_axes(ax)
#Processing for size specification ↑↑ Up to here ↑↑
ax.plot(x,y)
ax.set_xlabel('input',fontsize=12)
ax.set_ylabel('output',fontsize=12)
plt.savefig('foo.png')
#Figure (whole image) size
fig_w_px = int(fig.get_figwidth() * fig.get_dpi())
fig_h_px = int(fig.get_figheight() * fig.get_dpi())
print(f'■ Fig size {fig_w_px} x {fig_h_px} [px]')
#Axis (plot area) size
ax_size_inch = ax.get_figure().get_size_inches()
ax_w_inch = ax_size_inch[0] * (ax.figure.subplotpars.right - ax.figure.subplotpars.left)
ax_h_inch = ax_size_inch[1] * (ax.figure.subplotpars.top - ax.figure.subplotpars.bottom)
ax_w_px = int( ax_w_inch * fig.get_dpi() )
ax_h_px = int( ax_h_inch * fig.get_dpi() )
print(f'■ Axis size {ax_w_px } x {ax_h_px } [px]')
#The print output above does not result in 400 x 300,
#Actual image ('foo.png'), The size of the plot area is 400 x 300.
Recommended Posts