2013-07-17 1 views
1

openCV C++ API를 사용하고 있으며 카메라 버퍼 (YUV_NV12)를 RGB 형식으로 변환하려고합니다. 그러나 내 이미지의 크기가 변경되어 (너비가 720에서 480으로 축소됨) 색이 잘못되었습니다 (다소 보라색/녹색).OpenCV cvtColor() 내 이미지 크기를 변경하고 색상이 잘못되었습니다.

unsigned char* myYUVBufferPointer = (something passed as argument) 
int myYUVBufferHeight = 1280 
int myYUVBufferWidth = 720 

cv::Mat yuvMat(myYUVBufferHeight, myYUVBufferWidth, CV_8U, myYUVBufferPointer); 
cv::Mat rgbMat; 
cv::cvtColor(yuvMat, rgbMat, CV_YUV2RGB_NV12); 
cv::imwrite("path/to/my/image.jpg",rgbMat); 

아이디어가 있으십니까? * (CV_YUV2GRAY_NV12로 변환하고 크기가 맞지 않기 때문에 색상보다 크기가 더 중요합니다.) *

답변

3

코드는 unsigned char 개 중에서 yuvMat이라는 단일 채널 (회색조) 이미지를 생성합니다. 이 단일 채널 이미지를 YUV 4 : 2 : 0에서 다중 채널 RGB로 강제 변환하려고 할 때 OpenCV 라이브러리는 각 행에 전체 4 : 4 : 4 정보 중 2/3이 있다고 가정합니다 (1 x height x width for YUV의 경우 3 x height x width 대신 및 1/2 height x width 인 경우 UV) 따라서 대상 이미지의 너비가 원래 너비의 2/3로 줄어 듭니다. 원래 이미지에서 읽은 데이터의 절반은 원래 이미지가 width x height uchar이지만 메모리에서 읽혀지기 때문에 할당되지 않은 메모리에서 나온다고 가정 할 수 있습니다! 당신의 uchar 버퍼가 이미 제대로 YUV_NV12 나타내는 바이트의 일련의 포맷하면

채널 당 기존의 width x height 바이트 (: 2 4 0 서브 샘플링을), 당신이 할 필요가 구축하는 것입니다 원래 yuvMatCV_8UC3 A와와 너는 가서 좋다. 위의 설명은 모든 인터 레이싱 및 채널 위치 지정이 이미 버퍼에 구현되어 있다고 가정합니다. 아마 이것은 경우가 아닙니다. YUV_NV12 데이터는 width x height ucharY이고, 다음으로 (1/2) width x (1/2) x height of 2 x uchars가 UV을 나타냅니다. 모두 UV 채널에서 수평 및 수직 간격을 채워 - - 별도 Y, UV 데이터를 읽을 수 및 크기 width x height 3 단일 채널 Mat의를 구성하는 당신은 아마 자신의 독자를 작성해야 다음 cv::merge()를 사용 CV_YUV2BGR 옵션을 사용하여 이미지를 변환하려면 cv::cvtColor()을 사용하기 전에 단일 채널 이미지를 3 채널 YUV에 결합해야합니다. RGB 대신 BGR을 사용합니다.

+0

감사합니다. 꿀벌! CV_8UC3을 시도하면 0x11d7ba8에서 cvtColor() __generic_memcpy()를 호출 할 때 segfault가 발생합니다. 그래서 당신은 내 버퍼의 모든 픽셀을 반복해야하고 새로운 3 단일 채널을 구성해야한다고 말했습니까? RGB 대신 BGR을 사용해야하는 이유는 무엇입니까? – nox

+0

참고 : cvtColor()를 호출 할 때 충돌이 발생합니다 (또는 imwrite()를 호출 할 때) – nox

+0

OpenCV에서 CV_8U3C 이미지의 기본 색상 순서는 Blue-Green-Red입니다. 예를 들어,'cv :: imwrite()'는 컬러 이미지의 BGR 순서를 요구합니다. segfault는 여러 가지 이유로 발생할 수 있으므로 segfault를 얻는 이유를 파악하는 것은 매우 어렵습니다. 때로는 릴리스 프로그램에서 디버그 라이브러리를 사용하거나 그 반대의 경우가 원인입니다. 가장 좋은 방법은 CV_8U를 사용하여 각 채널을 따로 구축하고 각 채널을 std :: vector 에 넣고 cv :: merge를 사용하여 벡터를 단일 CV_8UC3 이미지로 병합하는 것입니다. – Bee

0

"인수로 전달 된 것"일 수 있습니다. 720 행을 채우기에 충분한 데이터가 없습니다. 일부 비디오 카메라의 경우 세 채널 모두가 동일한 비트 수를 사용하여 표현되는 것은 아닙니다. 예를 들어 iPhone에서 비디오를 캡처 할 때 세 개의 채널은 8-8-8 대신 8-4-4 바이트를 사용합니다. OpenCV에서이 유형의 카메라를 사용하지는 않았지만 문제가있을 가능성이 큽니다.

관련 문제