基于OpenCV实现的灰度图幻影坦克

对于png透明图片,在QQ,贴吧等平台上,看缩略图时默认是以白色为背景,而点开看原图时默认是以黑色为背景,基于此显示逻辑可以实现一种图像,看缩略图时是表图,看原图时是里图,这就是幻影坦克。

基于图像线性融合原理,公式: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);



}

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值