简体   繁体   中英

convolution using a 3X3 low pass filter for a .pgm image in C++

I'm trying to write a program in C++ which has following 3 functions: (i) read_pgm_image() - to read the image in .pgm format from a file; (ii) convolve() - to perform convolution on the image using a 3X3 low pass filter; and, (iii) write_pgm_image() - to write the image data back into a separate file

Here is my code:

#include<iostream>
#include<fstream>
#include<string>
using namespace std;

void read_pgm_image(char name[]);
void convolve(int img[][256], int M, int N, int img_intensity);
void write_pgm_image(char name[], int img[256][256], int img_data[]);

int main()
{   read_pgm_image("lenna2.pgm");

    getchar();
    return 0;
}

void read_pgm_image(char name[])
{   string magic, creator_info;
    int img_intensity, M, N;
    ifstream file(name, ios::binary);
    if(file.is_open())
    {   cout<<"File successfully opened! \n\n";
        cout<<"Reading the file...\n";
        cout<<"Name of the file:\t"<<name<<'\n';

        getline(file,magic); // get the magic number

        getline(file,creator_info); // get the creator information

        file>>M; // get width of the image
        cout<<"Width of the Image:\t"<<M<<'\n';

        file>>N; // get length of the image
        cout<<"Length of the Image:\t"<<N<<'\n';

        file>>img_intensity; // get the image intensity
        cout<<"Maximum Intensity:\t"<<img_intensity<<'\n'; 

        int img[256][256]; // create an array to store image data
        for(int i=0; i<N; i++)
        {   for(int j=0; j<M; j++)
            {   file.read((char*)&img[i][j],sizeof(int));
            }
        }
        file.close();

        convolve(img, M, N, img_intensity); // Calling the Convolve function
    }
    else
    {   cout<<"Error in opening image!";
        file.close();
    }
}



void convolve(int img[256][256], int M, int N, int img_intensity)
{   int con_img[256][256], sum=0, img_data[3]={M,N,img_intensity};

    for(int i=0; i<N; i++)
    {   for(int j=0; j<M; j++)
        {   con_img[i][j]=img[i][j];
        }
    }

    for(int i=1; i<(N-1); i++)
{   for(int j=1; j<(M-1); j++)
    {   for(int k=(i-1); k<(i+1); k++)
        {   for(int l=(j-1); l<(j+1); l++)
            {   sum = sum + img[k][l];
            }
        }
        con_img[i][j] = sum/9;
        sum=0;
    }
}

write_pgm_image("image_convolve.pgm", con_img, img_data);
}



void write_pgm_image(char name[], int img[256][256], int img_data[3])
{ cout<<"\nCreating image file...\n";

  ofstream file(name,ios::binary);

  if(file.is_open())
  {   cout<<"File successfully created!\n";
      cout<<"Writing image data...\n";

      file<<"P5\n"<<img_data[0]<<' '<<img_data[1]<<' '<<img_data[2]; //Writing P5, image width, image length and maximum intensity

      cout<<"Image data written!\n";

      for(int i=0; i<img_data[1]; i++)  //Write image data to the file
        {   for(int j=0; j<img_data[0]; j++)
            {   file.write((char*)&(img[i][j]), sizeof(int));
            }
        }
      cout<<"Image pixel info written!\n";
      file.close();
  }
  else
  { cout <<"Error in creating file!";
    file.close();
  }
}

There seems to be some problem in the convolve() function. Ideally, I should be getting a blurred version of input image (which I'm not able to upload). But I'm getting a garbage image instead.

Any help is much appreciated... Thank you.

k和l的循环边界有一个小错误(<应该是<=),所以你总计4个像素而不是9个。你以后用9除以得到平均值,如果你添加了这个是正确的增加正确的像素数,但总和已经存在缺陷。

You are declaring img to be a 2D array of integers, that is to say every entry in the array is 4 bytes. You are also reading the file 4 bytes at a time using sizeof(int) .

 int img[256][256]; // create an array to store image data
 for(int i=0; i<N; i++)
 {   for(int j=0; j<M; j++)
     {   file.read((char*)&img[i][j],sizeof(int));
     }
 }

According to the PGM file specification , pixel values are either 1 or 2 bytes , (either char or shorts ) depending on whether the max intensity value is larger than 255. You are reading either 2 or 4 pixel values from the file into 1 entry in your img array.

Your file reader should look more liked this. We can read the file in all at once since both C++ and PGM arrays store data in row-major order.

char img[N][M];
file.ignore(); // ignore one character (as described in file specification)
file.read((char*)img,(streamsize)sizeof(img));

If it still isn't working, make sure you can reproduce the results of this PGM file test.pgm :

P5
# this is a comment
5 5
255
!!!!!AAAAA~~~~~AAAAA!!!!!

Printing out the matrix gives these values:

33 33 33 33 33 
65 65 65 65 65 
126 126 126 126 126 
65 65 65 65 65 
33 33 33 33 33

The image viewer on my computer displays it like this (zoomed in 2000%):

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM