gpt4 book ai didi

python-3.x - 矢量化自定义 RGB -> 灰度转换

转载 作者:行者123 更新时间:2023-12-02 16:13:15 24 4
gpt4 key购买 nike

如标题中所述,我想进行从 RGB 到灰度的非常具体的转换。

我有一堆可能看起来像这样的图像:

enter image description here

我想把它们转换成这样的图像
enter image description here .

现在你可能想知道为什么我不只是使用 opencv 的内置函数。原因是我需要将 RGB 图像的每种颜色映射到灰度中的特定强度值,这并不难,因为我只有六种颜色。

Red, rgb(255,0,0)           ->  25
Brown, rgb(165,42,42) -> 120
Light Blue, rgb(0,255,255) -> 127
Green, rgb(127,255,0) -> 50
Yellow, rgb(255,255,255) -> 159
Purple, rgb(128, 0, 128) -> 90

现在我已经创建了一个数组,其中包含一些包含这些映射的对象,我只是在我的图像上进行迭代以分配新的颜色代码。然而,这是非常缓慢的,我希望在完成所有图像之前长出华丽的 mustache (我也想知道这一点以用于学习目的)。到目前为止,这是我运行速度非常慢的代码和映射对象:
colorMapping = [ColorMapping(RGB=[255, 0, 0], Grayscale=25),
ColorMapping(RGB=[165, 42, 42], Grayscale=120), ... ]

def RGBtoGray(RGBimg, colorMapping):
RGBimg = cv2.cvtColor(RGBimg, cv2.COLOR_BGR2RGB)
row = RGBimg.shape[0]
col = RGBimg.shape[1]
GRAYimg = np.zeros((row, col))
for x in range(0,row):
for y in range(0,col):
pixel = RGBimg[x,y,:]
for cm in colorMapping:
if np.array_equal(pixel, np.array(cm.RGB)):
GRAYimg[x,y] = cm.Grayscale
return GRAYimg

对于使用内置库或改进此代码计算的任何建议,我都很高兴。
颜色图是从 json 文件中读取的,该文件用作自动化步骤,因为我必须至少对两批具有不同编码的图像执行此操作。

最佳答案

方法#1
这是一个基于 1D 的矢量化转型 + np.searchsorted , 灵感来自 this post -

def map_colors(img, colors, vals, invalid_val=0):
s = 256**np.arange(3)
img1D = img.reshape(-1,img.shape[2]).dot(s)
colors1D = colors.reshape(-1,img.shape[2]).dot(s)
sidx = colors1D.argsort()
idx0 = np.searchsorted(colors1D, img1D, sorter=sidx)
idx0[idx0==len(sidx)] = 0
mapped_idx = sidx[idx0]
valid = colors1D[mapped_idx] == img1D
return np.where(valid, vals[mapped_idx], invalid_val).reshape(img.shape[:2])
sample 运行 -
# Mapping colors array
In [197]: colors
Out[197]:
array([[255, 0, 0],
[165, 42, 42],
[ 0, 255, 255],
[127, 255, 0],
[255, 255, 255],
[128, 0, 128]])

# Mapping values array
In [198]: vals
Out[198]: array([ 25, 120, 127, 50, 155, 90])

# Input 3D image array
In [199]: img
Out[199]:
array([[[255, 255, 255],
[128, 0, 128],
[255, 0, 0],
[127, 255, 0]],

[[127, 255, 0],
[127, 255, 0],
[165, 42, 42],
[ 0, 0, 0]]]) # <= one color absent in mappings

# Output
In [200]: map_colors(img, colors, vals, invalid_val=0)
Out[200]:
array([[155, 90, 25, 50],
[ 50, 50, 120, 0]])
我们可以对映射进行预排序,从而摆脱 searchsorted 所需的排序,这应该会进一步提高性能 -
def map_colors_with_sorting(img, colors, vals, invalid_val=0):
s = 256**np.arange(3)
img1D = img.reshape(-1,img.shape[2]).dot(s)
colors1D = colors.reshape(-1,img.shape[2]).dot(s)
sidx = colors1D.argsort()
colors1D_sorted = colors1D[sidx]
vals_sorted = vals[sidx]

idx0 = np.searchsorted(colors1D_sorted, img1D)
idx0[idx0==len(sidx)] = 0
valid = colors1D_sorted[idx0] == img1D
return np.where(valid, vals_sorted[idx0], invalid_val).reshape(img.shape[:2])

方法#2
我们可以使用一个映射数组,当它被 1D 索引时转换后的颜色会直接将我们带到最终的“灰度”图像,如下所示 -
def map_colors_with_mappingar_solution(img):
# Edit the custom colors and values here
colors = np.array([
[ 0, 0, 255],
[ 42, 42, 165],
[255, 255, 0],
[ 0, 255, 127],
[255, 255, 255],
[128, 0, 128]], dtype=np.uint8) # BGR format
vals = np.array([25, 120, 127, 50, 155, 90], dtype=np.uint8)
return map_colors_with_mappingar(img, colors, vals, 0)

def map_colors_with_mappingar(img, colors, vals, invalid_val=0):
s = 256**np.arange(3)
img1D = img.reshape(-1,img.shape[2]).dot(s)
colors1D = colors.reshape(-1,img.shape[2]).dot(s)

N = colors1D.max()+1
mapar = np.empty(N, dtype=np.uint8)
mapar[colors1D] = vals

mask = np.zeros(N, dtype=bool)
mask[colors1D] = True

valid = img1D < N
valid &= mask[img1D]

out = np.full(len(img1D), invalid_val, dtype=np.uint8)
out[valid] = mapar[img1D[valid]]
return out.reshape(img.shape[:2])
随着您增加自定义颜色的数量,这应该可以很好地扩展。
让我们为给定的示例图像计时 -
# Read in sample image
In [360]: im = cv2.imread('blobs.png')

# @Mark Setchell's solution
In [362]: %timeit remap2(im)
7.45 ms ± 105 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# Method2 from this post
In [363]: %timeit map_colors_with_mappingar_solution(im)
6.76 ms ± 46.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
进一步的表现。助推
更进一步,我们可以以更高效的方式进行一维缩减,从而实现进一步的性能。提升,就像这样 -
# https://stackoverflow.com/a/57236217/ @tstanisl
def scalarize(x):
# compute x[...,2]*65536+x[...,1]*256+x[...,0] in efficient way
y = x[...,2].astype('u4')
y <<= 8
y +=x[...,1]
y <<= 8
y += x[...,0]
return y

def map_colors_with_mappingar(img, colors, vals, invalid_val=0):
img1D = scalarize(img)
colors1D = scalarize(colors)

N = colors1D.max()+1
mapar = np.empty(N, dtype=np.uint8)
mapar[colors1D] = vals

mask = np.zeros(N, dtype=bool)
mask[colors1D] = True

valid = img1D < N
valid &= mask[img1D]

out = np.full(img1D.shape, invalid_val, dtype=np.uint8)
out[valid] = mapar[img1D[valid]]
return out

# On given sample image
In [10]: %timeit map_colors_with_mappingar_solution(im)
5.45 ms ± 143 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

关于python-3.x - 矢量化自定义 RGB -> 灰度转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61596016/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com