zoukankan      html  css  js  c++  java
  • 【计算机视觉】OPENCV对于有alpha通道的透明背景图片的读取和图片叠加

    这个是我自己做的粗略的螺旋丸的图,导出为png并带有alpha通道。

    最后和一只狗合成成这个样子。

    效果还是可以的。

    为了实现这个效果,首先我们要明白具有透明通道的图片的OpenCV的读取方式。在OpenCV里,正常是读取图像和写入图像默认都是忽略透明通道的,如果想要读取原图像中的透明通道,则在使用imread()函数时,后面的参数要使用CV_LOAD_IMAGE_UNCHANGED参数或是直接写-1也可以。比如:

    Mat inimg = imread("dog.png", CV_LOAD_IMAGE_UNCHANGED); // 读取透明通道  
    // 输出RGBA数值  
    cout << (int)inimg.at<Vec4b>(0,0)[0] << endl  
         << (int)inimg.at<Vec4b>(0,0)[1] << endl  
         << (int)inimg.at<Vec4b>(0,0)[2] << endl  
         << (int)inimg.at<Vec4b>(0,0)[3] << endl;  

    这样我们读取的图片就有了四个通道,也就是BGRA四个通道,第四个就是Alpha通道,这个通道通过0-255的数值来代表该像素的透明度。

    我通过split函数分解矩阵的通道把png图片分解为B1矩阵,G1矩阵,R1矩阵,A1矩阵把背景图片分解为了B0矩阵,G0矩阵,R0矩阵。于是叠加的结果:令alpha = A1 , 令beta = 255 - alpha。
    #include <vector>  
    #include <stdio.h>  
    #include <opencv2/opencv.hpp>  
      
    using namespace cv;  
    using namespace std;  
      
    int cvAdd4cMat_q(cv::Mat &dst, cv::Mat &scr, double scale);  
      
    int main()  
    {  
        char str[16];  
        Mat img1 = imread("bk.jpg"), img2 = imread("img.png", -1);  
        Mat img1_t1(img1, cvRect(0, 0, img2.cols, img2.rows));  
        cvAdd4cMat_q(img1_t1,img2,1.0);  
        imshow("final",img1);  
        waitKey(0);  
        return 0;  
    }  
      
    int cvAdd4cMat_q(cv::Mat &dst, cv::Mat &scr, double scale)    
    {    
        if (dst.channels() != 3 || scr.channels() != 4)    
        {    
            return true;    
        }    
        if (scale < 0.01)    
            return false;    
        std::vector<cv::Mat>scr_channels;    
        std::vector<cv::Mat>dstt_channels;    
        split(scr, scr_channels);    
        split(dst, dstt_channels);    
        CV_Assert(scr_channels.size() == 4 && dstt_channels.size() == 3);    
      
        if (scale < 1)    
        {    
            scr_channels[3] *= scale;    
            scale = 1;    
        }    
        for (int i = 0; i < 3; i++)    
        {    
            dstt_channels[i] = dstt_channels[i].mul(255.0 / scale - scr_channels[3], scale / 255.0);    
            dstt_channels[i] += scr_channels[i].mul(scr_channels[3], scale / 255.0);    
        }    
        merge(dstt_channels, dst);    
        return true;    
    }    
    最终使用这个方法,可以到达前图的效果。
  • 相关阅读:
    常用资源
    printf打印颜色
    Vue开发中踩坑-Day3
    Vue开发踩坑-Day2
    Vue开发中的踩坑-day1
    Python中virtualenv的使用
    第十一章:Python高级编程-协程和异步IO
    第十章:Python高级编程-多线程、多进程和线程池编程
    第九章:Python高级编程-Python socket编程
    自定义Element父子不关联的穿梭树
  • 原文地址:https://www.cnblogs.com/huty/p/8517371.html
Copyright © 2011-2022 走看看