[python] 정확한 크기의 그림을 픽셀 단위로 지정하고 저장

3841 x 7195 픽셀 크기의 이미지가 있다고 가정 해보십시오. 그림의 내용을 디스크에 저장하여 픽셀로 지정한 정확한 크기 의 이미지를 만듭니다.

축도없고 제목도 없습니다. 이미지 만. 디스크 에서 이미지를 디스크 단위로 픽셀 단위 로 지정하기 때문에 DPI에 대해서는 개인적으로 신경 쓰지 않습니다 .

다른 스레드를 읽었으며 모두 인치로 변환 한 다음 그림의 크기를 인치로 지정하고 dpi를 조정합니다. 픽셀 간 변환으로 인해 발생할 수있는 정확도 손실을 처리하지 않으려 고합니다.

나는 시도했다 :

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)

운이없는 (Python은 너비와 높이가 각각 32768 (?) 미만이어야한다고 불평합니다)

내가 본 모든 것에서 matplotlib그림 크기를 inchesand에 지정해야 dpi하지만 그림이 디스크에서 차지하는 픽셀 에만 관심이 있습니다. 어떻게해야합니까?

명확히하기 위해 : matplotlib다른 이미지 저장 라이브러리가 아닌 으로이 작업을 수행하는 방법을 찾고 있습니다.



답변

Matplotlib은 픽셀과 직접 작동하지 않지만 실제 크기와 DPI에서 작동합니다. 특정 픽셀 크기의 그림을 표시하려면 모니터의 DPI를 알아야합니다. 예를 들어이 링크 는이를 감지합니다.

3841×7195 픽셀의 이미지가있는 경우 모니터 할 정도로 크지 않을 수 있으므로 해당 크기의 그림을 표시 할 수 없습니다 (matplotlib은 그림을 요구할 경우 화면에 맞게 그림을 요구합니다) 너무 크면 화면 크기가 줄어 듭니다.) 예를 들어 800×800 픽셀 이미지를 원한다고 가정 해 봅시다. 내 모니터 ( my_dpi=96) 에 800×800 픽셀 이미지를 표시하는 방법은 다음과 같습니다 .

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

따라서 기본적으로 DPI로 치수를 인치 단위로 나눕니다.

특정 크기의 그림을 저장하려면 다른 문제입니다. 화면 DPI는 더 이상 중요하지 않습니다 (화면에 맞지 않는 그림을 요청하지 않는 한). 800×800 픽셀 그림의 동일한 예를 사용하여의 dpi키워드를 사용하여 다른 해상도로 저장할 수 있습니다 savefig. 화면과 동일한 해상도로 저장하려면 동일한 dpi를 사용하십시오.

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

이미지를 8000×8000 픽셀 이미지로 저장하려면 10 배 큰 dpi를 사용하십시오.

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

DPI의 설정이 모든 백엔드에서 지원되는 것은 아닙니다. 여기에서는 PNG 백엔드가 사용되지만 pdf 및 ps 백엔드는 크기를 다르게 구현합니다. 또한 DPI와 크기를 변경하면 글꼴 크기와 같은 요소에도 영향을 미칩니다. DPI가 클수록 글꼴 및 요소의 상대적 크기가 동일하게 유지되지만 큰 그림의 글꼴을 작게하려면 DPI 대신 물리적 크기를 늘려야합니다.

예를 들어 3841 x 7195 픽셀의 이미지를 저장하려면 다음을 수행하십시오.

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

필자는 대부분의 화면에 맞도록 그림 dpi를 100으로 사용했지만 dpi=1000필요한 해상도를 달성하기 위해 저장했습니다 . 내 시스템에서 이것은 3840×7190 픽셀의 png를 생성합니다. 저장된 DPI는 선택한 값보다 항상 0.02 픽셀 / 인치 작으므로 큰 이미지 크기에 (작은) 영향을 미칩니다. 이것에 대한 더 많은 토론은 여기에 있습니다 .


답변

이것은 코드를 기반으로 색상 노이즈와 원하는 크기의 93Mb PNG 이미지를 생성하는 데 도움이되었습니다.

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)

Linux Mint 13에서 Python 2.7 라이브러리의 마지막 PIP 버전을 사용하고 있습니다.

희망이 도움이됩니다!


답변

tiago가 승인 한 응답을 기반으로 다음은 배열과 동일한 해상도의 이미지로 numpy 배열을 내보내는 작은 일반 함수입니다.

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()

tiago의 이전 답변에서 말했듯이 화면 DPI를 먼저 찾아야합니다. 예를 들면 다음과 같습니다. http://dpi.lv

예를 resize_fact들어 이미지를 원래 해상도의 50 % (0.5)로 내보낼 수있는 함수에 추가 인수 를 추가했습니다 .


답변

OP는 1 : 1 픽셀 데이터를 유지하려고합니다. 과학 이미지로 작업하는 천문학 자로서, 알 수없고 예측할 수없는 노이즈 나 오류가 발생할 수 있으므로 이미지 데이터의 보간을 허용 할 수 없습니다. 예를 들어, 다음은 pyplot.savefig ()를 통해 저장된 480×480 이미지의 스 니펫입니다. matplotlib가 대략 2×2로 리샘플링했지만 1×2 픽셀의 열을 확인한
픽셀의 세부 사항

대부분의 픽셀은 단순히 두 배가되었으므로 (1×1 픽셀은 2×2가 됨) 일부 열과 행은 픽셀 당 1×2 또는 2×1이되었으므로 원래 과학 데이터가 변경되었음을 의미합니다.

Alka가 암시 한 것처럼 plt.imsave ()는 OP가 요구하는 것을 달성합니다. 이미지 배열 이미지에 이미지 데이터가 저장되어 있다고 가정하면 다음과 같은 작업을 수행 할 수 있습니다

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

이 예제에서 파일 이름의 확장자는 “png”입니다 (그러나 어쨌든 format = ‘png’로 형식을 지정해야 함). 이미지 배열은 arr이며 반전 된 회색조 “gray_r”을 선택했습니다. 컬러 맵으로. 일반적으로 동적 범위를 지정하기 위해 vmin 및 vmax를 추가하지만 선택 사항입니다.

최종 결과는 im 배열과 정확히 같은 픽셀 크기의 png 파일입니다.

참고 : OP는이 솔루션이 정확히 수행하는 축 등을 지정하지 않았습니다. 축, 눈금 등을 추가하려는 경우 선호하는 방법은 transparent = True (PNG 또는 PDF)로 저장하고 이미지에 오버레이를 오버레이하는 별도의 플롯에서 수행하는 것입니다. 이렇게하면 원본 픽셀을 그대로 유지할 수 있습니다.


답변

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)


답변