2014-01-29 3 views
1

과제를 위해 우리는 구겨진 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 

어떤 도움이 많이 주시면 감사하겠습니다, 감사합니다. 우선 들어

답변

0

, 당신의 getBlock 방법이보고 : 리턴 블록이 삭제되지 없구요 때문에 힙 메모리 유출을 의미 한 후

return t; 
delete[] block; 

은 삭제합니다.

지금 당신은 왜 힙 손상이 있습니다 (? 당신이 최종 계산하는 방법을 참조 - 시작을 그 항상 32 될 것) 당신은 항상 32 * 32 블록을 할당하려고

// This is how you call, x = startRow, x+32 is endRow. 
Matrix block = ShuffledCode.getBlock(x, (x + 32), y, (y + 32)); 

// This is inside your method: (endRow is startRow + 32) = 32 always 
int Row = endRow - startRow; 

하지만 그 방법에서는 입력 매개 변수를 사용하여 32를 넘어선 방법으로 액세스하고 있습니다. 따라서 루프가 i = 1이되면 startRow는 32이고 끝 행은 64입니다. 그러나 행렬은 32로만 이동합니다!

+0

답장을 보내 주셔서 감사합니다. 나는 .getBlock이 의미하는 바를 오해했다고 생각합니다. 저는 행과 열의 datamemberrs를 0-32로 검색하고, 그 값을 포함하는 더 작은 행렬을 만들었지 만 시작 행/열과 끝 행/열 변수 만 지시하면 블록의 크기가 포함 된 값을 어떻게 변경할 수 있습니까? 예를 들어 ShuffledCode 행렬의 32,64,32,64 위치에있는 값을 블록에 넣고 싶다면? – user2780101

+0

해당 메서드에 impl을 작성 했습니까? – Lother

+0

get 블록은 더 큰 행렬의 값을 가진 32x32 행렬을 반환합니다. 어쨌든, 당신은 해결책에 가깝습니다. 누락 된 핵심은 getBlock 이중 루프 내부에서 증가하는 방식입니다.계산 k에서 얻는 값은 작은 행렬의 크기보다 훨씬 커야합니다. 이 점과 왜 그런 일이 일어 났는지 확신하십시오. 그런 다음 k를 계산하는 방법을 수정하십시오 (32x32 범위로 다시 크기를 조정하는 것입니다) – Lother