библиотека обработки изображений Python PIL (2)

Python

Как и в предыдущей статье «Библиотека классов обработки изображений Python PIL (1)», в этой статье по-прежнему используется изображение dog.jpeg в качестве примера для демонстрации интерфейса экземпляра модуля PIL Image.

1. Импортируйте модуль Image и откройте изображение dog.jpeg.

from PIL import Image

image = Image.open("dog.jpeg")

dog.jpeg 可将此图保存到电脑,以运行本文的代码

2. Чтение свойств изображения

2.1 Размеры ширины и высоты (в пикселях)

width, height = image.size

print("width: {} pixels\nheight: {} pixels".format(width, height))
width: 320 pixels
height: 320 pixels

2.2 Цветовой режим

mode = image.mode

print("color mode: ", mode)
color mode:  RGB

2.3 Формат хранения

format = image.format

print("image format: ", format)
image format:  JPEG

2.4 Метаинформация

image.info
{'dpi': (72, 72),
 'exif': b'Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x05\x01\x12\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\x01\x1a\x00\x05\x00\x00\x00\x01\x00\x00\x00J\x01\x1b\x00\x05\x00\x00\x00\x01\x00\x00\x00R\x01(\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00\x87i\x00\x04\x00\x00\x00\x01\x00\x00\x00Z\x00\x00\x00\x00\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00H\x00\x00\x00\x01\x00\x03\xa0\x01\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00\xa0\x02\x00\x04\x00\x00\x00\x01\x00\x00\x01@\xa0\x03\x00\x04\x00\x00\x00\x01\x00\x00\x01@\x00\x00\x00\x00',
 'jfif': 257,
 'jfif_density': (72, 72),
 'jfif_unit': 0,
 'jfif_version': (1, 1),
 'parsed_exif': {274: 1,
  282: (72, 1),
  283: (72, 1),
  296: 2,
  34665: 90,
  40961: 1,
  40962: 320,
  40963: 320},
 'photoshop': {1028: b'',
  1061: b'\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\t\x98\xec\xf8B~'}}

3. Чтение данных изображения

3.1 load()

Возвращает объект доступа к пикселю. Объект доступа к пикселям ведет себя так же, как двумерный массив, а доступ к значениям пикселей и их изменение можно получить с помощью методов индексации [x, y]. Обычно нам не нужно вызывать этот метод, класс Image автоматически вызывает этот метод при первом доступе к данным изображения.

ps: Image.open() — ленивая операция.Перед вызовом load() или других методов доступа к данным он не считывает данные изображения, а только считывает информацию об атрибутах изображения.

pix = image.load()

x = image.size[0] // 2
y = image.size[1] // 2

pixdata = pix[x, y]

print("pixel at ({},{}) is {}.".format(x, y, pixdata))
pixel at (160,160) is (184, 171, 155).

3.2 getdata()

Возвращает сериализованный объект данных изображения. В отличие от метода load() возвращаемый сериализованный объект ведет себя как одномерный массив. То есть за первой строкой изображения следует вторая строка данных. в состоянии пройтиlist(image.getdata())Превратите его в обычный список.

image_data = image.getdata()

if len(image_data) == image.size[0] * image.size[1]:
    print("length of image.getdata() is equal to the total number of pixels.")

print("pixel data from 318 to 322 is ", list(image_data)[318:322])
length of image.getdata() is equal to the total number of pixels.
pixel data from 318 to 322 is  [(144, 90, 44), (144, 90, 44), (130, 78, 38), (130, 78, 38)]

Во многих случаях мы хотим получить данные изображения в виде двумерного массива, что требует от нас самостоятельно преобразовать сериализованный объект, возвращаемый функцией getdata(), в двумерный массив или список.

Ниже представлены три метода, при этом для сравнения эффективности выполнения каждого метода распечатывается время, затраченное на процесс преобразования.

3.2.1 Прямой обход сериализованного объекта для создания двумерного списка

from time import time

w, h = image.size

start_time = time()

image_data_2d_1 = []
row = 0
for i, pixdata in enumerate(image_data):
    if i % w == 0:
        image_data_2d_1.append([])
        row = i // w
    image_data_2d_1[row].append(pixdata)

print("cost time: {} ms".format((time()-start_time)*1000))
cost time: 47.84393310546875 ms

3.2.2 Использование срезов списка для создания двумерных списков

Сериализованный объект, возвращаемый getdata(), поддерживает только целые индексы и не поддерживает нарезанный доступ к элементам, поэтому вам нужно использовать list() для преобразования в список.

start_time = time()

image_data_list = list(image_data)
image_data_2d_2 = [image_data_list[w*i:w*(i+1)] for i in range(h)]

print("cost time: {} ms".format((time()-start_time)*1000))
cost time: 18.110036849975586 ms

3.2.3 Использование numpy.array() для создания двумерного массива

numpy.array() может напрямую преобразовывать объекты изображений PIL без вызова метода getdata().

import numpy as np

start_time = time()

image_data_2d_3 = np.array(image)

print("cost time: {} ms".format((time()-start_time)*1000))
cost time: 0.6780624389648438 ms

Для сравнения, время, затрачиваемое тремя методами преобразованияПрямой обход> Нарезка списка> numpy. Поэтому используйтеnumpyЭффективность преобразования самая высокая. без импортаnumpyситуация, предпочтительное использованиечасть спискаспособ преобразования двумерного списка.

3 split(): отдельные цветовые каналы

Возвращает кортеж объектов Image. Элементами кортежа являются одноканальные изображения, разделенные каждым цветовым каналом. Например, для изображения RGB возвращается изображение R, G и B через соответствующее изображение в градациях серого.

R, G, B = image.split()
R.show()
G.show()
B.show()

портал


Нелегко настаивать на написании колонки. Если вы считаете, что эта статья полезна для вас, не забудьте поставить лайк. Спасибо за поддержку!


Отсканируйте QR-код в WeChat, чтобы получить оригиналы новейших технологий