tikz - 绘制 RGB-YUV 色彩空间 3D 模型

tikz - 绘制 RGB-YUV 色彩空间 3D 模型

我希望绘制一个 3D RGB-YUV 颜色空间模型。如下所示:

在此处输入图片描述

RGB立方体颜色空间(0,255),RGB到YUV的转换公式为:

在此处输入图片描述

YUV转RGB公式:

在此处输入图片描述

我确实希望得到如公式所述的精确图形。哪个包可能更适合绘制这样的图表?

答案1

是的,可以教 TiZ 进行线性变换。您的屏幕截图显示了非正交投影。因此,我在答案的末尾添加了这样的投影,尽管我个人不太喜欢它们。我添加了一个RGBvec执行线性变换的函数(模数拼写错误,因为我不擅长从屏幕显示中输入文本,特别是当我不知道这些东西来自哪里时),并添加了一个将 RGB 坐标转换为其他配色方案的快速样式。所有这些都可以调整,但至少这表明了原则上如何做到这一点。

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\def\matCC{{0.257, 0.504, 0.098},% 
        {-0.148, -0.291, 0.439},%
        {0.439, -0.368,0.071}}%
\pgfmathdeclarefunction{RGBvec}{3}{%
\begingroup%
\pgfmathsetmacro{\myY}{16+{\matCC}[0][0]*#1+{\matCC}[0][1]*#2+{\matCC}[0][2]*#3}%
\pgfmathsetmacro{\myCb}{128+{\matCC}[1][0]*#1+{\matCC}[1][1]*#2+{\matCC}[1][2]*#3}%
\pgfmathsetmacro{\myCr}{128+{\matCC}[2][0]*#1+{\matCC}[2][1]*#2+{\matCC}[2][2]*#3}%
\edef\pgfmathresult{\myCr,\myCb,\myY}%
\pgfmathsmuggle\pgfmathresult\endgroup%
}%

\begin{document}
\tdplotsetmaincoords{70}{110}
\begin{tikzpicture}[bullet/.style={circle,inner
    sep=2pt,fill},line cap=round,line join=round,
    RGB coordinate/.code args={(#1,#2,#3)}{\pgfmathparse{RGBvec(#1,#2,#3)}%
    \tikzset{insert path={(\pgfmathresult)}}},font=\sffamily,thick]
 \begin{scope}[tdplot_main_coords,scale=1/40]
  \draw[-stealth] (0,0,0) coordinate (O) -- (280,0,0) coordinate[label=below:Cr] (Cr);
  \draw[-stealth]  (O) -- (0,280,0) coordinate[label=below:Cb] (Cb);
  \draw[-stealth]  (O) -- (0,0,280) coordinate[label=left:Y] (Y);
  \path [RGB coordinate={(255,255,255)}] node[bullet,draw,fill=white] (white){}
    [RGB coordinate={(0,0,0)}] node[bullet] (black){}
    [RGB coordinate={(255,0,0)}] node[bullet,red] (red){}
    [RGB coordinate={(0,255,0)}] node[bullet,green] (green){}
    [RGB coordinate={(0,0,255)}] node[bullet,blue] (blue){}
    [RGB coordinate={(255,0,255)}] node[bullet,magenta] (magenta){}
    [RGB coordinate={(255,255,0)}] node[bullet,yellow] (yellow){}
    [RGB coordinate={(0,255,255)}] node[bullet,cyan] (cyan){};
   \draw (red) -- (black) -- (blue) -- (magenta) -- (red) -- (yellow) 
   -- (green) edge (black) -- (cyan) edge (blue) -- (white)  edge (magenta) -- (yellow); 
   \draw[thin] (255,0,0) node[left]{255} -- (255,255,0) -- (0,255,0) node[above]{255}
   (0,0,255) node[left]{255} -- (255,0,255) edge (255,0,0)
    -- (255,255,255)  edge (255,255,0) -- (0,255,255)  edge (0,255,0)
   -- cycle ;
 \end{scope}
 \begin{scope}[xshift=8cm,scale=1/40]
  \pgfmathdeclarefunction*{RGBvec}{3}{%
  \begingroup%
  \pgfmathsetmacro{\myY}{16+{\matCC}[0][0]*#1+{\matCC}[0][1]*#2+{\matCC}[0][2]*#3}%
  \pgfmathsetmacro{\myCb}{128+{\matCC}[1][0]*#1+{\matCC}[1][1]*#2+{\matCC}[1][2]*#3}%
  \pgfmathsetmacro{\myCr}{128+{\matCC}[2][0]*#1+{\matCC}[2][1]*#2+{\matCC}[2][2]*#3}%
  \edef\pgfmathresult{\myCb,\myY,\myCr}%
  \pgfmathsmuggle\pgfmathresult\endgroup%
  }%
  \draw[-stealth] (0,0,0) coordinate (O) -- (255,0,0) coordinate[label=below:Cb] (Cb);
  \draw[-stealth]  (O) -- (0,255,0) coordinate[label=left:Y] (Y);
  \draw[-stealth]  (O) -- (0,0,255) coordinate[label=below:Cr] (Cr);
  \path [RGB coordinate={(255,255,255)}] node[bullet,draw,fill=white] (white){}
    [RGB coordinate={(0,0,0)}] node[bullet] (black){}
    [RGB coordinate={(255,0,0)}] node[bullet,red] (red){}
    [RGB coordinate={(0,255,0)}] node[bullet,green] (green){}
    [RGB coordinate={(0,0,255)}] node[bullet,blue] (blue){}
    [RGB coordinate={(255,0,255)}] node[bullet,magenta] (magenta){}
    [RGB coordinate={(255,255,0)}] node[bullet,yellow] (yellow){}
    [RGB coordinate={(0,255,255)}] node[bullet,cyan] (cyan){};
   \draw (red) -- (black) -- (blue) -- (magenta) -- (red) -- (yellow) 
   -- (green) edge (black) -- (cyan) edge (blue) -- (white)  edge (magenta) -- (yellow); 
  \end{scope}   
\end{tikzpicture}
\end{document}

在此处输入图片描述

正交投影的优点在于您可以应用正交变换,即旋转,并且结果是逼真的(最多透视效果,可以使用库处理perspective)。

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\def\matCC{{0.257, 0.504, 0.098},% 
        {-0.148, -0.291, 0.439},%
        {0.439, -0.368,0.071}}%
\pgfmathdeclarefunction{RGBvec}{3}{%
\begingroup%
\pgfmathsetmacro{\myY}{16+{\matCC}[0][0]*#1+{\matCC}[0][1]*#2+{\matCC}[0][2]*#3}%
\pgfmathsetmacro{\myCb}{128+{\matCC}[1][0]*#1+{\matCC}[1][1]*#2+{\matCC}[1][2]*#3}%
\pgfmathsetmacro{\myCr}{128+{\matCC}[2][0]*#1+{\matCC}[2][1]*#2+{\matCC}[2][2]*#3}%
\edef\pgfmathresult{\myCr,\myCb,\myY}%
\pgfmathsmuggle\pgfmathresult\endgroup%
}%
\tikzset{RGB coordinate/.code args={(#1,#2,#3)}{\pgfmathparse{RGBvec(#1,#2,#3)}%
    \tikzset{insert path={(\pgfmathresult)}}}}
\begin{document}
\foreach \X in {0,10,...,350}
{\tdplotsetmaincoords{70}{\X}
\begin{tikzpicture}[bullet/.style={circle,inner
    sep=2pt,fill},line cap=round,line join=round,font=\sffamily,thick]
 \path[use as bounding box] (-5.5,-2)   rectangle (5.5,8);
 \begin{scope}[tdplot_main_coords,scale=1/40,shift={(-128,-128,0)}]
  \draw[-stealth] (0,0,0) coordinate (O) -- (280,0,0) coordinate[label=below:Cr] (Cr);
  \draw[-stealth]  (O) -- (0,280,0) coordinate[label=below:Cb] (Cb);
  \draw[-stealth]  (O) -- (0,0,280) coordinate[label=left:Y] (Y);
  \path [RGB coordinate={(255,255,255)}] node[bullet,draw,fill=white] (white){}
    [RGB coordinate={(0,0,0)}] node[bullet] (black){}
    [RGB coordinate={(255,0,0)}] node[bullet,red] (red){}
    [RGB coordinate={(0,255,0)}] node[bullet,green] (green){}
    [RGB coordinate={(0,0,255)}] node[bullet,blue] (blue){}
    [RGB coordinate={(255,0,255)}] node[bullet,magenta] (magenta){}
    [RGB coordinate={(255,255,0)}] node[bullet,yellow] (yellow){}
    [RGB coordinate={(0,255,255)}] node[bullet,cyan] (cyan){};
   \draw (red) -- (black) -- (blue) -- (magenta) -- (red) -- (yellow) 
   -- (green) edge (black) -- (cyan) edge (blue) -- (white)  edge (magenta) -- (yellow); 
   \draw[thin] (255,255,0) -- (255,0,0) node[pos=1.1]{255} 
   (255,255,0) --(0,255,0) node[pos=1.1]{255}
   (0,0,255) node[left]{255} -- (255,0,255) edge (255,0,0)
    -- (255,255,255)  edge (255,255,0) -- (0,255,255)  edge (0,255,0)
   -- cycle ;
 \end{scope}
\end{tikzpicture}}
\end{document}

在此处输入图片描述

当然,我们可以让连接呈现出颜色的转变。

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\def\matCC{{0.257, 0.504, 0.098},% 
        {-0.148, -0.291, 0.439},%
        {0.439, -0.368,0.071}}%
\pgfmathdeclarefunction{RGBvec}{3}{%
\begingroup%
\pgfmathsetmacro{\myY}{16+{\matCC}[0][0]*#1+{\matCC}[0][1]*#2+{\matCC}[0][2]*#3}%
\pgfmathsetmacro{\myCb}{128+{\matCC}[1][0]*#1+{\matCC}[1][1]*#2+{\matCC}[1][2]*#3}%
\pgfmathsetmacro{\myCr}{128+{\matCC}[2][0]*#1+{\matCC}[2][1]*#2+{\matCC}[2][2]*#3}%
\edef\pgfmathresult{\myCr,\myCb,\myY}%
\pgfmathsmuggle\pgfmathresult\endgroup%
}%
\tikzset{RGB coordinate/.code args={(#1,#2,#3)}{\pgfmathparse{RGBvec(#1,#2,#3)}%
    \tikzset{insert path={(\pgfmathresult)}}}}
\begin{document}
\tdplotsetmaincoords{70}{110}
\begin{tikzpicture}[bullet/.style={circle,inner
    sep=2pt,outer sep=0pt,fill},connection bar/.style args={(#1)--(#2)}{%
    insert path={let \p1=(#1),\p2=(#2),\n1={atan2(\y2-\y1,\x2-\x1)} in 
    [left color=#1,right color=#2,shading angle=\n1+90]
    (#1.\n1-25) arc(\n1-25:\n1+25:40*2pt) 
    -- (#2.\n1-180-25)  arc(\n1-180-25:\n1-180+25:40*2pt) -- cycle}},
    line cap=round,line join=round,font=\sffamily,thick]
 \path[use as bounding box] (-5.5,-2)   rectangle (5.5,8);
 \begin{scope}[tdplot_main_coords,scale=1/40,shift={(-128,-128,0)}]
  \draw[-stealth] (0,0,0) coordinate (O) -- (280,0,0) coordinate[label=below:Cr] (Cr);
  \draw[-stealth]  (O) -- (0,280,0) coordinate[label=below:Cb] (Cb);
  \draw[-stealth]  (O) -- (0,0,280) coordinate[label=left:Y] (Y);
  \path [RGB coordinate={(255,255,255)}] node[bullet,draw,fill=white] (white){}
    [RGB coordinate={(0,0,0)}] node[bullet] (black){}
    [RGB coordinate={(255,0,0)}] node[bullet,red] (red){}
    [RGB coordinate={(0,255,0)}] node[bullet,green] (green){}
    [RGB coordinate={(0,0,255)}] node[bullet,blue] (blue){}
    [RGB coordinate={(255,0,255)}] node[bullet,magenta] (magenta){}
    [RGB coordinate={(255,255,0)}] node[bullet,yellow] (yellow){}
    [RGB coordinate={(0,255,255)}] node[bullet,cyan] (cyan){};
  \path[connection bar={(black)--(blue)}];
  \path[connection bar={(blue)--(magenta)}];
  \path[connection bar={(magenta)--(red)}];
  \path[connection bar={(red)--(black)}];
  \path[connection bar={(white)--(magenta)}];
  \path[connection bar={(cyan)--(blue)}];
  \path[connection bar={(green)--(black)}];
  \path[connection bar={(yellow)--(red)}];
  \path[connection bar={(yellow)--(green)}];
  \path[connection bar={(green)--(cyan) }];
  \path[connection bar={(cyan)--(white)}];
  \path[connection bar={(white)--(yellow)}];
   \draw[thin] (255,255,0) -- (255,0,0) node[pos=1.1]{255} 
   (255,255,0) --(0,255,0) node[pos=1.1]{255}
   (0,0,255) node[left]{255} -- (255,0,255) edge (255,0,0)
    -- (255,255,255)  edge (255,255,0) -- (0,255,255)  edge (0,255,0)
   -- cycle ;
 \end{scope}
\end{tikzpicture}
\end{document}

在此处输入图片描述

一些评论:

  1. 原则上,如果进行线性变换,则有一种更简单的方法:\begin{scope}[x={(x)},y={(y)},x={(y)}] ... \end{scope},其中(x)(y)(z)是基向量。但是随着额外的移位,事情变得有点混乱,我认为明确地使用坐标可能更有意义。
  2. \pgfshadecolortorgb允许将颜色转换为 RGB 坐标。在撰写这篇文章时,我还没有想过要使用它。

答案2

一个起点。现在您可以绘制 3D 坐标。看您的个人资料,我相信您可以这样做。

\documentclass[tikz,margin=3]{standalone}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}[z={(-135:.5)},>=Stealth]
  \draw[thick,->] (0,0,0) -- (5,0,0) node[below] {Cb};
  \draw[thick,->] (0,0,0) -- (0,5,0) node[left] {Y};
  \draw[thick,->] (0,0,0) -- (0,0,5) node[below] {Cr};
  \draw (4,0,0) node[anchor=135] {255} |- (0,4,0) node[anchor=-30] {255} 
    -- (0,4,4) |- (4,0,4) -- cycle
    (0,4,4) -| (4,0,4) (4,4,4) -- (4,4,0)
    (0,0,4) node[anchor=-30] {255};
  \path (0,0) node[below] {0};
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容