基于QWidget和QImage的水印添加实现

news2025/1/12 8:43:40

目录

1. 基于QWidget的屏幕阅读水印的添加

1.1 平铺

1.1.1 核心代码

1.1.2  构造函数中设置透明度和鼠标穿透

1.1.3 调用

1.1.4 效果展示

1.2 指定位置添加水印

1.2.1 核心代码

1.2.2 设置水印透明度和鼠标穿透

1.2.3 调用

1.2.4 效果展示

 2、基于QImage的屏幕水印的添加

2.1 平铺

2.1.1 核心代码

2.1.2 效果展示

2.2 指定位置添加

2.2.1 核心代码

2.2.2 效果展示

 3. 附加


最近研究了QT添加水印阅读和打印功能,参考各资源之后,考虑以两种方式实现:

1、平铺

2、指定位置(共九种a、水平位置-【左、中、右】 B、垂直位置-【上、中、下】)

这里分别基于QWidget和QImage添加水印文本。

可支持功能:

(1)支持自定义文本字体、颜色、间距、透明度、旋转角度以及绘制方式。实现个性化定制水印需求。

(2)支持水印文本宽、高自定义,可换行显示。

1. 基于QWidget的屏幕阅读水印的添加

1.1 平铺

1.1.1 核心代码

 /* 函数名称:
     *      ScreenWindowAddMarkByTile 【窗口添加水印-平铺】
     * 参数含义:
     *      vContent:水印的文本
     *      vFontFamily: 水印字体
     *      vFontSize: 水印字体大小(100)
     *      vAlpha: 透明度
     *      vColor: 水印字体颜色("#ffffff")
     *      vFontSpceing: 字体间距
     * 返回值:
     *      添加水印之后的QPixmap
    */
void ScreenWindowAddMarkByTile(const QString &vContent,
                                              const QString &vFontFamily,
                                              const int &vFontSize,
                                              const int &vFontSpceing,
                                              const QString &vColor,
                                              const int &vAlpha,
                                              const qreal &vAngle,
                                              const int &vWindowW,
                                              const int &vWindowH,
                                              const int &vMarkW,
                                              const int &vMarkH)
{
    // 设置水印内容
    QString content = vContent;

    // 当前窗口的宽高(即设置水印的区域)
    int width = vWindowW;
    int height = vWindowH;

    // 设置字体
    QFont font;
    font.setFamily(vFontFamily);
    font.setPointSize(vFontSize);
    font.setItalic(true);
    font.setLetterSpacing(QFont::AbsoluteSpacing, vFontSpceing);

    // 设置画笔
    QColor color(vColor);
    color.setAlpha(vAlpha); // 0-100之间(数值越小,越透明)
    QPen pen;
    pen.setColor(color);

    // 逆时针旋转角度
    int watermark_inclination_angle = vAngle;
    qreal angle = -watermark_inclination_angle;

    // 计算水印文本的宽高,以及绘制步长(X方向、Y方向)
    int watermark_width = vMarkW;
    int watermark_height = vMarkH;
    int x_step = vMarkW;
    int y_step = vMarkH;

    QFontMetrics fontMetrics(font);
    const int stepSpaceX = 20;
    const int stepSpaceY = 30;  // 步长间隙
    const int textW = fontMetrics.width(vContent);
    const int textH = fontMetrics.height();
    if(0 == watermark_width && 0 == watermark_height)       //1-宽高均未设置
    {
        x_step = watermark_width =  textW +  stepSpaceX;
        y_step = watermark_height = textH + stepSpaceY;
    }
    else if(0 == watermark_width)                           //2-只设置高,未设置宽
    {
        if(watermark_height < textH)
        {
           x_step = watermark_width = textW;
        }
        else
        {
            int row = watermark_height / textH;
            if(row == 0)                                    // 所设置到高度满足字体本身的倍数
            {
               row = 1;                                     // 默认行数为1
            }
            x_step = watermark_width = (textW / row);
        }
    }
    else if(0 == watermark_height)                          //3-只设置宽,未设置高
    {
        if( watermark_width > textW)
        {
            y_step = watermark_height = textH + stepSpaceY * 2;
        }
        else
        {
            int row = textW / watermark_width;
            if(row == 0)
            {
                row += 1;
            }
            y_step = watermark_height = (textH * row) + stepSpaceX * 4;
        }
        x_step += stepSpaceX;
    }

    y_step =  y_step*cos(abs(angle)) + x_step*sin(abs(angle));
    x_step =  y_step*sin(abs(angle)) + x_step*cos(abs(angle));

    // 投影长度(倾斜之后)
    // int project_Y = abs(this->width() * sin(angle)) + abs(this->height() * sin(angle)); // 原图像Y坐标在新坐标系Y轴上的投影长度
    // int project_X = abs(this->height()*sin(angle)) + abs(this->width()*cos(angle));     // 原图像x坐标在新坐标系x轴上的投影长度

    // 计算水印行数、列数
    int row_count = height / y_step;       //水印写多少行
    int col_count = width / x_step + 10; //水印写多少列 因为旋转了,如果不多加会导致水印缺少一块

    // 开始绘制
    for (int r = 0; r <= row_count; r++)
    {
        for (int c = 0; c <= col_count; c++)
        {
            QPainter p(this);
            p.setRenderHint(QPainter::Antialiasing, true);
            p.setFont(font);
            p.setPen(pen);
            p.translate(x_step * c, y_step * r);
            p.rotate(angle);
            p.drawText(QRect(0, 0, x_step, y_step), Qt::TextWordWrap, content);

        }
    }
}

