Главная » 2025 » Ноябрь » 30 » Класс UImage: получение информации об объекте изображения
20:01
Класс UImage: получение информации об объекте изображения

Класс UImage: получение информации об объекте изображения

Получить информацию об объекте изображения позволяют следующие методы::

  • get_width() и get_height() — возвращают ширину и высоту соответственно. Пример:
from unicross_image.ucolor import UColor
from unicross_image.uimage import UImage

img = UImage(300, 200, UColor(255, 0, 0, 128))
w = img.get_width()
h = img.get_height()
print(w, h) # 300 200
  • get_size() —  возвращает объект USize с размерами изображения. Пример:
s = img.get_size()
print(s)                # USize(width=300, height=200)
w = s.get_width()
h = s.get_height()
print(w, h)             # 300 200
w, h = img.get_size()
print(w, h)             # 300 200
  • get_rect() — возвращает объект URect с координатами и размерами изображения. Пример:
r = img.get_rect()
print(r)       # URect(x=0, y=0, width=300, height=200)
x = r.get_x()
y = r.get_y()
w = r.get_width()
h = r.get_height()
print(x, y, w, h)             # 0 0 300 200
x, y, w, h = img.get_rect()
print(x, y, w, h)             # 0 0 300 200
  • get_num_channels() — возвращает число каналов. Пример:
print(img.get_num_channels()) # 4
  • get_img_mode() — возвращает режим изображения в виде строки. Пример:
print(img.get_img_mode()) # RGBA
  • get_mat_type() — возвращает тип матрицы (значение UMat.Type_8U). Пример:
print(img.get_mat_type()) # 1
  • get_arr_len() — возвращает количество элементов списка arr, в котором хранится изображение. При этом вычисление размера списка не производится. Размер списка вычисляется только при создании объекта изображения и при вызове метода update_arr_len(). Если объект не является валидным, то значение, возвращаемое методом, будет неправильным. Пример:
print(img.get_arr_len()) # 240000
print(len(img.arr))      # 240000
  • update_arr_len() — обновляет информацию о размере списка с изображением. Ничего не возвращает;
  • is_valid() — возвращает значение True, если объект изображения является валидным, и False — в противном случае. Проверяется соответствие размеров изображения и числа каналов размеру списка. Содержимое списка не проверяется. Пример:
img = UImage(300, 200, UColor(255, 0, 0, 128))
print(img.is_valid())      # True
img2 = UImage(3, 2, create_arr=False)
print(img2.arr)            # []
print(img2.get_arr_len())  # 0

img2.arr = [255] * 24      # Добавляем существующий список
print(img2.is_valid())     # False
img2.update_arr_len()      # Обновление данных
print(img2.is_valid())     # True
print(img2.get_arr_len())  # 24
  • is_transparent() — возвращает значение True, если объект изображения содержит прозрачные пиксели, и False — в противном случае. Пример:
img = UImage(300, 200, UColor(255, 0, 0, 128))
print(img.is_transparent())      # True
img2 = UImage(3, 2, UColor(255, 0, 0, 255))
print(img2.is_transparent())     # False

Получение и изменение пикселей изображения

Получить или изменить значений пикселей изображения позволяют следующие методы:

  • fill(<UColor>) — заливает все изображение заданным цветом. В качестве параметра указывается объект UColor. В результате выполнения операции создается новый список, который заменит старый список. Метод возвращает значение True, если операция выполнена успешно, и False — в противном случае. Пример:
from unicross_image.ucolor import UColor
from unicross_image.uimage import UImage

img = UImage(3, 2)
print(img.fill(UColor(255, 0, 0, 128)))      # True
print(img.arr)
# [255, 0, 0, 128,   255, 0, 0, 128,   255, 0, 0, 128,
#  255, 0, 0, 128,   255, 0, 0, 128,   255, 0, 0, 128]
  • get_pixel(x, y) — возвращает кортеж из 4-х элементов (r, g, b, a) для пикселя, расположенного по координатам x и y. Валидность объекта не проверяется. Если координаты находятся вне пределов изображения, то метод вернет значение None. Пример:
print(img.get_pixel(0, 0))   # (255, 0, 0, 128)
print(img.get_pixel(10, -1)) # None
  • get_pixel_ucolor(x, y) — возвращает объект UColor с характеристиками цвета  для пикселя, расположенного по координатам x и y. Валидность объекта не проверяется. Если координаты находятся вне пределов изображения, то метод вернет значение None. Пример:
print(img.get_pixel_ucolor(0, 0))
# UColor(red=255, green=0, blue=0, opacity=128)
print(img.get_pixel_ucolor(10, -1))
# None
  • set_pixel(x, y, r, g, b, a) — изменяет цвет пикселя, расположенного по координатам x и y. Валидность объекта и диапазоны значений для компонентов цвета не проверяются. Если операция выполнена успешно, то метод вернет значение True. Если координаты находятся вне пределов изображения, то метод вернет значение False. Пример:
