python - 如何有效地将函数应用于图像中每个像素的每个 channel (用于颜色转换)?

标签 python algorithm numpy opencv image-processing

我正在尝试实现 Reinhard 的方法,以使用目标图像的颜色分布对研究项目中传入的图像进行颜色标准化。我已经让代码工作并且它输出正确但是它很慢。迭代 300 张图像大约需要 20 分钟。我很确定瓶颈是我如何处理将函数应用于每个图像。我目前正在遍历图像的每个像素并将以下函数应用于每个 channel 。

def reinhard(target, img):

    #converts image and target from BGR colorspace to l alpha beta
    lAB_img = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
    lAB_tar = cv2.cvtColor(target, cv2.COLOR_BGR2Lab)

    #finds mean and standard deviation for each color channel across the entire image
    (mean, std) = cv2.meanStdDev(lAB_img)
    (mean_tar, std_tar) = cv2.meanStdDev(lAB_tar)

    #iterates over image implementing formula to map color normalized pixels to target image
    for y in range(512):
        for x in range(512):
            lAB_tar[x, y, 0] = (lAB_img[x, y, 0] - mean[0]) / std[0] * std_tar[0] + mean_tar[0]
            lAB_tar[x, y, 1] = (lAB_img[x, y, 1] - mean[1]) / std[1] * std_tar[1] + mean_tar[1]
            lAB_tar[x, y, 2] = (lAB_img[x, y, 2] - mean[2]) / std[2] * std_tar[2] + mean_tar[2]
    mapped = cv2.cvtColor(lAB_tar, cv2.COLOR_Lab2BGR)
    return mapped

我的主管告诉我,我可以尝试使用矩阵一次应用所有函数以改进运行时间,但我不确定如何去做。

最佳答案

原文与译文:

enter image description here enter image description here

使用 Reinhard 方法在 5 毫秒 内获得颜色转移结果:

enter image description here enter image description here


除了 python 循环,我更喜欢在 numpy 向量化操作 中实现该公式。

# implementing the formula
#(Io - mo)/so*st + mt  = Io * (st/so) + mt - mo*(st/so)
ratio = (std_tar/std_ori).reshape(-1)
offset = (mean_tar - mean_ori*std_tar/std_ori).reshape(-1)
lab_tar = cv2.convertScaleAbs(lab_ori*ratio + offset)

代码如下:

# 2019/02/19 by knight-金
# https://stackoverflow.com/a/54757659/3547485

import numpy as np
import cv2

def reinhard(target, original):
    # cvtColor: COLOR_BGR2Lab
    lab_tar = cv2.cvtColor(target, cv2.COLOR_BGR2Lab)
    lab_ori = cv2.cvtColor(original, cv2.COLOR_BGR2Lab)

    # meanStdDev: calculate mean and stadard deviation
    mean_tar, std_tar = cv2.meanStdDev(lab_tar)
    mean_ori, std_ori = cv2.meanStdDev(lab_ori)

    # implementing the formula
    #(Io - mo)/so*st + mt  = Io * (st/so) + mt - mo*(st/so)
    ratio = (std_tar/std_ori).reshape(-1)
    offset = (mean_tar - mean_ori*std_tar/std_ori).reshape(-1)
    lab_tar = cv2.convertScaleAbs(lab_ori*ratio + offset)

    # convert back
    mapped = cv2.cvtColor(lab_tar, cv2.COLOR_Lab2BGR)
    return mapped

if __name__ == "__main__":
    ori = cv2.imread("ori.png")
    tar = cv2.imread("tar.png")

    mapped = reinhard(tar, ori)
    cv2.imwrite("mapped.png", mapped)

    mapped_inv = reinhard(ori, tar)
    cv2.imwrite("mapped_inv.png", mapped)

关于python - 如何有效地将函数应用于图像中每个像素的每个 channel (用于颜色转换)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54752325/

相关文章:

python - 如何安装 'glob'模块?

python - 打印到作为后台进程运行的文件 python 脚本

python - 如何将参数传递给 Python 中的回调函数?

algorithm - Dijkstra 银行家算法

algorithm - 计算二值图像中对象的长度 - 算法

python - 对于具有排序、浮点索引和列的 DataFrame,根据 DataFrame 值使用线性插值计算值

Python-夏娃 : More than one additional lookup

java - 如何将具有给定索引的新元素添加到链表中?

python - np 数组是不可变的 - "assignment destination is read-only"

python - 求解器 'CPLEX' 在 CVXPY 中失败