1.1.2  构造函数中设置透明度和鼠标穿透

 setWindowOpacity(0.1);
 this->setAttribute(Qt::WA_TransparentForMouseEvents, true);

1.1.3 调用

stackedLayout即可。

1.1.4 效果展示

1.2 指定位置添加水印

可自定义位置共包含9个位置:

a、水平位置-【左、中、右】

B、垂直位置-【上、中、下】

1.2.1 核心代码

void ScreenWindowsAddMarkByPosition(
                           const QString &v_markContent,
                           const QString &v_fontFamily,
                           const int &v_fontSize,
                           const int &v_alpha,
                           const qreal &v_angle,
                           const QString &v_fontColor,
                           const int &v_fontSpaceing,
                           const int &v_WindowW,
                           const int &v_WindowH,
                           const int &v_markW,
                           const int &v_markH,
                           const emMarkPosition &v_posH,
                           const emMarkPosition &v_posV,
                           const int &v_padding)
{

    int fontSize = v_fontSize;

    emMarkPosition posH = v_posH;
    emMarkPosition posV = v_posV;

    //添加文字水印
    QFont font;
    font.setFamily(v_fontFamily);
    font.setPixelSize(fontSize);
    font.setLetterSpacing(QFont::AbsoluteSpacing, v_fontSpaceing);

    // 文字颜色
    QColor fontColor(v_fontColor);
    fontColor.setAlpha(v_alpha);

    QFontMetrics fm(font);
    int textW = fm.width(v_markContent);
    int textH = fm.height();
    int textMarkX = 0;
    int textMarkY = 0;
    int picMarkX = 0;
    int picMarkY = 0;

    // 计算水印文本的宽高,以及绘制步长(X方向、Y方向)
    int watermark_width = v_markW;
    int watermark_height = v_markH;
    const int stepSpaceX = 20;
    const int stepSpaceY = 20;
    if(0 == watermark_width && 0 == watermark_height)       //1-宽高均未设置
    {
        watermark_width =  textW +  stepSpaceX;
        watermark_height = textH + stepSpaceY;
    }
    else if(0 == watermark_width)                           //2-只设置高,未设置宽
    {
        if(watermark_height < textH)
        {
           watermark_width = textW + stepSpaceX;
        }
        else
        {
            int row = watermark_height / textH;
            if(row == 0)                                    // 所设置到高度满足字体本身的倍数
            {
               row = 1;                                     // 默认行数为1
            }
            watermark_width = (textW / row) + stepSpaceX;
        }
    }
    else if(0 == watermark_height)                          //3-只设置宽,未设置高
    {
        if( watermark_width > textW)
        {
           watermark_height = textH + stepSpaceY * 2;
        }
        else
        {
            int row = textW / watermark_width;
            if(row == 0)
            {
                row += 1;
            }
            watermark_height = (textH * row) + stepSpaceX * 4;
        }
    }

    int padding = v_padding;
    switch(posH)
    {
    case emLeft:
        picMarkX = padding;
        textMarkX = picMarkX + watermark_width + padding;
        break;
    case emRight:
        textMarkX = v_WindowW - /*textW*/watermark_width - padding;
        picMarkX = textMarkX;//- watermark_width - padding;
        break;
    case emHCenter:
        picMarkX = v_WindowW / 2 - (watermark_width/* + padding + textW*/) / 2;
        textMarkX = picMarkX + watermark_width + padding;
        break;
    default:
        break;
    }

    switch(posV)
    {
    case emTop:
        if (watermark_height >= textH)
        {
            picMarkY = padding;
            textMarkY = picMarkY + watermark_height / 2 - textH / 2;
        }
        else
        {
            textMarkY = padding;
            picMarkY = textMarkY + textH / 2 - watermark_height / 2;
        }
        break;
    case emBottom:
        if (watermark_height >= textH)
        {
            picMarkY = v_WindowH - padding - watermark_height;
            textMarkY = picMarkY + watermark_height / 2 - textH / 2;
        }
        else
        {
            textMarkY = v_WindowH - padding - textH;
            picMarkY = textMarkY + textH / 2 - watermark_height / 2;
        }
        break;
    case emVCenter:
        picMarkY = v_WindowH / 2 - watermark_height / 2;
        textMarkY = v_WindowH / 2 - textH / 2;
        break;
    default:
        break;
    }

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setFont(font);
    painter.setPen(fontColor);
    painter.translate(picMarkX, picMarkY);
    painter.rotate(v_angle);
    painter.drawText(QRect(0, 0, watermark_width, watermark_height),  Qt::TextWordWrap, v_markContent);
}

