Python实现RGB和Lab颜色空间互转

版权声明:authored by zzubqh https://blog.csdn.net/qq_36810544/article/details/83855962

在网上找了一圈,只找到C++版本的,有个python版本的只有RGB转Lab,只好自己写了。C++版本传送门,这里把原理已经写的很清楚了,我只是比葫芦画瓢的写个python版本,没做任何优化。只有一点需要小心,opencv读取的图像格式是[b,g,r],剩下的就是按公式写代码了。

# -*- coding: utf-8 -*-
# 提供图像处理辅助函数,色彩空间转换
# @Author  : BQH
# @File    : tools.py
# @Date    : 2018-11-07

import numpy as np
import cv2


# region 辅助函数
# RGB2XYZ空间的系数矩阵
M = np.array([[0.412453, 0.357580, 0.180423],
              [0.212671, 0.715160, 0.072169],
              [0.019334, 0.119193, 0.950227]])


# im_channel取值范围:[0,1]
def f(im_channel):
    return np.power(im_channel, 1 / 3) if im_channel > 0.008856 else 7.787 * im_channel + 0.137931


def anti_f(im_channel):
    return np.power(im_channel, 3) if im_channel > 0.206893 else (im_channel - 0.137931) / 7.787
# endregion


# region RGB 转 Lab
# 像素值RGB转XYZ空间,pixel格式:(B,G,R)
# 返回XYZ空间下的值
def __rgb2xyz__(pixel):
    b, g, r = pixel[0], pixel[1], pixel[2]
    rgb = np.array([r, g, b])
    # rgb = rgb / 255.0
    # RGB = np.array([gamma(c) for c in rgb])
    XYZ = np.dot(M, rgb.T)
    XYZ = XYZ / 255.0
    return (XYZ[0] / 0.95047, XYZ[1] / 1.0, XYZ[2] / 1.08883)


def __xyz2lab__(xyz):
    """
    XYZ空间转Lab空间
    :param xyz: 像素xyz空间下的值
    :return: 返回Lab空间下的值
    """
    F_XYZ = [f(x) for x in xyz]
    L = 116 * F_XYZ[1] - 16 if xyz[1] > 0.008856 else 903.3 * xyz[1]
    a = 500 * (F_XYZ[0] - F_XYZ[1])
    b = 200 * (F_XYZ[1] - F_XYZ[2])
    return (L, a, b)


def RGB2Lab(pixel):
    """
    RGB空间转Lab空间
    :param pixel: RGB空间像素值,格式:[G,B,R]
    :return: 返回Lab空间下的值
    """
    xyz = __rgb2xyz__(pixel)
    Lab = __xyz2lab__(xyz)
    return Lab


# endregion

# region Lab 转 RGB
def __lab2xyz__(Lab):
    fY = (Lab[0] + 16.0) / 116.0
    fX = Lab[1] / 500.0 + fY
    fZ = fY - Lab[2] / 200.0

    x = anti_f(fX)
    y = anti_f(fY)
    z = anti_f(fZ)

    x = x * 0.95047
    y = y * 1.0
    z = z * 1.0883

    return (x, y, z)


def __xyz2rgb(xyz):
    xyz = np.array(xyz)
    xyz = xyz * 255
    rgb = np.dot(np.linalg.inv(M), xyz.T)
    # rgb = rgb * 255
    rgb = np.uint8(np.clip(rgb, 0, 255))
    return rgb


def Lab2RGB(Lab):
    xyz = __lab2xyz__(Lab)
    rgb = __xyz2rgb(xyz)
    return rgb
# endregion

if __name__ == '__main__':
    img = cv2.imread(r'E:\code\collor_recorrect\test_1.jpg')
    w = img.shape[0]
    h = img.shape[1]
    img_new = np.zeros((w,h,3))
    lab = np.zeros((w,h,3))
    for i in range(w):
        for j in range(h):
            Lab = RGB2Lab(img[i,j])
            lab[i, j] = (Lab[0], Lab[1], Lab[2])

    for i in range(w):
        for j in range(h):
            rgb = Lab2RGB(lab[i,j])
            img_new[i, j] = (rgb[2], rgb[1], rgb[0])

	cv2.imwrite(r'E:\code\collor_recorrect\test.jpg', img_new)

原图:
在这里插入图片描述

经过RGB->XYZ->Lab->XYZ->RGB后的图像:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_36810544/article/details/83855962