Как эффективно применить функцию к каждому каналу каждого пикселя в изображении (для преобразования цвета)? - PullRequest
0 голосов
/ 18 февраля 2019

Я пытаюсь реализовать метод Рейнхарда, чтобы использовать распределение цветов целевого изображения для нормализации цвета переданного изображения для исследовательского проекта.Я получил код для работы, и он выводит правильно, но это довольно медленно.Для перебора 300 изображений требуется около 20 минут.Я уверен, что узким местом является то, как я обращаюсь с применением этой функции к каждому изображению.В настоящее время я перебираю каждый пиксель изображения и применяю приведенные ниже функции к каждому каналу.

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

Мой руководитель сказал мне, что я могу попробовать использовать матрицу дляприменить функцию сразу, чтобы улучшить время выполнения, но я не совсем уверен, как это сделать.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Оригинал и цель :

enter image description here enter image description here

Повтор передачи цветов с использованием метода Рейнхарда в 5 ms:

enter image description here enter image description here


Я предпочитаю реализовать формулу в numpy vectorized operations, отличном от python loops.

# 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)
0 голосов
/ 18 февраля 2019

Мне удалось выяснить это после просмотра нудистской документации.Мне просто нужно было заменить мой вложенный цикл на правильный доступ к массиву.Это заняло менее минуты, чтобы перебрать все 300 изображений с этим.

lAB_tar[:,:,0] = (lAB_img[:,:,0] - mean[0])/std[0] * std_tar[0] + mean_tar[0]
lAB_tar[:,:,1] = (lAB_img[:,:,1] - mean[1])/std[1] * std_tar[1] + mean_tar[1]
lAB_tar[:,:,2] = (lAB_img[:,:,2] - mean[2])/std[2] * std_tar[2] + mean_tar[2]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...