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

【Go】:图片上添加水印的全面指南——从基础到高级特性

前言

在数字内容日益重要的今天,保护版权和标识来源变得关键。为图片添加水印有助于声明所有权、提升品牌认知度,并防止未经授权的使用。本文将介绍如何用Go语言实现图片水印,包括静态图片和带旋转、倾斜效果的文字水印,帮助您有效保护数字内容。我们将逐步解析关键步骤,确保清晰易懂。

一、准备工作

为了顺利实现图片水印功能,您需要完成以下几个准备步骤:

1.安装Go语言环境:确保您的开发环境中已经安装了Go语言,并具备基本的Go编程知识。

2.安装必要的库

  • golang.org/x/image/draw:支持高质量缩放及其他图像绘制操作。
  • github.com/disintegration/imaging:提供简便的API用于图像变换,如旋转和倾斜。

3.准备图像资源

  • 主图 (Base Image):这是您想要添加水印的原始图像。它可以是任何您有权处理的图像文件。
  • 水印图 (Watermark Image):这是将被放置在主图之上的图像,通常是一个透明背景的PNG文件,这样可以确保它不会遮挡主图的重要细节。

确保您拥有上述所有工具和资源后,就可以开始编写代码来实现图片水印功能了。接下来的章节将逐步指导您如何加载主图、应用水印图并保存最终结果。

二、图片加水印

2.1 图片水印

2.1.1 打开主图

首先,我们需要打开并读取主图文件。这一步确保了程序能够访问到用户想要处理的原始图像。

// 打开主图文件
mainImageFile, err := os.Open("main.png")
if err != nil {log.Fatalf("Failed to open main image: %v", err)
}
defer mainImageFile.Close()

2.1.2 解码主图

接下来,从输入流中读取原始图像并解码它。如果解码过程中出现问题,程序将返回错误信息。这里我们使用image.Decode函数自动识别图像格式。

mainImageFile, err := os.Open("main.png")
if err != nil {log.Fatalf("Failed to open main image: %v", err)
}
defer mainImageFile.Close()

2.1.3 打开水印图片

然后,我们需要打开水印图片文件。与主图类似,我们也需要确保能够正确读取和解码水印图像。

// 打开水印图片
watermarkImageFile, err := os.Open("logo.png") // 可以替换为其他图片文件名
if err != nil {log.Fatalf("Failed to open watermark image: %v", err)
}
defer watermarkImageFile.Close()

2.1.4 解码水印图片

接下来,从输入流中读取水印图像并解码它。如果解码过程中出现问题,程序将返回错误信息。这里我们再次使用image.Decode函数自动识别图像格式。

// 解码水印
watermarkImage, _, err := image.Decode(watermarkImageFile)
if err != nil {log.Fatalf("Failed to decode watermark image: %v", err)
}

2.1.5 计算缩放比例

为了保证水印不会过于显眼或遮挡过多内容,根据原始图像的尺寸计算水印的最大宽度和高度。通常,我们会设定最大值为原始图像宽高的25%。然后基于这些最大值计算出适当的缩放比例。

// 获取主图和水印的边界矩形
mainImageBounds := mainImage.Bounds()
watermarkImageBounds := watermarkImage.Bounds()// 计算水印的最大尺寸
maxWatermarkWidth := int(float64(mainImageBounds.Max.X) * 0.25)  // 最大宽度为主图宽度的25%
maxWatermarkHeight := int(float64(mainImageBounds.Max.Y) * 0.25) // 最大高度为主图高度的25%// 计算水印的缩放比例
scale := 1.0
if watermarkImageBounds.Max.X > maxWatermarkWidth || watermarkImageBounds.Max.Y > maxWatermarkHeight {scale = math.Min(float64(maxWatermarkWidth)/float64(watermarkImageBounds.Max.X),float64(maxWatermarkHeight)/float64(watermarkImageBounds.Max.Y),)
}// 应用缩放比例
watermarkWidth := int(float64(watermarkImageBounds.Max.X) * scale)
watermarkHeight := int(float64(watermarkImageBounds.Max.Y) * scale)

2.1.6 创建新的图像

创建一个新的RGBA图像,其大小与原始图像相同,并将原始图像复制到这个新图像中。

// 创建一个新的图像,大小与主图相同
resultImage := image.NewRGBA(mainImageBounds)// 将主图复制到新图像中
draw.Draw(resultImage, mainImageBounds, mainImage, mainImageBounds.Min, draw.Src)