print(img.set_pixel(0, 0, 128, 255, 0, 255)) # True
print(img.get_pixel(0, 0))      # (128, 255, 0, 255)
print(img.set_pixel(10, -1, 0, 0, 0, 255))   # False
# Диапазоны значений не проверяются!
print(img.set_pixel(0, 0, -1, 256, 300, 0)) # True
print(img.get_pixel(0, 0))      # (-1, 256, 300, 0)
  • set_pixel_ucolor(x, y, <UColor>) — изменяет цвет пикселя, расположенного по координатам x и y. Характеристики цвета задаются с помощью объекта UColor. Валидность объекта не проверяется. Если операция выполнена успешно, то метод вернет значение True. Если координаты находятся вне пределов изображения, то метод вернет значение False. Пример:
print(img.set_pixel_ucolor(0, 0, UColor(128, 255, 0, 255)))
# True
print(img.get_pixel(0, 0))
# (128, 255, 0, 255)
print(img.set_pixel_ucolor(10, -1, UColor(0, 0, 0, 255)))
# False

В основе объекта изображения лежит одномерный список, доступный через атрибут arr. Размер списка вычисляется следующим образом:

arr_len = width * height * num_channels

Строки двумерной матрицы записываются в список слева направо и сверху вниз. Каждый пиксель описывается 4-я элементами в последовательности RGBA. Давайте зальем все изображение прозрачным цветом с помощью метода set_pixel() и измерим время выполнения:

import time
from unicross_image.uimage import UImage

img = UImage(3000, 2000)

d_start = time.time()
r, g, b, a = 0, 0, 0, 0
for y in range(img.get_height()):
    for x in range(img.get_width()):
        img.set_pixel(x, y, r, g, b, a)
print(time.time() - d_start) # 8.520143985748291

Этот код с синтаксической точки зрения абсолютно верный. Однако он содержит огромную проблему. Код абсолютно неэффективный! Если мы заменим метод set_pixel() методом set_pixel_ucolor(), то эффективность еще уменьшится в несколько раз. Проблема кроется в огромном количестве лишних действий и проверок. Посмотрите на результат. Время выполнения составляет почти 9 секунд. Катастрофа!

Чтобы повысить эффективность, нужно обращаться к пикселям напрямую через атрибут arr. При этом обращаться к списку следует не через объект изображения, а через ссылку, предварительно сохраненную в переменной. Вычисление положения элемента внутри списка arr, при известных координатах x и y, производится по следующей формуле:

i = x * num_channels + y * width * num_channels

Переделаем наш предыдущий пример:

import time
from unicross_image.uimage import UImage

img = UImage(3000, 2000)

d_start = time.time()
r, g, b, a = 0, 0, 0, 0
img_width = img.get_width()
img_height = img.get_height()
img_num_channels = img.get_num_channels()
img_line = img_width * img_num_channels
img_arr = img.arr
for y in range(img_height):
    for x in range(img_height):
        i = x * img_num_channels + y * img_line
        img_arr[i] = r
        img_arr[i + 1] = g
        img_arr[i + 2] = b
        img_arr[i + 3] = a
print(time.time() - d_start) # 2.805180549621582

Время выполнения сократилось почти в три раза! Учитывая, что положение пикселя по осям X и Y в этой задаче нам не нужно, будем работать с одномерным списком:

import time
from unicross_image.uimage import UImage

img = UImage(3000, 2000)

d_start = time.time()
r, g, b, a = 0, 0, 0, 0
img_arr_len = img.get_arr_len()
img_num_channels = img.get_num_channels()
img_arr = img.arr
for i in range(0, img_arr_len, img_num_channels):
    img_arr[i] = r
    img_arr[i + 1] = g
    img_arr[i + 2] = b
    img_arr[i + 3] = a
print(time.time() - d_start) # 2.6563830375671387

Выиграли еще несколько десятых секунды. Мы можем лучше! В нашей задаче одно значение должно заполнить весь список. Для этого перебирать все значения списка не нужно, достаточно создать список заново средствами языка Python:

import time
from unicross_image.uimage import UImage

img = UImage(3000, 2000)

d_start = time.time()
img.arr = [0] * img.get_arr_len()
print(time.time() - d_start) # 0.18751168251037598
print(img.is_valid())        # True

Ну вот, наша задача оказывается решается за две десятых секунды, вместо девяти секунд! Так что, используйте список напрямую и выбирайте способ выполнения в зависимости от задачи!

Заполнить список произвольными значениями можно так:

from unicross_image.uimage import UImage

