物理の駅 by onsanai

Physics Station → PhSt 質問・疑問・間違いの指摘は、コメントに書くか、直接伝えるときっと良いことがあります。主にWindows or Ubuntu用の記事です

C++ OpenCV の cv::encode, cv::decodeを使ってみる

C++ OpenCVの導入、サンプル画像の作り方は

Visual Studio 2017 + OpenCV 3.2.0 + x64の初期設定 とOpenCVに関する質問の受け付け(コメント欄へ) - 物理の駅 by onsanai

を参照されたし。

cv::encode cv::decode を使うと、ファイル出力なしに出力用のバイト列を取得する(エンコードする)ことが出来るし、ファイル入力なしにバイト列から読み込む(デコードする)こともできる。

#include <iostream>
#include <fstream>

#include <opencv2/opencv.hpp>
using namespace cv;

void write_bin(const std::string& filepath, const std::vector<uchar>& vout)
{
    std::ofstream ofs;
    ofs.exceptions(std::ios::failbit | std::ios::badbit);
    ofs.open(filepath, std::ios::binary);
    for (auto p = vout.begin(); p != vout.end(); ++p)
    {
        ofs.write((char*)&*p, sizeof(uchar));
    }
    ofs.close();
}

int main() {

    //サンプル画像生成は https://phst.hateblo.jp/entry/2016/11/30/081749 参照
    Mat src = Mat::zeros(150, 220, CV_8UC3);
    putText(src, "Hello World", Point(5, 50), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 200), 2, CV_AA);
    line(src, Point(190, 25), Point(190, 45), Scalar(0, 200, 0), 3);
    for (int x = 188; x < 192; x++)
        for (int y = 53; y < 57; y++)
            for (int i = 0; i < 2; i++)
                src.at<uchar>(Point(x * 3 + i, y)) = saturate_cast<uchar>(200);

    cv::imshow("a", src);
    cv::waitKey(0);

    //PNGでの出力用パラメータ
    vector<int> param = vector<int>(2);
    param[0] = CV_IMWRITE_PNG_COMPRESSION;
    param[1] = 3;//default(3)  0-9.

    std::vector<uchar>buf;
    cv::imencode(".png", src, buf, param); //エンコード

    cv::Mat dst = cv::imdecode(Mat(buf), CV_LOAD_IMAGE_COLOR); //デコード

    cv::imshow("b", dst);
    cv::waitKey(0);

    //ファイル出力
    write_bin("test.png", buf);

    return 0;
}

めっちゃ便利やん。なんでこれまで使ってこなかったんや。