C++で画像の保存をマスターする7つの方法

C++で画像を保存するプロセスを表すイラストC++
この記事は約17分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

C++を使用して画像を保存する方法について学ぶことは、プログラミングの世界で非常に重要なスキルです。

画像の保存は、ウェブ開発、データ分析、ゲーム開発など多岐にわたる分野で役立ちます。

この記事では、C++を使って画像を保存する基本的な手法から応用的なテクニックまで、段階的に解説します。

C++に初めて触れる方から経験豊富なプログラマーまで、どんなレベルの方にも役立つ内容を目指しています。

●C++における画像保存の基礎

C++で画像を扱う基本は、画像ファイルを読み込み、加工し、保存するプロセスを理解することから始まります。

画像の保存には、様々なライブラリが存在しますが、ここでは特にポピュラーで使いやすいライブラリを例に取り上げます。

初心者でも理解しやすいように、必要なコードとその解説を交えながら進めていきましょう。

○サンプルコード1:基本的な画像の保存方法

最も基本的な画像保存の方法を紹介します。

ここでは、OpenCVというライブラリを使用します。

OpenCVは、画像処理やコンピュータビジョンに関する豊富な機能を提供するオープンソースのライブラリです。

まずは、OpenCVを使って画像を読み込み、そのまま保存する簡単な例を見てみましょう。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("example.jpg"); // 画像を読み込む
    if(image.empty()) {
        std::cout << "画像が読み込めませんでした。" << std::endl;
        return -1;
    }
    cv::imwrite("saved_image.jpg", image); // 画像を保存
    return 0;
}

このコードでは、まずOpenCVのヘッダーファイルをインクルードしています。

cv::Matは、OpenCVにおける画像データの基本的な型です。

cv::imread関数で画像を読み込み、cv::imwrite関数で読み込んだ画像を別のファイル名で保存しています。

もし画像が読み込めなかった場合、エラーメッセージを出力しています。

○サンプルコード2:異なるフォーマットで画像を保存

次に、画像を異なるフォーマットで保存する方法を見ていきましょう。

多くの場合、JPEGやPNGなどの異なるファイル形式で画像を保存する必要があります。

OpenCVを使用して、画像を異なる形式で保存する方法を示します。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("example.jpg");
    if(image.empty()) {
        std::cout << "画像が読み込めませんでした。" << std::endl;
        return -1;
    }
    cv::imwrite("saved_image.png", image); // PNG形式で画像を保存
    return 0;
}

このコードでは、cv::imwrite関数の第一引数にファイル名を指定することで、保存する画像の形式を指定しています。

ファイル名の拡張子を変更するだけで、JPEG、PNG、BMPなど、さまざまな形式で画像を保存できます。

○サンプルコード3:画像の圧縮と品質調整

最後に、画像を圧縮し、品質を調整しながら保存する方法について説明します。

画像の品質とファイルサイズはトレードオフの関係にあります。

高品質な画像ほどファイルサイズが大きくなるため、ウェブサイトなどでは適切なバランスを見つけることが重要です。

OpenCVを使用して、画像の圧縮率を指定しながら保存する方法を見ていきましょう。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("example.jpg");
    if(image.empty()) {
        std::cout << "画像が読み込めませんでした。" << std::endl;
        return -1;
    }
    std::vector<int> compression_params;
    compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
    compression_params.push_back(95); // JPEGの品質を95に設定

    cv::imwrite("compressed_image.jpg", image, compression_params);
    return 0;
}

このコードでは、JPEG画像の品質を95(最高品質100)に設定しています。

cv::imwrite関数の第三引数に圧縮パラメータを指定することで、画像の品質を調整できます。

品質を下げるほどファイルサイズが小さくなりますが、画像の劣化が生じる可能性があることに注意が必要です。

●C++での画像処理の応用

C++を使った画像処理には、単に画像を保存するだけでなく、そのサイズを変更したり、色彩を変化させたりするなど、様々な応用が可能です。

ここでは、より実践的な画像処理の応用例をいくつか紹介します。

これらのテクニックをマスターすることで、C++を使った画像処理の幅が大きく広がります。

○サンプルコード4:画像のリサイズと保存

画像を特定のサイズにリサイズすることは、ウェブサイトのローディング時間を短縮するためや、画像処理の前処理として頻繁に行われます。

下記のサンプルコードでは、OpenCVを用いて画像をリサイズし、新しいサイズで保存する方法を紹介します。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("example.jpg");
    if(image.empty()) {
        std::cout << "画像が読み込めませんでした。" << std::endl;
        return -1;
    }

    cv::Mat resized_image;
    cv::resize(image, resized_image, cv::Size(640, 480)); // 画像を640x480にリサイズ

    cv::imwrite("resized_image.jpg", resized_image);
    return 0;
}

このコードでは、cv::resize関数を使用して画像サイズを変更しています。

この関数では、変更後の画像サイズをピクセル単位で指定します。

リサイズされた画像はresized_imageに保存され、その後、cv::imwrite関数を使って新しいファイルとして保存されます。