1.2.2 设置水印透明度和鼠标穿透

setWindowOpacity(0.1);
this->setAttribute(Qt::WA_TransparentForMouseEvents, true);  

1.2.3 调用

StackedLayout方式布局即可。

1.2.4 效果展示

 2、基于QImage的屏幕水印的添加

2.1 平铺

2.1.1 核心代码

/* 函数名称:
     *      PixmapAddMarkByTile 【以平铺的方式给pixmap添加水印,平铺】
     * 参数含义:
     *      v_pixmap: 需要添加水印的图片
     *      v_markContent:水印的文本
     *      v_markW:水印宽度
     *      v_markH: 水印高度
     *      v_fontFamily: 水印字体
     *      v_fontSize: 水印字体大小(100)
     *      v_alpha: 透明度
     *      v_fontColor: 水印字体颜色("#ffffff")
     *      v_fontSpaceing: 字体间距
     *      v_angle: 旋转角度
     * 返回值:
     *      添加水印之后的QPixmap
    */
QPixmap CustomizeMarkImage::PixmapAddMarkByTile(const QPixmap &v_pixmap,
                                     const QString &v_markContent,
                                     const int &v_markW,
                                     const int &v_markH,
                                     const QString &v_fontFamily,
                                     const int &v_fontSize,
                                     const int &v_alpha,
                                     const QString &v_fontColor,
                                     const int &v_fontSpaceing,
                                     const qreal &v_angle)
{
    QPixmap pixmap(v_pixmap);

    int fontSize = v_fontSize;
    int spacing = v_fontSpaceing;

    QFont font(v_fontFamily, fontSize, QFont::Thin);
    font.setLetterSpacing(QFont::AbsoluteSpacing, spacing);

    QColor color(v_fontColor);
    color.setAlpha(v_alpha);

    qreal angle = -v_angle;

    int x_step = v_markW;
    int y_step = v_markH;
    QFontMetrics fontMetrics(font);
    const int textW = fontMetrics.width(v_markContent);
    const int textH = fontMetrics.height();
    if(0 == v_markW && 0 == v_markH)                //1-宽高均未设置
    {
        x_step = textW;
        y_step = textH;
    }
    else if(0 == v_markW)                           //2-只设置高,未设置宽
    {
        if(v_markH < textH)
        {
           x_step = textW;
        }
        else
        {
            int row = v_markH / textH;
            if(row == 0)                            // 所设置到高度满足字体本身的倍数
            {
               row = 1;                             // 默认行数为1
            }
            x_step = (textW / row);
        }
    }
    else if(0 == v_markH)                          //3-只设置宽,未设置高
    {
        if(v_markH > textW)
        {
            y_step = textH;
        }
        else
        {
            int row = textW / v_markW;
            if(row == 0)
            {
                row += 1;
            }
            y_step = (textH * row);
        }
    }

    y_step =  y_step*cos(abs(angle)) + x_step*sin(abs(angle));
    x_step =  y_step*sin(abs(angle)) + x_step*cos(abs(angle));

    int col_count = pixmap.width() / y_step;            // 水印写多少列 因为旋转了,如果不多加会导致水印缺少一块
    int row_count  = pixmap.height() / x_step + 10;     // 水印写多少行

    for (int r = 0; r <= row_count; r++)
    {
        for (int c = 0; c <= col_count; c++)
        {
            QPainter painter(&pixmap);
            painter.setRenderHint(QPainter::Antialiasing, true);
            painter.setFont(font);
            painter.setPen(QColor(color));
            painter.translate(x_step * c, y_step * r);
            painter.rotate(angle);
            painter.drawText(QRect(0, 0, x_step, y_step), Qt::TextWordWrap, v_markContent);
        }
    }

    return pixmap;
}

