HSI образ неправильно выровнен в Python - PullRequest
0 голосов
/ 24 октября 2019

Я реализовал выравнивание для цветных изображений HSI. Я использовал numpy и математические модули.

Сначала я конвертирую RGB-изображение в HSI, используя следующие функции:

import math
import numpy as np

def rgb2hsi_px(px):
    eps = 0.00000001

    r, g, b = float(px[0]) / 255, float(px[1]) / 255, float(px[2]) / 255

    # Hue component
    numerator = 0.5 * ((r - g) + (r - b))
    denominator = math.sqrt((r - g) ** 2 + (r - b) * (g - b))
    theta = math.acos(numerator / (denominator + eps))
    h = theta
    if b > g:
        h = 2 * math.pi - h

    # Saturation component
    num = min(r, g, b)
    den = r + g + b
    if den == 0:
        den = eps
    s = 1 - 3 * num / den
    if s == 0:
        h = 0

    # Intensity component
    i = (r + g + b) / 3

    return h, s, i


def rgb2hsi(image):
    hsi_image = np.zeros_like(image).astype('float')
    height, width, _ = image.shape
    for x in range(height):
        for y in range(width):
            px = rgb2hsi_px(image[x, y])
            hsi_image[x, y] = px
    return np.array(hsi_image)

Затем я выравниваю значение интенсивности преобразованного изображения. Функция equalize была реализована с использованием этой статьи :

import math
import numpy as np

def equalize(img):
    eps = 0.000000000001
    h, w, _ = img.shape
    num_of_pxs = h * w
    mean = 0.0
    new_img = np.array(img)
    while not abs(mean - 0.5) < eps:
        for i in range(h):
            for j in range(w):
                mean += new_img[i, j, 2]
        mean /= num_of_pxs
        if mean != 0.5:
            theta = math.log(0.5, math.e) / math.log(mean, math.e)
            for x in range(h):
                for y in range(w):
                    px = list(new_img[x, y])
                    px[2] = (px[2] ** theta)
                    new_img[x, y] = px
    return new_img

После этого я преобразую изображение HSI обратно в RGB, используя следующий код:

import math
import numpy as np

def hsi2rgb_px(px):
    h, s, i = float(px[0]), float(px[1]), float(px[2]) * 255
    if 0 <= h < 2 * math.pi / 3:
        b = i * (1 - s)
        r = i * (1 + (s * math.cos(h)) / math.cos(math.pi / 3 - h))
        g = 3 * i - (r + b)
    elif 2 * math.pi / 3 <= h < 4 * math.pi / 3:
        r = i * (1 - s)
        g = i * (1 + (s * math.cos(h - 2 * math.pi / 3) / math.cos(math.pi / 3 - (h - 2 * math.pi / 3))))
        b = 3 * i - (r + g)
    elif 4 * math.pi / 3 <= h <= 2 * math.pi:
        g = i * (1 - s)
        b = i * (1 + (s * math.cos(h - 4 * math.pi / 3) / math.cos(math.pi / 3 - (h - 4 * math.pi / 3))))
        r = 3 * i - (g + b)
    else:
        raise IndexError('h is out of range: {}'.format(h))
    return round(r), round(g), round(b)


def hsi2rgb(image):
    rgb_image = np.zeros_like(image).astype(np.uint8)
    height, width, _ = image.shape
    for x in range(height):
        for y in range(width):
            px = hsi2rgb_px(image[x, y])
            rgb_image[x, y] = px
    return np.array(rgb_image)

Ноуравнение дает неверный результат. Размер выровненного изображения (в мегабайтах) больше исходного. Я не уверен, нормально ли это, но если да, пожалуйста, дайте мне знать. И еще одна проблема заключается в том, что выходное изображение имеет худшее качество.

Вот оригинальное изображение:

enter image description here

И выровненное изображение:

enter image description here

Может ли кто-нибудь помочь мне исправить мой код или дать ссылку на аналогичную статью / вопрос?

[ОБНОВЛЕНИЕ]

Программа драйвера для проверки алгоритма:

import matplotlib.image as mp_img

input_img = mp_img.imread('input.bmp')

hsi_img = rgb2hsi(input_img)
equalized_img = equalize(hsi_img)
out_img = hsi2rgb(equalized_img)

mp_img.imsave('out.bmp', out_img)
...