web-dev-qa-db-ja.com

C ++画像処理-画像ファイルを2D配列に読み込む

Javaプログラミングに精通しているだけなので、私はC++の完全な初心者です。私がやろうとしているのは、画像ファイル(.bmp)をマトリックスに読み込んで、 3x3マトリックス(フィルター)で畳み込みを実行して、畳み込み画像を含む新しい画像ファイルを作成できます。

私はグーグルを見回して、次の実装を考え出すことができました:

Image.hファイル:

//  Image.h

#include <fstream> // for file I/O

using namespace std;
typedef unsigned char unchar; // Easier to understand & code.

class MImage {

public:
    MImage(const char* fileName); //Constructor
    ~MImage(); //Deconstructor
    void write(const char* fileName);
    void smoothFilter(); //smoothing filer.
private:
    ifstream* pInFile; 
    ofstream* pOutFile;
    unchar imageHeaderData[1078]; //.bmp header data with offset 1078.
    unchar** imageData;
    unchar m_smoothFilter[3][3]; // Smoothing Filter.
    unchar**  filteredData;
};

Image.cppファイル:

//  Image.cpp
//

#ifndef _Image_h
#define _Image_h
#define WIDTH 128
#define HEIGHT 128

#include "Image.h"
#include <cmath>

#endif

using namespace std;
typedef unsigned char unchar;

//Constructor

MImage::MImage(const char* fileName){

    imageData = new unchar* [HEIGHT]; // create new array size: height of image.
    filteredData = new unchar* [HEIGHT];// create new array size: height of image.

    for (int i = 0; i < HEIGHT; i++) {

        imageData[i] = new unchar [WIDTH]; //create matrix.
        filteredData[i] = new unchar [WIDTH]; //create matrix.
    }

    //image I/O
    pInFile = new ifstream;
    pInFile->open(fileName, ios::in | ios::binary); // open fileName and read as binary.
    pInFile->seekg(0, ios::beg); //pos filter at beginning of image file.
    pInFile->read(reinterpret_cast<char*>(imageHeaderData),1078); //read bmp header data into array.

    for(int i=0; i<HEIGHT; i++) {
        pInFile->read(reinterpret_cast<char*>(imageData[i]),WIDTH);//read row into each array entry.
    }

    pInFile->close(); //close stream.

    char m_smoothFilter[3][3] = {
                                 {1,1,1},
                                 {1,2,1},
                                 {1,1,1}
                                };

}

MImage::~MImage(){

    delete pInFile;
    delete pOutFile;

    for(int i=0; i<HEIGHT; i++){
        delete[] imageData[i];
        delete[] filteredData[i];
    }

    delete[] imageData;
    delete[] filteredData;
}

void MImage::write(const char* fileName) {

    smoothFilter();
    pOutFile = new ofstream;
    pOutFile->open(fileName, ios::out | ios::trunc | ios::binary);
    pOutFile->write(reinterpret_cast<char*>(imageHeaderData), 1078); //write header data onto output

    for(int i = 0; i < HEIGHT; i++){

        pOutFile->write(reinterpret_cast<char*>(filteredData[i]),WIDTH); // write new image data.

    }

    pOutFile->close(); //close stream
}

void MImage::smoothFilter(){

    //copy input image into new image
    for(int i = 0; i < HEIGHT; i++) {
        strcpy(reinterpret_cast<char*>(filteredData[i]), reinterpret_cast<char*>(imageData[i]));
    }

    int sumOfPixels = 0;

    for(int i = 1; i < HEIGHT -1; i++) {

        for(int j = 1; j < WIDTH -1; j++) {

            sumOfPixels = m_smoothFilter[0][0] * imageData[i+1][j-1] + // top left corner
                          m_smoothFilter[0][1] * imageData[i+1][j]   + // top center
                          m_smoothFilter[0][2] * imageData[i+1][j+1] + // top right corner
                          m_smoothFilter[1][0] * imageData[i][j-1]   + // center left
                          m_smoothFilter[1][1] * imageData[i][j]     + // center center
                          m_smoothFilter[1][2] * imageData[i][j+1]   + // center right
                          m_smoothFilter[2][0] * imageData[i-1][j-1] + // bottom left corner
                          m_smoothFilter[2][1] * imageData[i-1][j]   + // bottom center
                          m_smoothFilter[2][2] * imageData[i-1][j+1];  // bottom right corner

            filteredData[i][j] = (sumOfPixels / ( m_smoothFilter[0][0] + m_smoothFilter[0][1] +
                                                  m_smoothFilter[0][2] + m_smoothFilter[1][0] +
                                                  m_smoothFilter[1][1] + m_smoothFilter[1][2] +
                                                  m_smoothFilter[2][0] + m_smoothFilter[2][1] +
                                                 m_smoothFilter[2][2]));
        }
    }

}

Main.cppファイル:

//
//  Main.cpp
//

#include <iostream>
#include "Image.cpp"
#include <fstream>

using namespace std;

int main() {

    MImage img("test.bmp");
    img.write("output.bmp");
    return 0;

}

次のファイルを実行しようとすると:

g++ Main.cpp -o main

./main

「segmentation:11」エラーが発生しましたが、このエラーの原因がわかりません!

注:純粋なC++実装を使用する必要があるため、他のライブラリを使用できません。

助けて!

編集:私は私にセグメンテーションエラーを与えているコードだと思います:

for(int i = 0; i < HEIGHT; i++) {
        strcpy(reinterpret_cast<char*>(filteredData[i]), reinterpret_cast<char*>(imageData[i]));
}

しかし、なぜだかわかりません!

編集#3:上記のコードを次のコードに置き換えた後に機能します:

for(int i= 0; i<HEIGHT; i++) {
        strncpy (reinterpret_cast<char*>(filteredData[i]), 
                 reinterpret_cast<char*>(imageData[i]), 
                 sizeof(reinterpret_cast<char*>(filteredData[i])));
    }
11
MathanMV

strcpy()strncpy()に置き換えました。これは明らかに安全性が高く、セグメンテーション違反が取り除かれました。

5
MathanMV

メイン関数に「Image.cpp」を含め、「Image.h」があるはずです。そうでない場合、コンパイラーはヘッダーファイルですでに定義されている関数の別の定義を認識します。

2
John Smith