datopdogg7
asked on
Padding of Image Error C++
Hi Experts,
I am trying to runn my edge detection algorithm, but there is an error with my padding algorithm. The algorithm follows directly after the commented line "//creats a single pixel layer of black border around the original image to apply the mask to boundary values"
Please let me know where I am going wrong. The mask I am applying to the image is a 5x5. Is the padding determined by the size of the input image?
Thanks
Dennis
I am trying to runn my edge detection algorithm, but there is an error with my padding algorithm. The algorithm follows directly after the commented line "//creats a single pixel layer of black border around the original image to apply the mask to boundary values"
Please let me know where I am going wrong. The mask I am applying to the image is a 5x5. Is the padding determined by the size of the input image?
Thanks
Dennis
#include <iostream>
#include <fstream>
#include <string>
#include <math.h>
#include <time.h>
using namespace std;
/*** New Data Types ***/
typedef unsigned char BYTE;
// create data structure to hold image
struct PIC
{
unsigned int nChannel;
bool InterLeaved;
unsigned int Width, Height, Maxval;
BYTE *img;
};
template <typename T>
T **AllocateDynamicArray( int nRows, int nCols)
{
T **dynamicArray;
dynamicArray = new T*[nRows];
for( int i = 0 ; i < nRows ; i++ )
dynamicArray[i] = new T [nCols];
return dynamicArray;
}
template <typename T>
void FreeDynamicArray(T** dArray)
{
delete [] *dArray;
delete [] dArray;
}
//function that loads in the header
bool LoadP5Header(ifstream &infile, PIC &pic)
{
bool rtv = true;
char buf[16];
int bufIndex;
int width, height, maxval;
infile.read(buf, 2); // get the magic number
buf[2]='\0';
if(buf[0] == 'P' && buf[1] == '5')
{
infile.read(buf, 1);
while(isspace(buf[0])) // Skip white space(s)
{
infile.read(buf,1);
}
// get width
bufIndex = 0;
while(bufIndex < 15 && !isspace(buf[bufIndex]))
{
bufIndex++;
infile.read(buf+bufIndex, 1);
}
buf[bufIndex] = NULL; // null terminated string
width = atoi(buf);
// get height
infile.read(buf,1);
while(isspace(buf[0])) // Skip white space(s)
{
infile.read(buf,1);
}
bufIndex = 0; //line
while(bufIndex < 15 && !isspace(buf[bufIndex]))
{
bufIndex++;
infile.read(buf+bufIndex, 1);
}
buf[bufIndex] = NULL; // null terminated string
height = atoi(buf);
// get Maxval
infile.read(buf,1);
while(isspace(buf[0])) // Skip white space(s)
{
infile.read(buf,1);
}
bufIndex = 0;
while(bufIndex < 15 && !isspace(buf[bufIndex]))
{
bufIndex++;
infile.read(buf+bufIndex, 1);
}
buf[bufIndex] = NULL; // null terminated string
maxval = atoi(buf);
// Skip white space(s)
//infile.read(buf,1);
// set the image information in the struct
pic.InterLeaved = false;
pic.Width = width;
pic.Height = height;
pic.Maxval = maxval;
}
else rtv = false;
return rtv;
}; // end of LoadP5Header()
//function that accepts an infile object and a PIC Object
//and reads in the PIC object
void LoadImage(ifstream &infile, PIC &pic)
{
infile.read(reinterpret_cast<char *>(pic.img), pic.Width*pic.Height);
}
//function that accepts an outstream file and a PIC object to
//and writes the output stream to the PIC object
void WritePGM(ofstream & outfile, PIC pic)
{
outfile << "P5" << endl;
outfile << pic.Width << " " << pic.Height << endl;
outfile << pic.Maxval << endl;
outfile.write(reinterpret_cast<char *>(pic.img), pic.Width*pic.Height);
}
void MaskFiltering(PIC Pin_t, int Mask[5][5], char *outFileName_Pout)
{
ofstream outfile_Pout;
outfile_Pout.open(outFileName_Pout, ios::binary);
int **IMG_matrix = AllocateDynamicArray<int>(Pin_t.Width+6,Pin_t.Height+6);
int **IMG_temp_matrix = AllocateDynamicArray<int>(Pin_t.Width,Pin_t.Height);
int Npixels, pixelCnt, LoGValue;
int threshVal = 300;
Npixels = Pin_t.Width*Pin_t.Height;
Pin_t.Maxval = 255;
//creats a single pixel layer of black border around the original image to apply the mask to boundary values
for(int j = 0; j <= Pin_t.Height+3; j++)
{
IMG_matrix[0][j] = 0;
IMG_matrix[Pin_t.Width+3][j] = 0;
}
for(int k = 0; k <= Pin_t.Width+3; k++)
{
IMG_matrix[k][0] = 0;
IMG_matrix[k][Pin_t.Height+3] = 0;
}
pixelCnt = 0;
//make 2D matrix of input
for(int j = 1; j <= Pin_t.Height; j++)
{
for(int k = 1; k <= Pin_t.Width; k++)
{
IMG_matrix[k][j] = (int) Pin_t.img[pixelCnt];
pixelCnt++;
}
}
for(int j=1; j <= Pin_t.Height; j++)
{
for(int k=1; k <= Pin_t.Width; k++)
{
LoGValue = Mask[2][2]*IMG_matrix[k][j] + Mask[3][2]*IMG_matrix[k+1][j] + Mask[4][2]*IMG_matrix[k+2][j] + Mask[1][2]*IMG_matrix[k-1][j] + Mask[0][2]*IMG_matrix[k-2][j]
+ Mask[2][3]*IMG_matrix[k][j+1] + Mask[2][4]*IMG_matrix[k][j+2] + Mask[2][1]*IMG_matrix[k][j-1] + Mask[2][0]*IMG_matrix[k][j-2]
+ Mask[3][1]*IMG_matrix[k+1][j-1] + Mask[3][4]*IMG_matrix[k+1][j+1]
+ Mask[1][1]*IMG_matrix[k-1][j-1] + Mask[1][4]*IMG_matrix[k-1][j+1];
if(LoGValue < threshVal) LoGValue = 0;
else if(LoGValue < threshVal) LoGValue = 255;
IMG_temp_matrix[k-1][j-1] = LoGValue;
}
}
//output the calculated 2D matrix to original 1D
pixelCnt = 0;
for(int j = 0; j < Pin_t.Height; j++)
{
for(int k = 0; k < Pin_t.Width; k++)
{
Pin_t.img[pixelCnt] = (unsigned char) (IMG_temp_matrix[k][j]);
pixelCnt++;
}
}
WritePGM(outfile_Pout, Pin_t);
}
int main()
{
ifstream infile_Pin1; /* input file */
char inFileName_Pin1[128]="Lena.pgm"; /* input file name */
PIC Pin1; //source image
/* open input/output file */
infile_Pin1.open(inFileName_Pin1, ios::binary);
/* check input file */
if(!infile_Pin1)
{
cout<<"Cannot open input file "<< inFileName_Pin1 <<endl;
return 1;
}
int LaplacianOfGaussian[5][5] = {{0, 0, 1, 0, 0},
{0, 1, 2, 1, 0},
{1, 2, -16, 2, 1},
{0, 1, 2, 1, 0},
{0, 0, 1, 0, 0}};
if (LoadP5Header(infile_Pin1, Pin1)) // load pgm (Pin) image header information
{
// allocate the memory for the input image
//the dimensions of the original
Pin1.img = new BYTE[Pin1.Width*Pin1.Height];
LoadImage(infile_Pin1, Pin1);
MaskFiltering(Pin1,LaplacianOfGaussian, "Lena_Hildreth_1.pgm");
}
}
ASKER
Hi Infinity,
Thanks Infinity. Unfortunately, when I updated the code with the one you supplied, I still get the same error. The main loop (with the mask multiplication) doesn't even go one iteration through, still k=1, and j=1.
This is the error I am getting. which appears in the line:
+ Mask[3][1]*IMG_matrix[k+1] [j-1] + Mask[3][4]*IMG_matrix[k+1] [j+1]
Unhandled exception at 0x008b1e74 in Marr-Hildreth.exe: 0xC0000005: Access violation reading location 0xfdfdfe01.
Thanks Infinity. Unfortunately, when I updated the code with the one you supplied, I still get the same error. The main loop (with the mask multiplication) doesn't even go one iteration through, still k=1, and j=1.
This is the error I am getting. which appears in the line:
+ Mask[3][1]*IMG_matrix[k+1]
Unhandled exception at 0x008b1e74 in Marr-Hildreth.exe: 0xC0000005: Access violation reading location 0xfdfdfe01.
ASKER
To confirm the code:
#include <iostream>
#include <fstream>
#include <string>
#include <math.h>
#include <time.h>
using namespace std;
/*** New Data Types ***/
typedef unsigned char BYTE;
// create data structure to hold image
struct PIC
{
unsigned int nChannel;
bool InterLeaved;
unsigned int Width, Height, Maxval;
BYTE *img;
};
template <typename T>
T **AllocateDynamicArray( int nRows, int nCols)
{
T **dynamicArray;
dynamicArray = new T*[nRows];
for( int i = 0 ; i < nRows ; i++ )
dynamicArray[i] = new T [nCols];
return dynamicArray;
}
template <typename T>
void FreeDynamicArray(T** dArray)
{
delete [] *dArray;
delete [] dArray;
}
//function that loads in the header
bool LoadP5Header(ifstream &infile, PIC &pic)
{
bool rtv = true;
char buf[16];
int bufIndex;
int width, height, maxval;
infile.read(buf, 2); // get the magic number
buf[2]='\0';
if(buf[0] == 'P' && buf[1] == '5')
{
infile.read(buf, 1);
while(isspace(buf[0])) // Skip white space(s)
{
infile.read(buf,1);
}
// get width
bufIndex = 0;
while(bufIndex < 15 && !isspace(buf[bufIndex]))
{
bufIndex++;
infile.read(buf+bufIndex, 1);
}
buf[bufIndex] = NULL; // null terminated string
width = atoi(buf);
// get height
infile.read(buf,1);
while(isspace(buf[0])) // Skip white space(s)
{
infile.read(buf,1);
}
bufIndex = 0; //line
while(bufIndex < 15 && !isspace(buf[bufIndex]))
{
bufIndex++;
infile.read(buf+bufIndex, 1);
}
buf[bufIndex] = NULL; // null terminated string
height = atoi(buf);
// get Maxval
infile.read(buf,1);
while(isspace(buf[0])) // Skip white space(s)
{
infile.read(buf,1);
}
bufIndex = 0;
while(bufIndex < 15 && !isspace(buf[bufIndex]))
{
bufIndex++;
infile.read(buf+bufIndex, 1);
}
buf[bufIndex] = NULL; // null terminated string
maxval = atoi(buf);
// Skip white space(s)
//infile.read(buf,1);
// set the image information in the struct
pic.InterLeaved = false;
pic.Width = width;
pic.Height = height;
pic.Maxval = maxval;
}
else rtv = false;
return rtv;
}; // end of LoadP5Header()
//function that accepts an infile object and a PIC Object
//and reads in the PIC object
void LoadImage(ifstream &infile, PIC &pic)
{
infile.read(reinterpret_cast<char *>(pic.img), pic.Width*pic.Height);
}
//function that accepts an outstream file and a PIC object to
//and writes the output stream to the PIC object
void WritePGM(ofstream & outfile, PIC pic)
{
outfile << "P5" << endl;
outfile << pic.Width << " " << pic.Height << endl;
outfile << pic.Maxval << endl;
outfile.write(reinterpret_cast<char *>(pic.img), pic.Width*pic.Height);
}
void MaskFiltering(PIC Pin_t, int Mask[5][5], char *outFileName_Pout)
{
ofstream outfile_Pout;
outfile_Pout.open(outFileName_Pout, ios::binary);
int **IMG_matrix = AllocateDynamicArray<int>(Pin_t.Width+6,Pin_t.Height+6);
int **IMG_temp_matrix = AllocateDynamicArray<int>(Pin_t.Width,Pin_t.Height);
int Npixels, pixelCnt, LoGValue;
int threshVal = 300;
Npixels = Pin_t.Width*Pin_t.Height;
Pin_t.Maxval = 255;
//create a two pixel layer of black border around the original image to apply the mask to boundary values
for(int j = 0; j <= Pin_t.Height+3; j++)
{
IMG_matrix[0][j] = 0;
IMG_matrix[1][j] = 0;
IMG_matrix[Pin_t.Width+2][j] = 0;
IMG_matrix[Pin_t.Width+3][j] = 0;
}
for(int k = 0; k <= Pin_t.Width+3; k++)
{
IMG_matrix[k][0] = 0;
IMG_matrix[k][1] = 0;
IMG_matrix[k][Pin_t.Height+2] = 0;
IMG_matrix[k][Pin_t.Height+3] = 0;
}
pixelCnt = 0;
//make 2D matrix of input
for(int j = 2; j < Pin_t.Height + 2; j++)
{
for(int k = 2; k < Pin_t.Width + 2; k++)
{
IMG_matrix[k][j] = (int) Pin_t.img[pixelCnt];
pixelCnt++;
}
}
for(int j=1; j <= Pin_t.Height; j++)
{
for(int k=1; k <= Pin_t.Width; k++)
{
LoGValue = Mask[2][2]*IMG_matrix[k][j] + Mask[3][2]*IMG_matrix[k+1][j] + Mask[4][2]*IMG_matrix[k+2][j] + Mask[1][2]*IMG_matrix[k-1][j] + Mask[0][2]*IMG_matrix[k-2][j]
+ Mask[2][3]*IMG_matrix[k][j+1] + Mask[2][4]*IMG_matrix[k][j+2] + Mask[2][1]*IMG_matrix[k][j-1] + Mask[2][0]*IMG_matrix[k][j-2]
+ Mask[3][1]*IMG_matrix[k+1][j-1] + Mask[3][4]*IMG_matrix[k+1][j+1]
+ Mask[1][1]*IMG_matrix[k-1][j-1] + Mask[1][4]*IMG_matrix[k-1][j+1];
if(LoGValue < threshVal) LoGValue = 0;
else if(LoGValue < threshVal) LoGValue = 255;
IMG_temp_matrix[k-1][j-1] = LoGValue;
}
}
//output the calculated 2D matrix to original 1D
pixelCnt = 0;
for(int j = 0; j < Pin_t.Height; j++)
{
for(int k = 0; k < Pin_t.Width; k++)
{
Pin_t.img[pixelCnt] = (unsigned char) (IMG_temp_matrix[k][j]);
pixelCnt++;
}
}
WritePGM(outfile_Pout, Pin_t);
}
int main()
{
ifstream infile_Pin1; /* input file */
char inFileName_Pin1[128]="Lena.pgm"; /* input file name */
PIC Pin1; //source image
/* open input/output file */
infile_Pin1.open(inFileName_Pin1, ios::binary);
/* check input file */
if(!infile_Pin1)
{
cout<<"Cannot open input file "<< inFileName_Pin1 <<endl;
return 1;
}
int LaplacianOfGaussian[5][5] = {{0, 0, 1, 0, 0},
{0, 1, 2, 1, 0},
{1, 2, -16, 2, 1},
{0, 1, 2, 1, 0},
{0, 0, 1, 0, 0}};
if (LoadP5Header(infile_Pin1, Pin1)) // load pgm (Pin) image header information
{
// allocate the memory for the input image
//the dimensions of the original
Pin1.img = new BYTE[Pin1.Width*Pin1.Height];
LoadImage(infile_Pin1, Pin1);
MaskFiltering(Pin1,LaplacianOfGaussian, "Lena_Hildreth_1.pgm");
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Excellent. Thank you Infinity.
Part of your code already supports that, by looping from 0 to (Pin_t.Height+3), which gives you enough room for the image height itself, and two pixels before and two pixels after (for the border).
But you then proceed to add only one pixel border, with the image not properly centered in it.
To add a two pixel border, and center the image, you can do something like below.
Another thing I noticed, is that you use the width and height indexes in a non-standard manner. Normally, the first index of a 2D array is the row number (ie. along the height of the image), and the second is the column number (ie. along the width of the image).
As long as you do that consistently, there's no problem, but you should realize that it's non-standard, and thus potentially error prone, especially when other people work with the code too.
Open in new window