作为我大学作业的一部分,我们需要比较两张 .txt 格式的图像,一张是普通图像,另一张是图像的混乱版本。
两张图片都是 512x512,我们被要求考虑它们已被分成 16x16 块,这意味着每个块都是 32x32。
为了比较这两个图像,我在图像块上使用平方差总和算法。从左上角开始,一路走来,直到找到合适的数学。然而,这是我的问题发生的地方,在成功地从未混杂的图像中获取单个块并将其与混杂图像中的另一个块进行比较后,第二次迭代会导致以下错误:
Windows 已在 Assignment1.exe 中触发断点。
这可能是由于堆损坏,这表明 Assignment1.exe 或其已加载的任何 DLL 中存在错误。
我的问题是是什么导致了我的代码中的错误?
以下是我的名为 Matrix.h 的头文件,它将从 txt 文件中获得的 2d 矩阵转换为 1d 图像。
#pragma
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
protected:
int M;
int N;
double* data;
Matrix(){M = 0; N = 0;data = 0;} //Constructor to avoid error
public:
Matrix(int sizeR, int sizeC, double* input_data); //Constructor
Matrix(int sizeR, int sizeC);
~Matrix(); //Destructor
Matrix(const Matrix& existingMatrix); //Copy Constructor
double get (int i , int j) const; //Returns value at specified location
const void set(int i, int j, double& val); //Changes value at specified location
int getM() const; //Return value of M
int getN() const; //Return value of N
Matrix getBlock(int startRow, int endRow, int startColumn, int endColumn); //Return section of Matrix
Matrix operator + (const Matrix& B);
Matrix operator = (const Matrix& B);
Matrix operator - (const Matrix& B);
Matrix operator * (const Matrix& B);
Matrix operator / (const Matrix& B);
Matrix operator ++ ();
double operator () (int i, int j);
void out();
double sum();
};
class BinaryImage
:public Matrix
{
public:
BinaryImage(int sizeR, int sizeC, double* input_data, double thresh);
~BinaryImage();
BinaryImage(const Matrix& rhs, double thresh);
BinaryImage(const BinaryImage& existingBinIm);
const void set(int i, int j, double& val);
};
#endif
下一节是我的 Main,我们在出现错误的情况下使用的方法称为 shuffledLogo()。
#include<iostream>
#include<Windows.h>
#include<fstream>
#include<string>
#include"Matrix.h"
using namespace std;
void shuffledLogo();
double* readTXT(char* fileName, int sizeR, int sizeC);
void writePGM(char* fileName, Matrix& toWrite, int Q);
int main()
{
int selection;
cout<<"Select a program to run:"<<endl<<"1 - Logo Reorganisation"<<endl<<"2 - Where's Wally"<<endl<<"Selection: ";
cin>>selection;
cout<<endl;
switch(selection)
{
case 1:
cout<<"Logo Reorganisation Commencing..."<<endl;
shuffledLogo();
break;
case 2:
cout<<"Where's Wally Commencing..."<<endl;
break;
default:
cout<<"Selection invalid"<<endl;
break;
}
Sleep(1000);
return 0;
}
//Consructor
Matrix::Matrix(int sizeR, int sizeC, double* inputData)
{
M = sizeR;
N = sizeC;
data = new double [M*N];
for (int ii = 0; ii < M*N; ii++)
{
data[ii] = inputData[ii];
}
}
Matrix::Matrix(int sizeR, int sizeC)
{
M = sizeR;
N = sizeC;
data = new double [M*N];
for (int ii = 0; ii < M*N; ii++)
{
*(data+ii) = 0;
}
}
//Destructor
Matrix::~Matrix()
{
delete [] data;
}
//Copy Constructor
Matrix::Matrix(const Matrix& existingMatrix)
{
M = existingMatrix.getM();
N = existingMatrix.getN();
data = new double[M*N];
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
int k = ii*N+jj;
data[k] = existingMatrix.get(ii,jj);
}
}
}
//Pass by constant value
double Matrix::get (int i , int j) const
{
int k = i*N + j;
return data[k];
}
//Pass by Refrence
const void Matrix::set(int i, int j, double& val)
{
int k = i*N + j;
val = data[k];
}
//Return Value of M
int Matrix::getM() const
{
return M;
}
//Return Value of N
int Matrix::getN() const
{
return N;
}
//Return Section of the Matrix.
Matrix Matrix::getBlock(int startRow, int endRow, int startColumn, int endColumn)
{
int Row = endRow-startRow;
int Column = endColumn - startColumn;
double* block = new double[(Row)*(Column)];
int n = endColumn-startColumn;
for (int ii = startRow; ii < endRow; ii++)
{
for (int jj = startColumn; jj < endColumn; jj++)
{
int k = ii*n+jj;
block[k] = data[ii*N+jj];
}
}
Matrix t(Row,Column,block);
delete [] block;
return t;
}
//Allows for addion of Matricies, Operation Overloading.
Matrix Matrix::operator +(const Matrix& B)
{
Matrix C = Matrix(M, N, 0);
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N+jj] + B.get(ii,jj);
C.set(ii,jj, temp);
}
}
return C;
}
//Makes x and y equal, Opperation Overloading.
Matrix Matrix::operator =(const Matrix& B)
{
if (this == &B)
{
return *this;
}
else
{
M = B.getM();
N = B.getN();
delete [] data;
data = new double [M*N];
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
data[ii*N+jj] = B.get(ii,jj);
}
}
return *this;
}
}
//Allows for subtraction of matricies, Operation Overloading.
Matrix Matrix::operator -(const Matrix& B)
{
Matrix C = Matrix(M, N);
double temp;
for (int ii = 0; ii < M-1; ii++)
{
for (int jj = 0; jj < N-1; jj++)
{
temp = data[ii*N+jj] - B.get(ii,jj);
C.set(ii,jj, temp);
}
}
return C;
}
//Allows for multiplication of Matricies, Operation Overloading.
Matrix Matrix::operator *(const Matrix& B)
{
Matrix C = Matrix(M, B.getN());
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N+jj] * B.get(ii,jj);
C.set(ii,jj, temp);
}
}
return C;
}
//Allows for addition of Matricies, Operation Overloading.
Matrix Matrix::operator /(const Matrix& B)
{
Matrix C = Matrix(M, B.getN(), 0);
double temp;
for (int ii = 0; ii < M; ii++)
{
for (int jj = 0; jj < N; jj++)
{
temp = data[ii*N+jj] / B.get(ii,jj);
C.set(ii,jj, temp);
}
}
return C;
}
//Incrmentation of all values in Matrix by 1, Operation Overloading.
Matrix Matrix::operator ++()
{
for (int ii = 0; ii < M*N; ii++)
{
data[ii] = data[ii]++;
}
return *this;
}
//Allows calling of "get" function indirectly.
double Matrix::operator() (int i, int j)
{
return data[i*N+j];
}
double Matrix::sum()
{
double total = 0.0;
for (int ii = 0; ii < M*N; ii++)
{
total = total + data[ii];
}
return total;
}
void Matrix::out()
{
for (int ii = 0; ii < M*N; ii++)
{
if(data[ii] == 255)
cout<<"1 ";
else
cout<<data[ii]<<" ";
}
}
BinaryImage ::BinaryImage(int sizeR, int sizeC, double*input_data, double thresh)
:Matrix(sizeR, sizeC, input_data)
{
for(int ii = 0; ii < M*N; ii++)
{
if (data[ii] > thresh)
{
data[ii] = 1;
}
else
{
data[ii] = 0;
}
}
}
BinaryImage::BinaryImage(const Matrix& rhs, double thresh)
:Matrix(rhs)
{
for(int ii = 0; ii < M*N; ii++)
{
if (data[ii] > thresh)
{
data[ii] = 1;
}
else
{
data[ii] = 0;
}
}
}
BinaryImage::BinaryImage(const BinaryImage& rhs)
{
M = rhs.getM();
N = rhs.getN();
data = new double[M*N];
for (int ii = 0; ii<M; ii++){
for (int jj = 0; jj<N; jj++){
data[ii] = rhs.get(ii, jj);
}
}
}
const void BinaryImage::set(int i, int j, double& val)
{
int k = i*N + j;
val = data[k];
}
void shuffledLogo()
{
char* filePath2 = "E:\\logo_shuffled.txt";
double* basIm2 = readTXT(filePath2, 512, 512);
Matrix logoWithNoise(512, 512, basIm2);
cout<<"done"<<endl;
//Reads in the Shuffled Image
char* filePath = "E:\\logo_shuffled.txt";
double* basIm = readTXT(filePath, 512, 512);
Matrix logoShuffled(512, 512, basIm);
cout<<"done"<<endl;
Matrix logoUnshuffled(512,512);
double Score = 0.0; //Current "Pixels" score
double bestScore = 0.0; //Best "Pixel" score
int bestX, bestY = 0;
//For Loop to begin Sum of Squared Differences
for (int x = 0; x < 480; x+=32)
{
for (int y = 0; y < 480; y += 32)
{
Matrix subWithNoise = logoWithNoise.getBlock(x,(x+32),y,(y+32));
//subShuffled.out();
bestScore = 70000.0;
for (int xx = 0; xx< 480; xx+=32)
{
for (int yy = 0; yy < 480; yy+=32)
{
//Calculating the Score starts here
cout<<"loop started"<<endl;
int t = yy+32;
int l = xx+32;
Matrix subShuffled = logoShuffled.getBlock(xx,l, yy, t);
cout<<"submade"<<endl;
Matrix diff = subWithNoise - logoWithNoise;
Matrix product = diff*diff;
Score = diff.sum();
if (Score < bestScore)
{
bestScore = Score;
bestX = xx;
bestY = yy;
}
cout<<"loop ended"<<endl;
}
}
//For loop to put the best option into the final Matrix
for (int ii = bestX; ii < (bestX+=32); ii++)
{
for (int jj = bestY; jj < (bestY+=32); jj++)
{
double temp = logoShuffled.get(ii,jj);
logoUnshuffled.set(ii,jj,temp);
}
}
}
}
//Creates file
char* newFile = "finished.pgm";
writePGM(newFile, logoUnshuffled, 1);
}
//Reads in file and from specified location and builds it
double* readTXT(char* fileName, int sizeR, int sizeC)
{
double* input_data = new double[sizeR*sizeC];
int i =0;
ifstream currentFile(fileName);
if (currentFile.is_open())
{
while(currentFile.good())
{
if (i>sizeR*sizeC-1) break;
currentFile >> *(input_data+i);
i++;
}
currentFile.close();
}
else
{
cout<<"File path not found"<<endl;
}
return input_data;
delete [] input_data;
}
void writePGM(char* fileName, Matrix& toWrite, int Q)
{
int x = toWrite.getM();
int y = toWrite.getN();
unsigned char *image;
ofstream myfile;
image = (unsigned char *) new unsigned char [x*y];
// convert the integer values to unsigned char
for(int i = 0; i<x; i++)
{
for (int j = 0; j<y; j++)
{
image[i*y+j]=(unsigned char)toWrite.get(i,j);
}
}
myfile.open(fileName, ios::out|ios::binary|ios::trunc);
if (!myfile)
{
cout << "Can't open file: " << fileName << endl;
exit(1);
}
myfile << "P5" << endl;
myfile << y << " " << x << endl;
myfile << Q << endl;
myfile.write( reinterpret_cast<char *>(image), (x*y)*sizeof(unsigned char));
if (myfile.fail())
{
cout << "Can't write image " << fileName << endl;
exit(0);
}
myfile.close();
delete [] image;
}
我冒昧地将我的文件夹放在公共保管箱文件中,以便大家查看是否希望更好地查看错误。我知道我的代码可能很混乱且显示效果不佳,所以如果有人对如何使它更好有任何建议,请说。