OpenCV:RGB到YUV转换,并显示像Wikipedia这样的通道

z0qdvdin  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(110)

我一直在寻找这个转换一段时间。如何在Linux上使用Python将RGB图像转换为YUV图像并访问Y,U和V通道?(使用opencv、skimage等)
更新:我用的是opencv

img_yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)
y, u, v = cv2.split(img_yuv)

cv2.imshow('y', y)
cv2.imshow('u', u)
cv2.imshow('v', v)
cv2.waitKey(0)

字符串
得到了这个结果,但它们看起来都是灰色的。无法获得像wikipedia page上那样表示的结果
我做错什么了吗?


的数据

wgx48brx

wgx48brx1#

注意:<->OpenCV 3.2.0之前版本的YUV RGB转换为buggy!首先,在许多情况下,U和V通道的顺序被交换。据我所知,2.x在www.example.com发布时仍然是坏2.4.13.2的。

它们显示灰度的原因是,在split绘制3通道YUV图像时,您创建了三个1通道图像。由于包含像素的数据结构不存储任何有关值表示的 * 内容 * 的信息,因此imshow将任何1通道图像视为灰度显示。类似地,它将任何3通道图像视为BGR。
在Wikipedia示例中看到的是色度通道的假彩色渲染。为了实现这一点,您需要应用预定义的色彩Map表或使用自定义查找表(LUT)。这将把U和V值Map到适当的BGR值,然后可以显示这些值。
事实证明,用于Wikipedia示例的颜色Map表相当简单。

U通道色彩Map表

绿色和蓝色之间的简单级数:

colormap_u = np.array([[[i,255-i,0] for i in range(256)]],dtype=np.uint8)

字符串
x1c 0d1x的数据

V通道色彩Map表

绿色和红色之间的简单渐变:

colormap_v = np.array([[[0,255-i,i] for i in range(256)]],dtype=np.uint8)


像示例一样可视化YUV

现在,我们可以把它们放在一起,重新创建这个例子:

import cv2
import numpy as np

def make_lut_u():
    return np.array([[[i,255-i,0] for i in range(256)]],dtype=np.uint8)

def make_lut_v():
    return np.array([[[0,255-i,i] for i in range(256)]],dtype=np.uint8)

img = cv2.imread('shed.png')

img_yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
y, u, v = cv2.split(img_yuv)

lut_u, lut_v = make_lut_u(), make_lut_v()

# Convert back to BGR so we can apply the LUT and stack the images
y = cv2.cvtColor(y, cv2.COLOR_GRAY2BGR)
u = cv2.cvtColor(u, cv2.COLOR_GRAY2BGR)
v = cv2.cvtColor(v, cv2.COLOR_GRAY2BGR)

u_mapped = cv2.LUT(u, lut_u)
v_mapped = cv2.LUT(v, lut_v)

result = np.vstack([img, y, u_mapped, v_mapped])

cv2.imwrite('shed_combo.png', result)


测试结果:


3j86kqsm

3j86kqsm2#

使用所描述的LUT值可能正是维基百科文章图像的制作方式,但描述暗示它是任意的,并且可能因为它很简单而使用。它不是任意的;结果基本上与RGBYUV转换如何工作相匹配<->。如果你使用的是OpenCV,那么方法BGR 2 YUV和YUV 2BGR使用维基百科上同一篇YUV文章中的转换公式给予结果。(我使用Java生成的图像稍微暗一点,否则是一样的。
补遗:我很抱歉,在Dan Mašek通过向我们展示查找表技巧完美而敏锐地回答了这个问题之后,我选择了他。Wikipedia YUV文章的作者并没有在文章中描述绿蓝和绿红渐变,但正如Dan Mašek指出的那样,它并不完美。U和V的颜色图像确实有点像实际发生的情况,所以我称之为夸张的颜色,而不是假色。维基百科上关于YCrCb的文章很相似,但不知何故有所不同。

// most of the Java program which should work in other languages with OpenCV:
// everything duplicated to do both the U and V at the same time
Mat src = new Mat();
Mat dstA = new Mat();
Mat dstB = new Mat();
src = Imgcodecs.imread("shed.jpg", Imgcodecs.IMREAD_COLOR);

List<Mat> channelsYUVa = new ArrayList<Mat>();
List<Mat> channelsYUVb = new ArrayList<Mat>();

Imgproc.cvtColor(src, dstA, Imgproc.COLOR_BGR2YUV); // convert bgr image to yuv
Imgproc.cvtColor(src, dstB, Imgproc.COLOR_BGR2YUV);

Core.split(dstA, channelsYUVa); // isolate the channels y u v
Core.split(dstB, channelsYUVb);

// zero the 2 channels we do not want to see isolating the 1 channel we want to see
channelsYUVa.set(0, Mat.zeros(channelsYUVa.get(0).rows(),channelsYUVa.get(0).cols(),channelsYUVa.get(0).type()));
channelsYUVa.set(1, Mat.zeros(channelsYUVa.get(0).rows(),channelsYUVa.get(0).cols(),channelsYUVa.get(0).type()));

channelsYUVb.set(0, Mat.zeros(channelsYUVb.get(0).rows(),channelsYUVb.get(0).cols(),channelsYUVb.get(0).type()));
channelsYUVb.set(2, Mat.zeros(channelsYUVb.get(0).rows(),channelsYUVb.get(0).cols(),channelsYUVb.get(0).type()));

Core.merge(channelsYUVa, dstA); // combine channels (two of which are zero)
Core.merge(channelsYUVb, dstB);

Imgproc.cvtColor(dstA, dstA, Imgproc.COLOR_YUV2BGR); // convert to bgr so it can be displayed
Imgproc.cvtColor(dstB, dstB, Imgproc.COLOR_YUV2BGR);

HighGui.imshow("V channel", dstA); // display the image
HighGui.imshow("U channel", dstB);

HighGui.waitKey(0);

字符串

相关问题