我正在尝试在一个YUV格式的OpenCV图像上进行图像稳定,其中有2个通道:一个包含Y值,另一个包含交替的U / V值(OpenCV中的YUV_YUY2)。
我遇到的问题是某些矩阵运算,特别是warpAffine和resize,可以移动数组,使得U值最终在V位置,反之亦然,反转颜色或在图像中引起条纹。 / p>
我的第一个想法是我可以将图像转换为不同的(非交错的)图像类型,应用转换,然后转换回来,但是使用我发现的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 :(得分:0)
如果有人有兴趣,这是我为避免这个问题而采取的流程。但是它很流氓,如果有人有更高效的方式,我会很高兴听到它。
步骤基本上是:
代码:
// 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);