2013-07-17 56 views
1

我使用openCV C++ API,並試圖將相機緩衝區(YUV_NV12)轉換爲RGB格式。然而,我的圖像尺寸發生了變化(寬度從720縮小到480),顏色錯了(有點紫色/綠色ish)。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 s中構建一個名爲yuvMat的單通道(灰度)圖像。當您試圖強制將這個單通道圖像從YUV 4:2:0轉換爲多通道RGB時,OpenCV庫假定每一行都具有完整4:4:4信息的2/3(對於1 x height x widthY1/2 height x widthUV each,而不是3 x height x width爲正常YUV),因此您的目標圖像的寬度收縮到原始寬度的2/3。可以認爲,從原始圖像中讀取的一半數據來自未分配的內存,儘管原始圖像只有width x height uchar s,但從內存中讀取了2 x width x height uchar

如果uchar緩衝器已經正確格式化用於表示YUV_NV12一系列字節的每個信道的常規width x height字節(4:4:2 0子採樣),所有需要做的是構造原來的yuvMat作爲CV_8UC3和你已準備好出發。上面假定所有的隔行掃描和通道定位已經在緩衝區中實現。但很可能情況並非如此。 YUV_NV12數據與width x height uchar s的Y,其次是(1/2) width x (1/2) x height of 2 x uchar s代表UV合併。你可能需要編寫自己的讀者分別讀取YUV數據,構建3單通道Mat的規模width x height的 - 在這兩個UV渠道在水平和垂直填補空白 - 然後使用cv::merge()將這些單通道圖像合併到3通道YUV,然後使用cv::cvtColor()使用CV_YUV2BGR選項轉換該圖像。請注意使用BGR而不是RGB

+0

非常感謝蜜蜂!當我嘗試CV_8UC3時,我在0x11d7ba8處調用cvtColor()__generic_memcpy()時會出現段錯誤。所以你說我應該遍歷我的緩衝區的所有像素,並構建一個新的3單通道?爲什麼選擇BGR而不是RGB? – nox

+0

僅供參考,當我調用cvtColor()時(或者當我調用imwrite()時發生崩潰) – nox

+0

在OpenCV中,CV_8U3C圖像中的默認顏色順序是Blue-Green-Red。例如,'cv :: imwrite()'預計彩色圖像的BGR排序。段錯誤可能因各種原因而發生,所以很難弄清楚爲什麼會出現段錯誤。有時在發佈程序中使用調試庫或反之亦然是罪魁禍首。您最好的選擇是使用CV_8U單獨構建每個通道,將每個通道推入std :: vector ,並使用cv :: merge將矢量合併到單個CV_8UC3圖像中。 – Bee

0

它可能是「東西作爲參數傳遞」沒有足夠的數據填充720行。對於某些攝像機,並非所有三個通道都使用相同的位數表示。例如,在iPhone上捕捉視頻時,三個通道使用8-4-4字節而不是8-8-8。我沒有使用OpenCV的這種類型的相機,但最有可能的問題在這裏。