2.1.2 效果展示

2.2 指定位置添加

共包含9个位置:

a、水平位置-【左、中、右】

B、垂直位置-【上、中、下】

2.2.1 核心代码

/* 函数名称:
     *      PixmapAddMarkByPosition 【给pixmap添加水印,通过指定位置】
     * 参数含义:
     *      v_pixmap: 需要添加水印的图片
     *      v_markContent:水印的文本
     *      v_markW:水印宽度
     *      v_markH: 水印高度
     *      v_fontFamily: 水印字体
     *      v_fontSize: 水印字体大小(100)
     *      v_alpha: 透明度
     *      v_fontColor: 水印字体颜色("#ffffff")
     *      v_fontSpaceing: 字体间距
     *      v_posH: 水平位置(左边、右边、水平居中)
     *      v_posV:垂直位置(顶部、底部、垂直居中)
     * 返回值:
     *      添加水印之后的QPixmap
    */

QPixmap CustomizeMarkImage::PixmapAddMarkByPosition(const QPixmap &v_pixmap,
                           const QString &v_markContent,
                           const int &v_markW,
                           const int &v_markH,
                           const QString &v_fontFamily,
                           const int &v_fontSize,
                           const int &v_alpha,
                           const int &v_angle,
                           const QString &v_fontColor,
                           const int &v_fontSpaceing,
                           const emMarkPosition &v_posH,
                           const emMarkPosition &v_posV,
                           const int &v_padding)
{
    QPixmap picMark(v_pixmap);
    int fontSize = v_fontSize;

    emMarkPosition posH = v_posH;
    emMarkPosition posV = v_posV;

    //添加文字水印
    QFont font;
    font.setFamily(v_fontFamily);
    font.setPixelSize(fontSize);
    font.setLetterSpacing(QFont::AbsoluteSpacing, v_fontSpaceing);

    QColor fontColor(v_fontColor);
    fontColor.setAlpha(v_alpha);

    QFontMetrics fm(font);
    int textW = fm.width(v_markContent);
    int textH = fm.height();
    int textMarkX = 0;
    int textMarkY = 0;
    int picMarkX = 0;
    int picMarkY = 0;

    // 计算水印文本的宽高,以及绘制步长(X方向、Y方向)
    int watermark_width = v_markW;
    int watermark_height = v_markH;
    const int stepSpaceX = 20;
    const int stepSpaceY = 20;
    if(0 == watermark_width && 0 == watermark_height)       //1-宽高均未设置
    {
        watermark_width =  textW +  stepSpaceX;
        watermark_height = textH + stepSpaceY;
    }
    else if(0 == watermark_width)                           //2-只设置高,未设置宽
    {
        if(watermark_height < textH)
        {
           watermark_width = textW + stepSpaceX;
        }
        else
        {
            int row = watermark_height / textH;
            if(row == 0)                                    // 所设置到高度满足字体本身的倍数
            {
               row = 1;                                     // 默认行数为1
            }
            watermark_width = (textW / row) + stepSpaceX;
        }
    }
    else if(0 == watermark_height)                          //3-只设置宽,未设置高
    {
        if( watermark_width > textW)
        {
           watermark_height = textH + stepSpaceY * 2;
        }
        else
        {
            int row = textW / watermark_width;
            if(row == 0)
            {
                row += 1;
            }
            watermark_height = (textH * row) + stepSpaceX * 4;
        }
    }

    int padding = v_padding;
    switch(posH)
    {
    case emLeft:
        picMarkX = padding;
        textMarkX = picMarkX + watermark_width + padding;
        break;
    case emRight:
        textMarkX = picMark.width() - /*textW*/watermark_width - padding;
        picMarkX = textMarkX;//- watermark_width - padding;
        break;
    case emHCenter:
        picMarkX = picMark.width() / 2 - (watermark_width/* + padding + textW*/) / 2;
        textMarkX = picMarkX + watermark_width + padding;
        break;
    default:
        break;
    }

    switch(posV)
    {
    case emTop:
        if (watermark_height >= textH)
        {
            picMarkY = padding;
            textMarkY = picMarkY + watermark_height / 2 - textH / 2;
        }
        else
        {
            textMarkY = padding;
            picMarkY = textMarkY + textH / 2 - watermark_height / 2;
        }
        break;
    case emBottom:
        if (watermark_height >= textH)
        {
            picMarkY = picMark.height() - padding - watermark_height;
            textMarkY = picMarkY + watermark_height / 2 - textH / 2;
        }
        else
        {
            textMarkY = picMark.height() - padding - textH;
            picMarkY = textMarkY + textH / 2 - watermark_height / 2;
        }
        break;
    case emVCenter:
        picMarkY = picMark.height() / 2 - watermark_height / 2;
        textMarkY = picMark.height() / 2 - textH / 2;
        break;
    default:
        break;
    }

    QPainter painter(&picMark);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setFont(font);
    painter.setPen(fontColor);
    painter.translate(picMarkX, picMarkY);
    painter.rotate(v_angle);
    painter.drawText(QRect(0, 0, watermark_width, watermark_height),  Qt::TextWordWrap, v_markContent);

    return picMark;
}

