pgm二进制文件操作中的扭曲图像

时间:2016-09-30 17:42:56

标签: c++ image-processing vector binary convolution

我尝试对类型为pgm的{​​{1}}图片执行卷积( binary ) 设置如下:

输入和输出数组

P5

过滤

vector<vector<char>> image(rows, vector<char>(cols, '\0'));
vector<vector<char>> out(rows, vector<char>(cols, '\0'));

const int SIZE = 3;

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

我正在阅读这样的PGM文件:

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

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

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]; 更改为char,但我仍然遇到同样的错误。

  1. 当我将uint8_t更改为outfile << out[i][j];时,我可以恢复实际图像,但看起来我可能会遇到一些问题,我将文件读入outfile << image[i][j];向量。不知道如何在这一点上。 我得到这张图片enter image description here
  2. Lena.pgm file

    MCVE(Pastebin)

2 个答案:

答案 0 :(得分:2)

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

我通过注意到你的图像在有黑色像素的地方出错而解决了这个问题,并且我认为ifstream当你实际上根本不想要它们被解释时这些空字节被错误地解释了。我降低了图像的对比度,因此像素的范围不再是0-255而是67-197,这一切都有效。因此,当图像中没有低值时,它会起作用。

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

infile >> image[i][j];

类似于:

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

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

答案 1 :(得分:-1)

查看text and binary streams的文档:

  

文本流是由行组成的有序字符序列(零个或多个字符加上终止'\n')。最后一行是否需要终止'\n'是实现定义的。可能必须在输入和输出上添加,更改或删除字符,以符合在OS中表示文本的约定(特别是,Windows OS上的C流在输出时将\n转换为\r\n,并在输入时将\r\n转换为\n

     

...

     

二进制流是一个有序的字符序列,可以透明地记录内部数据。从二进制流读入的数据总是等于先前写入该流的数据。实现只允许在流的末尾附加一些空字符。宽二进制流不需要以初始移位状态结束。

std::fstream的默认格式是非二进制格式,即它将输入和输出视为文本流。您希望操纵文件中的原始字节,因此您希望将其视为二进制流。要指定二进制流,请在std::ios::binary对象的构造函数中使用std::fstream标志。