pgm 二进制文件操作中的图像失真

distorted image in pgm binary file manipulation

我正在尝试对 P5 类型的 pgm 图像执行卷积(二进制) 设置如下:

输入输出数组

vector<vector<char>> image(rows, vector<char>(cols, '[=10=]'));
vector<vector<char>> out(rows, vector<char>(cols, '[=10=]'));

const int SIZE = 3;

过滤器

vector<vector<int>> filter = { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } };

将二进制数据插入图像数组

我正在这样读取 PGM 文件:

getline(infile, type);
//getline(infile, comment);   
infile >> rows >> cols;   
getline(infile, line);
getline(infile, highest);    
//getline(infile, line);

for (int i = 0; i < rows; i++)
    for (int j = 0; j < cols; j++)
        infile >> image[i][j]; //infile is from filestream


outfile.open("output.pgm");

//Insert default header attributes into output pgm file.
outfile << type  << "\n" << rows << " " << cols << "\n" << maxpx << "\n";


    for (int i = SIZE / 2; i < rows - SIZE / 2; i++)
    {
        for (int j = SIZE / 2; j < cols - SIZE / 2; j++)
        {
            uint8_t sum = 0;
            for (int k = -SIZE / 2; k <= SIZE / 2; k++)
            {
                for (int l = -SIZE / 2; l <= SIZE / 2; l++)
                {
                    sum += image[i+k][j+l] * filter[k + SIZE / 2][l + SIZE / 2];
                }
            }
          out[i][j] = sum;
        }
    }

将二进制数据写入输出文件

for (int i = 0; i < rows; i++)
    for (int j = 0; j < cols; j++)
        outfile << out[i][j];

当我 运行 代码时我没有得到任何错误,但是图像失真了。我可以清楚地辨认出输出图像的某些部分,但它并不完整。

不知道是不是和我的操作有关

更新:

我把uint8_t改成了char,但还是报同样的错误。

  1. 当我将 outfile << out[i][j]; 更改为 outfile << image[i][j]; 以便恢复实际图像时,但看起来我将文件读入 image 的方式可能存在一些问题向量。不知道在这一点上如何。 我得到这张图片

Lena.pgm file

MCVE(Pastebin)

查看 text and binary streams 的文档:

A text stream is an ordered sequence of characters composed into lines (zero or more characters plus a terminating '\n'). Whether the last line requires a terminating '\n' is implementation-defined. Characters may have to be added, altered, or deleted on input and output to conform to the conventions for representing text in the OS (in particular, C streams on Windows OS convert \n to \r\n on output, and convert \r\n to \n on input)

...

A binary stream is an ordered sequence of characters that can transparently record internal data. Data read in from a binary stream always equals to the data that were earlier written out to that stream. Implementations are only allowed to append a number of null characters to the end of the stream. A wide binary stream doesn't need to end in the initial shift state.

std::fstream 的默认格式是非二进制的,也就是说,它将输入和输出视为文本流。你想操作文件中的原始字节,所以你想把它当作二进制流。要指定二进制流,请在 std::fstream 对象的构造函数中使用 std::ios::binary 标志。

我不是 C++ 专家,但我相信您不能(或者不应该)使用 >> 运算符来读取二进制文件。

我注意到你的图像在有黑色像素的地方出错了,我相信这些空字节被 ifstream 错误地解释了,而你实际上根本不想解释它们。我降低了图像的对比度,因此像素范围不再是 0-255,而是 67-197,一切正常。所以当你的图像中没有低值时它会起作用。

我认为您需要更改从以下位置读取二进制图像数据的方式:

infile >> image[i][j];

类似于:

infile.read((char*)&image[i][j],1);

或者使用 get() 的东西。抱歉,我不能说得更准确,因为 C++ 不是我的强项,但希望您现在可以更进一步。如果有人想在评论中解释我在说什么 - 请随时教我!谢谢。