Lem*_*hat 1 python opencv pytorch
为了加速我过去的一些 opencv/numpy 支持的操作,我尝试将它们转换为 PyTorch,以便在 GPU 上运行。其中第一个步骤是将 RGB 转换为 LAB。
我提到:
我已经成功地生成了这段代码:
import torch
def tensor_like(source_data, target_tensor):
return torch.tensor(
source_data,
device=target_tensor.device,
dtype=target_tensor.dtype,
)
RGB_TO_XYZ_FACTOR_MATRIX = [
[0.412453, 0.357580, 0.180423],
[0.212671, 0.715160, 0.072169],
[0.019334, 0.119193, 0.950227],
]
def cie_f(input_: torch.Tensor):
e = 6 / 29
return torch.where(
input_ > e ** 3,
input_ ** (1 / 3),
input_ / (3 * e ** 2) + 4 / 29,
)
def tensor_rgb_to_lab(input_: torch.Tensor):
# input_ is expected to be RGB 0-255, and of shape B, C, H, W
# Implemented based on formulas written here (may need to scroll down):
# https://docs.opencv.org/4.x/de/d25/imgproc_color_conversions.html
dtype = input_.dtype
if not torch.is_floating_point(input_):
input_ = input_.float()
input_ = input_.permute(0, 2, 3, 1)
rgb_colors = input_.reshape(-1, 3)
rgb_colors /= 255.0
# RGB -> XYZ
factor_matrix = tensor_like(RGB_TO_XYZ_FACTOR_MATRIX, rgb_colors)
xyz_colors = torch.mm(rgb_colors, factor_matrix.T)
# xyz_colors.mul_(255)
# XYZ -> LAB
xyz_colors *= tensor_like([1 / 0.950456, 1.0, 1 / 1.088754], xyz_colors)
f_xyz_colors = cie_f(xyz_colors)
fxyz_to_lab_factor_matrix = tensor_like([
[0.0, 500.0, 0.0],
[116.0, -500.0, 200.0],
[0.0, 0.0, -200.0],
], f_xyz_colors)
lab_colors = torch.mm(f_xyz_colors, fxyz_to_lab_factor_matrix)
lab_colors += tensor_like([-16, 128, 128], lab_colors)
lab_colors[:, 0] *= 255 / 100
lab_colors = lab_colors.view_as(input_).permute(0, 3, 1, 2)
lab_colors = lab_colors.round_().clamp_(0, 255).type(dtype)
return lab_colors
Run Code Online (Sandbox Code Playgroud)
将我的输出与 进行比较时cv2.cvtColor(image, cv2.COLOR_RGB2LAB),我的代码确实产生了正确的 RGB 颜色结果,例如 (000, 000, 000)、(255, 255, 255)、(000, 255, 255)、(255, 000, 255), ( 255, 255, 000), (255, 000, 000), (000, 255, 000), (000, 000, 255),但它在许多其他情况下失败(根据我的说法,超过 99% 的 RGB 颜色)测试)。
其中一种失败的情况是 RGB(128, 128, 128),open-cv 表示它对应于 Lab(137, 128, 128),但我的代码指示 Lab(194, 128, 128)。这是一个有趣的失败案例,因为只有 1 个值是错误的,我只能手动执行 L 公式的不同步骤,以尝试隔离问题:
g = np.array((0.412453+0.357580+0.180423, 0.212671+0.715160+0.072169,0.019334+0.119193+0.950227)) * 128/255
g[0]/=0.950456
g[2]/=1.088754
# g => array([0.50196078, 0.50196078, 0.50196078]). Makes sense since 128/255=0.50196078
l = 116*g[1]**(1/3)-16 # since 0.50196078>0.008856
# l => 76.18945600835188 This is already wrong according to online RGB converters
l *= 255/100
# l => 194.2831128212973 This contradicts opencv's value and correlates with mine
Run Code Online (Sandbox Code Playgroud)
在对我的代码进行四重检查之后,我开始认为 opencv 的代码中可能存在错误/舍入错误,或者他们正在执行与文档中所述不同的额外步骤。所以我查找了一些在线RGB到Lab转换器(1和2),在将输出L值重新调整到255范围后,它们与opencv一致。我想这确实表明了我的错误(除非网站内部依赖 opencv?)。
考虑到 RGB 值 0 和 255(或缩放到 0..1 时的 0 和 1)的结果如何正确,我认为所有 ax+b 操作都必须正确,并且一定是t**(1/3)问题所在。 ..行业是否可能出于性能优势而以某种方式使用不同的指数?
我在这里缺少什么?我使用的是opencv 4.4.0.46
| 归档时间: |
|
| 查看次数: |
1959 次 |
| 最近记录: |