如何在YUV420p框架上绘制矩形

时间:2018-07-18 06:34:39

标签: opencv

我想在YUV420P框架上使用以下功能绘制一个红色矩形。下面的代码改变了框架,我可以看到两个黑色的线(顶部和底部)剩余的黑色点分散了。有什么建议吗?

void draw_rectangle(uint8_t *frame, int x, int y, 
                    int width, int height,
                    int img_width, int img_height)
{
    cv::Mat frame_yuv;
    int size[2];
    Point pt1, pt2;
    cv::Scalar color = Scalar(255, 0, 0);

    size[0] = img_width + img_width/2;
    size[1] = img_height;
    frame_yuv = cv::Mat(2, size, CV_8UC1, frame);

    pt1.x = x;
    pt1.y = y;
    pt2.x = x + width;
    pt2.y = y + height;

    rectangle(frame_yuv, pt1, pt2, Scalar(0, 0, 255));
}

3 个答案:

答案 0 :(得分:2)

由于您未提供任何示例数据,请使用@zindarod提供的尺寸为144x176的文件。

这是YUV数据在内存中的外观:

enter image description here

在流中注意底部...所有Y像素排在最前面。然后,所有的U像素都将采样率降低为4。然后,所有的V像素,也将采样率降低为4。

我没有时间在OpenCV中编写代码,但是我可以向您展示如何用它制作常规Mat。

第1步-提取Y频道

获取前144x176个字节,并将其放入称为Y的144x176 8UC1 Mat中。

enter image description here

第2步-提取U频道

跳过前144x176个字节,然后提取下一个72x88个字节,然后将它们放入另一个称为U的72x88 8UC1 Mat中。调整此Mat的大小以使其宽度加倍并使其高度加倍,即144x176。

enter image description here

第3步-提取V频道

跳过第一个(144x176)+(88x72)字节,然后将下一个72x88字节放入另一个称为V的72x88 8UC1 Mat中。调整此Mat的大小以使其宽度加倍,高度加倍,即144x176。

enter image description here

第4步-合并

采用Y,U和V垫并将它们合并为8UC3垫:

// Now merge the 3 individual channels into 3-band bad boy
auto channels = std::vector<cv::Mat>{Y, U, V};
cv::Mat ThreeBandBoy;
cv::merge(channels, ThreeBandBoy);

enter image description here


有些代码here或多或少地完全执行了步骤1-3所需的操作。

答案 1 :(得分:2)

最后,我的代码可以正常工作了。下面给出了一些步骤供参考。

count > 1

框架没有多余的副本。

答案 2 :(得分:0)

我正在从文件YUV_I420中读取this YUV image

fstream file;
file.open("yuv_i420.yuv", ios::in | ios::binary);

// size of image in RGB
size_t rows = 144, cols = 176;

if (!file.is_open())
stderr<<"Error opening file"<<endl;
else {
// get total size of file
auto size = file.tellg();
file.seekg(0,ios::end);
size = file.tellg() - size;
file.seekg(0,ios::beg);
char *buffer = new char[size];

// read image from file
if (file.read(buffer, size)) {
  // create YUV Mat
  Mat yuv_I420(rows + rows / 2, cols, CV_8UC1, buffer);

  // draw a rectangle on YUV image, keep in mind that the YUV image is a
  // single channel grayscale image, size is different than the BGR image
  rectangle(yuv_I420, Point(10, 10), Point(50, 50), Scalar(255));
  // convert to BGR to check validity
  Mat bgr;
  cvtColor(yuv_I420, bgr, cv::COLOR_YUV2BGR_I420);
  cv::imshow("image", bgr);
  cv::waitKey(0);
}

file.close();
delete[] buffer;
}