이미지 튜토리얼 #

Matplotlib로 이미지를 플로팅하는 방법에 대한 짧은 자습서입니다.

시작 명령 #

먼저 IPython을 시작하겠습니다. 표준 Python 프롬프트에 대한 가장 뛰어난 개선 사항이며 특히 Matplotlib와 잘 연결됩니다. 셸에서 직접 IPython을 시작하거나 Jupyter Notebook(여기서 IPython은 실행 중인 커널임)을 사용하여 IPython을 시작합니다.

IPython이 시작되면 이제 GUI 이벤트 루프에 연결해야 합니다. 이것은 IPython에게 플롯을 표시할 위치(및 방법)를 알려줍니다. GUI 루프에 연결하려면 IPython 프롬프트에서 %matplotlib 매직을 실행합니다. 이것이 정확히 무엇을 하는지에 대한 자세한 내용은 GUI 이벤트 루프에 대한 IPython의 문서에 있습니다 .

Jupyter Notebook을 사용하는 경우 동일한 명령을 사용할 수 있지만 사람들은 일반적으로 %matplotlib 매직에 대한 특정 인수를 사용합니다.

In [1]: %matplotlib inline

이렇게 하면 플롯 그래픽이 노트북에 표시되는 인라인 플로팅이 켜집니다. 이것은 상호 작용에 중요한 의미를 갖습니다. 인라인 플로팅의 경우 플롯을 출력하는 셀 아래 셀의 명령은 플롯에 영향을 주지 않습니다. 예를 들어 플롯을 생성하는 셀 아래의 셀에서는 컬러맵을 변경할 수 없습니다. 그러나 별도의 창을 여는 Qt와 같은 다른 백엔드의 경우 플롯을 생성하는 셀 아래의 셀은 플롯을 변경합니다. 이는 메모리의 라이브 객체입니다.

이 자습서에서는 Matplotlib의 암시적 플로팅 인터페이스인 pyplot을 사용합니다. 이 인터페이스는 전역 상태를 유지하며 다양한 플롯 설정을 빠르고 쉽게 실험하는 데 매우 유용합니다. 대안은 대규모 애플리케이션 개발에 더 적합한 명시적입니다. 암시적 인터페이스와 명시적 인터페이스 간의 장단점에 대한 설명은 Matplotlib 애플리케이션 인터페이스(API)빠른 시작 가이드 를 참조하여 명시적 인터페이스 사용을 시작하세요. 지금은 암시적 접근 방식을 사용하겠습니다.

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

이미지 데이터를 Numpy 배열로 가져오기 #

Matplotlib는 Pillow 라이브러리를 사용하여 이미지 데이터를 로드합니다.

다음은 우리가 사용할 이미지입니다.

../../_images/stinkbug.png

24비트 RGB PNG 이미지(R, G, B 각각에 대해 8비트)입니다. 데이터를 얻는 위치에 따라 가장 많이 접하게 되는 다른 종류의 이미지는 투명도를 허용하는 RGBA 이미지 또는 단일 채널 회색조(광도) 이미지입니다. 이 튜토리얼의 나머지 부분을 위해 stinkbug.png 를 컴퓨터에 다운로드 하십시오.

우리가 간다...

img = mpimg.imread('../../doc/_static/stinkbug.png')
print(img)
[[[0.40784314 0.40784314 0.40784314]
  [0.40784314 0.40784314 0.40784314]
  [0.40784314 0.40784314 0.40784314]
  ...
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]]

 [[0.4117647  0.4117647  0.4117647 ]
  [0.4117647  0.4117647  0.4117647 ]
  [0.4117647  0.4117647  0.4117647 ]
  ...
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]]

 [[0.41960785 0.41960785 0.41960785]
  [0.41568628 0.41568628 0.41568628]
  [0.41568628 0.41568628 0.41568628]
  ...
  [0.43137255 0.43137255 0.43137255]
  [0.43137255 0.43137255 0.43137255]
  [0.43137255 0.43137255 0.43137255]]

 ...

 [[0.4392157  0.4392157  0.4392157 ]
  [0.43529412 0.43529412 0.43529412]
  [0.43137255 0.43137255 0.43137255]
  ...
  [0.45490196 0.45490196 0.45490196]
  [0.4509804  0.4509804  0.4509804 ]
  [0.4509804  0.4509804  0.4509804 ]]

 [[0.44313726 0.44313726 0.44313726]
  [0.44313726 0.44313726 0.44313726]
  [0.4392157  0.4392157  0.4392157 ]
  ...
  [0.4509804  0.4509804  0.4509804 ]
  [0.44705883 0.44705883 0.44705883]
  [0.44705883 0.44705883 0.44705883]]

 [[0.44313726 0.44313726 0.44313726]
  [0.4509804  0.4509804  0.4509804 ]
  [0.4509804  0.4509804  0.4509804 ]
  ...
  [0.44705883 0.44705883 0.44705883]
  [0.44705883 0.44705883 0.44705883]
  [0.44313726 0.44313726 0.44313726]]]

