Resize (downsize) YUV420sp image

后端 未结 3 782
南旧
南旧 2020-12-14 23:19

I am trying to resize (scale down) an image which comes in YUV420sp format. Is it possible to do such image resizing without converting it into RGB, so directly manipulating

3条回答
  •  [愿得一人]
    2020-12-15 00:14

    YUV 4:2:0 planar looks like this:

    ----------------------
    |     Y      | Cb|Cr |
    ----------------------
    

    where:

    Y = width x height pixels
    Cb = Y / 4 pixels
    Cr = Y / 4 pixels
    
    Total num pixels (bytes) = width * height * 3 / 2
    

    And the subsamling used like this:

    420

    Which means that each chroma-pixel-value is shared between 4 luma-pixels.

    One approach is just to remove pixels, making sure that corresponding Y-Cb-Cr relationship are kept/recalculated.

    Something close to the Nearest-neighbor interpolation but reversed.

    Another approach is to first convert the 4:2:0 subsampling to 4:4:4

    444

    Here you have a 1 to 1 mapping between luma and chroma data.

    This is the correct way to interpolate chroma between 4:2:0 and 4:2:2 (luma is already at correct resolution) Code in python, follow html-link for c-dito. Code is not very pythonic, just a direct translation of the c-version.

    def __conv420to422(self, src, dst):
        """
        420 to 422 - vertical 1:2 interpolation filter
    
        Bit-exact with
        http://www.mpeg.org/MPEG/video/mssg-free-mpeg-software.html
        """
        w = self.width >> 1
        h = self.height >> 1
    
        for i in xrange(w):
            for j in xrange(h):
                j2 = j << 1
                jm3 = 0 if (j<3) else j-3
                jm2 = 0 if (j<2) else j-2
                jm1 = 0 if (j<1) else j-1
                jp1 = j+1 if (j>8
    
                dst[i+w*j2] = pel if pel > 0 else 0
                dst[i+w*j2] = pel if pel < 255 else 255
    
                pel = (3*src[i+w*jp3]
                     -16*src[i+w*jp2]
                     +67*src[i+w*jp1]
                    +227*src[i+w*j]
                     -32*src[i+w*jm1]
                     +7*src[i+w*jm2]+128)>>8
    
                dst[i+w*(j2+1)] = pel if pel > 0 else 0
                dst[i+w*(j2+1)] = pel if pel < 255 else 255
        return dst
    

    Run this twice to get 4:4:4. Then it's just a matter of removing rows and columns.

    Or you can just quadruple the chroma-pixels to go from 4:2:0 to 4:4:4, remove rows and columns and then average 4 Cb/Cr values into 1 to get back to 4:2:0 again, it all depends on how strict you need to be :-)

提交回复
热议问题