과제를 위해 우리는 구겨진 512x512 그레이 스케일 이미지를 언 셔플 할 수있는 프로그램을 생성하라는 요청을 받았습니다 (32x32 블록으로 분해 됨으로써 섞여서). 그레이 스케일 이미지는 텍스트 파일을 통해 프로젝트로 가져온 다음 미리 정의 된 함수를 사용하여 값을 1 차원 배열로 변환합니다. 이것을 사용하여 우리는 shuffled 이미지를 복원하려는 의도로 이미지를 저장하고 궁극적으로 조작 할 수있는 매트릭스 클래스를 생성해야했습니다.C++ 서브 매트릭스 생성
비교 방식으로 사용하기 위해 하위 매트릭스를 생성하는 데 문제가 있습니다. 일반적인 아이디어는 셔플 링 된 첫 번째 32x32 블록을 선택하고 일반 이미지는 픽셀 값을 비교하여 일치하는 것을 찾습니다. 다음과 같이 내 getBlock 기능에 대한 기능은 다음과 같습니다
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);
return t;
delete[] block;
}
와의
내()는 다음과 같이 전 기능을 구현하려고했습니다 주 :for (int x = 0; x < 480; x += 32) // so starts at 0 and continues if x less than 480 as 480 + 32 = 512
{
for (int y = 0; y < 480; y += 32) // same as x but with y
{
Matrix block = ShuffledCode.getBlock(x, (x + 32), y, (y + 32));
cout << block.sum() << endl;
}
}
내 문제가 발생할 때마다 시작 열과 시작 행 위의 코드에서 예를 들어, 첫 번째 블록 (startrow 0, endrow 32, startcolumn 0, endcolumn 32)에 대한 값이 올바르게 표시되지만 루프가 반복 될 때 힙 손상 오류가 발생하고 ' 무엇이 잘못되었는지 알아 내십시오. 또 다른 관찰은 내가 32보다 높은 endrow와 endcolumn을 증가 시킨다면 (예를 들어 64로 증가 시키면) 그것은 올바르게 작동하고 올바른 값을 반환하는 것처럼 보입니다.
누군가가 어떤 아이디어를 가지고 있다면 나는 매우 감사 할 것이고 며칠 동안 일해 왔으며 어떤 진전도 이루지 못했습니다. 문제가 프로그램의 다른 부분과 관련된 경우를 대비하여 아래의 모든 코드도 포함 시켰습니다. source.cpp 파일 :
다음과#include <sstream> // stringstream
#include <iostream> // cout, cerr
#include <fstream> // ifstream
#include <istream>
#include <assert.h>
#include "Matrix.H"
using namespace std;
// Input data are provided in .txt format and can be converted to .pgm files for visualization
// Download (free) ImageJ for plotting images in .pgm format
// http://rsb.info.nih.gov/ij/download.html
// Reads .txt file representing an image of R rows and C Columns stored in filename
// and converts it to a 1D array of doubles of size R*C
// Memory allocation is performed inside readTXT
double* readTXT(char *fileName, int sizeR, int sizeC);
// Converts a 1D array of doubles of size R*C to .pgm image of R rows and C Columns
// and stores .pgm in filename
// Use Q = 255 for greyscale images and Q=1 for binary images.
void WritePGM(char *filename, double *data, int sizeR, int sizeC, int Q);
int main()
{
// This part will show you how to use the two functions.
//M and N represent the number of rows and columns in the image,
//e.g. for task 1: logo_with_noise and logo_shuffled, M = 512, N = 512
//e.g. for task 2, Cluttered_scene, M = 768, N = 1024
//e.g. for task 2, Wally_grey, M = 49, N = 36
int M = 512; int N = 512; int count = 0;
// input_data is a pointer to a 1D array of M*N doubles stored in heap. Memory allocation is performed
// inside readTXT. readTXT will read an image (in .pgm format) of size MxN and will store the result in input_data.
// once you're done with data DO NOT forget to delete the memory as in the end of this main() function
double* input_data = 0;
double* noise_data = 0;
cout << endl;
cout << "Data from text file -------------------------------------------" << endl;
// shuffled image is stored in inputFileName, input_data holds the data in a 1d array
char* inputFileName = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\logo_shuffled.txt";
input_data = readTXT(inputFileName, M, N);
// the img with noise is stored in inputFileName2, noise_data holds the data in a 1d array
char* inputFileName2 = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\logo_with_noise.txt";
noise_data = readTXT(inputFileName2, M, N);
// this loop reduces the noise on the provided image to make it clear, uses threshold 170 as i found that gives the best results
for (int x = 0; x < 262144; x++)
{
if (noise_data[x] < 170)
{
noise_data[x] = 0;
}
else
{
noise_data[x] = 255;
}
}
/*long int pLength = 262144; // total length in pixels of 1d array holding the image
long int bLength = 1024; // total length in pixels of each block (32x32)
long int cLength = 262144; // current remaning length in pixels of 1d array holding the image
long int sum = 0; // theoretical limit of 262144 (if all pixels are white thus have the value 255)
for (int rBlocks = 0; rBlocks < 254; rBlocks++)
{
sum = 0;
cLength = pLength - ((rBlocks) * 1024);
double *sub = noise_data - cLength;
assert(sub[0] == noise_data[bLength * rBlocks]);
for (int i = 0; i < 1024; i++)
{
sum += sub[i];
}
cout << sum << endl;
}
*/
// at this point noise_data holds the original image.
Matrix ShuffledCode(512, 512, input_data);
Matrix SortedCode(512, 512, noise_data);
bool wedone = false;
int val = 1024;
// issue with increasing the start row and column above 0, end row and column can be increased fine.
for (int x = 0; x < 480; x += 32) // so starts at 0 and continues if x less than 480 as 480 + 32 = 512
{
for (int y = 0; y < 480; y += 32) // same as x but with y
{
Matrix block = ShuffledCode.getBlock(x, (x + 32), y, (y + 32));
cout << block.sum() << endl;
}
}
/*for (int x = 0; x < 262144; x++)
{
input_data[x] = noise_data[x];
}
*/
/*int MAX = 262144;
for (int i=0; i<MAX; i++)
{
for (int j = i + 1; j < MAX; j++)
{
if (input_data[i] == input_data[j] && noise_data[i] == noise_data[j])
{
}
else
{
input_data[i] = noise_data[i];
input_data[j] = noise_data[j];
}
}
}
*/
// writes data back to .pgm file stored in outputFileName
char* outputFileName = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\logo_restored.pgm";
char* cleanFile = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\logo_clean.pgm";
char* tester = "C:\\Users\\Jamie\\SkyDrive\\Documents\\SoftwareDevAss\\ADS_Assignment\\Datafile\\tester.pgm";
// Use Q = 255 for greyscale images and 1 for binary images.
int Q = 255;
WritePGM(outputFileName, input_data, M, N, Q);
WritePGM(cleanFile, noise_data, M, N, Q);
delete[] noise_data;
delete[] input_data;
return 0;
}
//Consructor
Matrix::Matrix(int sizeR, int sizeC, double* input_data)
{
M = sizeR;
N = sizeC;
data = new double[M*N];
for (int ii = 0; ii < M*N; ii++)
{
data[ii] = input_data[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;
}
//Returns part 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);
return t;
delete[] block;
}
//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] << " ";
}
}
// Read .txt file with image of size RxC, and convert to an array of doubles
double* readTXT(char *fileName, int sizeR, int sizeC)
{
double* data = new double[sizeR*sizeC];
int i = 0;
ifstream myfile(fileName);
if (myfile.is_open())
{
while (myfile.good())
{
if (i>sizeR*sizeC - 1) break;
myfile >> *(data + i);
// cout << *(data+i) << ' '; // This line display the converted data on the screen, you may comment it out.
i++;
}
myfile.close();
}
else cout << "Unable to open file";
//cout << i;
return data;
}
// convert data from double to .pgm stored in filename
void WritePGM(char *filename, double *data, int sizeR, int sizeC, int Q)
{
int i, j;
unsigned char *image;
ofstream myfile;
image = (unsigned char *) new unsigned char[sizeR*sizeC];
// convert the integer values to unsigned char
for (i = 0; i<sizeR*sizeC; i++)
image[i] = (unsigned char) data[i];
myfile.open(filename, ios::out | ios::binary | ios::trunc);
if (!myfile) {
cout << "Can't open file: " << filename << endl;
exit(1);
}
myfile << "P5" << endl;
myfile << sizeC << " " << sizeR << endl;
myfile << Q << endl;
myfile.write(reinterpret_cast<char *>(image), (sizeR*sizeC)*sizeof(unsigned char));
if (myfile.fail()) {
cout << "Can't write image " << filename << endl;
exit(0);
}
myfile.close();
delete[] image;
}
매트릭스 클래스 헤더 파일입니다 같이
#pragma
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
protected:
int M;
int N;
double* data;
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); // addition
Matrix operator = (const Matrix& B); // equals
Matrix operator - (const Matrix& B); // subtraction
Matrix operator * (const Matrix& B); // multiplication
Matrix operator/(const Matrix& B); // division
Matrix operator ++(); // increment by 1
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
어떤 도움이 많이 주시면 감사하겠습니다, 감사합니다. 우선 들어
답장을 보내 주셔서 감사합니다. 나는 .getBlock이 의미하는 바를 오해했다고 생각합니다. 저는 행과 열의 datamemberrs를 0-32로 검색하고, 그 값을 포함하는 더 작은 행렬을 만들었지 만 시작 행/열과 끝 행/열 변수 만 지시하면 블록의 크기가 포함 된 값을 어떻게 변경할 수 있습니까? 예를 들어 ShuffledCode 행렬의 32,64,32,64 위치에있는 값을 블록에 넣고 싶다면? – user2780101
해당 메서드에 impl을 작성 했습니까? – Lother
get 블록은 더 큰 행렬의 값을 가진 32x32 행렬을 반환합니다. 어쨌든, 당신은 해결책에 가깝습니다. 누락 된 핵심은 getBlock 이중 루프 내부에서 증가하는 방식입니다.계산 k에서 얻는 값은 작은 행렬의 크기보다 훨씬 커야합니다. 이 점과 왜 그런 일이 일어 났는지 확신하십시오. 그런 다음 k를 계산하는 방법을 수정하십시오 (32x32 범위로 다시 크기를 조정하는 것입니다) – Lother