○サンプルコード5:カラー画像をグレースケールに変換して保存

カラー画像をグレースケール(白黒)に変換する処理は、画像解析や画像処理において基本的な操作です。

下記のサンプルコードでは、OpenCVを使用してカラー画像をグレースケールに変換し、それを保存する方法を説明しています。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat color_image = cv::imread("example.jpg");
    if(color_image.empty()) {
        std::cout << "画像が読み込めませんでした。" << std::endl;
        return -1;
    }

    cv::Mat grayscale_image;
    cv::cvtColor(color_image, grayscale_image, cv::COLOR_BGR2GRAY); // カラー画像をグレースケールに変換

    cv::imwrite("grayscale_image.jpg", grayscale_image);
    return 0;
}

このコードでは、cv::cvtColor関数を使用してカラー画像をグレースケールに変換しています。

変換されたグレースケール画像はgrayscale_imageに保存され、その後cv::imwriteを用いてファイルとして保存されます。

●よくあるエラーとその対処法

C++で画像を扱う際には、さまざまなエラーが発生する可能性があります。

ここでは、C++における画像処理で頻繁に遭遇するエラーとその対処方法について詳しく解説します。

これらのエラーを適切に理解し、対処することで、プログラミングの効率が大幅に向上します。

○エラー対処1:ファイルパスの誤りとその解決策

画像処理を行う際、最も一般的なエラーの一つは、ファイルパスの誤りです。

ファイルパスが間違っていると、プログラムは画像ファイルを見つけることができず、エラーが発生します。

このエラーの解決策は、ファイルパスが正しいかどうかを確認し、必要に応じて修正することです。

#include <fstream>
#include <iostream>

int main() {
    std::string file_path = "path/to/your/image.jpg";

    std::ifstream file(file_path);
    if(!file) {
        std::cout << "ファイルが見つかりません: " << file_path << std::endl;
    } else {
        std::cout << "ファイルが存在します: " << file_path << std::endl;
    }
    return 0;
}

このコードでは、指定されたパスにファイルが存在するかどうかを確認しています。ファイルが存在しない場合は、エラーメッセージを表示します。

○エラー対処2:メモリ不足の対処法

大きな画像を扱う場合、または多数の画像を一度に処理する場合、メモリ不足のエラーが発生することがあります。

この問題に対処するためには、画像のサイズを調整するか、処理する画像の数を減らす必要があります。

メモリ使用量を減らすための一例として、画像サイズを小さくする方法を紹介します。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat large_image = cv::imread("large_image.jpg");
    cv::Mat small_image;
    cv::resize(large_image, small_image, cv::Size(), 0.5, 0.5); // 画像サイズを半分にする

    // small_imageを使用して処理を行う
    // ...

    return 0;
}

このコードでは、cv::resize関数を使用して画像サイズを半分にしています。これにより、メモリ使用量を減らすことができます。

○エラー対処3:サポートされていない画像フォーマットの取り扱い

C++で使用するライブラリによっては、特定の画像フォーマットがサポートされていない場合があります。

このような場合、サポートされているフォーマットに画像を変換する必要があります。

例として、非サポートのフォーマットからサポートされているフォーマットへの変換方法を紹介します。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat unsupported_image = cv::imread("unsupported_format.tiff");
    if(unsupported_image.empty()) {
        std::cout << "サポートされていないフォーマットの画像です。" << std::endl;
    } else {
        cv::imwrite("converted_image.jpg", unsupported_image); // サポートされているフォーマット(例:JPEG)に変換
    }
    return 0;
}

このコードでは、サポートされていないTIFFフォーマットの画像を読み込んだ後、サポートされているJPEGフォーマットに変換しています。

これにより、非サポートのフォーマットによる問題を解決できます。

●C++での画像処理の応用例

C++を使った画像処理では、単に画像を保存するだけでなく、さまざまな効果や変更を加えることができます。

ここでは、画像にテキストや図形を追加する方法と、画像フィルターを適用して保存する方法を紹介します。

これらの応用は、C++での画像処理のスキルをさらに拡張し、より創造的なプロジェクトに取り組む際に役立ちます。

○サンプルコード6:画像にテキストや図形を追加して保存

画像にテキストや図形を追加することは、注釈を付けたり、ビジュアルコンテンツをより魅力的にするためによく使用されます。

下記のコードは、OpenCVを使用して画像にテキストと図形を追加し、その結果を保存する方法を表しています。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("example.jpg");
    if(image.empty()) {
        std::cout << "画像が読み込めませんでした。" << std::endl;
        return -1;
    }

    // テキストを追加
    cv::putText(image, "こんにちは、C++!", cv::Point(50, 50), 
                cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);

    // 図形(円)を追加
    cv::circle(image, cv::Point(150, 150), 50, cv::Scalar(255, 0, 0), 3);

    cv::imwrite("annotated_image.jpg", image);
    return 0;
}

このコードでは、cv::putText関数を使用して画像にテキストを追加し、cv::circle関数で円を描いています。

色とサイズは関数の引数で調整できます。

