我想在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));
}
答案 0 :(得分:2)
由于您未提供任何示例数据,请使用@zindarod提供的尺寸为144x176的文件。
这是YUV数据在内存中的外观:
在流中注意底部...所有Y像素排在最前面。然后,所有的U像素都将采样率降低为4。然后,所有的V像素,也将采样率降低为4。
我没有时间在OpenCV中编写代码,但是我可以向您展示如何用它制作常规Mat。
第1步-提取Y频道
获取前144x176个字节,并将其放入称为Y
的144x176 8UC1 Mat中。
第2步-提取U频道
跳过前144x176个字节,然后提取下一个72x88个字节,然后将它们放入另一个称为U的72x88 8UC1 Mat中。调整此Mat的大小以使其宽度加倍并使其高度加倍,即144x176。
第3步-提取V频道
跳过第一个(144x176)+(88x72)字节,然后将下一个72x88字节放入另一个称为V的72x88 8UC1 Mat中。调整此Mat的大小以使其宽度加倍,高度加倍,即144x176。
第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);
有些代码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;
}