2013-06-19 2 views
7

YUV420sp 형식으로 제공되는 이미지의 크기를 조정하려고합니다. YUV420sp 픽셀 배열을 직접 조작하므로 RGB로 변환하지 않고 이미지 크기를 조정할 수 있습니까? 어디에서 그런 알고리즘을 찾을 수 있습니까?YUV420sp 이미지의 크기 조정 (크기 축소)

감사

답변

13

YUV 4 : 2 : 0의 평면은 다음과 같다 :

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

여기서

Y = width x height pixels 
Cb = Y/4 pixels 
Cr = Y/4 pixels 

Total num pixels (bytes) = width * height * 3/2 

와 같이 사용 subsamling :

420

각 채도 픽셀 값이 4 루마 픽셀 사이에서 공유됨을 의미합니다.

한 가지 방법은 해당하는 Y-Cb-Cr 관계가 유지/재 계산되는지 확인하여 픽셀을 제거하는 것입니다.

뭔가가 Nearest-neighbor interpolation에 가깝지만 반대입니다. 4 : 4 : 4

여기

444

당신은 루마 및 크로마 데이터 사이의 일대일 매핑이 4 0 서브 샘플링 : 2 :

또 다른 방법은 먼저 4를 변환하는 것입니다.

이것은 4 : 2 : 0과 4 : 2 : 2 사이의 채도를 보간하는 올바른 방법입니다 (luma는 이미 정확한 해상도로되어 있습니다). 코드는 python으로 c-dito의 html-link를 따르십시오. 코드는 python이 아니며 c 버전의 직접 번역입니다.

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<h-1) else h-1 
      jp2 = j+2 if (j<h-2) else h-1 
      jp3 = j+3 if (j<h-3) else h-1 

      pel = (3*src[i+w*jm3] 
       -16*src[i+w*jm2] 
       +67*src[i+w*jm1] 
       +227*src[i+w*j] 
       -32*src[i+w*jp1] 
        +7*src[i+w*jp2]+128)>>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 

이것을 4 회 4시 4 분으로 두 번 실행하십시오. 그런 다음 행과 열을 제거하는 것만 큼 문제가됩니다.

또는 4 : 2 : 0에서 4 : 4 : 4로 이동하여 행과 열을 제거한 다음 4 : 2로 돌아가려면 평균 4Cb/Cr 값을 1로 평균 4 배 증가시킬 수 있습니다. 0 다시, 그것은 모두 얼마나 엄격해야하는지에 달려 있습니다 :-)

+0

4 : 4 : 4로 돌아갈 필요가없고 4 : 2 : 0으로 되돌릴 수 있습니다. 마지막 단계는 이미지를 다시 서브 샘플링하여 품질을 더욱 떨어 뜨립니다. 컬러 평면을 분할하면됩니다. http://stackoverflow.com/questions/17187193/resize-downsize-yuv420sp-image/30659193#30659193 –

7

다음은 YUV 420 (또는 NV21)을 2 배로 축소하는 데 사용하는 Java 함수입니다.

이 함수는 원본 이미지의 너비와 높이를 입력으로 사용하여 바이트 배열로 이미지를 가져 와서 너비와 높이가 모두 원래 너비와 높이의 절반 인 이미지를 바이트 배열로 반환합니다. . 내가 이것을 사용 내 코드의 기초로

: Rotate an YUV byte array on Android

public static byte[] halveYUV420(byte[] data, int imageWidth, int imageHeight) { 
    byte[] yuv = new byte[imageWidth/2 * imageHeight/2 * 3/2]; 
    // halve yuma 
    int i = 0; 
    for (int y = 0; y < imageHeight; y+=2) { 
     for (int x = 0; x < imageWidth; x+=2) { 
      yuv[i] = data[y * imageWidth + x]; 
      i++; 
     } 
    } 
    // halve U and V color components 
    for (int y = 0; y < imageHeight/2; y+=2) { 
     for (int x = 0; x < imageWidth; x += 4) { 
      yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x]; 
      i++; 
      yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x + 1)]; 
      i++; 
     } 
    } 
    return yuv; 
} 
1

YUV420sp은 하나 개의 평면과 다른의 U & V의 Y 있습니다. U & V를 별도의 플레인으로 분할하면 4 : 2 : 0 -> 4 : 4 : 4에서 먼저 이동하지 않고도 3 개의 플레인 각각에 동일한 스케일링 작업을 차례대로 수행 할 수 있습니다.

libyuv의 소스 코드를 살펴보십시오. https://code.google.com/p/libyuv/source/browse/trunk/source/scale.cc

관련 문제