거기에 있는 dtype에 주목하십시오 - float32. Matplotlib는 각 채널의 8비트 데이터를 0.0과 1.0 사이의 부동 소수점 데이터로 재조정했습니다. 참고로 Pillow가 사용할 수 있는 유일한 데이터 유형은 uint8입니다. Matplotlib 플로팅은 float32 및 uint8을 처리할 수 있지만 PNG 이외의 형식에 대한 이미지 읽기/쓰기는 uint8 데이터로 제한됩니다. 왜 8비트인가? 대부분의 디스플레이는 컬러 그라데이션의 채널당 8비트만 렌더링할 수 있습니다. 왜 8비트/채널만 렌더링할 수 있습니까? 그것이 인간의 눈으로 볼 수 있는 전부이기 때문입니다. 자세한 내용은 여기(사진 관점에서): Luminous Landscape 비트 심도 튜토리얼 .

각 내부 목록은 픽셀을 나타냅니다. 여기서 RGB 이미지에는 3가지 값이 있습니다. 흑백 이미지이기 때문에 R, G, B가 모두 비슷합니다. RGBA(A는 알파 또는 투명도)는 내부 목록당 4개의 값을 가지며 간단한 휘도 이미지는 하나의 값만 갖습니다(따라서 3D 배열이 아닌 2D 배열일 뿐입니다). RGB 및 RGBA 이미지의 경우 Matplotlib는 float32 및 uint8 데이터 유형을 지원합니다. 회색조의 경우 Matplotlib는 float32만 지원합니다. 배열 데이터가 이러한 설명 중 하나를 충족하지 않는 경우 크기를 조정해야 합니다.

numpy 배열을 이미지로 그리기 #

따라서 데이터를 가져오거나 생성하여 numpy 배열에 데이터가 있습니다. 그것을 렌더링합시다. Matplotlib에서 이것은 imshow()함수를 사용하여 수행됩니다. 여기서 우리는 플롯 객체를 잡을 것입니다. 이 개체를 사용하면 프롬프트에서 플롯을 쉽게 조작할 수 있습니다.

이미지

numpy 배열을 그릴 수도 있습니다.

이미지 플롯에 유사색 구성표 적용 #

Pseudocolor는 대비를 강화하고 데이터를 보다 쉽게 ​​시각화하는 데 유용한 도구가 될 수 있습니다. 이는 프로젝터를 사용하여 데이터를 프레젠테이션할 때 특히 유용합니다. 프로젝터의 대비는 일반적으로 상당히 나쁩니다.

Pseudocolor는 단일 채널, 회색조, 광도 이미지에만 관련이 있습니다. 현재 RGB 이미지가 있습니다. R, G 및 B는 모두 유사하므로(위 또는 데이터에서 직접 참조) 데이터의 한 채널만 선택할 수 있습니다.

lum_img = img[:, :, 0]

# This is array slicing.  You can read more in the `Numpy tutorial
# <https://numpy.org/doc/stable/user/quickstart.html>`_.

plt.imshow(lum_img)
이미지
<matplotlib.image.AxesImage object at 0x7f2cdd608610>

이제 광도(2D, 무색) 이미지와 함께 기본 컬러맵(일명 조회 테이블, LUT)이 적용됩니다. 기본값은 viridis입니다. 선택할 수있는 다른 많은 것들이 있습니다.

plt.imshow(lum_img, cmap="hot")
이미지
<matplotlib.image.AxesImage object at 0x7f2cddcc2aa0>

set_cmap()다음 방법 을 사용하여 기존 플롯 객체의 색상표를 변경할 수도 있습니다 .

이미지

메모

그러나 인라인 백엔드가 있는 Jupyter 노트북에서는 이미 렌더링된 플롯을 변경할 수 없습니다. 여기 한 셀에서 imgplot을 생성하면 이후 셀에서 그것에 대해 set_cmap()을 호출할 수 없으며 이전 플롯이 변경될 것으로 예상할 수 있습니다. 이러한 명령을 하나의 셀에 함께 입력해야 합니다. plt 명령은 이전 셀의 플롯을 변경하지 않습니다.