img = UImage(3, 2)
img.arr = [255, 128, 0, 255] * (img.get_width() * img.get_height())
print(img.is_valid()) # True
print(img.arr)
# [255, 128, 0, 255,   255, 128, 0, 255,   255, 128, 0, 255,
#  255, 128, 0, 255,   255, 128, 0, 255,   255, 128, 0, 255]

Метод fill() выполняет аналогичное действие, поэтому код можно записать так:

from unicross_image.uimage import UImage
from unicross_image.ucolor import UColor

img = UImage(3, 2)
img.fill(UColor(255, 128, 0, 255))
print(img.is_valid()) # True
print(img.arr)
# [255, 128, 0, 255,   255, 128, 0, 255,   255, 128, 0, 255,
#  255, 128, 0, 255,   255, 128, 0, 255,   255, 128, 0, 255]

Нормализация диапазона значений

Значения внутри списка arr должны находиться в диапазоне от 0 до 255. При выполнении различных операций можно выйти за границы этого диапазона. Учитывая, что список в Python может хранить весь диапазон целых чисел, увеличение максимального значения на единицу приведет лишь к числу 256. Если подобную операцию выполнить при использовании массива NumPy с типом uint8, то мы получим число 0, т. е. белый цвет превратится в черный. В Python такой проблемы нет.

Если внутри списка существует хотя бы одно значение вне диапазона от 0 до 255, то сохранить такое изображение или преобразовать его в другой объект не получится. Проверить валидность объекта и целостность диапазона значений позволяет метод is_normal(). Метод возвращает значение True, если объект валидный и список можно преобразовать в массив байтов, и False — в противном случае. Пример:

from unicross_image.uimage import UImage
from unicross_image.ucolor import UColor

img = UImage(3, 2, UColor(255, 128, 0, 255))
print(img.is_normal()) # True
img.arr[0] = 256
img.arr[1] = -1
print(img.arr[:4])     # [256, -1, 0, 255]
print(img.is_normal()) # False

Вернуть значения внутрь диапазона позволяет метод normalize(). Если значение меньше 0, то оно будет заменено значением 0, если значение больше 255, то оно будет заменено значением 255. Метод возвращает значение True, если объект валидный и список можно преобразовать в массив байтов, и False — в противном случае. Пример:

print(img.normalize()) # True
print(img.arr[:4])     # [255, 0, 0, 255]
print(img.is_normal()) # True

Создание копии изображения

Создать копию изображения позволяет метод copy(). Если операция выполнена успешно, то метод вернет копию объекта, а в противном случае — значение None. Пример:

from unicross_image.uimage import UImage
from unicross_image.ucolor import UColor

img = UImage(3, 2, UColor(255, 128, 0, 255))
print(img.arr[:4])     # [255, 128, 0, 255]
img2 = img.copy()
print(img2)            # UImage(width=3, height=2)
print(img2 is img)     # False
img2.arr[0] = 0
print(img2.arr[:4])    # [0, 128, 0, 255]
print(img.arr[:4])     # [255, 128, 0, 255]

Если объект изображения не является валидным, то метод вернет значение None:

img3 = UImage(3, 2, create_arr=False)
img4 = img3.copy()
print(img4)            # None

Если просто присвоить объект другой переменной, то будет скопирована лишь ссылка на объект, а не сам объект:

img2 = img
print(img2)            # UImage(width=3, height=2)
print(img2 is img)     # True
img2.arr[0] = 0
print(img2.arr[:4])    # [0, 128, 0, 255]
print(img.arr[:4])     # [0, 128, 0, 255]

Как видно из результата, изменение списка через один объект, привело к изменению списка в другом объекте. Иными словами, оба объекта ссылаются на один и тот же список.

Сравнение изображений

Сравнить два объекта изображений можно с помощью операторов == и !=.Пример:

from unicross_image.uimage import UImage
from unicross_image.ucolor import UColor

img = UImage(3, 2, UColor(255, 128, 0, 255))
img2 = UImage(3, 2, UColor(255, 128, 0, 255))
img3 = UImage(3, 2, UColor(255, 255, 255, 255))

print(img == img2)     # True
print(img == img3)     # False

print(img != img2)     # False
print(img != img3)     # True

Для проверки, ссылаются ли две переменные на один и тот же объект, нужно использовать оператор is:

img4 = img
print(img is img4)     # True
print(img is img2)     # False

Класс входит в состав графической библиотеки UImage для Python 3. Описание библиотеки UImage

Категория: UImage | Просмотров: 2 | Добавил: unicross | Теги: ImageMagick, Python, UImage, PIL | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Категории раздела
Списки слов [10]
Списки слов и словари
OCR [4]
Оптическое распознавание символов
UImage [18]
Графическая библиотека для Python
Программы [4]
Полезные программы
Прочее [3]
Другие темы
Календарь
«  Ноябрь 2025  »
Пн Вт Ср Чт Пт Сб Вс
     12
3456789
10111213141516
17181920212223
24252627282930
Архив записей