gpt4 book ai didi

c++ - 制作一个 Mat 类型对象的数组。输出窗口显示相同的帧

转载 作者:行者123 更新时间:2023-11-28 06:17:21 25 4
gpt4 key购买 nike

以下是我的代码。它有一个 Mat 类型对象数组。然后我将在 for 循环内创建的 Mat 添加为 imgArr[index] = img。但是当我输出所有帧在窗口上看动画时,它只显示最后一帧并显示同一帧。

namedWindow( "Display window", WINDOW_AUTOSIZE );// Create a window for display.

int numFrames = endFrame - startFrame; // Total number of frames
Mat imgArr[100];

for(long int FrameNumber = startFrame; FrameNumber < endFrame; FrameNumber++){

fp.seekg( BytesPerFrame*(FrameNumber), std::ios::beg);
char buffer[BytesPerImage];

fp.read(buffer, BytesPerImage);
short image[512*512];

short min = 20000, max=1000;


for ( int i = 0; i < BytesPerImage; i=i+2 )
{
int a;
a = floor(i/2)+1;
// take first character
image[a] = (static_cast<unsigned int>(static_cast<unsigned char>(buffer[i+1]))*256+static_cast<unsigned int>(static_cast<unsigned char>(buffer[i])));
if(image[a] < min){
min = image[a];
}
if(image[a] > max){
max = image[a];
}

}

// Processing the image
Mat img(512, 512, CV_16S, image);
img -= (min);
img *= (32767/max); // (330000/2500);
img *= ((max/min)/2) + 2; // 16;
imgArr[FrameNumber-startFrame] = img;
}

for(int i = 0; i<numFrames; i++){
imshow( "Display window", imgArr[i]); // Show our image inside it.
waitKey(50);
}

最佳答案

您的代码在很多方面都做得不对。我将尝试列出它们:

namedWindow( "Display window", WINDOW_AUTOSIZE );// Create a window for display.

int numFrames = endFrame - startFrame; // Total number of frames
Mat imgArr[100];

第一个问题:如果你的帧数numFrames怎么办?大于100 ?这样会更安全:

std::vector<Mat> imgVector;
imgVector.reserve(numFrames);

然后在每个新帧你push_back一个图像。让我们继续。

for(long int FrameNumber = startFrame; FrameNumber < endFrame; FrameNumber++){

fp.seekg( BytesPerFrame*(FrameNumber), std::ios::beg); //Hmmm, when did you compute BytesPerFrame?
char buffer[BytesPerImage]; //This is actually not C++, you probably even got a warning

您应该替换 char buffer[BytesPerImage]char* buffer = new char[BytesPerImage]; .您还应该在循环之前 预先分配这个中间缓冲区,这样您就只需分配一次并多次使用它。然后,在循环之后,您释放它:delete[] buffer; .

    fp.read(buffer, BytesPerImage); //This seems fine
short image[512*512]; //What's this?

什么是 512 ?我可以稍后再看你的代码,但你应该在某个地方定义如下内容:

const int MYWIDTH = 512;
const int MYHEIGHT = 512;
const int BYTES_PER_IMAGE = MYWIDTH * MYHEIGHT * 2; //Maybe also the 2 should be a constant named `BYTES_PER_PIXEL`

此外,在这种情况下,让我们使用 short* image = new short[MYWIDTH*MYHEIGHT]; 动态分配您的数据.然而,这不会正常工作:不幸的是,如果你构造一个 Mat从外部缓冲区,那么释放将不会被自动管理。最好以相反的方式进行:创建你的 Mat然后将其用作缓冲区。它看起来像这样:

    Mat img(MYHEIGHT, MYWIDTH, CV_16S); //
short* image = static_cast<short*> img.ptr();

进一步操作的一个问题是可能存在“填充字节”。对于 512x512 图像不太可能,但谁知道呢。请断言以下内容为真(参见 doc ):

    (img.cols == img.step1() )

然后:

    short min = 20000, max=1000; 

为什么不 max=0 ?另外,min可以初始化为 32767,或者更优雅地初始化为 std::numeric_limits<short>::max() (#include <limits.h>)

    for ( int i = 0; i < BytesPerImage; i=i+2 )
{
int a;
a = floor(i/2)+1;
// take first character
image[a] = (static_cast<unsigned int>(static_cast<unsigned char>(buffer[i+1]))*256+static_cast<unsigned int>(static_cast<unsigned char>(buffer[i])));
if(image[a] < min){
min = image[a];
}
if(image[a] > max){
max = image[a];
}

}

我的理解是:您的输入缓冲区是一个以大端表示的 16 位图像(最高有效字节在最低有效字节之前)。我看到的问题:

  • 如果最高有效字节大于 127 怎么办?那么你的输出值就会溢出,如128*256=32768 > 32767 .
  • floor(i/2) . floor没有必要:当您除以一个整数值时,它总是返回结果的整数部分。此外,鉴于您的 for 的定义循环,i总是偶数(你递增 2)所以 floor操作是两倍
  • int a; a = floor(i/2)+1;删除 +1 : 想想0索引像素,您会立即看到您将值分配给了错误的像素。对于最后一个像素,您实际上会遇到段错误。您的指令变为:const int a = i/2; (Ehi,多么简单!:))
  • image[a] = [...]; :您正在执行的某些类型转换实际上是必要的,尤其是对 unsigned char 的类型转换.不过,我想知道你为什么不读 buffer作为 unsigned char 的缓冲区首先。所有 unsigned int可以省略转换,因为您不需要最低有效字节,而使用整数值 256将已经推广像素数据
  • 客串:minmax更新函数可以写成:

    min = std::min(min,image[a]);
    max = std::max(max,image[a]);

让我们继续:

    // Processing the image
Mat img(512, 512, CV_16S, image); //Already done, now remove

Mat 的创建已经完成。

   img -= (min);
img *= (32767/max); // (330000/2500);

好的,这有一个更简单的等价物,使用 opencv 库,我们稍后会谈到它。这里有一个问题:这次你真的应该使用 float为你的部门

   img *= (float(32767)/max);

顺便说一句,我想在这种情况下你想要 max-min在分母处:

   img *= (float(32767)/(max-min));

以下我不明白:

   img *= ((max/min)/2) + 2;    // 16;

进一步看,

 imgArr[FrameNumber-startFrame] = img;

鉴于我上面建议的更改(图像的 std::vector),这变成:

 imgVector.push_back(img); 

完成了!


最后一点:在我看来,您可以通过 cv::normalize 获得您想要做的事情。 .你可以这样做:

cv::normalize(img, img, 0, 32767, NORM_MINMAX, CV_16UC1);

关于c++ - 制作一个 Mat 类型对象的数组。输出窗口显示相同的帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30012166/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com