2.2.2 效果展示

 3. 附加

修改QPrintPreviewDialog背景色:

QPrintPreviewDialog *pPreviewDlg;
pPreviewDlg->setStyleSheet("QGraphicsView {qproperty-backgroundBrush: #F0F0F0; border:0px}");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/145947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QT 学习笔记(十四)

文章目录一、TCP/IP 通信过程简介1. Socket 通信2. Linux 下的 TCP/IP 通信过程3. QT 下的 TCP/IP 通信过程3.1 在 QT 中实现 TCP/IP 服务器端通信的流程3.2 客户端通信流程二、TCP/IP 通信过程操作实现1. 服务器端2. 客户端三、服务器端和客户端实现代码1. 主函数 main.c2. 服…

重装系统重新分区方法教程

对电脑进行系统重装以后&#xff0c;若是想电脑使用起来更稳定舒适&#xff0c;就要对电脑硬盘进行系统分区&#xff0c;但是许多用户都不知道怎样分区&#xff0c;今天小编就来为大家详细介绍一下重装系统重新分区方法教程。 工具/原料&#xff1a; 系统版本&#xff1a;win1…

11 个非常实用的 Python 和 Shell 拿来就用脚本实例!

我工作中用到的几个脚本&#xff0c;主要分为&#xff1a;Python和Shell两个部分。 Python 脚本部分实例&#xff1a;企业微信告警、FTP 客户端、SSH 客户端、Saltstack 客户端、vCenter 客户端、获取域名 ssl 证书过期时间、发送今天的天气预报以及未来的天气趋势图&#xff…

