物理の駅 Physics station by 現役研究者

テクノロジーは共有されてこそ栄える

C++ OpenCVでalphaチャンネルなし画像からalphaチャンネルを作る

入力画像は、アルファチャンネルあり、なしBGR、グレースケールの3種類に対応した。 アルファチャンネルは8bitの4チャンネルの4つ目で、0-255で与える。0の場合は完全に透過する。 今回は、BGRの輝度値が真っ白付近(245-255)を透過する条件とした。

変換前(左)と変換後(右)

f:id:onsanai:20201204114949p:plain

TEST(TestOpenCV, TestAlphaChannel) {

    cv::Mat src = cv::imread("alpha_src.png", 1);
    cv::Mat alpha_img(src.size(), CV_8UC4);
    cv::Mat img;
    if (src.type() == CV_8UC4) {
        cv::cvtColor(src, img, CV_BGRA2BGR);
        std::cout << "CV_BGRA2BGR" << std::endl;
    }
    else if (src.type() == CV_8UC1) {
        std::cout << "CV_GRAY2BGR" << std::endl;
        cv::cvtColor(src, img, CV_GRAY2BGR);
    }
    else if (src.type() == CV_8UC3) {
        img = src;
    }
    else {
        throw std::exception();
    }

    //メインの実装
    for (int y = 0; y < img.rows; y++) {
        for (int x = 0; x < img.cols; x++) {
            cv::Vec3b p = img.at<cv::Vec3b>(cv::Point(x, y));
            if (p[0] + p[1] + p[2] > (255 * 3 - 30)) {//好きな条件
                alpha_img.at<cv::Vec4b>(cv::Point(x, y)) 
                                = cv::Vec4b(p[0], p[1], p[2], 0); //透過
            }
            else {
                alpha_img.at<cv::Vec4b>(cv::Point(x, y)) 
                                = cv::Vec4b(p[0], p[1], p[2], 255); //不透過
            }
        }
    }
    cv::imwrite("alpha_dst.png", alpha_img);
}