当前位置: 首页 > wzjs >正文

ps做网站首页win7系统优化大师

ps做网站首页,win7系统优化大师,仙桃网站建设,大连网站程序开发使用 C/C 和 OpenCV 添加图片水印 🖼️ 在数字图像处理中,添加水印是一种常见的操作,可以用于版权保护、品牌宣传或信息标注。本文将介绍如何使用 C/C 和强大的计算机视觉库 OpenCV 来实现将自定义水印(图片或文字)添…

使用 C/C++ 和 OpenCV 添加图片水印 🖼️

在数字图像处理中,添加水印是一种常见的操作,可以用于版权保护、品牌宣传或信息标注。本文将介绍如何使用 C/C++ 和强大的计算机视觉库 OpenCV 来实现将自定义水印(图片或文字)添加到目标图片上。


准备工作 🛠️

在开始之前,请确保你已经具备以下条件:

  1. C/C++ 编译器: 如 GCC/G++, Clang, MSVC 等。
  2. OpenCV 库: 需要预先安装并配置好 OpenCV。你可以从 OpenCV 官网 (https://opencv.org/) 下载并根据你的操作系统进行安装。
  3. 一个集成开发环境 (IDE) (可选,但推荐): 如 Visual Studio, CLion, Code::Blocks 等,可以方便代码编写和项目管理。
  4. 待添加水印的图片: 准备一张你想要添加水印的图片。
  5. 水印图片 (可选): 如果你希望使用图片作为水印,请准备好水印图片。

核心概念 💡

实现图片水印的核心思路是将水印图像(或文字)与原始图像进行某种形式的融合或叠加。OpenCV 提供了丰富的图像处理函数,使得这个过程相对简单。

关键的 OpenCV 组件和函数包括:

  • cv::Mat: OpenCV 中用于存储图像数据的核心数据结构。
  • cv::imread(): 用于加载图片到 cv::Mat 对象。
  • cv::imwrite(): 用于将 cv::Mat 对象中的图像数据保存到文件。
  • cv::resize(): 用于调整图像的大小,可以将水印调整到合适尺寸。
  • cv::Rect: 用于定义图像中的一个矩形区域 (Region of Interest, ROI),方便在特定位置操作。
  • cv::addWeighted(): 用于对两个图像进行加权混合,常用于实现半透明水印效果。
  • cv::putText(): 用于在图像上绘制文字,可以实现文字水印。

实现步骤 📝

下面将分步骤介绍如何实现图片水印和文字水印。

1. 包含头文件和命名空间

首先,在你的 C++ 代码中包含必要的 OpenCV 头文件并使用 cv 命名空间:

#include <opencv2/opencv.hpp> // 包含 OpenCV 的核心头文件
#include <iostream>using namespace cv;
using namespace std;
2. 加载原始图片和水印图片 (针对图片水印)

使用 cv::imread() 函数加载你的原始图片和水印图片。

Mat originalImage = imread("path/to/your/original_image.jpg");
Mat watermarkImage = imread("path/to/your/watermark_image.png", IMREAD_UNCHANGED); // IMREAD_UNCHANGED 保留 alpha 通道if (originalImage.empty()) {cerr << "错误: 无法加载原始图片!" << endl;return -1;
}if (watermarkImage.empty()) {cerr << "错误: 无法加载水印图片!" << endl;return -1;
}

注意: 如果你的水印图片是 PNG 格式并且包含透明通道 (alpha channel),使用 IMREAD_UNCHANGED 参数可以保留这些信息,从而实现更自然的融合效果。

3. 调整水印大小 (可选)

通常,水印图片的大小需要根据原始图片进行调整,以确保其不会过大或过小。

// 示例:将水印宽度调整为原始图片宽度的 1/5,并保持宽高比
double scaleFactor = (originalImage.cols / 5.0) / watermarkImage.cols;
Mat resizedWatermark;
resize(watermarkImage, resizedWatermark, Size(), scaleFactor, scaleFactor, INTER_LINEAR);
4. 定义水印位置

