C++ 图像处理 - 将图像文件读入二维数组

Posted

技术标签:

【中文标题】C++ 图像处理 - 将图像文件读入二维数组【英文标题】:C++ Image Processing - Reading an Image file into 2D Array 【发布时间】:2012-12-06 18:29:46 【问题描述】:

我是 C++ 的绝对菜鸟,因为我只熟悉 Java 编程。我要做的是将图像文件(.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

我收到一个分段: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])));
    

【问题讨论】:

【参考方案1】:

strcpy() 替换为strncpy(),这显然更安全,并且消除了分段错误。

【讨论】:

【参考方案2】:

在主函数中包含“Image.cpp”并且应该有“Image.h”,否则编译器会识别头文件中已经定义的函数的另一个定义

【讨论】:

以上是关于C++ 图像处理 - 将图像文件读入二维数组的主要内容,如果未能解决你的问题,请参考以下文章

C++ RGB 图像数据叠加成二维数组(向量的向量)

使用 openCV 在 C++ 中查看灰度 RAW 图像文件

C++:读取位图图像的问题

将图像读入数组?

使用 sklearn 库中的 KMeans 实现彩色图像聚类分割

如何在 MATLAB 中将多个图像读入一个数组?