首页 > 解决方案 > 使用 OpenCV C++ 访问帧数据

问题描述

我正在尝试编写一个 Gaussian Blurr OpenCv 程序,在该程序中我输入一个 mp4 视频,逐帧读取它,并在每一帧上应用一个 3x3 模板,该模板基本上模糊了图像。但是,我的问题是我不知道如何访问每一帧的数据。我试着用这种方式做“frame.data”:

int main(int argc, const char** argv) {

// VideoCapture class for playing video for which faces to be detected 
VideoCapture capture;
Mat frame,temp, image;

// PreDefined trained XML classifiers with facial features 
CascadeClassifier cascade, nestedCascade;
double scale = 1;

// Load classifiers from "opencv/data/haarcascades" directory  
nestedCascade.load("C:/opencv/sources/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml");

// Change path before execution  
cascade.load("C:/opencv/sources/data/haarcascades/haarcascade_frontalcatface.xml");

// Start Video..1) 0 for WebCam 2) "Path to Video" for a Local Video 
capture.open("C:/Users/antho/Downloads/videoplayback.mp4");


capture >> frame;
Mat frame1 = frame.clone();
int width = capture.get(CV_CAP_PROP_FRAME_WIDTH);
int height = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
size_t frame_size = 360 * 640 * sizeof(unsigned char);

cout << "Width: " << width << endl;;
cout << "Height: " << height;
unsigned char* d_src;
unsigned char* d_gs;
d_gs = new unsigned char[frame_size];

serialTest(frame1.data, temp.data, width, height);

imshow("blurr", temp);
waitKey(0);

我明白我必须先为 temp 分配数据,但我也不知道该怎么做。我在 d_dst[j * width + i] 处抛出异常错误:

void serialTest(const unsigned char d_src[], unsigned char d_dst[], int width, int height) {

for (int j = 1; j < width - 1; j++) {
     for(int i = 1; i <height -1; i++){

        uchar3 rgb; // (i)(j)
        rgb.x = d_src[j * width + i];

        uchar3 rgb1; //(i-1)(j-1)
        rgb1.x = d_src[(j - 1) * width + (i - 1)];

        uchar3 rgb2; //(i)(j-1)
        rgb2.x = d_src[(j - 1) * width + i];

        uchar3 rgb3; //(i+1)(j-1)
        rgb3.x = d_src[(j - 1) * width + (i + 1)];

        uchar3 rgb4; //(i-1)(j)
        rgb4.x = d_src[(j)*width + (i - 1)];

        uchar3 rgb5; //(i+1)(j)
        rgb5.x = d_src[j * width + (i + 1)];

        uchar3 rgb6; //(i-1)(j+1)
        rgb6.x = d_src[(j + 1) * width + (i - 1)];

        uchar3 rgb7; //(i)(j+1)
        rgb7.x = d_src[(j + 1) * width + i];

        uchar3 rgb8; //(i+1)(j+1)
        rgb8.x = d_src[(j + 1) * width + (i + 1)];

        unsigned char blurr_rgbx = (unsigned char)(rgb.x * (0.25f) + (rgb5.x + rgb4.x + rgb7.x + rgb2.x) * (0.125f) + (rgb1.x + rgb3.x + rgb6.x + rgb8.x) * (0.0625f));

        d_dst[j * width + i] = blurr_rgbx;
    }
}

}

总结一下我的问题如下:

  1. 如何为 Mat 类型的 temp 分配内存?
  2. 如何访问帧的单个像素以便应用模板?
  3. mp4类型是三通道RGB吗?或单个通道,如果是这样,这就是为什么我的模板不适用于像素的原因?我需要包括 rgb.y 和 rgb.z 吗?如果是这样,我怎么知道我的 mp4 视频文件是否有三个频道以及如何访问它们?我之前曾与 CImg 合作过,他们基本上将他们的数据排列在一个 3 维 3 x 宽 x 高的数组中,我可以在其中访问像素,但我如何使用 openCV 做到这一点?

标签: c++opencvgaussianblur

解决方案


  1. 在 OpenCV 中,您可以使用Mat 构造函数来指定 Mat 的大小(高度、宽度、通道),并将分配内存。您正在使用默认构造函数,它不会初始化对象。

  2. 有不同的方法可以访问像素值。您可以使用 Mat .at() 方法,您可以访问原始数据指针...除了从 Mat 参考(检查链接),您可以在此处此处找到更多信息。

  3. 默认情况下,我认为 VideoCapture 将帧转换为 BGR 颜色空间,因此您将拥有 3 个通道(蓝色、绿色、红色)。您还可以直接从 Mat 对象中检查通道数和其他信息(查看文档链接)。


推荐阅读