最後に、加工した画像を新しいファイルとして保存しています。

○サンプルコード7:画像フィルターの適用と保存

画像フィルターは、画像の外観を変更するのに役立ちます。

例えば、エッジ強調、ぼかし、色彩調整などがあります。

下記のコード例では、OpenCVを使用して画像にガウシアンぼかしを適用し、その結果を保存する方法を表しています。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("example.jpg");
    if(image.empty()) {
        std::cout << "画像が読み込めませんでした。" << std::endl;
        return -1;
    }

    cv::Mat blurred_image;
    cv::GaussianBlur(image, blurred_image, cv::Size(7, 7), 1.5); // ガウシアンぼかしを適用

    cv::imwrite("blurred_image.jpg", blurred_image);
    return 0;
}

このコードでは、cv::GaussianBlur関数を使用して画像にぼかし効果を追加しています。

この関数では、ぼかしの強さを調整するためのパラメーターを設定できます。

加工後の画像は、新しいファイルとして保存されます。

●C++と画像処理の豆知識

C++を用いた画像処理では、多くの便利なライブラリや高度な技術が利用可能です。

これらの知識を身に付けることで、より効率的かつ効果的な画像処理が行えるようになります。

ここでは、特に有用なライブラリとGPUを用いた高速画像処理に関する情報を提供します。

○豆知識1:効率的な画像処理のためのC++ライブラリ

C++で画像処理を行う際、多くの開発者は様々なライブラリに頼っています。

これらのライブラリは、基本的な画像読み込みから複雑な画像操作やアルゴリズムの実装まで、幅広い機能を提供します。

代表的なライブラリとしては、OpenCV、Boost.GIL(Generic Image Library)、CImgなどがあります。

OpenCVは、オープンソースのコンピュータビジョンライブラリであり、画像処理、ビデオキャプチャ、顔認識、機械学習などの機能を提供します。

Boost.GILは、Boostライブラリの一部として提供される汎用画像ライブラリであり、基本的な画像処理機能を豊富に持っています。

CImgは、簡潔なAPIで複雑な画像処理アルゴリズムを実装するのに適しています。

これらのライブラリを使用することで、開発者は低レベルの画像処理操作から解放され、より高度な画像処理機能に集中することができます。

○豆知識2:C++でのGPUを利用した高速画像処理

近年、GPU(グラフィックス処理ユニット)を用いた画像処理が注目されています。

GPUは、大量の並列演算を高速に行うことができるため、特に大規模な画像処理やデータ集約型のアプリケーションでその性能を発揮します。

C++でGPUを用いた高速画像処理を実現するためには、CUDA(NVIDIAの並列コンピューティングプラットフォーム)やOpenCL(オープンスタンダードの並列コンピューティングAPI)などの技術が利用できます。

これらの技術を使用することで、開発者はGPUの計算能力を最大限に活用し、従来のCPUベースの処理よりもはるかに高速な画像処理を実現できます。

例えば、CUDAを使用した画像処理のサンプルコードは下記のようになります。

// このコードはCUDAを使用したサンプルの疑似コードです。
__global__ void imageProcessingKernel(uchar* input, uchar* output, int width, int height) {
    int x = threadIdx.x + blockIdx.x * blockDim.x;
    int y = threadIdx.y + blockIdx.y * blockDim.y;

    if (x < width && y < height) {
        // ここに画像処理のロジックを実装
    }
}

void processImageWithCuda(uchar* input, uchar* output, int width, int height) {
    // GPUにデータを転送
    uchar *d_input, *d_output;
    cudaMalloc(&d_input, width * height * sizeof(uchar));
    cudaMalloc(&d_output, width * height * sizeof(uchar));
    cudaMemcpy(d_input, input, width * height * sizeof(uchar), cudaMemcpyHostToDevice);

    // カーネルを実行
    dim3 blockSize(16, 16);
    dim3 gridSize((width + blockSize.x - 1) / blockSize.x, (height + blockSize.y - 1) / blockSize.y);
    imageProcessingKernel<<<gridSize, blockSize>>>(d_input, d_output, width, height);

    // 結果をCPUに転送
    cudaMemcpy(output, d_output, width * height * sizeof(uchar), cudaMemcpyDeviceToHost);

    // リソースを解放
    cudaFree(d_input);
    cudaFree(d_output);
}

このコードでは、CUDAを使って画像処理のカーネルを定義し、GPUでの実行を行っています。

実際には、GPUで実行する画像処理のロジックに応じて、カーネルの内容を変更する必要があります。

CUDAを用いることで、大規模な画像処理も高速に行うことができるようになります。

まとめ

この記事では、C++を用いた画像保存の基本から応用までを幅広く紹介しました。

初心者向けの基本的な操作から、GPUを活用した高度な画像処理技術に至るまで、C++を用いた画像処理の可能性は非常に広いです。

各セクションで紹介したサンプルコードを活用し、実践的なスキルを身につけていただければ幸いです。

C++による画像処理で、あなたの創造性がさらに輝くことを願っています。