c++调用opencv实现图片叠加以及添加水印效果
前言
本篇文章参考了以下文章:
https://blog.csdn.net/mars_xiaolei/article/details/78791133
https://answers.opencv.org/question/73016/how-to-overlay-an-png-image-with-alpha-channel-to-another-png/
素材
demo例子起码用到了几个素材,在这里下载:
logo_pc.png
005.jpg
转存失败
underlay.png
overlay.png
转存失败
test.png
代码
头文件:
#ifndef DEMO_IMAGEMIX_H #define DEMO_IMAGEMIX_H#include <iostream> #include "opencv2/opencv.hpp" #include "opencv2/core.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgcodecs.hpp"#include <opencv2/imgproc.hpp> #include <opencv2/imgproc/types_c.h> #include <vector> using namespace cv; using namespace std; class Demo_ImageMix { public:Demo_ImageMix();void mix1(std::string orgImg, std::string logoPic,double alphaValue);void mix2(std::string orgImg, std::string logoPic,double alphaValue);int MakeWatermarkTest(std::string underlayPic,std::string overlayPic,std::string testPic);int MakeWatermark(std::string underlayPic,std::string overlayPic,double alphaValue);private:void overlayImage(Mat* src, Mat* overlay, const Point& location); };#endif // DEMO_IMAGEMIX_H
cpp源文件:
#include "demo_imagemix.h"/*** * 该class用于演示 * 1、两张图片叠加包含 透明 效果 * 2、底图上面添加png图片水印【水印背景透明】 **/ Demo_ImageMix::Demo_ImageMix() {}/** 任意图片叠加 **/ void Demo_ImageMix::mix1(std::string orgImg, std::string logoPic,double alphaValue){//两图像的权值 // double alphaValue = 0.3; // alphaValue=0.5; double betaValue = 1 - alphaValue; /** 整体思路: 1、分别读取两张图片,然后根据图片尺寸创建一个新的能够容纳两张图片. 2、在底图上面获取logo对应区域 3、logo_img与没有东西的imgPart4Logo混合,得到有透明度的结果图片:dstImage 5、dstImage复制到imgPart4logo区域上面。--因为直接在底图上面操作的,这时候应该已经改变了。 6、显示结果图片 image_src **/ Mat image_src=cv::imread(orgImg,1); cv::Mat logo_img=cv::imread(logoPic,1); Mat imgPart4logo=image_src(Rect(0,0,logo_img.cols,logo_img.rows)); Mat dstImage; cv::addWeighted(logo_img, alphaValue, imgPart4logo,betaValue, 0.0,dstImage);dstImage.copyTo(imgPart4logo);cv::imshow("result",image_src); waitKey(0); return;}/** 任意图片叠加 https://blog.csdn.net/mars_xiaolei/article/details/78791133 *@param alphaValue logo图片的透明度 **/ void Demo_ImageMix::mix2(std::string orgImg, std::string logoPic,double alphaValue){//两图像的权值 // double alphaValue = 0.3; // alphaValue=0.5; double betaValue = 1 - alphaValue; /** 整体思路: 1、分别读取两张图片,然后根据图片尺寸创建一个新的能够容纳两张图片最大宽度与最大高度的mat对象--img_merge 2、分别在img_merge上面取src以及logo两个图片区域 3、image_src先复制到对应的img_merge区域上面 4、logo_img与没有东西的imgPart4Logo混合,得到有透明度的结果图片:dstImage 5、dstImage复制到imgPart4logo区域上面。 6、显示结果图片 img_merge **/ Mat image_src=cv::imread(orgImg,1); cv::Mat logo_img=cv::imread(logoPic,1); Mat img_merge; cv::Size size(MAX(image_src.cols,logo_img.cols),MAX(image_src.rows,logo_img.rows)); img_merge.create(size,CV_MAKETYPE(image_src.depth(),3)); img_merge=Scalar::all(0); Mat imgPart4Src=img_merge(Rect(0,0,image_src.cols,image_src.rows)); Mat imgPart4logo=img_merge(Rect(0,0,logo_img.cols,logo_img.rows));image_src.copyTo(imgPart4Src); /*******/ //logo_img.copyTo(imgPart4logo);Mat dstImage; cv::addWeighted(logo_img, alphaValue, imgPart4logo,betaValue, 0.0,dstImage);dstImage.copyTo(imgPart4logo);cv::imshow("result",img_merge); waitKey(0); return;}/*** 光是看这个函数就像是在 合并两张图片的某个通道的值。。。 https://answers.opencv.org/question/73016/how-to-overlay-an-png-image-with-alpha-channel-to-another-png/ **/ void Demo_ImageMix::overlayImage(Mat* src, Mat* overlay, const Point& location) {for (int y = max(location.y, 0); y < src->rows; ++y){int fY = y - location.y;if (fY >= overlay->rows)break;for (int x = max(location.x, 0); x < src->cols; ++x){int fX = x - location.x;if (fX >= overlay->cols)break;double opacity = ((double)overlay->data[fY * overlay->step + fX * overlay->channels() + 3]) / 255;for (int c = 0; opacity > 0 && c < src->channels(); ++c){unsigned char overlayPx = overlay->data[fY * overlay->step + fX * overlay->channels() + c];unsigned char srcPx = src->data[y * src->step + x * src->channels() + c];src->data[y * src->step + src->channels() * x + c] = srcPx * (1. - opacity) + overlayPx * opacity;}}} }/** 打水印 https://answers.opencv.org/question/73016/how-to-overlay-an-png-image-with-alpha-channel-to-another-png/ **/ int Demo_ImageMix::MakeWatermarkTest(std::string underlayPic,std::string overlayPic,std::string testPic){Mat underlay = imread(underlayPic,IMREAD_UNCHANGED);Mat overlay = imread(overlayPic,IMREAD_UNCHANGED);Mat test = imread(testPic,IMREAD_UNCHANGED);if( underlay.empty() || overlay.empty() || test.empty() ){cout << "Could not read input image files " << endl;return -1;}Mat rgba[4];split(underlay,rgba);imshow("alpha1.png",rgba[3]);imwrite("alpha1.png",rgba[3]);split(overlay,rgba);imshow("alpha2.png",rgba[3]);imwrite("alpha2.png",rgba[3]);overlayImage( &underlay, &overlay, Point() );overlayImage( &test, &underlay, Point(120,180) );split(underlay,rgba);imshow("alpha3.png",rgba[3]);imwrite("alpha3.png",rgba[3]);imshow("result1",underlay);imwrite("result1.png",underlay);imshow("result2",test);imwrite("result2.png",test);waitKey();return 0; } /*** 在原有基础上顺便加一个透明度。 **/ int Demo_ImageMix::MakeWatermark(std::string underlayPic,std::string overlayPic,double alphaValue){Mat underlay = imread(underlayPic,IMREAD_UNCHANGED);Mat overlay = imread(overlayPic,IMREAD_UNCHANGED);double betaValue = 1 - alphaValue;if( underlay.empty() || overlay.empty() ){cout << "Could not read input image files " << endl;return -1;} //--处理透明度Mat dstImage;Mat img_merge;cv::Size size(overlay.cols,overlay.rows);//--!!!注意,png图片应该是四通道的,jpg应该是3通道的,如果这里设置为3通道,那么跟overlay图片运算时候就会出问题。img_merge.create(size,CV_MAKETYPE(overlay.depth(),4));img_merge=Scalar::all(0);Mat imgPart4OverLay=img_merge(Rect(0,0,overlay.cols,overlay.rows));cv::addWeighted(overlay, alphaValue, imgPart4OverLay,betaValue, 0.0,dstImage);Mat rgba[4];imshow("添加透明度之后的logo图片",dstImage);overlayImage( &underlay, &dstImage, Point() );imshow("打水印结果",underlay);waitKey();return 0; }
入口函数 main.cpp
#include <iostream> #include <fstream> #include "demo_imagemix.h" using namespace std;static const std::string LogoPcPath="/home/too-white/temp/logo_pc.png"; static const std::string DemoImage005 = "/home/too-white/temp/005.jpg"; static const std::string DemoUnderLayImage = "/home/too-white/temp/underlay.png"; static const std::string DemoOverlayImage = "/home/too-white/temp/overlay.png"; static const std::string DemoTestLayImage = "/home/too-white/temp/test.png";int checkFileEsits(std::string & filePath){fstream file;file.open(filePath.data(),ios::in);if(file.fail()){file.close();return 0;}file.close();return 1; }int main(){std::cout<<"开始执行"<<std::endl;Demo_ImageMix imgMix; //imgMix.mix1(DemoImage005,LogoPcPath,0.5); //imgMix.MakeWatermarkTest(DemoUnderLayImage,LogoPcPath,DemoImage005); imgMix.MakeWatermark(DemoImage005,LogoPcPath,0.5);return 0; }
测试结果
注意,测试的时候只执行了
mix1【与mix2的结果是一样的,只是写法不一样】,MakeWaterMarkTest与MakeWaterMark三个方法,下面是结果:
mix1:
两张图片叠加的效果是---真的是叠加啊。。。
MakeWaterMarkTest:
转存失败
看到这个结果,感觉就是合并其中一条通道实现效果的。
MakeWaterMark:
转存失败
可以设置透明度的水印,这个实用价值才大。。
我。。。老是提示转存失败,原素材可以到下面拿:
http://www.52play.net/blog/post?id=52
c++调用opencv实现图片叠加以及添加水印效果相关推荐
- 基于Ubuntu系统,调用opencv在图片上显示数字和汉字
文章目录 一.汉字编码的介绍 1.汉字编码的发展过程 (1)汉字编码产生的原因 (2)常用的汉字编码 2.区位码 (1)产生原因 (2)概念简述 (3)区域分布情况 3.机内码 (1)基本概念 (2) ...
- Java调用opencv实现图片去水印
opencv实现图片去水印案例 Java调用opencv实现图片去水印 环境安装配置 IDEA下开发配置 测试案例 Java调用opencv实现图片去水印 最近项目中遇到个需求,图片去水印下载,由于上 ...
- Android OpenCV实现图片叠加,水印
关于如何用纯OpenCV实现图片叠加的例子实在是太少,太多的是使用 C++,JNI实现的,如果要用C++的话,我们为啥不转行做C++ 下面的例子基于 Android JavaCV 实现了在im_bea ...
- php 图片裁剪保存,PHP实现图片裁剪、添加水印效果代码
这篇文章主要介绍了PHP实现图片裁剪.添加水印效果代码,本文给出代码示例,代码中包含一些说明注释,需要的朋友可以参考下 3.PHP对图像的裁剪 裁剪之前 header("content-ty ...
- Android仿拼多多实现图片叠加部分覆盖效果
Android仿拼多多实现图片叠加部分覆盖效果 需要实现的效果如下: 代码部分: AppIconStackView: public class AppIconStackView extends Vie ...
- Ubuntu 下调用 opencv 在图片显示汉字和数字
目录 实验要求: 1 环境准备 1.1创建文件 实验要求: 学习理解汉字的机内码.区位码编码规则和字形数据存储格式.在Ubuntu下用C/C++(或python) 调用opencv库编程显示一张图片, ...
- python调用opencv放大图片
代码如下,简单易懂: import cv2# 横纵轴放大比例 fx = 2 fy = 2 img = cv2.imread('frame_000001.jpg') enlarge = cv2.resi ...
- python 调用opencv查看图片尺寸
代码如下,简单易懂: import cv2img_path = 'frame_000001.jpg' img = cv2.imread(img_path) size = img.shape # ==& ...
- Shader学习12——简易图片叠加
看到蛮牛有人想要两个带透明通道的图片叠加,就是最简单的纹理混合,想想其实实现起来应该很简单,但是搜了一下还真没搜到,这里简单实现一下,要求底图需要是不透明的: image.png image.png ...
最新文章
- hdu 1598 find the most comfortable road
- SQL SERVER全面优化-------写出好语句是习惯
- The application's PagerAdapter changed the adapter's contents without calling notifyDataSetChanged
- Fiori Elements的metadata和ui annotation
- devops定义_在层中定义DevOps
- JAVA8的双重循环怎么优化_Java8处理List的双层循环问题代码实例
- spring 定时任务---task
- 台达PLC,触摸屏程序工程案例 含电气图 台达与伺服变频通讯实例
- 基础回顾:10W+ 字 C 语言入门教程(上)
- 鼠标键盘的使用:用左ALT+左SHIFT+NUM LOCK即可启动或关闭键盘的鼠标键
- mui赋值_mui input用法
- untiy 请求安卓权限
- [USACO18DEC]Fine Dining
- pyscripter与python的关系_我用过的最好的python编辑器PyScripter
- Ubuntu 22.04 使用私钥登录时提示 server refused our key
- Pytorch打怪路(三)Pytorch创建自己的数据集2
- A_A02_003 ST-LINK驱动安装
- 企业智能通信办公系统UCM6510领跑企业办公通信
- 弗洛伊德算法——最短路径算法
- 转:真正的高情商,是“很会”发脾气
热门文章
- selenium报错信息-- Python 中 ‘unicodeescape‘ codec can‘t decode bytes in position XXX: trun错误解决方案
- 30岁学习编程晚么?
- python兔子繁殖问题循环_for循环——兔子繁殖问题
- linux中的批量删除和查找
- python调用rarfile进行解压rar压缩包时,报了如下错误
- Laravel Guzzle封装
- Android studio 运行警告 We recommend using a newer Android Gradle plugin to use compileSdk = 33
- 微信开放平台PC端扫码登录功能个人总结
- 火车,飞机 查询接口
- 从自媒体人到服务商 职业信鸽主播的快手商业之路