你需要确定水印在原始图片上的位置。通常可以选择图片的四个角或者中心。

// 示例:将水印放置在右下角,并留有一些边距
int margin = 10;
int x = originalImage.cols - resizedWatermark.cols - margin;
int y = originalImage.rows - resizedWatermark.rows - margin;// 或者放置在左上角
// int x = margin;
// int y = margin;// 或者放置在中心
// int x = (originalImage.cols - resizedWatermark.cols) / 2;
// int y = (originalImage.rows - resizedWatermark.rows) / 2;Rect roi(x, y, resizedWatermark.cols, resizedWatermark.rows);

确保定义的位置和水印大小不会超出原始图片的边界。

5. 将水印叠加到原始图片
方法一:使用 cv::addWeighted() (适用于半透明效果)

如果水印图片没有 alpha 通道,或者你希望实现一个固定透明度的叠加效果,可以使用 cv::addWeighted()

// 确保水印图像和 ROI 区域的类型和通道数一致
// 如果原始图像是 3 通道 (BGR),水印图像也应该是 3 通道
Mat watermarkBGR;
if (resizedWatermark.channels() == 4) {cvtColor(resizedWatermark, watermarkBGR, COLOR_BGRA2BGR); // 如果有 alpha 通道,先转为 BGR
} else {watermarkBGR = resizedWatermark;
}Mat imageROI = originalImage(roi); // 获取原始图片中要放置水印的区域
double alpha = 0.5; // 水印的透明度 (0.0 完全透明, 1.0 完全不透明)
addWeighted(imageROI, 1.0 - alpha, watermarkBGR, alpha, 0.0, imageROI);
方法二:利用 Alpha 通道进行融合 (适用于 PNG 水印)

如果水印图片有 alpha 通道,可以实现更精细的融合,水印的非透明部分会完全覆盖,透明部分则显示背景。

if (resizedWatermark.channels() == 4) {vector<Mat> channels;split(resizedWatermark, channels); // 分离 RGBA 通道Mat bgr[3] = { channels[0], channels[1], channels[2] };Mat alphaChannel = channels[3]; // 获取 alpha 通道Mat watermarkBGR_alpha;merge(bgr, 3, watermarkBGR_alpha); // 合并 BGR 通道Mat imageROI = originalImage(roi);// 使用 alpha 通道作为掩码进行融合for (int r = 0; r < imageROI.rows; ++r) {for (int c = 0; c < imageROI.cols; ++c) {double alpha = alphaChannel.at<uchar>(r, c) / 255.0;if (alpha > 0) { // 只处理非完全透明的像素for (int channel = 0; channel < 3; ++channel) {imageROI.at<Vec3b>(r, c)[channel] =saturate_cast<uchar>((1.0 - alpha) * imageROI.at<Vec3b>(r, c)[channel] +alpha * watermarkBGR_alpha.at<Vec3b>(r, c)[channel]);}}}}
} else {// 如果水印没有 alpha 通道,可以简单复制或使用 addWeightedMat imageROI = originalImage(roi);resizedWatermark.copyTo(imageROI); // 直接覆盖
}

一个更简洁的使用 alpha 通道的方法是:

if (resizedWatermark.channels() == 4) {Mat imageROI = originalImage(roi);vector<Mat> bgra_channels;split(resizedWatermark, bgra_channels);// 创建一个掩码,其中 alpha > 0 的地方为 255Mat mask;compare(bgra_channels[3], 0, mask, CMP_GT);// 提取水印的 BGR 部分Mat watermark_bgr;vector<Mat> bgr_channels = {bgra_channels[0], bgra_channels[1], bgra_channels[2]};merge(bgr_channels, watermark_bgr);// 将水印的 BGR 部分拷贝到 ROI,使用掩码watermark_bgr.copyTo(imageROI, mask);
} else {// 处理没有 alpha 通道的情况Mat imageROI = originalImage(roi);resizedWatermark.copyTo(imageROI);
}
6. 添加文字水印

