OPENCV 实现png绘制,alpha通道叠加。
一夜未眠,一直在找一个好点的方法将带alpha通道的png图片叠加到其他三通道图片上。
下面进入正题:
在这段代码中,cvAdd4cMat 其实是一个宏,由 CA4M_EXCAT 宏来控制它展开成什么。
#ifdef CA4M_EXCAT
#define cvAdd4cMat cvAdd4cMat_e
#else
#define cvAdd4cMat cvAdd4cMat_q
#endif
注:e版函数是精确版,q版函数是快速版。我也不知道实际使用e版和q版差别多大,速度e版更快,但是绘制出来的质量我用肉眼完全看不出差别,文章后面有我对两版函数速度测试的说明。如果你要直接使用我的模块,那么我建议你不要定义CA4M_EXCAT这个宏。因为我认为q版函数更加优秀。如果你不知道怎么使用它,你可以到底部获得演示程序的下载地址。
原理:
显存中每个点是以BGR方式存储的,B、G、R分别叫蓝色通道、绿色通道、红色通道
而对于一些图片来所,它们还需要有一个A通道,阿尔法通道,即不透明度通道。来控制这个点的不透明度,其实所谓的不透明度,只在与其他图片叠时反应出来。
对于某一个像素点的叠加公式:
b = b1 * a1/255 + b0 * (255 - a1)/255g = g1 * a1/255 + g0 * (255 - a1)/255r = r1 * a1/255 + r0 * (255 - a1)/255
B=B1 * alpha/255 + B0 * beta/255G=G1 * alpha/255 + G0 * beta/255R=R1 * alpha/255 + R0 * beta/255
newalpha = alpha * scale
newbeta = 255 - newalpha
以上只是该模块的基本思想,为了防止溢出,减少冗余计算,源码在算法上做了较大的调整,具体请看代码了:
cvAdd4cMat.h
#pragma once#include <vector>
#include <opencv2/opencv.hpp>static int createtable = false;//init lookup-table;
static cv::Mat table(1, 256, CV_32FC1);
static cv::Mat otable(1, 256, CV_32FC1);
int cvAdd4cMat_e(cv::Mat &dst, cv::Mat &scr, double scale);
int cvAdd4cMat_e(cv::Mat &dst, cv::Mat &scr);
int cvAdd4cMat_q(cv::Mat &dst, cv::Mat &scr, double scale = 1.0);
void InitLookupTable(void);#ifdef CA4M_EXCAT
#define cvAdd4cMat cvAdd4cMat_e
#else
#define cvAdd4cMat cvAdd4cMat_q
#endif
cvAdd4cMat.cpp
#include "cvAdd4cMat.h"int cvAdd4cMat_e(cv::Mat &dst, cv::Mat &scr, double scale)
{if (createtable == false){InitLookupTable();}if (dst.channels() != 3 || scr.channels() != 4){return 0;}if (scale < 0.01)return 1;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);cv::Mat alpha(dst.rows, dst.cols, CV_32FC1);LUT(scr_channels[3], table, alpha);for (int i = 0; i < 3; i++){scr_channels[i].convertTo(scr_channels[i], CV_32FC1);dstt_channels[i].convertTo(dstt_channels[i], CV_32FC1);dstt_channels[i] = dstt_channels[i].mul(1 - alpha*scale);dstt_channels[i] += scr_channels[i].mul(alpha * scale);dstt_channels[i].convertTo(dstt_channels[i], CV_8UC1);}merge(dstt_channels, dst);return 1;
}int cvAdd4cMat_e(cv::Mat &dst, cv::Mat &scr)
{if (createtable == false){InitLookupTable();}if (dst.channels() != 3 || scr.channels() != 4){return 0;}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);cv::Mat alpha(dst.rows, dst.cols, CV_32FC1);cv::Mat beta(dst.rows, dst.cols, CV_32FC1);LUT(scr_channels[3], table, alpha);LUT(scr_channels[3], otable, beta);for (int i = 0; i < 3; i++){scr_channels[i].convertTo(scr_channels[i], CV_32FC1);dstt_channels[i].convertTo(dstt_channels[i], CV_32FC1);dstt_channels[i] = dstt_channels[i].mul(beta);dstt_channels[i] += scr_channels[i].mul(alpha);dstt_channels[i].convertTo(dstt_channels[i], CV_8UC1);}merge(dstt_channels, dst);return 1;
}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++){//newalpha equal scale * alphadstt_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;
}void InitLookupTable(void)
{for (int i = 0; i < 256; i++){table.at<float>(i) = i / 255.0f;otable.at<float>(i) = 1 - table.at<float>(i);}createtable = true;
}
对两版函数的分析:
for (int i = 0; i < 5000;i++)
cvAdd4cMat(img1_t2, img2);
e版测两次:26344ms 26547ms
q版测两次:20094ms 19996ms
for (int i = 0; i < 5000;i++)
cvAdd4cMat(img1_t2, img2, 1.5);
e版测两次:29851ms 29725ms
q版测两次:21051ms 21023ms
for (int i = 0; i < 5000;i++)
cvAdd4cMat(img1_t2, img2, 0.5);
e版测两次:29281ms 29221ms
q版测两次:22031ms 22031ms
综上看出
e版函数平均每次绘图4ms,q版函数平均每次绘图6ms。
e版函数在绘制速度上不如q版函数,e版函数绘制时如果使用scale参数,速度还会减慢10%左右
q版函数相对更快,但在scale参数小于1时因为算法原因,绘制速度也会减慢10%左右
下面是我写的一个小example:
下载地址:http://download.csdn.net/detail/u013097499/7483975
OPENCV 实现png绘制,alpha通道叠加。相关推荐
- python opencv 为图片添加alpha通道并设置透明,判断是否存在alpha通道
读取图片 使用函数cv2.imread(filepath,flags)读入一副图片 filepath:要读入图片的完整路径 flags:读入图片的标志 cv2.IMREAD_COLOR:默认参数,读入 ...
- unity加载sprite_Unity 分离贴图 alpha 通道实践
引言 在做手机游戏时可能会遇到这些问题: UI 同学天天抱怨 iOS 上一些透明贴图压缩后模糊不堪 一些古早的 Android 手机上同样的贴图吃内存超过其他手机数倍,游戏经常闪退 这篇文章给出了一种 ...
- Unity 分离贴图 alpha 通道实践
在做手机游戏时可能会遇到这些问题: UI 同学天天抱怨 iOS 上一些透明贴图压缩后模糊不堪 一些古早的 Android 手机上同样的贴图吃内存超过其他手机数倍,游戏经常闪退 这篇文章给出了一种手机游 ...
- OpenCV绘制透明底的图片,简单易懂讲解alpha通道怎么用
今天忽然想做抠图和图形绘制,那这里就涉及到一个透明底的问题 OpenCV是很强大的,但是网上大多教程并没有讲清楚 alpha 通道的参数怎么设置 首先我们来看最简单的非 alpha 通道代码: imp ...
- 【计算机视觉】OPENCV对于有alpha通道的透明背景图片的读取和图片叠加
这个是我自己做的粗略的螺旋丸的图,导出为png并带有alpha通道. 最后和一只狗合成成这个样子. 效果还是可以的. 为了实现这个效果,首先我们要明白具有透明通道的图片的OpenCV的读取方式.在Op ...
- OPENCV对于有alpha通道的透明背景图片的读取和图片叠加
这个是我自己做的粗略的螺旋丸的图,导出为png并带有alpha通道. 最后和一只狗合成成这个样子. 效果还是可以的. 为了实现这个效果,首先我们要明白具有透明通道的图片的opencv的读取方式.在Op ...
- 使用opencv中的merge()函数为BGR图像添加alpha通道
先上代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # 图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 # 图像处理 ...
- 【笔记】opencv的python实现·像素处理 像素访问 alpha通道
像素概念 计算机在处理某个图像时,会首先将其划分为一个个小方块,每个小方块是一个独立的处理单位,成为像素点 记录一些基础语法: ,X[:,0]就是取矩阵X的所有行的第0列的元素,X[:,1] 就是取所 ...
- OpenCV中拆分通道、合并通道、alpha通道的讲解及实战演示(附python源码 超详细)
需要源码和图片请点赞关注收藏后评论区留言私信~~~ 在BGR色彩空间中,图像的通道由B通道.G通道和B通道构成,下面将介绍OpenCV提供的方法拆分和合并通道 一.拆分通道 为了拆分图像中的通道 Op ...
- 【Opencv入门】RGB三通道直方图的计算与绘制
文章目录 一. 直方图概述 Overview of histogram 二.直方图的建立 Establishment of histogram 三.直方图的作用 The function of his ...
最新文章
- docker镜像创建redis5.0.3容器集群
- java怎么通过ip地址查具体地址_制作通过IP 查询地址的java版程序
- 用Unity快速开发太空飞机大战游戏实战经验分享(上)
- jdk8永久代从方法区移除的验证
- jzoj6826-[2020.10.17提高组模拟]隔膜【博弈论】
- UNIX(多线程):13---condition_variable、wait、notify_one、notify_all
- LeetCode 1020. 飞地的数量(图的BFS/DFS)
- JDK+SDK 环境变量记录
- cpu 被挂起和阻塞_同步异步阻塞非阻塞并发并行讲解
- Visual Studio Code 使用 ESLint 增强代码风格检查
- VS2010:外部依赖目录错误,怎么办
- 二十年后的回眸(1)——报到上班
- Hvv近期0day总结二
- VM14 15 pro Mac更改最大分辨率
- vi: 未找到命令_vi技巧和窍门:十个很棒的命令一定会给您的朋友留下深刻的印象...
- 美丽炫酷的Html5简历网页模板
- 【安全】eWebeditor编辑器上传webshell
- Java泛型详解:<T>和Class<T>的使用。泛型类,泛型方法的详细使用实例
- C/C++cmath库常用函数
- leetcode算法练习 JavaScript实现
热门文章
- 计算机地图概括的原理,第五章地图概括与自动综合
- red hat linux7下载地址,Red Hat Enterprise Linux 7 百度下载地址分享
- 全球及中国电子材料市场需求分析与十四五投资潜力预测报告2021年版
- SEO优化:站群的操作方法有哪些,网站集群系统是什么?
- 计算机和现代通讯的应用,现代计算机通信技术特点及通信网络的应用.docx
- 河北对口升学计算机VB知识点,vb对口升学试题.docx
- 2022电大国家开放大学网上形考任务-电子商务概论非免费(非答案)
- 以太网--车载以太网
- 【渝粤题库】陕西师范大学209019 鲁迅研究 作业(专升本)
- 服务器来料检测作用,IQC来料检验项目