OpenCV与Matlab的RGB值有所不同?

3
我在尝试将一个MATLAB项目转换为C++代码。然而,当我尝试按帧读取MP4视频时,每个像素的RGB值与MATLAB非常不同。这是否意味着OpenCV使用了不同的RGB值表示法?如果是这样,我该如何将OpenCV值更改为MATLAB?否则,我无法通过检查值来验证我的实现是否正确。
例如: 我正在尝试检查OpenCV和MATLAB中点(0,0)处的值。OpenCV给出以下结果:蓝色=106 绿色=105 红色=102。然而,在MATLAB中,结果是:蓝色=85 绿色=86 红色=83。我尝试获取200帧中点(1,1)(在MATLAB中为点(0,0))的RGB值。
获取OpenCV中RGB值的C++代码如下:
Mat img;
number = 0;
VideoCapture cap(filename_input_video);
if(!cap.isOpened()) {
    printf("No video to Read!\n");
    return -1;
}

for( ; ; ) {
    cap >> img;
    if(img.empty())
        break;
    number++;

    for(int i=0; i<img.rows; i++) {
        for(int j=0; j<img.cols; j++) {
            int blue = img.at<Vec3b>(i, j)[0];
            int green = img.at<Vec3b>(i, j)[1];
            int red = img.at<Vec3b>(i, j)[2];

            if(number == 200 && i==0 && j==0) {
                printf("blue=%d green=%d red=%d", blue, green, red);
            }
        }
    }

    if(number == 200) {
        number = 0;
    }
}

Matlab代码如下:

OBJ = VideoReader(filename_source);
fBlock = 200;
nFrame = get(OBJ, 'NumberOfFrames');
nBlock = ceil(nFrame / fBlock);

for iBlock = 1:nBlock
    display(['Processing video 1 block #' num2str(iBlock) '...']);
    start_index = (iBlock-1)*fBlock+1;
    end_index = min(iBlock*fBlock, nFrame);

    vSource = read(OBJ,[start_index end_index]);
    display(['red ' num2str(vSource(1,1,1,200))]);
    display(['green ' num2str(vSource(1,1,2,200))]);
    display(['blue ' num2str(vSource(1,1,3,200))]);

我该如何解决这个问题?

1
请提供代码和示例数据,以便能够重现您的问题。 - Daniel
提供的代码没有重现任何问题。首先,没有Matlab代码。其次,OpenCV代码太笼统了。如果你声称某一帧的(0, 0)的RGB值是错误的,那么请展示检查/显示该值的代码。最后,有关引起问题的数据可能会有所帮助。 - horchler
2
你应该比较从硬盘读取的单张图像的RGB值。如果你读取了从视频中捕获的帧/图像,则可能会有差异,因为视频解码器可能不同。请尝试并告诉我们结果。 - Pervez Alam
@PervezAlam没错,你说得对!从磁盘读取图像是正确的。但我需要的是从视频中读取,那么为了保持数值与Matlab相同,我该怎么做呢?否则,我很难知道我的实现是否正确。 - user2970089
我将我的评论扩展为答案。这可能对其他人也有帮助。 - Pervez Alam
显示剩余2条评论
2个回答

2
为了验证差异,您应该比较从光盘读取的单个图像的RGB值。如果这里读取的值相同,则表明您的代码可能没有问题,而是解码方面有差异。
可能发生的情况:如果您读取从视频中捕获的帧/图像,则可能存在差异,因为OpenCV(默认为ffmpeg)和MATLAB的视频解码器可能不同。不同的解码器可能会以不同的方式处理某些事件/错误,并且无法保证完全相同的解码结果。
建议的解决方案:
1)相同的解码器 - 如果您需要两个工具的结果相同,请使用相同的解码器。更改OpenCV或MATLAB的解码器都可以。如果您搜索一下,就会发现一些相关文章。 这篇 这篇 可能会有所帮助。
2)相同的视频 - 首先使用任何解码器(我喜欢ffmpeg)将视频转换为原始格式。现在,您可以在两个工具上使用它而不必担心差异。以下是一个从压缩格式获取原始格式的命令:
`c:/> ffmpeg -i compressed_or_original_video.avi -vcodec rawvideo raw_converted_video.avi`

-1
不是的!你看到不同的结果是因为C++数组索引从零开始,而Matlab/Octave索引从1开始。

1
我已经更新了我的问题。是的,我知道索引,所以我在C++中检查(0,0),在Matlab中检查(1,1),没有索引错误。 - user2970089
那么i和j呢?你也在它们上面使用了正确的索引吗? - Amen
尝试在零值(黑色)像素或255(白色)像素上检查您的代码,如果它们不相同,则肯定存在代码问题或您忽略了某些内容。 - Amen
i和j是图像点位置的索引。我已经更新了。 - user2970089
2
你在双重循环中访问的是视频的哪一帧?在Matlab中你访问的是哪一帧?你确定这两个帧是相同的吗? - Amen
我已经更新了问题。我每200帧检查一次像素值。然而,即使我在Matlab中检查190-210帧,仍然没有与OpenCV匹配的单个帧。 - user2970089

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接