title: How to convert sRGB to NV12 format using NumPy?
body: <p><strong>NV12</strong> format defines specific color channels ordering of YUV color space with 420 subsampling.<br>
  NV12 format is mostly used in video encoding/decoding pipeline.  </p>
  
  <p><a href="https://chromium.googlesource.com/libyuv/libyuv/+/HEAD/docs/formats.md#nv12-and-nv21" rel="nofollow noreferrer">libyuv description of NV12</a>:  </p>
  
  <blockquote>
    <p>NV12 is a biplanar format with a full sized Y plane followed by a single chroma plane with weaved U and V values. NV21 is the same but with weaved V and U values. The 12 in NV12 refers to 12 bits per pixel. NV12 has a half width and half height chroma channel, and therefore is a 420 subsampling.  </p>
  </blockquote>
  
  <p>In context of NV12, YUV format is mainly referred as <a href="https://en.wikipedia.org/wiki/YCbCr" rel="nofollow noreferrer">YCbCr</a> color space.<br>
  NV12 elements are 8 bits per element (<code>uint8</code> type).<br>
  In the context of the post, YUV elements are in "limited range" standard: Y range is [16, 235], U,V range is [16, 240].  </p>
  
  <p><strong>sRGB</strong> (standard Red Green Blue) is a standard color space used by PC systems.<br>
  In the context of the post, <a href="https://en.wikipedia.org/wiki/SRGB" rel="nofollow noreferrer">sRGB</a> color components range is [0, 255] (<code>uint8</code> type).<br>
  RGB elements ordering is not relevant to the post (assume 3 color planes).  </p>
  
  <p>There are currently at least 2 possible YCbCr formats applying NV12:  </p>
  
  <ul>
  <li><a href="https://en.wikipedia.org/wiki/Rec._601" rel="nofollow noreferrer">BT.601</a> - Applies SDTV.  </li>
  <li><a href="https://en.wikipedia.org/wiki/Rec._709" rel="nofollow noreferrer">BT.709</a> - Applies HDTV.  </li>
  </ul>
  
  <p>Example for NV12 elements ordering:<br>
  <code>YYYYYY</code><br>
  <code>YYYYYY</code><br>
  <code>UVUVUV</code>  </p>
  
  <p><a href="https://i.stack.imgur.com/LgxEl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/LgxEl.png" alt="NV12"></a>  </p>
  
  <p>RGB to NV12 conversion can be described by the following stages:  </p>
  
  <ul>
  <li>Color space conversion - convert from sRGB to YUV color space.  </li>
  <li>Chroma downsampling - shrink U,V channels by a factor of x2 in each axis (converting from YUV444 to YUV420).  </li>
  <li>Chroma elements interleaving - arrange U,V elements as U,V,U,V...  </li>
  </ul>
  
  <p>Following figure illustrates the conversion stages applying image size of 6x6 pixels:  </p>
  
  <p><a href="https://i.stack.imgur.com/aRrOy.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/aRrOy.png" alt="RGBtoNV12"></a>  </p>
  
  <p><strong>How can we convert sRGB to NV12 using NumPy?</strong>  </p>
  
  <p>Note:<br>
  The question refers Python implementation that demonstrates the conversion process (post is not intended for existing function like OpenCV implementation).  </p>