问题
I'm trying to perform convolution on a pgm
image of type P5
(binary)
with the set up below:
input and output array
vector<vector<char>> image(rows, vector<char>(cols, '\0'));
vector<vector<char>> out(rows, vector<char>(cols, '\0'));
const int SIZE = 3;
Filter
vector<vector<int>> filter = { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } };
insert binary data into image array
I'm reading PGM file like this:
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;
}
}
Write binary data into out file
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
outfile << out[i][j];
I do not get any error when I run the code, but the image is distorted. I can clearly make out some part of the output image, but it's is not coming out complete.
Not sure if it has to do with my manipulation.
Update:
I changed uint8_t
to char, but I still get the same error.
- When I change
outfile << out[i][j];
tooutfile << image[i][j];
so I can get the actual image back, but looks like there could be some issues with how I'm reading the file intoimage
vector. Not sure how to at this point. I get this image
Lena.pgm file
MCVE(Pastebin)
回答1:
I am no expert on C++, but I believe you cannot (or maybe should not) use the >>
operator to read binary files.
I worked this out by noticing that your image goes wrong where there are black pixels and I believe that these null bytes are being interpreted incorrectly by ifstream
when you don't actually want them interpreted at all. I decreased the contrast on your image so the range of the pixels was no longer 0-255 but 67-197 and it all works. So it works when there are no low values in your image.
I believe you need to change the way you read the binary image data from:
infile >> image[i][j];
to something like:
infile.read((char*)&image[i][j],1);
or maybe something using get()
. Sorry, I cannot be more precise, as C++ is not my forte but hopefully you can now proceed further. If anyone cares to explain what I am saying in a comment - please feel free to teach me! Thank you.
回答2:
Check out the documentation for 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.
The default format for a std::fstream
is non-binary, that is, it treats the input and output as a text stream. You want to manipulate the raw bytes in the file, so you want to treat it as a binary stream. To specify a binary stream, use the std::ios::binary
flag in the constructor of your std::fstream
object.
来源:https://stackoverflow.com/questions/39797167/distorted-image-in-pgm-binary-file-manipulation