사용할 수 있는 다른 많은 색상표 체계가 있습니다. 컬러맵의 목록과 이미지를 참조하십시오 .

컬러 스케일 참조 #

색상이 나타내는 값을 이해하는 것이 도움이 됩니다. 그림에 색상 막대를 추가하여 이를 수행할 수 있습니다.

이미지
<matplotlib.colorbar.Colorbar object at 0x7f2cdf5297e0>

특정 데이터 범위 검사 #

때때로 이미지의 대비를 향상시키거나, 크게 다르지 않거나 중요하지 않은 색상의 세부 사항을 희생하면서 특정 영역의 대비를 확장하고 싶을 수 있습니다. 흥미로운 영역을 찾는 좋은 도구는 히스토그램입니다. 이미지 데이터의 히스토그램을 생성하기 위해 hist()함수를 사용합니다.

plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')
이미지
(array([2.000e+00, 2.000e+00, 3.000e+00, 3.000e+00, 2.000e+00, 2.000e+00,
       3.000e+00, 1.000e+00, 7.000e+00, 9.000e+00, 7.000e+00, 2.000e+00,
       7.000e+00, 1.000e+01, 1.100e+01, 1.500e+01, 1.400e+01, 2.700e+01,
       2.100e+01, 2.400e+01, 1.400e+01, 3.100e+01, 2.900e+01, 2.800e+01,
       2.400e+01, 2.400e+01, 4.000e+01, 2.600e+01, 5.200e+01, 3.900e+01,
       5.700e+01, 4.600e+01, 8.400e+01, 7.600e+01, 8.900e+01, 8.000e+01,
       1.060e+02, 1.130e+02, 1.120e+02, 9.000e+01, 1.160e+02, 1.090e+02,
       1.270e+02, 1.350e+02, 9.800e+01, 1.310e+02, 1.230e+02, 1.110e+02,
       1.230e+02, 1.160e+02, 1.010e+02, 1.170e+02, 1.000e+02, 1.010e+02,
       9.000e+01, 1.060e+02, 1.260e+02, 1.040e+02, 1.070e+02, 1.110e+02,
       1.380e+02, 1.000e+02, 1.340e+02, 1.210e+02, 1.400e+02, 1.320e+02,
       1.390e+02, 1.160e+02, 1.330e+02, 1.180e+02, 1.080e+02, 1.170e+02,
       1.280e+02, 1.200e+02, 1.210e+02, 1.100e+02, 1.160e+02, 1.180e+02,
       9.700e+01, 9.700e+01, 1.140e+02, 1.070e+02, 1.170e+02, 8.700e+01,
       1.070e+02, 9.800e+01, 1.040e+02, 1.120e+02, 1.110e+02, 1.180e+02,
       1.240e+02, 1.340e+02, 1.200e+02, 1.410e+02, 1.520e+02, 1.360e+02,
       1.610e+02, 1.380e+02, 1.620e+02, 1.570e+02, 1.350e+02, 1.470e+02,
       1.690e+02, 1.710e+02, 1.820e+02, 1.980e+02, 1.970e+02, 2.060e+02,
       2.160e+02, 2.460e+02, 2.210e+02, 2.520e+02, 2.890e+02, 3.450e+02,
       3.620e+02, 3.760e+02, 4.480e+02, 4.630e+02, 5.170e+02, 6.000e+02,
       6.200e+02, 6.410e+02, 7.440e+02, 7.120e+02, 8.330e+02, 9.290e+02,
       1.061e+03, 1.280e+03, 1.340e+03, 1.638e+03, 1.740e+03, 1.953e+03,
       2.151e+03, 2.290e+03, 2.440e+03, 2.758e+03, 2.896e+03, 3.384e+03,
       4.332e+03, 5.584e+03, 6.197e+03, 6.422e+03, 6.404e+03, 7.181e+03,
       8.196e+03, 7.968e+03, 7.474e+03, 7.926e+03, 8.460e+03, 8.091e+03,
       9.148e+03, 8.563e+03, 6.747e+03, 6.074e+03, 6.328e+03, 5.291e+03,
       6.472e+03, 6.268e+03, 2.864e+03, 3.760e+02, 1.620e+02, 1.180e+02,
       1.270e+02, 9.500e+01, 7.600e+01, 8.200e+01, 6.200e+01, 6.700e+01,
       5.600e+01, 5.900e+01, 4.000e+01, 4.200e+01, 3.000e+01, 3.400e+01,
       3.200e+01, 4.300e+01, 4.200e+01, 2.300e+01, 2.800e+01, 1.900e+01,
       2.200e+01, 1.600e+01, 1.200e+01, 1.800e+01, 9.000e+00, 1.000e+01,
       1.700e+01, 5.000e+00, 2.100e+01, 1.300e+01, 8.000e+00, 1.200e+01,
       1.000e+01, 8.000e+00, 8.000e+00, 5.000e+00, 1.300e+01, 6.000e+00,
       3.000e+00, 7.000e+00, 6.000e+00, 2.000e+00, 1.000e+00, 5.000e+00,
       3.000e+00, 3.000e+00, 1.000e+00, 1.000e+00, 1.000e+00, 5.000e+00,
       0.000e+00, 1.000e+00, 3.000e+00, 0.000e+00, 1.000e+00, 1.000e+00,
       2.000e+00, 1.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00]), array([0.        , 0.00390625, 0.0078125 , 0.01171875, 0.015625  ,
       0.01953125, 0.0234375 , 0.02734375, 0.03125   , 0.03515625,
       0.0390625 , 0.04296875, 0.046875  , 0.05078125, 0.0546875 ,
       0.05859375, 0.0625    , 0.06640625, 0.0703125 , 0.07421875,
       0.078125  , 0.08203125, 0.0859375 , 0.08984375, 0.09375   ,
       0.09765625, 0.1015625 , 0.10546875, 0.109375  , 0.11328125,
       0.1171875 , 0.12109375, 0.125     , 0.12890625, 0.1328125 ,
       0.13671875, 0.140625  , 0.14453125, 0.1484375 , 0.15234375,
       0.15625   , 0.16015625, 0.1640625 , 0.16796875, 0.171875  ,
       0.17578125, 0.1796875 , 0.18359375, 0.1875    , 0.19140625,
       0.1953125 , 0.19921875, 0.203125  , 0.20703125, 0.2109375 ,
       0.21484375, 0.21875   , 0.22265625, 0.2265625 , 0.23046875,
       0.234375  , 0.23828125, 0.2421875 , 0.24609375, 0.25      ,
       0.25390625, 0.2578125 , 0.26171875, 0.265625  , 0.26953125,
       0.2734375 , 0.27734375, 0.28125   , 0.28515625, 0.2890625 ,
       0.29296875, 0.296875  , 0.30078125, 0.3046875 , 0.30859375,
       0.3125    , 0.31640625, 0.3203125 , 0.32421875, 0.328125  ,
       0.33203125, 0.3359375 , 0.33984375, 0.34375   , 0.34765625,
       0.3515625 , 0.35546875, 0.359375  , 0.36328125, 0.3671875 ,
       0.37109375, 0.375     , 0.37890625, 0.3828125 , 0.38671875,
       0.390625  , 0.39453125, 0.3984375 , 0.40234375, 0.40625   ,
       0.41015625, 0.4140625 , 0.41796875, 0.421875  , 0.42578125,
       0.4296875 , 0.43359375, 0.4375    , 0.44140625, 0.4453125 ,
       0.44921875, 0.453125  , 0.45703125, 0.4609375 , 0.46484375,
       0.46875   , 0.47265625, 0.4765625 , 0.48046875, 0.484375  ,
       0.48828125, 0.4921875 , 0.49609375, 0.5       , 0.50390625,
       0.5078125 , 0.51171875, 0.515625  , 0.51953125, 0.5234375 ,
       0.52734375, 0.53125   , 0.53515625, 0.5390625 , 0.54296875,
       0.546875  , 0.55078125, 0.5546875 , 0.55859375, 0.5625    ,
       0.56640625, 0.5703125 , 0.57421875, 0.578125  , 0.58203125,
       0.5859375 , 0.58984375, 0.59375   , 0.59765625, 0.6015625 ,
       0.60546875, 0.609375  , 0.61328125, 0.6171875 , 0.62109375,
       0.625     , 0.62890625, 0.6328125 , 0.63671875, 0.640625  ,
       0.64453125, 0.6484375 , 0.65234375, 0.65625   , 0.66015625,
       0.6640625 , 0.66796875, 0.671875  , 0.67578125, 0.6796875 ,
       0.68359375, 0.6875    , 0.69140625, 0.6953125 , 0.69921875,
       0.703125  , 0.70703125, 0.7109375 , 0.71484375, 0.71875   ,
       0.72265625, 0.7265625 , 0.73046875, 0.734375  , 0.73828125,
       0.7421875 , 0.74609375, 0.75      , 0.75390625, 0.7578125 ,
       0.76171875, 0.765625  , 0.76953125, 0.7734375 , 0.77734375,
       0.78125   , 0.78515625, 0.7890625 , 0.79296875, 0.796875  ,
       0.80078125, 0.8046875 , 0.80859375, 0.8125    , 0.81640625,
       0.8203125 , 0.82421875, 0.828125  , 0.83203125, 0.8359375 ,
       0.83984375, 0.84375   , 0.84765625, 0.8515625 , 0.85546875,
       0.859375  , 0.86328125, 0.8671875 , 0.87109375, 0.875     ,
       0.87890625, 0.8828125 , 0.88671875, 0.890625  , 0.89453125,
       0.8984375 , 0.90234375, 0.90625   , 0.91015625, 0.9140625 ,
       0.91796875, 0.921875  , 0.92578125, 0.9296875 , 0.93359375,
       0.9375    , 0.94140625, 0.9453125 , 0.94921875, 0.953125  ,
       0.95703125, 0.9609375 , 0.96484375, 0.96875   , 0.97265625,
       0.9765625 , 0.98046875, 0.984375  , 0.98828125, 0.9921875 ,
       0.99609375, 1.        ]), <BarContainer object of 256 artists>)