2.1.7 缩放水印图像

根据前面计算的缩放比例调整水印图像的大小。我们可以使用golang.org/x/image/draw包中的draw.CatmullRom.Scale方法来进行高质量缩放。

// 创建一个用于存放缩放后水印的新图像
resizedWatermarkImage := image.NewRGBA(image.Rect(0, 0, watermarkWidth, watermarkHeight))// 使用高质量缩放算法缩放水印图像
draw.CatmullRom.Scale(resizedWatermarkImage, resizedWatermarkImage.Bounds(), watermarkImage, watermarkImageBounds, draw.Over, nil)

2.1.8 确定水印位置

根据用户提供的参数确定水印应该放置的位置,例如左上角、右上角等。对于每个预设的位置,我们计算出相应的坐标点。这里仅给出右下角的例子:

// 引入 position 变量,并赋值为一个有效的水印位置常量
position := "left_top" // 假设使用 "left_top" 作为示例// 计算水印放置的位置
var watermarkX, watermarkY int
switch position {
case "left_top":watermarkX = int(float64(mainImageBounds.Max.X) * 0.02) // 2% of the widthwatermarkY = int(float64(mainImageBounds.Max.Y) * 0.02) // 2% of the height
case "right_top":watermarkX = int(float64(mainImageBounds.Max.X)*0.98) - watermarkWidth // 98% of the width minus watermark widthwatermarkY = int(float64(mainImageBounds.Max.Y) * 0.02)                // 2% of the height
case "left_bottom":watermarkX = int(float64(mainImageBounds.Max.X) * 0.02)                 // 2% of the widthwatermarkY = int(float64(mainImageBounds.Max.Y)*0.98) - watermarkHeight // 98% of the height minus watermark height
case "right_bottom":watermarkX = int(float64(mainImageBounds.Max.X)*0.98) - watermarkWidth  // 98% of the width minus watermark widthwatermarkY = int(float64(mainImageBounds.Max.Y)*0.98) - watermarkHeight // 98% of the height minus watermark height
default:log.Fatalf("Invalid watermark position: %v", position)
}

2.1.9 绘制水印

最后,使用draw.Draw方法将调整后的水印绘制到新图像的指定位置。

// 将水印绘制到新图像的指定位置
draw.Draw(resultImage, image.Rectangle{Min: image.Point{X: watermarkX, Y: watermarkY},Max: image.Point{X: watermarkX + watermarkWidth, Y: watermarkY + watermarkHeight},
}, resizedWatermarkImage, image.Point{X: 0, Y: 0}, draw.Over)

2.1.10 绘制旋转水印(可选)

为了让水印更加多样化,可以引入旋转或倾斜的效果。这可以通过创建一个仿射变换矩阵并应用于文字图像来完成。以下是实现旋转功能的代码片段:

