2016-11-01 76 views
1

我試圖對YUV格式的OpenCV圖像進行圖像穩定,其中有2個通道:一個包含Y值,另一個包含交替的U/V值(在OpenCV中的YUV_YUY2)。OpenCV矩陣運算導致YUV圖像顏色損壞

我遇到的問題是,某些矩陣操作(特別是warpAffine和調整大小)可能會移動數組,使U值最終位於V位置,反之亦然,顛倒顏色或導致圖像出現條紋。我的第一個想法是,我可以將圖像轉換爲不同的(非交錯圖像)圖像類型,應用轉換,然後轉換回來,但是使用我發現的cvtColor()可用的轉換: http://docs.opencv.org/3.1.0/d7/d1b/group__imgproc__misc.html

我可以將YUV_YUY2轉換成其他格式,但沒有可用的轉換回YUV_YUY2格式。

我可能能夠手動重建YUY2矩陣,但我懷疑有可能是我失蹤的更簡單的方法。任何OpenCV大師都有什麼建議?謝謝。

代碼片段:

cv::Mat stabilize (VideoFrame* curFrame, VideoFrame* prevFrame) 
{ 
    Mat locCurMat, locPrevMat; 
    locCurMat = Mat(1080, 1920, CV_8UC2, curFrame->video); 
    locPrevMat = Mat(1080, 1920, CV_8UC2, prevFrame->video); 

    // Calculate the transformation matrix 
    Mat locTransform; 
    // I’ll spare you this part 
    // … 

    // Apply the transformation 
    Mat locStabFrame; 
    // Make the border value (0, 128) for black: 
    // If you leave it at 0,0 it's bright green 
    Scalar locBorderVal(0, 128); 
    warpAffine(locCurMat, locStabFrame, locTransform, locCurMat.size(), 
       INTER_LINEAR, BORDER_CONSTANT, locBorderVal); 

    // Crop the borders to make the video look better 
    // Get the aspect ratio correct 
    int locVertBorder = HORIZONTAL_BORDER_CROP * 
         locCurMat.rows/locCurMat.cols; 
    locStabFrame = locStabFrame(
     Range(locVertBorder, locStabFrame.rows - locVertBorder), 
     Range(HORIZONTAL_BORDER_CROP, 
      locStabFrame.cols - HORIZONTAL_BORDER_CROP)); 

    // Resize locStabFrame back to the proper frame size 
    resize(locStabFrame, locStabFrame, locCurMat.size()); 

    // Return the stabilized result 
    return locStabFrame; 
} 

回答

0

如果有人有興趣,這裏是我走上避免這個問題的過程。儘管如此,如果有人有更高效的方式,我會很高興聽到它。

的步驟是基本上是:

  1. 在2信道YUV的u值和V值創建掩模
  2. 從2信道YUV轉換爲RGB
  3. 運行warpAffine &調整上的RGB圖像
  4. 將RGB轉換爲3聲道YUV
  5. 使用u/v掩膜從3聲道重建2聲道YUV YUV
  6. 回到2路YUV圖像

代碼:

// Apply the transformation 
Mat rgbFrame, stabFrame, outputFrame; 
// Convert the frame to RGB 
cvtColor(locCurMat, rgbFrame, COLOR_YUV2RGB_YUY2); 

// Apply the image translation 
warpAffine(rgbFrame, stabFrame, T, rgbFrame.size()); 

// Crop the borders to make the video look better 
// Get the aspect ratio correct 
int vert_border = HORIZONTAL_BORDER_CROP * locCurMat.rows/locCurMat.cols; 
stabFrame = stabFrame(Range(vert_border, stabFrame.rows - vert_border), 
         Range(HORIZONTAL_BORDER_CROP, 
          stabFrame.cols - HORIZONTAL_BORDER_CROP)); 


// Resize regFrame back to the correct frame size 
resize(stabFrame, stabFrame, rgbFrame.size()); 

// Convert back from RGB to YUV 
// First, see if the u/v masks are the correct size, and populate them 
// if not. Hopefully this only happens once 
if (locCurMat.rows != m_uMask.rows || locCurMat.cols != m_uMask.cols) 
{ 
    printf("Creating U/V image masks\n"); 
    m_uMask = cv::Mat::zeros(locCurMat.size(), CV_8UC1); 
    m_vMask = cv::Mat::zeros(locCurMat.size(), CV_8UC1); 
    cv::Mat onesCol = cv::Mat::ones(locCurMat.rows, 1, CV_8UC1); 
    // Populate the masks with alternating columns of 1s 
    for (int i = 0; i < locCurMat.cols; i++) 
    { 
     // Copy even columns to the u mask 
     if (i % 2 == 0) 
     { 
      onesCol.copyTo(m_uMask.col(i)); 
     } 
     // Copy odd columns to the v mask 
     else 
     { 
      onesCol.copyTo(m_vMask.col(i)); 
     } 
     } 
    } 

// Convert the stabilized rgb frame to YUV 
Mat yuvFrame; 
cvtColor(stabFrame, yuvFrame, COLOR_RGB2YUV); 

// Split the YUV frame into individual channels 
vector<Mat> yuv3Channels; 
split(yuvFrame, yuv3Channels); 

// Copy the 3 channel YUV values into 2 channel YUV 
vector<Mat> yuv2Channels; 
Mat uvChannel; 
yuv3Channels[1].copyTo(uvChannel, m_uMask); 
yuv3Channels[2].copyTo(uvChannel, m_vMask); 
yuv2Channels.push_back(yuv3Channels[0]); 
yuv2Channels.push_back(uvChannel); 

// Merge the 2 channel yuv back into the output frame 
cv::merge(yuv2Channels, outputFrame); 
+0

好像在API中一個大洞不能夠轉換回YUY2,不是嗎? –

+0

是的,看起來很奇怪,他們會讓你轉換出這種格式,但不會回到它。 – npulaski