대부분의 경우 이미지의 "흥미로운" 부분은 피크 주변에 있으며 피크 위 및/또는 아래 영역을 클리핑하여 추가 대비를 얻을 수 있습니다. 히스토그램에서 하이엔드에 유용한 정보가 많지 않은 것처럼 보입니다(이미지에 흰색이 많지 않음). 히스토그램의 일부를 효과적으로 "확대"할 수 있도록 상한을 조정해 보겠습니다. imshow에 clim 인수를 전달하여 이를 수행합니다. 이미지 플롯 개체의 메서드를 호출하여 이 작업을 수행할 수도 set_clim()있지만 Jupyter Notebook으로 작업할 때 플롯 명령과 동일한 셀에서 수행해야 합니다. 이전 셀의 플롯은 변경되지 않습니다.

에 대한 호출에서 clim을 지정할 수 있습니다 plot.

imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))
이미지

반환된 객체를 사용하여 clim을 지정할 수도 있습니다.

fig = plt.figure()
ax = fig.add_subplot(1, 2, 1)
imgplot = plt.imshow(lum_img)
ax.set_title('Before')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
ax = fig.add_subplot(1, 2, 2)
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0.0, 0.7)
ax.set_title('After')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
전 후
<matplotlib.colorbar.Colorbar object at 0x7f2cdf75fa30>