Verilog语法笔记(夏宇闻第三版)-赋值语句和块语句

目录 赋值语句: (1).非阻塞(Non_Blocking)赋值方式( 如 b < a; ): (2).阻塞(Blocking)赋值方式( 如 b a; ): 例&#xff1a; 块语句&#xff1a; 顺序块&#xff1a; 例&#xff1a; 并行块&#xff1a; 例&#xff1a; ​编辑 块名&#xff1a; 起始时间和结束…

php学习笔记-php运算符,类型转换,打印输出语句相较于其他语言的特殊部分-day02

php运算符&#xff0c;类型转换&#xff0c;打印输出语句相较于其他语言的特殊部分php运算符php的类型转换php打印输出语句php运算符 1.php运算符与其他高级语言相同的部分 算术运算符&#xff08;&#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;%&#xff09;&#xff0…

使用Flask快速部署PyTorch模型

对于数据科学项目来说&#xff0c;我们一直都很关注模型的训练和表现&#xff0c;但是在实际工作中如何启动和运行我们的模型是模型上线的最后一步也是最重要的工作。 今天我将通过一个简单的案例&#xff1a;部署一个PyTorch图像分类模型&#xff0c;介绍这个最重要的步骤。 …

OAK-PoE设备故障排查详解

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手…

Linux小黑板(5):磁盘与文件系统

"这月蹦迪没我" 一、浅谈磁盘 磁盘作为计算机硬件里&#xff0c;唯一的机械设备。在数据存储的领域&#xff0c;有着不可磨灭的作用。相较于&#xff0c;保持通电情况下具有保持数据的不丢失的内存&#xff0c;磁盘能够"永久性"地存储 数据。 磁盘是计算机…

1. R语言介绍、Rstudio的基本使用、【R包的安装与使用】、帮助命令、内置数据集

课程视频链接&#xff1a;https://www.bilibili.com/video/BV19x411X7C6?p1 本笔记参照该视频&#xff0c;笔记顺序做了些调整【个人感觉逻辑顺畅】&#xff0c;并删掉一些不重要的内容 系列笔记目录【持续更新】&#xff1a;https://blog.csdn.net/weixin_42214698/category_…

【Linux】进程控制:父进程与子进程

目录1 进程创建1.1 认识fork1.2 进程创建的目的1.3 写时拷贝1.4 进程创建失败的场景2 进程退出2.1 进程退出状态2.2 进程退出的方式2.3 exit、_exit、return2.3.1 概念2.3.2 区别3 进程等待3.1 理解进程等待3.2 进程等待的方式3.2.1 wait和waitpid3.2.2 status位图结构3.3 阻塞…