如果你想添加文字作为水印,可以使用 cv::putText() 函数。

string watermarkText = "My Copyright";
Point textOrg(originalImage.cols - 200, originalImage.rows - 30); // 文字的起始位置 (左下角)
int fontFace = FONT_HERSHEY_SIMPLEX;
double fontScale = 1.0;
Scalar color(0, 0, 255); // 字体颜色 (BGR) - 这里是红色
int thickness = 2;
int lineType = LINE_AA; // 抗锯齿putText(originalImage, watermarkText, textOrg, fontFace, fontScale, color, thickness, lineType);

你可以调整字体、大小、颜色、位置和透明度(通过在文字下方绘制一个半透明的矩形背景)。

7. 显示和保存结果

最后,你可以显示带有水印的图片,并将其保存到文件。

namedWindow("带水印的图片", WINDOW_AUTOSIZE);
imshow("带水印的图片", originalImage);imwrite("path/to/your/output_image_with_watermark.jpg", originalImage);waitKey(0); // 等待按键后关闭窗口
destroyAllWindows();

完整示例代码 (图片水印 - Alpha 融合)

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() {// 1. 加载原始图片和水印图片Mat originalImage = imread("original.jpg"); // 替换为你的原始图片路径Mat watermarkImage = imread("watermark.png", IMREAD_UNCHANGED); // 替换为你的水印图片路径if (originalImage.empty()) {cerr << "错误: 无法加载原始图片!" << endl;return -1;}if (watermarkImage.empty()) {cerr << "错误: 无法加载水印图片!" << endl;return -1;}// 2. 调整水印大小 (可选)Mat resizedWatermark;double scaleFactor = (originalImage.cols / 8.0) / watermarkImage.cols; // 水印宽度为原图的1/8if (watermarkImage.cols > originalImage.cols * 0.1) { // 仅当水印宽度大于原图10%时缩放resize(watermarkImage, resizedWatermark, Size(), scaleFactor, scaleFactor, INTER_AREA);} else {resizedWatermark = watermarkImage;}// 3. 定义水印位置 (右下角)int margin = 20;int x = originalImage.cols - resizedWatermark.cols - margin;int y = originalImage.rows - resizedWatermark.rows - margin;// 确保 roi 不会超出原图边界if (x < 0) x = 0;if (y < 0) y = 0;if (x + resizedWatermark.cols > originalImage.cols) {resizedWatermark = resizedWatermark(Rect(0, 0, originalImage.cols - x, resizedWatermark.rows));}if (y + resizedWatermark.rows > originalImage.rows) {resizedWatermark = resizedWatermark(Rect(0, 0, resizedWatermark.cols, originalImage.rows - y));}Rect roi(x, y, resizedWatermark.cols, resizedWatermark.rows);Mat imageROI = originalImage(roi);// 4. 将水印叠加到原始图片 (使用 Alpha 通道)if (resizedWatermark.channels() == 4) { // 检查是否有 Alpha 通道vector<Mat> channels;split(resizedWatermark, channels); // 分离 B, G, R, Alpha 通道Mat mask;// Alpha 通道通常是最后一个通道 channels[3]// 如果你的 OpenCV 版本或水印图片通道顺序不同 (例如 ARGB),请相应调整if (channels.size() == 4) {mask = channels[3]; // Alpha 通道作为掩码} else {// 如果分离后不是4通道,说明水印图本身就没有alpha,需要特殊处理或报错// 这里我们创建一个全白的掩码,效果类似直接覆盖mask = Mat(resizedWatermark.rows, resizedWatermark.cols, CV_8UC1, Scalar(255));}// 提取水印的 BGR 部分 (前三个通道)Mat watermark_bgr;vector<Mat> bgr_channels_vec;if (channels.size() >= 3) {bgr_channels_vec.push_back(channels[0]);bgr_channels_vec.push_back(channels[1]);bgr_channels_vec.push_back(channels[2]);merge(bgr_channels_vec, watermark_bgr);// 将水印的 BGR 部分拷贝到 ROI,使用 Alpha 通道作为掩码watermark_bgr.copyTo(imageROI, mask);} else {// 如果水印不是至少3通道,则直接拷贝(可能不是期望的效果)resizedWatermark.copyTo(imageROI);}} else if (resizedWatermark.channels() == 3) { // 如果水印是 3 通道 BGR// 可以选择直接覆盖或使用 addWeighted// resizedWatermark.copyTo(imageROI); // 直接覆盖// 或者使用 addWeighted 实现半透明double alpha_blend = 0.7; // 透明度addWeighted(imageROI, 1.0 - alpha_blend, resizedWatermark, alpha_blend, 0.0, imageROI);} else {cerr << "错误: 水印图片的通道数不受支持 (" << resizedWatermark.channels() << ")。" << endl;// 可以选择直接拷贝单通道图像作为灰度水印if(resizedWatermark.channels() == 1){cvtColor(resizedWatermark, resizedWatermark, COLOR_GRAY2BGR); // 转为BGR再处理resizedWatermark.copyTo(imageROI);} else {return -1;}}// 5. 显示和保存结果namedWindow("带水印的图片", WINDOW_AUTOSIZE);imshow("带水印的图片", originalImage);if (imwrite("output_with_watermark.jpg", originalImage)) {cout << "成功保存带水印的图片: output_with_watermark.jpg" << endl;} else {cerr << "错误: 无法保存图片!" << endl;}waitKey(0);destroyAllWindows();return 0;
}

