对于png透明图片,在,贴吧等平台上,看缩略图时默认是以白色为背景,而点开看原图时默认是以黑色为背景,基于此显示逻辑可以实现一种图像,看缩略图时是表图,看原图时是里图,这就是幻影坦克。
基于图像线性融合原理,公式:g(x)=α*f(x)+(1-α)h(x),可以假设最后生成图与白色叠加得到表图,最后生成图与黑色叠加得到里图,套用公式即可得到幻影坦克的理论公式:
公式和原理都源自B站视频,BV1kV411v7fR,讲的很细致。
需要注意的是,公式里α透明度有一项是表图的灰度值减里图灰度值,必须保证这个值时刻大于0,不然会出现α值大于255的情况,造成错误,即里图显示时出现表图部分,如图:

在我把背景换成橙色以后,图中错误部分也显示为橙色,所以判断为这些地方透明度计算出现问题。


经过初步分析得到:显示错误的地方在原图中的灰度值非常低,导致P表-P里小于0,使α超出上限,造成完全透明。
如何保证P表-P里大于0?我的想法是里图调暗一些,最后保证表图每一像素的灰度大于里图灰度即可。
经过一段时间的调试,我得到了我的解决办法:以里图尺寸为基准,遍历全部像素点,分别读取表图和里图的灰度,将读取到的里图灰度乘0.35,灰度的范围是0-255,因此最大值255*0.35=89.25。对于表图的灰度,如果出现小于上面这个值的灰度,就给他强行赋值为100,这样一定能够保证P表-P里大于0,α正常,里图显示正常。
可能会有人问:改变了表图灰度,会不会对最终结果造成影响?这个问题我还不清楚,但是根据生成的幻影坦克来看,这点影响可以忽略不计。
希望大神指点更好的方法以保证α不出问题。
最后附上源码
#include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; int main() { Mat A_origin = imread("A.jpg", 0); Mat A; Mat B = imread("B.jpg",0); resize(A_origin, A, B.size()); //以里图尺寸resize表图 Mat C = Mat::zeros(B.size(), CV_8UC4); //以里图尺寸为基础创建新图 int PA, PB, PC; int Alpha; for (int i = 0; i < B.rows; i++) { for (int j = 0; j < B.cols; j++) { PA = (int)A.at<uchar>(i, j); PB = ((int)B.at<uchar>(i, j)) * 0.35; if (PA < 100) //解决问题的关键 { PA = 100; } Alpha = 255 - (PA - PB); if (Alpha == 0) { Alpha = 1; } PC = (int)(255 * PB / Alpha); C.at<Vec4b>(i, j) = Vec4b(PC, PC, PC, Alpha); } } imwrite("Mirage Tank.png", C); }
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/62325.html