// 创建一个新的图像,大小与水印相同
rotatedWatermarkImage := image.NewRGBA(resizedWatermarkImage.Bounds())// 引入 rotation 变量,并赋值为一个有效的旋转角度(度数)
rotation := 45.0 // 假设使用 45.0 度作为示例// 计算旋转角度的弧度
radians := rotation * math.Pi / 180.0// 计算旋转后的中心点
centerX := float64(watermarkWidth) / 2.0
centerY := float64(watermarkHeight) / 2.0// 遍历每个像素点并应用旋转
for y := 0; y < watermarkHeight; y++ {for x := 0; x < watermarkWidth; x++ {// 将像素点转换为相对于中心点的坐标relX := float64(x) - centerXrelY := float64(y) - centerY// 应用旋转矩阵newX := relX*math.Cos(radians) - relY*math.Sin(radians)newY := relX*math.Sin(radians) + relY*math.Cos(radians)// 将旋转后的坐标转换回图像坐标newX += centerXnewY += centerY// 如果旋转后的坐标在图像范围内,则绘制像素if newX >= 0 && newX < float64(watermarkWidth) && newY >= 0 && newY < float64(watermarkHeight) {rotatedWatermarkImage.Set(int(newX), int(newY), resizedWatermarkImage.At(x, y))}}
}// 将旋转后的水印绘制到新图像的指定位置
draw.Draw(resultImage, image.Rectangle{Min: image.Point{X: watermarkX, Y: watermarkY}, Max: image.Point{X: watermarkX + watermarkWidth, Y: watermarkY + watermarkHeight}}, rotatedWatermarkImage, image.Point{X: 0, Y: 0}, draw.Over)

2.1.11 保存结果图像

根据原始图像的格式(如PNG或JPEG),将带有水印的新图像编码并保存到内存中的缓冲区,然后再写入磁盘。

// 保存结果图像到内存
var buffer bytes.Buffer
switch fileExtension {
case ".png":err = png.Encode(&buffer, resultImage)
case ".jpg", ".jpeg":err = jpeg.Encode(&buffer, resultImage, nil)
default:log.Fatalf("Unsupported file extension: %v", fileExtension)
}
if err != nil {log.Fatalf("Failed to encode image: %v", err)
}// 保存结果图像到文件
outputFileName := "output" + fileExtension
outputFile, err := os.Create(outputFileName)
if err != nil {log.Fatalf("Failed to create output file: %v", err)
}
defer outputFile.Close()// 将内存中的图像数据写入文件
_, err = buffer.WriteTo(outputFile)
if err != nil {log.Fatalf("Failed to write to output file: %v", err)
}

2.1.12 完整代码和效果

package mainimport ("bytes""golang.org/x/image/draw""image""image/jpeg""image/png""log""os""path/filepath"
)func main() {// 打开主图文件mainImageFile, err := os.Open("main.png")if err != nil {log.Fatalf("Failed to open main image: %v", err)}defer mainImageFile.Close()// 获取文件扩展名fileExtension := filepath.Ext(mainImageFile.Name())// 解码主图mainImage, _, err := image.Decode(mainImageFile)if err != nil {log.Fatalf("Failed to decode main image: %v", err)}// 打开水印图片watermarkImageFile, err := os.Open("logo.png") // 你可以将 "logo.png" 替换为 "logo.jpg" 或其他图片文件名if err != nil {log.Fatalf("Failed to open watermark image: %v", err)}defer watermarkImageFile.Close()// 解码水印watermarkImage, _, err := image.Decode(watermarkImageFile)if err != nil {log.Fatalf("Failed to decode watermark image: %v", err)}// 获取主图和水印的边界矩形mainImageBounds := mainImage.Bounds()watermarkImageBounds := watermarkImage.Bounds()// 计算水印的最大尺寸maxWatermarkWidth := int(float64(mainImageBounds.Max.X) * 0.20)  // 你可以将 "0.20" 替换为 "0.15" 或其他值maxWatermarkHeight := int(float64(mainImageBounds.Max.Y) * 0.20) // 你可以将 "0.20" 替换为 "0.15" 或其他值// 计算水印的缩放比例watermarkWidth := watermarkImageBounds.Max.XwatermarkHeight := watermarkImageBounds.Max.Y// 计算缩放比例scale := 1.0if watermarkWidth > maxWatermarkWidth {scale = float64(maxWatermarkWidth) / float64(watermarkWidth)}if watermarkHeight > maxWatermarkHeight {if scale > float64(maxWatermarkHeight)/float64(watermarkHeight) {scale = float64(maxWatermarkHeight) / float64(watermarkHeight)}}// 应用缩放比例watermarkWidth = int(float64(watermarkWidth) * scale)watermarkHeight = int(float64(watermarkHeight) * scale)// 创建一个新的图像,大小与主图相同resultImage := image.NewRGBA(mainImageBounds)// 将主图复制到新图像中draw.Draw(resultImage, mainImageBounds, mainImage, mainImageBounds.Min, draw.Src)// 缩放水印图像resizedWatermarkImage := image.NewRGBA(image.Rect(0, 0, watermarkWidth, watermarkHeight))draw.NearestNeighbor.Scale(resizedWatermarkImage, resizedWatermarkImage.Bounds(), watermarkImage, watermarkImageBounds, draw.Over, nil)// 引入 position 变量,并赋值为一个有效的水印位置常量position := "left_top" // 假设使用 "left_top" 作为示例// 计算水印放置的位置var watermarkX, watermarkY intswitch position {case "left_top":watermarkX = int(float64(mainImageBounds.Max.X) * 0.02) // 宽度的2%watermarkY = int(float64(mainImageBounds.Max.Y) * 0.02) // 高度的2%case "right_top":watermarkX = int(float64(mainImageBounds.Max.X)*0.98) - watermarkWidth // 宽度的98%减去水印宽度watermarkY = int(float64(mainImageBounds.Max.Y) * 0.02)                // 高度的2%case "left_bottom":watermarkX = int(float64(mainImageBounds.Max.X) * 0.02)                 // 宽度的2%watermarkY = int(float64(mainImageBounds.Max.Y)*0.98) - watermarkHeight // 高度的98%减去水印高度case "right_bottom":watermarkX = int(float64(mainImageBounds.Max.X)*0.98) - watermarkWidth  // 宽度的98%减去水印宽度watermarkY = int(float64(mainImageBounds.Max.Y)*0.98) - watermarkHeight // 高度的98%减去水印高度default:log.Fatalf("Invalid watermark position: %v", position)}// 将水印绘制到新图像的指定位置draw.Draw(resultImage, image.Rectangle{Min: image.Point{X: watermarkX, Y: watermarkY}, Max: image.Point{X: watermarkX + watermarkWidth, Y: watermarkY + watermarkHeight}}, resizedWatermarkImage, image.Point{X: 0, Y: 0}, draw.Over)// 保存结果图像到内存var buffer bytes.Bufferswitch fileExtension {case ".png":err = png.Encode(&buffer, resultImage)case ".jpg", ".jpeg":err = jpeg.Encode(&buffer, resultImage, nil)default:log.Fatalf("Unsupported file extension: %v", fileExtension)}if err != nil {log.Fatalf("Failed to encode image: %v", err)}// 保存结果图像到文件outputFile, err := os.Create("output" + fileExtension)if err != nil {log.Fatalf("Failed to create output file: %v", err)}defer outputFile.Close() // 添加文件关闭操作// 将内存中的图像数据写入文件_, err = buffer.WriteTo(outputFile)if err != nil {log.Fatalf("Failed to write to output file: %v", err)}
}

2.2 文字水印

敬请期待!!!

总结

通过以上步骤,我们不仅完成了在图片上添加静态图片水印的功能实现,还增加了旋转、倾斜的水印功能,使得生成的水印更加多样化和个性化。您可以根据自己的需求进一步优化代码,比如支持更多的水印位置选项,或者允许用户上传自定义水印图片。希望这篇文章能帮助您理解和实现这一常见但非常有用的功能。如果您有任何问题或遇到困难,请随时查阅相关文档或寻求社区的帮助。

相关文章:

【Go】:图片上添加水印的全面指南——从基础到高级特性

前言 在数字内容日益重要的今天&#xff0c;保护版权和标识来源变得关键。为图片添加水印有助于声明所有权、提升品牌认知度&#xff0c;并防止未经授权的使用。本文将介绍如何用Go语言实现图片水印&#xff0c;包括静态图片和带旋转、倾斜效果的文字水印&#xff0c;帮助您有…...

R语言的语法糖

R语言的语法糖 引言 在编程语言中&#xff0c;所谓的“语法糖”是指那些使得程序员能够以更简洁、直观的方式书写代码的语法形式。R语言作为一种用于统计分析和数据可视化的编程语言&#xff0c;具有丰富的功能和灵活的语法。本文将深入探讨R语言中的语法糖&#xff0c;帮助读…...

乙游的尽头是虚拟偶像吗?

眼花了&#xff0c;竟然看到二次元乙游男主角走红毯了。 12月20日&#xff0c;某国际知名奢侈品品牌宣布&#xff0c;《恋与深空》四位男主将受邀出席品牌在上海举办的TF戏瘾之夜活动&#xff0c;并公开了四位男主的红毯照片。 没有真人实体的乙游男主走红毯&#xff1f;这是…...

【源码+文档+调试讲解】农产品研究报告管理系统

摘 要 农产品研究报告管理系统是一个旨在收集、整理、存储和分析农产品相关研究数据的综合性平台。农产品研究报告管理系统通常包含一个强大的数据库&#xff0c;它能够处理大量的研究数据&#xff0c;并对这些数据进行有效的管理和备份。农产品研究报告管理系统是现代农业科学…...

SQL UNION 操作符

SQL UNION 操作符 SQL UNION 操作符用于合并两个或多个 SELECT 语句的结果集。它将多个结果集组合成一个单独的结果集&#xff0c;并去除重复的行。为了使用 UNION&#xff0c;每个 SELECT 语句必须具有相同的列数&#xff0c;并且对应列的数据类型必须兼容。 语法 SELECT c…...

springboot vue uniapp 仿小红书 1:1 还原 (含源码演示)

线上预览: 移动端 http://8.146.211.120:8081/ 管理端 http://8.146.211.120:8088/ 小红书凭借优秀的产品体验 和超高人气 目前成为笔记类产品佼佼者 此项目将详细介绍如何使用Vue.js和Spring Boot 集合uniapp 开发一个仿小红书应用&#xff0c;凭借uniapp 可以在h5 小程序 app…...

扩散模型学习

扩散模型学习 DDPM&#xff08;参考1&#xff09; DDIM&#xff08;参考1&#xff0c;参考2&#xff09;...

【面试】MySQL 最左匹配原则

MySQL的最左匹配原则是在使用联合索引时非常重要的概念&#xff0c;理解并合理运用该原则能显著提升查询性能。以下从多个方面详细介绍&#xff1a; 1. 联合索引结构基础 联合索引是对多个列创建的索引。在MySQL中&#xff0c;联合索引以多列值的组合形式&#xff0c;按照创建…...

Mac 删除ABC 输入法

参考链接&#xff1a;百度安全验证 Mac下删除系统自带输入法ABC&#xff0c;正解&#xff01;_mac删除abc输入法-CSDN博客 ABC 输入法和搜狗输入法等 英文有冲突~~ 切换后还会在英文状态&#xff0c;可以删除 &#xff1b;可能会对DNS 输入有影响&#xff0c;但是可以通过复…...

Nginx代理同域名前后端分离项目的完整步骤

前后端分离项目&#xff0c;前后端共用一个域名。通过域名后的 url 前缀来区别前后端项目。 以 vue php 项目为例。直接上 server 模块的 nginx 配置。 server{ listen 80; #listen [::]:80 default_server ipv6onlyon; server_name demo.com;#二配置项目域名 index index.ht…...

21、Transformer Masked loss原理精讲及其PyTorch逐行实现

1. Transformer结构图 2. python import torch import torch.nn as nn import torch.nn.functional as Ftorch.set_printoptions(precision3, sci_modeFalse)if __name__ "__main__":run_code 0batch_size 2seq_length 3vocab_size 4logits torch.randn(batch…...

CNN张量输入形状和特征图

CNN张量输入形状和特征图 这个是比较容易理解的张量的解释&#xff0c;比较直观 卷积神经网络 在这个神经网络编程系列中&#xff0c;我们正在逐步构建一个卷积神经网络&#xff08;CNN&#xff09;&#xff0c;所以让我们看看CNN的张量输入。 ​ ​ 在最后两篇文章中&…...

RK3399开发板Linux实时性改造

本次测试基于NanoPC-T4开发板&#xff08;国产化处理器RK3399&#xff09;&#xff0c;4.19.111内核Xenomai实时性改造测试。 Xenomai下载网站&#xff1a;https://xenomai.org/downloads/ NanoPC-T4网站&#xff1a;https://wiki.friendlyarm.com/wiki/index.php/NanoPC-T4/z…...

ASP.NET Core 中的高效后台任务管理

一、引言 在当今快速发展的 Web 开发领域&#xff0c;ASP.NET Core 凭借其卓越的性能、强大的功能和高度的灵活性&#xff0c;已然成为众多开发者构建现代 Web 应用程序的首选框架。它不仅能够高效地处理各种复杂的业务逻辑&#xff0c;还为开发者提供了丰富多样的工具和功能&…...

Spring Boot 2 学习指南与资料分享

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今竞争激烈的 Java 后端开发领域&#xff0c;Spring Boot 2 凭借其卓越的特性&#xff0c;为开发者们开辟了一条高效、便捷的开发之路。如果你渴望深入学习 Spring Boot 2&#xff0c;以下这份精心…...

知识追踪模型DKT,DLKT详解及代码复现

定义与应用 知识追踪是一种 教育技术领域的重要方法 ,旨在通过分析学生的学习行为和表现,预测其掌握特定知识点的程度。这种方法的核心在于建立能够反映学习者认知状态的动态模型,从而实现对学生学习进度的实时监控和个性化指导。 DKT模型 DKT模型 是最早的知识追踪模型之…...

一类特殊积分的计算

一类特殊积分的计算 前言一、第一个引理二、第二个引理三、积分的计算后记 前言 今天讨论的这类积分是十分有趣的&#xff0c;在 Mathematics Stack Exchange 看见后&#xff0c;便打算在此将其中的计算过程完善一下。在本篇文章中&#xff0c;我们重点考虑求解如下积分&#…...

VScode 配置 C语言环境

遇到的问题集合 mingw官方下载网站&#xff08;https://sourceforge.net/projects/mingw-w64/files/&#xff09;更新之后&#xff0c;与网上大多数教程上写的界面不同了。 网上大多数教程让下载这个&#xff1a; 但是现在找不到这个文件。 写hello.c文件时&#xff0c;报错&…...

spring mvc源码学习笔记之十一

pom.xml 内容如下 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/P…...

小结:路由器和交换机的指令对比

路由器和交换机的指令有一定的相似性&#xff0c;但也有明显的区别。以下是两者指令的对比和主要差异&#xff1a; 相似之处 基本操作 两者都支持类似的基本管理命令&#xff0c;比如&#xff1a; 进入系统视图&#xff1a;system-view查看当前配置&#xff1a;display current…...

ffmpeg7.0 aac转pcm

#pragma once #define __STDC_CONSTANT_MACROS #define _CRT_SECURE_NO_WARNINGSextern "C" { #include "libavcodec/avcodec.h" }//缓冲区大小&#xff08;缓存5帧数据&#xff09; #define AUDIO_INBUF_SIZE 40960 /*name depthu8 8s16 …...

C#读取本地网络配置信息全攻略

一、引言 在当今数字化时代&#xff0c;网络已深度融入我们生活与工作的方方面面。对于软件开发而言&#xff0c;掌握本地计算机的网络配置信息显得尤为关键。想象一下&#xff0c;你正在开发一款网络诊断工具&#xff0c;需要精准定位网络连接问题&#xff0c;此时 IP 地址、…...

解决aerich init -t xx 报错ModuleNotFoundError: No module named ‘tomli_w‘

今天在学习fastapi的时候&#xff0c;发现一款数据库迁移工具&#xff0c;通过这个工具可以根据模型类来对数据库做出改变。 随跟着学: 在执行 aerich init -t settings.TORTOISE_ORM的时候&#xff0c; 彼其娘之。。 报了一些错误&#xff1a; Traceback (most recent ca…...

python检测gitlab中某个标签在一个月内添加和移除了多少次

可以通过 Python 脚本和 GitLab API 检测一个标签在一个月内被添加和移除的次数。以下是实现的步骤和示例代码&#xff1a; 步骤 获取 GitLab API 访问令牌&#xff1a;在 GitLab 中生成一个 Personal Access Token。设置时间范围&#xff1a;确定一个月的时间范围。调用 Git…...

学习模板之一

学习目标&#xff1a; 提示&#xff1a;这里可以添加学习目标 例如&#xff1a; 一周掌握 Java 入门知识 学习内容&#xff1a; 提示&#xff1a;这里可以添加要学的内容 例如&#xff1a; 搭建 Java 开发环境掌握 Java 基本语法掌握条件语句掌握循环语句 学习时间&#x…...

2025-微服务—SpringCloud-1~3

2025-微服务—SpringCloud 第一章、从Boot和Cloud版本选型开始说起1、Springboot版本2、Springcloud版本3、Springcloud Alibaba4、本次讲解定稿版 第二章 关于Cloud各种组件的停更/升级/替换1、微服务介绍2、SpringCloud是什么&#xff1f;能干吗&#xff1f;产生背景&#xf…...

centos7.6 安装nginx 1.21.3与配置ssl

1 安装依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel2 下载Nginx wget http://nginx.org/download/nginx-1.21.3.tar.gz3 安装目录 mkdir -p /data/apps/nginx4 安装 4.1 创建用户 创建用户nginx使用的nginx用户。 #添加www组 # groupa…...

PL/SQL语言的数据库交互

PL/SQL语言的数据库交互 引言 在当今的信息化时代&#xff0c;数据库管理系统&#xff08;DBMS&#xff09;在各行各业中扮演着至关重要的角色。为了高效地与数据库进行交互&#xff0c;许多程序员、数据库管理员和系统分析师选择使用PL/SQL&#xff08;Procedural Language/…...

ARP欺骗

文章目录 ARP协议ARP欺骗原理断网攻击ARP欺骗(不断网) ARP协议 在局域网中&#xff0c;网络传输的是帧&#xff0c;帧里面有目标主机的MAC地址。arp协议负责将IP地址解析成对应的MAC地址 ARP欺骗原理 即通过伪造IP地址和MAC地址实现ARP欺骗&#xff0c;能够在网络中产生大量…...

Genymotion配套VirtualBox所在地址

在 Genymotion打开虚拟机前需要先打开VirtualBox中的虚拟机 C:\Program Files\Oracle\VirtualBox\VirtualBox.exe 再开启genymotion中的虚拟机开关...

TPS61022 PFM的机制以及TPS61xxx转换器的PFM与PWM之间的负载阈值

引言 TI 的大多数 TPS61xxx 低压升压转换器都配备了 PSM&#xff08;省电模式&#xff09;&#xff0c;以帮助提高轻负载效率。但是&#xff0c;当它处于重负载状态时&#xff0c;输出纹波通常会高于 PWM。此外&#xff0c;PSM 和 PWM 之间的负载电流阈值不会直观地写入数据表中…...

1. npm 常用命令详解

npm 常用命令详解 npm&#xff08;Node Package Manager&#xff09;是 Node.js 的包管理工具&#xff0c;用于安装和管理 Node.js 应用中的依赖库。下面是 npm 的一些常用命令及其详细解释和示例代码。 镜像源 # 查询当前使用的镜像源 npm get registry# 设置为淘宝镜像源 …...

黑马linux入门笔记(01)初始Linux Linux基础命令 用户和权限 实用操作

B站 黑马程序员 的视频 BV1n84y1i7td 黑马程序员新版Linux零基础快速入门到精通&#xff0c;全涵盖linux系统知识、常用软件环境部署、Shell脚本、云平台实践、大数据集群项目实战等 增强自控力 冥想慢呼吸绿色锻炼充分休息减少决策次数优先做重要的事情(早晨)融入强自控群控…...

Markdown中甘特图的使用

Markdown中甘特图的使用 1. 前言2. 语法详解2.1 甘特图语法 3. 使用场景及实例4. 小结5. 其他文章快来试试吧&#x1f58a;️ Markdown中甘特图的使用 &#x1f448;点击这里也可查看 1. 前言 Markdown 的原生语法不支持绘制图形&#xff0c;但通过扩展模块&#xff0c;我们可…...

Django创建数据表、模型、ORM操作

1、创建项目 django-admin startproject PersonInfosProject 2、创建项目应用&#xff0c;进入PersonInfosProject文件夹&#xff0c;新建index应用&#xff0c;使用命令 cd PersonInfosProject python manage.py startapp 新建完成之后的目录结构 3、新建数据模型&#xf…...

No. 31 笔记 | Web安全-SQL手工注入技术学习 Part 2

一、研究背景 背景介绍 SQL注入是一种常见且高危的Web安全漏洞。攻击者可以通过构造恶意SQL查询语句来绕过验证机制&#xff0c;执行未授权操作&#xff0c;如获取敏感信息、篡改数据库内容甚至控制服务器。 研究内容 本笔记探讨以下数据库的手工注入技术&#xff1a; MySQLAc…...

Spring Boot中的扫描注解如何使用

在 Spring Boot 中&#xff0c;扫描注解是指通过注解来告诉 Spring 框架应该扫描哪些包、哪些类或哪些特定的组件&#xff0c;并将其作为 Spring 容器中的 bean 进行管理。Spring Boot 主要通过以下几种注解来实现自动扫描&#xff1a; ComponentScanSpringBootApplicationCom…...

用 Python 从零开始创建神经网络(十九):真实数据集

真实数据集 引言数据准备数据加载数据预处理数据洗牌批次&#xff08;Batches&#xff09;训练&#xff08;Training&#xff09;到目前为止的全部代码&#xff1a; 引言 在实践中&#xff0c;深度学习通常涉及庞大的数据集&#xff08;通常以TB甚至更多为单位&#xff09;&am…...

深入探讨 Vue.js 的动态组件渲染与性能优化

Vue.js 作为一款前端领域中备受欢迎的渐进式框架&#xff0c;以其简单优雅的 API 和灵活性受到开发者的喜爱。在开发复杂应用时&#xff0c;动态组件渲染是一项极其重要的技术&#xff0c;它能够在页面中动态地加载或切换组件&#xff0c;从而显著提升应用的灵活性与用户体验。…...

qml TextArea、TextEdit、TextField、TextInput的区别于联系

在 QML 中&#xff0c;TextArea、TextEdit、TextField 和 TextInput 都是用来接收用户输入的控件&#xff0c;但它们之间有一些区别和联系。 区别&#xff1a; TextArea&#xff1a;用于多行文本输入&#xff0c;可以接收多行文本输入。TextEdit&#xff1a;也用于多行文本输入…...

《探索 PC 端的开源神经网络多模态模型宝藏》

《探索 PC 端的开源神经网络多模态模型宝藏》 一、多模态模型&#xff1a;开启智能交互新纪元二、主流 PC 端开源多模态模型大赏1. Obsidian&#xff1a;轻量级多模态先锋2. GLM-Edge 系列&#xff1a;移动端与 PC 端的全能选手3. Minicpm-llama3-v2.6&#xff1a;紧凑高效的多…...

centos 搭建nginx+配置域名+windows访问

准备工作&#xff1a;一个完整的centos环境&#xff0c;nginx安装包(可以从官网下载)nginx: download 一&#xff1a;centos可能有精简版&#xff0c;部分环境没有相关依赖包&#xff0c; 需要检查以下项&#xff1a; 1.gcc检查&#xff1a;gcc -v&#xff08;回车后应当有版…...

docker的数据卷和自定义镜像

docker的数据卷&#xff1a; 容器与宿主机之间&#xff0c;或者容器和容器之间的数据共享&#xff08;目录&#xff09;。 创建容器的时间&#xff0c;通过指定目录&#xff0c;实现容器于宿主机之间&#xff0c;或者容器和容器之间的数据共享。 容器的生命周期有限&#xff0c…...

在 Linux 下Ubuntu创建同权限用户

我是因为不小心把最开始创建的用户的文件夹颜色搞没了&#xff0c;再后来全白用习惯了&#xff0c;就不想卸载了&#xff0c;像创建一个和最开始创建的用户有一样的权限可以执行sudo -i进入root一样的用户 如图这是最原始的样子 第一步 创建新用户&#xff0c;我这里是因为之前…...

计算机视觉算法实战——面部特征点检测

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​ ​​​​​​​​​​​​​​​​​​ 1. 领域介绍✨✨ 面部特征点检测&#xff08;Facial Landmark Detection&#xff09;是计算机视觉中…...

电力场景红外测温图像均压环下的避雷器识别分割数据集labelme格式2436张1类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;2436 标注数量(json文件个数)&#xff1a;2436 标注类别数&#xff1a;1 标注类别名称:["arrester"] 每个类别标注的框数&am…...

4种革新性AI Agent工作流设计模式全解析

文章目录 导读&#xff1a;AI Agent的四种关键设计模式如下&#xff1a;1. 反思2. 工具使用3. 规划4. 多Agent协作 总结内容简介&#xff1a; 导读&#xff1a; AI Agent是指能够在特定环境中自主执行任务的人工智能系统&#xff0c;不仅接收任务&#xff0c;还自主制定和执行…...

C#基础 枚举 Enumeration从基础到进阶

目录 一、入门篇&#xff1a;枚举基础1. 枚举类型的定义2. 枚举类型的优点3. 枚举的基本使用3.1 枚举的类型转换3.2 遍历枚举成员3.3 判断枚举值是否有效3.4枚举的比较 4. 枚举的设计规范 二、深入底层篇&#xff1a;存储、值与继承限制1. 枚举的存储与表示2. 枚举底层类型选择…...

SOME/IP 协议详解——服务发现

文章目录 1. Introduction &#xff08;引言&#xff09;2. SOME/IP Service Discovery (SOME/IP-SD)2.1 General&#xff08;概述)2.2 SOME/IP-SD Message Format2.2.1 通用要求2.2.2 SOME/IP-SD Header2.2.3 Entry Format2.2.4 Options Format2.2.4.1 配置选项&#xff08;Co…...

android studio使用DataBinding

DataBinding 是谷歌官方发布的在android上对MVVM设计模式的一个实现框架&#xff0c;其作用是实现数据绑定。 Android DataBinding主要实现了View和ViewModel的双向绑定&#xff0c;包括用户的响应。并且实现了自动更新。 DataBinding优点&#xff1a; 1.大量减少Act…...