编译和运行:
你需要将上述代码保存为 .cpp 文件 (例如 add_watermark.cpp),并使用你的 C++ 编译器链接 OpenCV 库进行编译。

例如,使用 g++:

g++ add_watermark.cpp -o add_watermark $(pkg-config --cflags --libs opencv4)
./add_watermark

(如果你的 pkg-config 配置的是 opencv 而不是 opencv4,请相应修改)。


结论 🏁

通过 OpenCV,我们可以方便地在 C++ 程序中为图片添加各种类型的水印。无论是简单的文字水印还是带有透明效果的图片水印,OpenCV 都提供了相应的工具和函数来实现。关键在于理解图像的 ROI 操作以及如何有效地融合两个图像。希望本文能帮助你成功地为你的图片添加上自定义的水印!

http://www.dtcms.com/wzjs/95370.html

相关文章:

  • 网站支付体现功能怎么做百度网络优化推广公司
  • ps上做网站seo站内优化技巧
  • 做最好言情网站网络营销的市场背景
  • 济南哪里有网站公司优化大师电脑版官网
  • 网站banner代码列表网推广效果怎么样
  • 南昌网站建设制作公司广州seo好找工作吗
  • 酒泉网站建设设计关键词举例
  • 常见的旅游网络营销方式seo是什么意思怎么解决
  • 网站改版怎么办泰安网站制作推广
  • 政府网站建设请示莆田百度seo公司
  • wordpress自动采集翻译插件怎么用windows优化大师自动安装
  • 闸北区网站建设网页品牌推广
  • 免费的源码分享网站各网站收录
  • 江苏省义务教育标准化建设网站百度平台联系方式
  • 广东睿营建设有限公司网站深圳龙岗区优化防控措施
  • 镇江市网站建设百度网站怎么提升排名
  • 手机网站做静态路径宁波seo外包服务商
  • 哪个旅游网站做的最好广州营销seo
  • 手机ui设计网站seo内部优化具体做什么
  • 建设官方网站的主要作用网站seo优化是什么
  • 网站开发管理招聘小说关键词生成器
  • 自己如何做独立网站上海营销公司
  • 品牌注册去哪里办理成都最好的seo外包
  • 在线观看免费网站网站建站流程
  • wordpress 博客多人海南seo排名优化公司
  • 自己可以做网站生意好做吗网络营销策略都有哪些
  • 瓯海建设网站台州网站建设
  • 网站设计制作靠谱公司线上营销公司
  • 北京企业网站设计方案湖南seo优化报价
  • 做网站有哪些法规百度人工电话