【一起从0开始学习人工智能0x04】python相关AI复习【超全面】【收藏】

基础小结 数据类型&#xff1a;Numbers、String、list、tuple、dict字符编码&#xff1a;可以直接.encode&#xff08;‘utf-8’&#xff09;、.decode(ascii)循环&#xff1a;for-in迭代器、whilelist列表-最频繁的数据类型。-完成大多数集合类的数据结构实现。它支持字符&am…

十六、状态管理——Vuex(4)

本章概要 表单处理Vuex 与组合 API模块 16.8 表单处理 在表单控件上通常会使用 v-model 指令进行数据绑定&#xff0c;如果绑定的数据是 Vuex 中的状态数据&#xff0c;就会遇到一些问题。看以下代码&#xff1a; form.html <div id"app"><my-component&…

一场衍生于产业的深度变革正在上演,总结起来就是产业互联网的变革

毫无疑问的是&#xff0c;一场衍生于产业的深度变革正在上演。在这样一场深度变革之中&#xff0c;曾经看似无法改变的存在&#xff0c;有了进化的可能性&#xff1b;曾经让玩家们望而却步的领域&#xff0c;有了进军的可能性。如果对这样一场深度变革进行一次总结的话&#xf…

vanishing point detection in autopilot

1. 概述 消失点一种直观的解释是图像中的平行线的交点&#xff0c;也就如下图中路面边界绘制的直线在图像中的交点。 这样的点在自动驾驶场景下可以为解析车辆状态提供一些信息&#xff0c;比如较为常规的运用便是用于车辆的pitch角度。在传统方法中会通过如霍夫算子检测图片…

2022稳定学习年度研究进展系列报告丨精华观点总结

近年来&#xff0c;在独立分布假设的前提下&#xff0c;机器学习模型的表现越来越好。但在实际应用场景中&#xff0c;数据本身却具有很强的异质性和差异性&#xff0c;这就对模型的泛化能力产生了较高的要求。为了解决分布外泛化问题&#xff0c;稳定学习应运而生。12月28日&a…

Python计算机视觉:人脸识别

讲明一下:并没有实现人脸识别的算法,只是利用人脸特征文件(文件从官网上下载),从而进行人脸识别,总感觉识别出来的效果还是有问题的,如:图片最好是人脸的正脸。 1. 人脸特征文件下载 直接去github或者gitee(建议gitee)上去搜索opencv即可,如下: 选择第一个直接进入即…

一篇文章带你了解——Linux中 文件权限 和 粘滞位的 概念 / 作用 及 实现方法

粘滞位首言用户权限文件权限文件类型分类文件访问者的分类实际解读文件权限文件权限设置方法为啥要有文件权限为啥要有粘滞位粘滞位的好处如何添加粘滞位首言 要了解粘滞位&#xff0c;首先得了解文件及用户权限 用户权限 Linux下有两种用户&#xff1a;超级用户&#xff08…

共享内存原理与使用

共享内存是System V版本的最后一个进程间通信方式。共享内存&#xff0c;顾名思义就是允许两个不相关的进程访问同一个逻辑内存&#xff0c;共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一…

vite学习详解

简介 前言 之前vite2刚出的时候其实已经自学过一波&#xff0c;但是老实说学起来完全不入脑&#xff0c;一方面本来这方面的基础就很差&#xff08;指项目配置&#xff09;&#xff0c;另一方面学的时候没有跟着去动手&#xff0c;纯理论的学那完全就是越看越困。最后就是急躁…

java书店带商家商城书店多单商书店系统源码

简介 Java ssm开发的多商家书店商城&#xff0c;用户可以浏览商品&#xff0c;加入购物车&#xff0c;直接下单支付&#xff0c;在我的个人中心里可以管理自己的订单&#xff0c;收货地址&#xff0c;编辑资料等&#xff0c;还可以申请开店&#xff0c;店铺开通后可以发布商品…