배열 보간 방식 #

보간법은 다양한 수학적 체계에 따라 픽셀의 색상 또는 값이 "해야 하는" 값을 계산합니다. 이런 일이 자주 발생하는 곳 중 하나는 이미지 크기를 조정할 때입니다. 픽셀 수는 변경되지만 동일한 정보를 원합니다. 픽셀이 불연속적이기 때문에 누락된 공간이 있습니다. 보간은 그 공간을 채우는 방법입니다. 이것이 이미지를 확대할 때 때때로 픽셀화된 것처럼 보이는 이유입니다. 원본 이미지와 확장 이미지의 차이가 클수록 효과가 더 두드러집니다. 이미지를 가져와서 축소해 봅시다. 선택된 몇 개만 유지하면서 효과적으로 픽셀을 폐기하고 있습니다. 이제 그래프를 그릴 때 해당 데이터가 화면 크기만큼 커집니다. 이전 픽셀은 더 이상 존재하지 않으며 컴퓨터는 해당 공간을 채우기 위해 픽셀을 그려야 합니다.

이미지를 로드하는 데 사용한 Pillow 라이브러리를 사용하여 이미지 크기를 조정합니다.

from PIL import Image

img = Image.open('../../doc/_static/stinkbug.png')
img.thumbnail((64, 64))  # resizes image in-place
imgplot = plt.imshow(img)
이미지

imshow()보간 인수 를 제공하지 않았기 때문에 기본 보간법인 bilinear가 있습니다.

다른 것을 시도해 봅시다. 보간을 수행하지 않는 "가장 가까운"이 있습니다.

imgplot = plt.imshow(img, interpolation="nearest")
이미지

쌍입방:

imgplot = plt.imshow(img, interpolation="bicubic")
이미지

Bicubic interpolation은 사진을 확대할 때 자주 사용됩니다. 사람들은 픽셀화된 것보다 흐릿한 것을 선호하는 경향이 있습니다.

스크립트의 총 실행 시간: (0분 8.344초)

Sphinx-Gallery에서 생성한 갤러리